Compare commits
151 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 697c368f5c | |||
| b6b3a2b45e | |||
| d9877fedf8 | |||
| fbd9b516e8 | |||
| 142fba4bf4 | |||
| 623f882625 | |||
| b262bd7821 | |||
| bdab867205 | |||
| 7dde98d821 | |||
| b12a029919 | |||
| d921225b30 | |||
| 26e65e2a72 | |||
| b01b38ed5a | |||
| dbaf23e144 | |||
| 6511368389 | |||
| 3808af1e34 | |||
| fc7486d182 | |||
| ec84ec85e1 | |||
| 52edef245f | |||
| a47571d8af | |||
| df88416247 | |||
| b948e5a433 | |||
| dfebbc3c45 | |||
| 37d1f1f17e | |||
| 968dc9de10 | |||
| d126d05f4d | |||
| 3c441310a4 | |||
| f5d44a3f8f | |||
| 386e89f8f3 | |||
| ba4d5e80e2 | |||
| 8eb2c67453 | |||
| 36ba0c1f0a | |||
| a42f281613 | |||
| e3cf876ccc | |||
| f83c928c47 | |||
| f17badaa68 | |||
| 32731bda89 | |||
| 4afd915f49 | |||
| 54e7130488 | |||
| f66984ced0 | |||
| b3a8881074 | |||
| 96e7b4827a | |||
| 4019438a48 | |||
| 0ad71bd579 | |||
| a7e57c575d | |||
| 4270668c7c | |||
| 9432e755e6 | |||
| 5e284757e7 | |||
| bd08e437b6 | |||
| 49a7b5e0b4 | |||
| 81ee62ef52 | |||
| 601bec1af2 | |||
| efbdef87fa | |||
| b794e5aebd | |||
| 9e3bf98788 | |||
| ef38318ce8 | |||
| 6619c5cc7f | |||
| 70553ded2f | |||
| 184fe5eb1b | |||
| f6111628b0 | |||
| 94bc0035d3 | |||
| d2e654bf25 | |||
| 36f291aba4 | |||
| 41840e657a | |||
| 64bbd09f15 | |||
| 18ad8159cd | |||
| 872b9d519f | |||
| 702190b65a | |||
| ee6b50cb82 | |||
| de75b64133 | |||
| 07052a4160 | |||
| 99e30cda4a | |||
| 2b489b529f | |||
| 4b32ec3950 | |||
| 24116b1633 | |||
| 6bcd90f9bc | |||
| 46ed947331 | |||
| 1a600b7851 | |||
| 64d75d9aef | |||
| 4fdbff209f | |||
| 63e55b74e2 | |||
| f6865fbfe4 | |||
| 8775794f64 | |||
| 510114e1db | |||
| 00edb34a9d | |||
| afd3407309 | |||
| 81bc33a1e9 | |||
| 2495d86655 | |||
| 712f7ddbc0 | |||
| d4888e088e | |||
| 8dbbe46636 | |||
| 4186722ab9 | |||
| 184acc6485 | |||
| 1e42c41971 | |||
| 3331da2399 | |||
| ec841dff60 | |||
| e429ff9a47 | |||
| aa3a35b840 | |||
| 4c2d28fb37 | |||
| 322d7af231 | |||
| 77f37ea74c | |||
| 3194088e94 | |||
| d8020505c3 | |||
| 57aaeae566 | |||
| ac56186cf7 | |||
| f6e295a3f5 | |||
| 09415adce2 | |||
| 3609f446cb | |||
| 145f0c6702 | |||
| 61947a5acc | |||
| 9d638839d6 | |||
| 39e2370fde | |||
| 1c25d760e2 | |||
| a869b20d2b | |||
| 4e44140183 | |||
| 8d36597e0e | |||
| cbca88ec9d | |||
| e4d89b5132 | |||
| 5feef83ae0 | |||
| 123fbb3fb4 | |||
| 2021e92467 | |||
| 26f4def6c3 | |||
| ace0cba558 | |||
| b669aba0dc | |||
| 3a20198e52 | |||
| c7e23817d6 | |||
| 8ab527e096 | |||
| baca55494c | |||
| 2ce47117e1 | |||
| 398d4cc342 | |||
| cbbfc629eb | |||
| a8d37525c3 | |||
| 08f15a687f | |||
| b3ff86ce8b | |||
| 17eeec3d26 | |||
| 702c2e01da | |||
| ff9885c5f8 | |||
| 021236498e | |||
| 28e159b8bd | |||
| 022a3ad303 | |||
| 71c9bcb05a | |||
| 6b8bccff1d | |||
| ea158a44b0 | |||
| c140ec8b21 | |||
| be581a8757 | |||
| 285babb9c9 | |||
| fa95157ab7 | |||
| e208f23363 | |||
| deab4d3df0 | |||
| 3fffc8d2df | |||
| ff41fe80c4 |
@@ -14,3 +14,7 @@ src/.vuepress/.cache
|
||||
src/.vuepress/.temp
|
||||
src/.vitepress/cache
|
||||
packages-list.json
|
||||
/.vale
|
||||
/.vscode
|
||||
/.vale.ini
|
||||
/.markdownlint.json
|
||||
@@ -1,6 +1,6 @@
|
||||
deploy-test-stand:
|
||||
stage: deploy
|
||||
image: harbor.vimpelcom.ru/dockerhub/library/alpine
|
||||
image: harbor.vimpelcom.ru/dockerhub/library/alpine:3.21.2
|
||||
variables:
|
||||
stand: cloud-stand.vega-dev.cloud.vimpelcom.ru
|
||||
rules:
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
deploy-prod:
|
||||
stage: deploy
|
||||
image: harbor.vimpelcom.ru/dockerhub/library/alpine:3.21.2
|
||||
variables:
|
||||
stand: beecloud-docs.beecloud-docs.cloud.vimpelcom.ru
|
||||
rules:
|
||||
- if: $CI_COMMIT_BRANCH && $CI_PIPELINE_SOURCE == "merge_request_event"
|
||||
when: never
|
||||
- if: $CI_PIPELINE_SOURCE == "push"
|
||||
when: manual
|
||||
before_script:
|
||||
- |
|
||||
sed -i s%https://dl-cdn.alpinelinux.org/%http://rhrepo.vimpelcom.ru/ext/ya/mirrors/% /etc/apk/repositories && \
|
||||
apk --no-cache add tzdata ca-certificates curl openssh-client yq jq && \
|
||||
rm -rf /var/cache/apk/*
|
||||
- which ssh-agent || (apt-get update -y && apt-get install openssh-client -y)
|
||||
- eval $(ssh-agent -s)
|
||||
- mkdir -p ~/.ssh
|
||||
- echo -n "$TECH_SSH_KEY" | tr -d '\r' > ~/.ssh/id_rsa
|
||||
- chmod 700 ~/.ssh
|
||||
- chmod 600 ~/.ssh/id_rsa
|
||||
- >
|
||||
echo "stand: ${stand}"
|
||||
ssh-keyscan "${stand}" >> ~/.ssh/known_hosts
|
||||
- chmod 644 ~/.ssh/known_hosts
|
||||
- PRODUCT="$PRODUCT_DMZ"
|
||||
script:
|
||||
- >
|
||||
echo -e "Connect to ${stand}..." &&
|
||||
scp -o StrictHostKeyChecking=no ci/deploy/deploy.sh "dorootless@${stand}:~/deploy.sh" &&
|
||||
ssh "dorootless@${stand}" "export CONTAINER_REGISTRY=$CONTAINER_REGISTRY &&
|
||||
export PRODUCT=$PRODUCT &&
|
||||
export PRODUCT_VERSION=$PRODUCT_VERSION &&
|
||||
export IMAGE_NAME=$IMAGE_NAME &&
|
||||
chmod 700 ~/deploy.sh &&
|
||||
~/deploy.sh ${IMAGE_NAME} &&
|
||||
rm -f ~/deploy.sh"
|
||||
needs:
|
||||
- job: build-image
|
||||
optional: true
|
||||
@@ -23,7 +23,7 @@
|
||||
# - git push origin HEAD:$CI_COMMIT_REF_NAME -o ci.skip
|
||||
|
||||
.deploy-template:
|
||||
image: harbor.vimpelcom.ru/dockerhub/library/alpine
|
||||
image: harbor.vimpelcom.ru/dockerhub/library/alpine:3.21.2
|
||||
before_script:
|
||||
- |
|
||||
sed -i s%https://dl-cdn.alpinelinux.org/%http://rhrepo.vimpelcom.ru/ext/ya/mirrors/% /etc/apk/repositories && \
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "docs",
|
||||
"version": "0.6.1",
|
||||
"description": "Vega docs portal",
|
||||
"version": "0.6.5-main",
|
||||
"description": "Beeline Cloud docs",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"dev": "vitepress dev src",
|
||||
@@ -15,16 +15,17 @@
|
||||
},
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@beeline/design-tokens": "^1.31.0",
|
||||
"vue": "3.4.7"
|
||||
"@beeline/design-tokens": "^1.31.6",
|
||||
"vue": "^3.5.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@docsearch/css": "3.3.0",
|
||||
"@types/node": "20.10.7",
|
||||
"@vitejs/plugin-vue": "4.3.4",
|
||||
"sass": "1.69.7",
|
||||
"typescript": "^5.8.3",
|
||||
"vitepress": "1.0.0-rc.40",
|
||||
"vitepress-plugin-tabs": "0.5.0"
|
||||
"@docsearch/css": "4.1.0",
|
||||
"@types/node": "^22.0.0",
|
||||
"@vitejs/plugin-vue": "^6.0.3",
|
||||
"sass": "^1.70.0",
|
||||
"typescript": "^5.9.3",
|
||||
"vite-plugin-static-copy": "^3.1.4",
|
||||
"vitepress": "^1.6.4",
|
||||
"vitepress-plugin-tabs": "^0.7.3"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,9 @@
|
||||
import { defineConfig } from 'vitepress'
|
||||
import { tabsMarkdownPlugin } from 'vitepress-plugin-tabs'
|
||||
import { viteStaticCopy } from 'vite-plugin-static-copy'
|
||||
import { overrideComponents } from './override-components'
|
||||
import { resolve } from 'node:path'
|
||||
import { fileURLToPath, URL } from 'node:url'
|
||||
|
||||
const gitlab = `<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
@@ -42,10 +45,12 @@ console.log({ base: typeof new_version !== 'undefined' ? '/' : '/docs/' })
|
||||
|
||||
// https://vitepress.dev/reference/site-config
|
||||
export default defineConfig({
|
||||
title: "Beeline Cloud",
|
||||
srcDir: ".",
|
||||
title: " ",
|
||||
description: "Документация Beeline Cloud",
|
||||
head: [['link', { rel: 'icon', type: 'image/png', sizes: '32x32', href: '/bee-favicon.png' }]],
|
||||
base: typeof new_version !== 'undefined' ? '/' : '/docs/',
|
||||
appearance: false,
|
||||
markdown: {
|
||||
config(md) {
|
||||
md.use(tabsMarkdownPlugin)
|
||||
@@ -53,8 +58,31 @@ export default defineConfig({
|
||||
},
|
||||
vite: {
|
||||
resolve: {
|
||||
alias: overrideComponents(),
|
||||
}
|
||||
alias: [
|
||||
...overrideComponents(),
|
||||
{
|
||||
find: '@',
|
||||
replacement: fileURLToPath(new URL('./theme', import.meta.url))
|
||||
},
|
||||
],
|
||||
},
|
||||
plugins: [
|
||||
viteStaticCopy({
|
||||
targets: [
|
||||
{
|
||||
src: resolve(__dirname, '../../node_modules/@beeline/design-tokens/assets/fonts'),
|
||||
dest: 'assets',
|
||||
},
|
||||
],
|
||||
}),
|
||||
],
|
||||
css: {
|
||||
preprocessorOptions: {
|
||||
scss: {
|
||||
api: 'modern-compiler',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
locales: {
|
||||
root: {
|
||||
@@ -63,7 +91,11 @@ export default defineConfig({
|
||||
}
|
||||
},
|
||||
themeConfig: {
|
||||
logo: '/favicon.svg',
|
||||
logo: {
|
||||
light: '/img/logo-cloud.svg',
|
||||
dark: '/img/logo-cloud.svg',
|
||||
alt: '',
|
||||
},
|
||||
search: {
|
||||
provider: 'local',
|
||||
options: {
|
||||
@@ -75,14 +107,8 @@ export default defineConfig({
|
||||
buttonAriaLabel: 'Поиск'
|
||||
},
|
||||
modal: {
|
||||
noResultsText: 'Нет результатов для',
|
||||
noResultsText: 'По вашему запросу ничего не найдено',
|
||||
resetButtonTitle: 'Сбросить',
|
||||
displayDetails: 'Показать расширенный список',
|
||||
footer: {
|
||||
selectText: 'Выбрать',
|
||||
closeText: 'Закрыть',
|
||||
navigateText: 'Перейти',
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -90,30 +116,27 @@ export default defineConfig({
|
||||
}
|
||||
},
|
||||
// https://vitepress.dev/reference/default-theme-config
|
||||
// nav: [
|
||||
// ],
|
||||
|
||||
// socialLinks: [
|
||||
// { icon: { svg: gitlab }, link: 'https://git.vimpelcom.ru/common/vega/docs' }
|
||||
// ],
|
||||
|
||||
// editLink: {
|
||||
// pattern: 'https://git.vimpelcom.ru/-/ide/project/common/vega/docs/edit/develop/-/src/:path',
|
||||
// text: 'Отредактируйте эту страницу на GitLab'
|
||||
// },
|
||||
// nav: [
|
||||
// {
|
||||
// text: 'Документация',
|
||||
// link: '/guide/',
|
||||
// },
|
||||
// {
|
||||
// text: 'API',
|
||||
// link: '',
|
||||
// },
|
||||
// {
|
||||
// text: 'Terraform',
|
||||
// // link: '/terraform/',
|
||||
// link: '',
|
||||
// },
|
||||
// ],
|
||||
|
||||
docFooter: {
|
||||
next: 'Вперед',
|
||||
prev: 'Назад'
|
||||
},
|
||||
|
||||
// lastUpdated: {
|
||||
// text: 'Обновлена',
|
||||
// formatOptions: {
|
||||
// dateStyle: 'long',
|
||||
// }
|
||||
// },
|
||||
|
||||
outline: {
|
||||
label: 'Содержание'
|
||||
},
|
||||
@@ -123,82 +146,381 @@ export default defineConfig({
|
||||
text: 'Платформа Beeline Cloud', link: '/platform/index.md',
|
||||
collapsed: true,
|
||||
items: [
|
||||
{text: 'Сервисы', link: '/platform/services/services.md'},
|
||||
{text: 'Обзор', link: '/platform/about.md'},
|
||||
{text: 'Техническая поддержка', link: '/platform/support/support-overview.md'},
|
||||
],
|
||||
},
|
||||
],
|
||||
'/legal/': [
|
||||
{ text: 'Юридические документы', link: '/legal/index.md' },
|
||||
{ text: 'Общие документы', link: '/legal/index.md' },
|
||||
],
|
||||
'/security/': [
|
||||
{
|
||||
text: 'Сервисы информационной безопасности в Beeline Cloud', link: '/security/index.md',
|
||||
},
|
||||
{
|
||||
text: 'Cloud Security Awareness (SA)', link: 'security/Cloud-SA/SA-index.md',
|
||||
collapsed: true,
|
||||
items: [
|
||||
{
|
||||
text: 'Состав сервиса SA', link: '/security/Cloud-SA/SA-index.md',
|
||||
collapsed: true,
|
||||
items: [
|
||||
{ text: 'Обзор сервиса', link: '/security/Cloud-SA/compond-SA/about.md' },
|
||||
{ text: 'Состав сервиса', link: '/security/Cloud-SA/compond-SA/compond-SA.md' },
|
||||
{ text: 'Настройки сервиса по умолчанию', link: '/security/Cloud-SA/compond-SA/default-service.md' },
|
||||
{ text: 'Почтовый ретранслятор (SMTP relay)', link: '/security/Cloud-SA/compond-SA/mail-relay.md' },
|
||||
{ text: 'Мониторинг работоспособности платформы', link: '/security/Cloud-SA/compond-SA/monitoring.md' },
|
||||
{ text: 'Модули платформы', link: '/security/Cloud-SA/compond-SA/platform-modules.md' },
|
||||
{ text: 'Ограничения платформы', link: '/security/Cloud-SA/compond-SA/restrictions.md' },
|
||||
{ text: 'Отказоустойчивость сервиса', link: '/security/Cloud-SA/compond-SA/stability.md' },
|
||||
{ text: 'Шаблоны почтовых сообщений и веб-форм', link: '/security/Cloud-SA/compond-SA/templates.md' },
|
||||
{ text: 'Дополнительные работы ', link: '/security/Cloud-SA/compond-SA/work.md' },
|
||||
]
|
||||
},
|
||||
{ text: 'Качественные характеристики сервиса', link: '/security/Cloud-SA/characteristics.md' },
|
||||
{ text: 'Инструкции для начала работы с сревисом', link: '/security/Cloud-SA/instructions.md' },
|
||||
{ text: 'Порядок платежей', link: '/security/Cloud-SA/payment-procedure.md' },
|
||||
{ text: 'Сроки и условия предоставления сервиса', link: '/security/Cloud-SA/provision.md' },
|
||||
]
|
||||
},
|
||||
{
|
||||
text: 'Cloud Vulnerability Scanner (VS)', link: '/security/Cloud-VS/VS-index.md',
|
||||
collapsed: true,
|
||||
items: [
|
||||
{ text: 'Обзор сервиса VS', link: '/security/Cloud-VS/about.md'},
|
||||
{ text: 'Варианты предоставления сервиса', link: '/security/Cloud-VS/provision-service.md' },
|
||||
{ text: 'Мониторинг работоспособности и отказоустойчивость сервиса', link: '/security/Cloud-VS/monitoring.md' },
|
||||
{ text: 'Состав работ', link: '/security/Cloud-VS/scope-work.md' },
|
||||
{ text: 'Дополнительные работы', link: '/security/Cloud-VS/work.md' },
|
||||
{ text: 'Зоны ответсвенности', link: '/security/Cloud-VS/areas-responsibility.md' },
|
||||
{ text: 'Качественные характеристики сервиса', link: '/security/Cloud-VS/characteristics.md' },
|
||||
{ text: 'Сроки предоставления сервиса', link: '/security/Cloud-VS/provision.md' },
|
||||
{ text: 'Порядок платежей', link: '/security/Cloud-VS/payment-procedure.md' },
|
||||
]
|
||||
},
|
||||
{
|
||||
text: 'Cloud Mobile Device Management (MDM)', link: '/security/Cloud-MDM/MDM-index.md',
|
||||
collapsed: true,
|
||||
items: [
|
||||
{ text: 'Обзор сервиса', link: '/security/Cloud-MDM/about.md' },
|
||||
{
|
||||
text: 'Описание сервиса MDM', link: '/security/Cloud-MDM/description/description-index.md',
|
||||
collapsed: true,
|
||||
items: [
|
||||
{ text: 'Состав сервиса', link: '/security/Cloud-MDM/description/compound.md' },
|
||||
{ text: 'Архитектура сервиса', link: '/security/Cloud-MDM/description/architecture.md' },
|
||||
{ text: 'Зоны ответственности', link: '/security/Cloud-MDM/description/areas-responsibility.md' },
|
||||
{ text: 'Мониторинг работоспособности и отказоустойчивость сервиса', link: '/security/Cloud-MDM/description/monitoring.md' },
|
||||
{ text: 'Дополнительные работы', link: '/security/Cloud-MDM/description/work.md' },
|
||||
]
|
||||
},
|
||||
{ text: 'Качественные характеристики сервиса', link: '/security/Cloud-MDM/characteristics.md' },
|
||||
{ text: 'Сроки и условия предоставления сервиса', link: '/security/Cloud-MDM/provision.md' },
|
||||
{ text: 'Порядок платежей', link: '/security/Cloud-MDM/payments.md' },
|
||||
{
|
||||
text: 'Инструкции', link: '/security/Cloud-MDM/instructions/index.md',
|
||||
collapsed: true,
|
||||
items: [
|
||||
{ text: 'Инструкции', link: '/security/Cloud-MDM/instructions/instructions.md' },
|
||||
{ text: 'Активация учетной записи', link: '/security/Cloud-MDM/instructions/activation.md' },
|
||||
{ text: 'Режим Device Owner', link: '/security/Cloud-MDM/instructions/device-owner.md' },
|
||||
]
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
text: 'Cloud NGFW', link: '/security/Cloud-NGFW/NGFW-index.md',
|
||||
collapsed: true,
|
||||
items: [
|
||||
{ text: 'Обзор сервиса', link: '/security/Cloud-NGFW/about.md'},
|
||||
{ text: 'Основные возможности', link: '/security/Cloud-NGFW/possibilities.md' },
|
||||
{ text: 'Спецификация сервиса', link: '/security/Cloud-NGFW/specification.md' },
|
||||
{ text: 'Состав сервиса', link: '/security/Cloud-NGFW/compound.md' },
|
||||
{ text: 'Сроки и условия предоставления сервиса. Зоны ответственности', link: '/security/Cloud-NGFW/provision.md' },
|
||||
{ text: 'Структура платежей', link: '/security/Cloud-NGFW/payment-structure.md' },
|
||||
]
|
||||
},
|
||||
{
|
||||
text: 'Cloud NGFW F', link: '/security/Cloud-NGFW-F/NGFW-F-index.md',
|
||||
collapsed: true,
|
||||
items: [
|
||||
{ text: 'Обзор сервиса', link: '/security/Cloud-NGFW-F/about.md'},
|
||||
{ text: 'Порядок подключения сервиса', link: '/security/Cloud-NGFW-F/connection.md' },
|
||||
{ text: 'Варианты предоставления', link: '/security/Cloud-NGFW-F/delivery-options.md' },
|
||||
{ text: 'Состав сервиса', link: '/security/Cloud-NGFW-F/compound.md' },
|
||||
{ text: 'Функциональные возможности', link: '/security/Cloud-NGFW-F/functional-capabilities.md' },
|
||||
{ text: 'Структура платежей', link: '/security/Cloud-NGFW-F/payment-structure.md' },
|
||||
{ text: 'Тестирование сервиса', link: '/security/Cloud-NGFW-F/testing.md' },
|
||||
]
|
||||
},
|
||||
{
|
||||
text: 'Cloud NGFW Pro', link: '/security/Cloud-NGFW-Pro/NGFW-Pro-index.md',
|
||||
collapsed: true,
|
||||
items: [
|
||||
{ text: 'Обзор сервиса', link: '/security/Cloud-NGFW-Pro/about.md'},
|
||||
{ text: 'Основные возможности', link: '/security/Cloud-NGFW-Pro/possibilities.md' },
|
||||
{ text: 'Спецификация сервиса', link: '/security/Cloud-NGFW-Pro/specification.md' },
|
||||
{ text: 'Состав сервиса', link: '/security/Cloud-NGFW-Pro/compound.md' },
|
||||
{ text: 'Сроки и условия предоставления сервиса', link: '/security/Cloud-NGFW-Pro/provision.md' },
|
||||
{ text: 'Демодоступ к сервису', link: '/security/Cloud-NGFW-Pro/demo-access.md' },
|
||||
{ text: 'Структура платежей', link: '/security/Cloud-NGFW-Pro/payment-structure.md' },
|
||||
]
|
||||
},
|
||||
],
|
||||
'/start/': [
|
||||
{
|
||||
text: 'Начало работы в Beeline Cloud', link: '/start/index.md',
|
||||
},
|
||||
{text: 'Начать работу', link: '/start/getting-started.md'},
|
||||
{text: 'Бесплатный период', link: '/start/trial.md'},
|
||||
{text: 'Платное использование', link: '/start/organization.md'},
|
||||
],
|
||||
|
||||
'/PaaS/': [
|
||||
{
|
||||
text: 'Начало работы в Cloud PostgreSQL', link: '/PaaS/index.md',
|
||||
},
|
||||
{ text: 'Cloud PostgreSQL', link: '/PaaS/PostgreSQL/PostgreSQL-index.md',
|
||||
collapsed: true,
|
||||
items: [
|
||||
{text: 'Начать работу', link: '/start/getting-started.md'},
|
||||
{text: 'Бесплатный период', link: '/start/trial.md'},
|
||||
{text: 'Платное использование', link: '/start/organization.md'},
|
||||
],
|
||||
},
|
||||
],
|
||||
items: [
|
||||
{text: 'Обзор сервиса', link: '/PaaS/PostgreSQL/about.md'},
|
||||
{text: 'Описание технических параметров', link: '/PaaS/PostgreSQL/cluster-parameter.md'},
|
||||
{text: 'Общая схема подключения', link: '/PaaS/PostgreSQL/connection.md'},
|
||||
{text: 'Возможности пользователя', link: '/PaaS/PostgreSQL/user-capabilities.md'},
|
||||
{text: 'Веб-интерфейс pgAdmin', link: '/PaaS/PostgreSQL/pgadmin.md'},
|
||||
{text: 'Веб-интерфейс Grafana', link: '/PaaS/PostgreSQL/grafana.md'},
|
||||
],
|
||||
},
|
||||
{text: 'IPSEC', link: '/PaaS/IPSEC.md'},
|
||||
|
||||
{
|
||||
text: 'Deckhouse', link: 'PaaS/Deckhouse/index.md',
|
||||
collapsed: true,
|
||||
items: [
|
||||
{text: 'Обзор сервиса', link: '/PaaS/Deckhouse/about.md'},
|
||||
{text: 'Права и возможности пользователей', link: '/PaaS/Deckhouse/user-permissions.md'},
|
||||
{text: 'Описание технических параметров', link: '/PaaS/Deckhouse/technical-parameters.md'},
|
||||
{text: 'Подключение к сервису', link: '/PaaS/Deckhouse/connection.md'}
|
||||
]
|
||||
}
|
||||
],
|
||||
|
||||
// '/billing/': [
|
||||
|
||||
// ],
|
||||
'/backups/': [
|
||||
{
|
||||
text: 'Резервное копирование', link: '/backups/index.md',
|
||||
},
|
||||
{
|
||||
text: 'Обзор сервиса', link: '/backups/backups-overview.md',
|
||||
collapsed: true,
|
||||
items: [
|
||||
{text: 'О сервисе', link: '/backups/about.md'},
|
||||
{text: 'Квоты и лимиты', link: '/backups/backup-quatos.md'},
|
||||
]
|
||||
},
|
||||
{text: 'Резервное копирование виртуальных машин Beeline Cloud', link: '/backups/backup-internal-infra.md'},
|
||||
{text: 'Резервное копирование собственной инфраструктуры в Beeline Cloud', link: '/backups/backup-external-infra.md'},
|
||||
{text: 'Каталог резервных копий', link: '/backups/view-backups.md'},
|
||||
|
||||
],
|
||||
'/vdc/': [
|
||||
{
|
||||
text: 'Виртуальные дата-центры на VMware', link: '/vdc/index.md',
|
||||
collapsed: true,
|
||||
items: [
|
||||
{text: 'Обзор сервиса', link: '/vdc/vdc-overview.md'},
|
||||
{text: 'Быстрый старт', link: '/vdc/vdc-getting-started.md'},
|
||||
{text: 'Виртуальные дата-центры', link: '/vdc/vdc-how-to/vdc-index.md',
|
||||
collapsed: true,
|
||||
items: [
|
||||
text: 'Виртуальные дата-центры на VMware', link: '/vdc/index.md',
|
||||
},
|
||||
{
|
||||
text: 'Обзор сервиса', link: '/vdc/vdc-overview.md',
|
||||
collapsed: true,
|
||||
items: [
|
||||
{ text: 'О сервисе', link: '/vdc/vdc-about.md' },
|
||||
{ text: 'Техническое описание', link: '/vdc/vdc-tech.md' },
|
||||
{ text: 'Квоты и лимиты', link: '/vdc/vdc-quatos.md' },
|
||||
]
|
||||
},
|
||||
{
|
||||
text: 'Быстрый старт', link: '/vdc/vdc-getting-started.md'
|
||||
},
|
||||
|
||||
{ text: 'Виртуальные дата-центры', link: '/vdc/vdc-how-to/vdc-index.md',
|
||||
collapsed: true,
|
||||
items: [
|
||||
{ text: 'Создание дата-центра', link: '/vdc/vdc-how-to/vdc-create.md' },
|
||||
{ text: 'Вход в дата-центр', link: '/vdc/vdc-how-to/vdc-enter.md' },
|
||||
{ text: 'Управление дата-центром', link: '/vdc/vdc-how-to/vdc-manage.md' },
|
||||
{ text: 'Управление дата-центром', link: '/vdc/vdc-how-to/vdc-manage.md'},
|
||||
],
|
||||
},
|
||||
{ text: 'Виртуальные машины', link: '/vdc/vdc-how-to/vm/vm-index.md',
|
||||
collapsed: true,
|
||||
items: [
|
||||
{text: 'Создание ВМ', link: '/vdc/vdc-how-to/vm/create-vm.md'},
|
||||
{text: 'Создание vApp', link: '/vdc/vdc-how-to/vm/create-vapp.md'},
|
||||
{text: 'Управление состоянием ВМ', link: '/vdc/vdc-how-to/vm/manage-vm.md'},
|
||||
{text: 'Клонирование ВМ', link: '/vdc/vdc-how-to/vm/clone-vm.md'},
|
||||
{text: 'Изменение конфигурации ВМ', link: '/vdc/vdc-how-to/vm/edit-vm.md'},
|
||||
{text: 'Удаление ВМ', link: '/vdc/vdc-how-to/vm/delete-vm.md'},
|
||||
{text: 'Группы размещения', link: '/vdc/vdc-how-to/vm/create-affinity-rules.md'},
|
||||
{text: 'Снимки ВМ', link: '/vdc/vdc-how-to/vm/create-snapshot.md'},
|
||||
{text: 'VMware Tools', link: '/vdc/vdc-how-to/vm/vmware-tools.md'},
|
||||
],
|
||||
},
|
||||
{ text: 'Диски', link: '/vdc/vdc-how-to/disks/disks-index.md',
|
||||
collapsed: true,
|
||||
items: [
|
||||
{text: 'Обзор', link: '/vdc/vdc-how-to/disks/about.md'},
|
||||
{text: 'Создание диска', link: '/vdc/vdc-how-to/disks/create-disk.md'},
|
||||
{text: 'Проверка состояния диска', link: '/vdc/vdc-how-to/disks/view-disk.md'},
|
||||
{text: 'Управление выделенными дисками', link: '/vdc/vdc-how-to/disks/attach-disk.md'},
|
||||
{text: 'Изменение политики хранения дисков ВМ', link: '/vdc/vdc-how-to/disks/change-storage-policy-of-vm.md'},
|
||||
{text: 'Редактирование параметров диска', link: '/vdc/vdc-how-to/disks/edit-disk.md'},
|
||||
{text: 'Удаление диска', link: '/vdc/vdc-how-to/disks/delete-disk.md'},
|
||||
],
|
||||
},
|
||||
{ text: 'Сети', link: '/vdc/vdc-how-to/networks/networks-index.md',
|
||||
collapsed: true,
|
||||
items: [
|
||||
{text: 'Обзор', link: '/vdc/vdc-how-to/networks/about.md'},
|
||||
{text: 'Настройка доступа к ВМ из интернета', link: '/vdc/vdc-how-to/networks/allow-external-connections-to-vm.md'},
|
||||
{text: 'Подключение ВМ в vApp к сети', link: '/vdc/vdc-how-to/networks/connect-vapp-to-network.md'},
|
||||
{text: 'Подключение ВМ к интернету', link: '/vdc/vdc-how-to/networks/connect-vm-to-network.md'},
|
||||
{text: 'Создание сети в организации и подключение к Edge Gateway', link: '/vdc/vdc-how-to/networks/create-network.md'},
|
||||
{text: 'Подключение сети к Edge Gateway', link: '/vdc/vdc-how-to/networks/connect-to-edge-gateway.md'},
|
||||
{text: 'Создание Pre-Shared Key', link: '/vdc/vdc-how-to/networks/create-psk.md'},
|
||||
{ text: 'Настройка site-to-site подключения с помощью IPSec', link: '/vdc/vdc-how-to/networks/how-to-setup-ipsec-vpn.md',
|
||||
collapsed: true,
|
||||
items: [
|
||||
{text: 'Настройка IPSec VPN', link: '/vdc/vdc-how-to/networks/ipsec/setup-ipsec-vpn.md'},
|
||||
{text: 'Настройка ASAv', link: '/vdc/vdc-how-to/networks/ipsec/asav.md'},
|
||||
{text: 'Настройка CSR 1000v', link: '/vdc/vdc-how-to/networks/ipsec/csr1000v.md'},
|
||||
{text: 'Настройка Fortigate', link: '/vdc/vdc-how-to/networks/ipsec/fortigate.md'},
|
||||
{text: 'Проверить сетевую связанность', link: '/vdc/vdc-how-to/networks/ipsec/check-vpn-status.md'},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{ text: 'Пользователи и роли', link: '/vdc/vdc-how-to/users/users-index.md',
|
||||
collapsed: true,
|
||||
items: [
|
||||
{text: 'Ролевая модель', link: '/vdc/vdc-how-to/users/roles.md'},
|
||||
{text: 'Создание пользователя', link: '/vdc/vdc-how-to/users/add-user.md'},
|
||||
{text: 'Изменение пароля пользователя', link: '/vdc/vdc-how-to/users/change-users-password.md'},
|
||||
{text: 'Настройка квот', link: '/vdc/vdc-how-to/users/quotas.md'},
|
||||
],
|
||||
},
|
||||
{ text: 'Двухфакторная аутентификация', link: '/vdc/vdc-how-to/vdc-2fa.md',
|
||||
collapsed: true,
|
||||
items: [
|
||||
{text: 'Подключение 2FA', link: '/vdc/vdc-how-to/vdc-2fa-start.md'},
|
||||
{text: 'Управление 2FA', link: '/vdc/vdc-how-to/vdc-2fa-manage.md'},
|
||||
{text: 'Подключение 2FA', link: '/vdc/vdc-how-to/vdc-2fa-start.md'},
|
||||
{text: 'Управление 2FA', link: '/vdc/vdc-how-to/vdc-2fa-manage.md'},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
// { text: 'Тарификация', link: '/vdc/vdc-tarif.md' },
|
||||
],
|
||||
},
|
||||
],
|
||||
|
||||
// { text: 'Тарификация', link: '/vdc/vdc-tarif.md' },
|
||||
'/compute/': [
|
||||
{
|
||||
text: 'Виртуальные машины', link: '/compute/index.md',
|
||||
collapsed: true,
|
||||
text: 'Виртуальные машины', link: '/compute/index.md',
|
||||
},
|
||||
{ text: 'Обзор сервиса', link: '/compute/compute-overview-index.md' ,
|
||||
collapsed: true,
|
||||
items: [
|
||||
{ text: 'Техническое описание', link: '/compute/compute-overview.md' },
|
||||
{ text: 'Квоты и лимиты', link: '/compute/compute-quatos.md' },
|
||||
]
|
||||
},
|
||||
{text: 'Быстрый старт', link: '/compute/compute-getting-started.md'},
|
||||
{ text: 'Виртуальные машины', link: '/compute/compute-how-to/compute-index.md',
|
||||
collapsed: true,
|
||||
items: [
|
||||
{text: 'Обзор сервиса', link: '/compute/compute-overview.md'},
|
||||
// {text: 'Быстрый старт', link: '/compute/compute-getting-started.md'},
|
||||
{text: 'Виртуальные машины', link: '/compute/compute-how-to/compute-index.md',
|
||||
collapsed: true,
|
||||
items: [
|
||||
{ text: 'Создание ВМ', link: '/compute/compute-how-to/compute-servers-create.md' },
|
||||
{ text: 'Подключение к ВМ', link: '/compute/compute-how-to/compute-connect.md' },
|
||||
{ text: 'Создание ВМ джамп-хоста', link: '/compute/compute-how-to/compute-servers-jump-create.md' },
|
||||
{ text: 'Подключение к ВМ', link: '/compute/compute-how-to/compute-connect-index.md',
|
||||
collapsed: true,
|
||||
items: [
|
||||
{ text: 'Подключение по SSH по внешнему IP-адресу с помощью ключевой пары', link: '/compute/compute-how-to/compute-connect-public.md'},
|
||||
{ text: 'Подключение по SSH по внутреннему IP-адресу с помощью ключевой пары', link: '/compute/compute-how-to/compute-connect-inside.md' },
|
||||
{ text: 'Подключение по SSH по логину и паролю', link: '/compute/compute-how-to/compute-connect-pwd.md' },
|
||||
]
|
||||
},
|
||||
{ text: 'Управление ВМ', link: '/compute/compute-how-to/compute-servers-manage.md' },
|
||||
],
|
||||
},
|
||||
{ text: 'Диски', link: '/compute/compute-how-to/compute-disks.md' },
|
||||
{ text: 'IP-адреса', link: '/compute/compute-how-to/compute-ip.md' },
|
||||
{ text: 'Группы размещения', link: '/compute/compute-how-to/compute-affinity.md' },
|
||||
{ text: 'Диски', link: '/compute/compute-how-to/compute-disks/compute-disk-index.md',
|
||||
collapsed: true,
|
||||
items: [
|
||||
{ text: 'Обзор', link: '/compute/compute-how-to/compute-disks/compute-disk-about.md' },
|
||||
{ text: 'Создание диска', link: '/compute/compute-how-to/compute-disks/compute-disk-create.md' },
|
||||
{ text: 'Управление дисками', link: '/compute/compute-how-to/compute-disks/compute-disk-manage.md' },
|
||||
{ text: 'Удаление диска', link: '/compute/compute-how-to/compute-disks/compute-disk-del.md' },
|
||||
]
|
||||
},
|
||||
{ text: 'IP-адреса', link: '/compute/compute-how-to/compute-ip/compute-ip-index.md',
|
||||
collapsed: true,
|
||||
items: [
|
||||
{ text: 'Обзор', link: '/compute/compute-how-to/compute-ip/compute-ip-about.md' },
|
||||
{ text: 'Просмотр IP-адресов', link: '/compute/compute-how-to/compute-ip/compute-ip-view.md' },
|
||||
{ text: 'Создание IP-адреса', link: '/compute/compute-how-to/compute-ip/compute-ip-create.md' },
|
||||
{ text: 'Управление IP-адресами', link: '/compute/compute-how-to/compute-ip/compute-ip-manager.md' },
|
||||
{ text: 'Удаление IP-адреса', link: '/compute/compute-how-to/compute-ip/compute-ip-del.md' },
|
||||
]
|
||||
},
|
||||
{ text: 'Группы размещения', link: '/compute/compute-how-to/compute-placement-groups/compute-placement-groups-index.md',
|
||||
collapsed: true,
|
||||
items: [
|
||||
{ text: 'Обзор', link: '/compute/compute-how-to/compute-placement-groups/compute-placement-groups-about.md'},
|
||||
{ text: 'Создание группы размещения', link: '/compute/compute-how-to/compute-placement-groups/compute-placement-groups-create.md'},
|
||||
{ text: 'Управление группами размещения', link: '/compute/compute-how-to/compute-placement-groups/compute-placement-groups-manager.md' },
|
||||
{ text: 'Удаление группы размещения', link: '/compute/compute-how-to/compute-placement-groups/compute-placement-groups-del.md' },
|
||||
]
|
||||
},
|
||||
{ text: 'Сети', link: '/compute/compute-how-to/compute-network/compute-network-index.md',
|
||||
collapsed: true,
|
||||
items: [
|
||||
{ text: 'Настройка site-to-site VPN с помощью VyOS', link: '/compute/compute-how-to/compute-network/compute-vpn-vyos.md' },
|
||||
{ text: 'Подключение ВМ закрытого контура к интернету', link: '/compute/compute-how-to/compute-network/compute-network-inside.md' },
|
||||
],
|
||||
},
|
||||
|
||||
],
|
||||
],
|
||||
'/admin/': [
|
||||
{
|
||||
text: 'Аккаунт Beeline Cloud', link: '/admin/acc-index.md',
|
||||
collapsed: true,
|
||||
items: [
|
||||
{text: 'Управление ключевыми парами', link: '/admin/ssh.md'},
|
||||
],
|
||||
text: 'Администрирование', link: '/admin/index.md',
|
||||
},
|
||||
{text: 'Управление ключевыми парами', link: '/admin/ssh.md'},
|
||||
],
|
||||
'/vdi/': [
|
||||
{
|
||||
text: 'Виртуальные рабочие столы', link: '/vdi/index.md',
|
||||
},
|
||||
],
|
||||
{
|
||||
text: 'Обзор сервиса', link: '/vdi/vdi-overview.md',
|
||||
collapsed: true,
|
||||
items: [
|
||||
{ text: 'О сервисе', link: '/vdi/vdi-about.md' },
|
||||
{ text: 'Техническое описание', link: '/vdi/vdi-tech.md' },
|
||||
{ text: 'Квоты и лимиты', link: '/vdi/vdi-quatos.md' },
|
||||
{ text: 'Тарификация', link: '/vdi/vdi-tarif.md' },
|
||||
]
|
||||
},
|
||||
{
|
||||
text: 'Заказ виртуальных рабочих столов', link: '/vdi/vdi-how-to/vdi-create.md'
|
||||
},
|
||||
{
|
||||
text: 'Настройка сервиса', link: '/vdi/vdi-how-to/vdi-nastroika.md',
|
||||
collapsed: true,
|
||||
items: [
|
||||
{ text: 'Настройка интеграции с Active Directory', link: '/vdi/vdi-how-to/vdi-connect-to-ad.md' },
|
||||
{ text: 'Настройка сети', link: '/vdi/vdi-how-to/vdi-interconnect.md' },
|
||||
]
|
||||
},
|
||||
// {
|
||||
// text: 'Gold-образ', link: '/vdi/vdi-how-to/vdi-gold.md'
|
||||
// },
|
||||
{
|
||||
text: 'Подключение к виртуальному рабочему месту', link: '/vdi/vdi-how-to/vdi-connect.md'
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -106,7 +106,7 @@ export default function(parameters: IParameters) {
|
||||
// window._paq elsewhere when needed, including closure scopes.
|
||||
const _paq = window._paq;
|
||||
// If user requests consent checking, do this before we actually track.
|
||||
// Note: this doesn't work at the moment because the user has no way to set
|
||||
// tip: this doesn't work at the moment because the user has no way to set
|
||||
// whether consent was given. Oops.
|
||||
if (requireConsent) {
|
||||
_paq.push(['requireConsent']);
|
||||
|
||||
@@ -5,7 +5,7 @@ import { EXTERNAL_URL_RE } from 'vitepress/dist/client/shared'
|
||||
|
||||
interface Props {
|
||||
tag?: string
|
||||
size?: 'medium' | 'big'
|
||||
size?: 'medium' | 'big' | 'small'
|
||||
theme?: 'brand' | 'alt' | 'sponsor'
|
||||
text: string
|
||||
href?: string
|
||||
@@ -51,6 +51,15 @@ const component = computed(() => {
|
||||
transition: color 0.1s, border-color 0.1s, background-color 0.1s;
|
||||
}
|
||||
|
||||
.VPButton.small {
|
||||
border-radius: 12px;
|
||||
padding: 0 16px;
|
||||
line-height: 20px;
|
||||
height: 40px;
|
||||
font-size: 15px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.VPButton.medium {
|
||||
border-radius: 12px;
|
||||
padding: 0 20px;
|
||||
|
||||
@@ -115,7 +115,7 @@ const { hasSidebar } = useSidebar()
|
||||
|
||||
.VPContent.has-sidebar {
|
||||
margin: var(--vp-layout-top-height, 0px) 0 0;
|
||||
padding-left: var(--vp-sidebar-width);
|
||||
padding-left: 320px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -54,10 +54,12 @@ const pageName = computed(() =>
|
||||
<div class="content-container">
|
||||
<slot name="doc-before" />
|
||||
<main class="main">
|
||||
<Content class="vp-doc" :class="[
|
||||
pageName,
|
||||
theme.externalLinkIcon && 'external-link-icon-enabled'
|
||||
]" />
|
||||
<div class="vp-doc" :class="[
|
||||
pageName,
|
||||
theme.externalLinkIcon && 'external-link-icon-enabled'
|
||||
]">
|
||||
<Content />
|
||||
</div>
|
||||
<SectionLinkList v-if="frontmatter.section_links" :links="frontmatter.section_links" />
|
||||
</main>
|
||||
<VPDocFooter>
|
||||
@@ -74,7 +76,7 @@ const pageName = computed(() =>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@use 'src/assets/scss/app/helpers/media';
|
||||
@use '@/scss/helpers/media';
|
||||
|
||||
.VPDoc {
|
||||
padding: 32px 24px 96px;
|
||||
|
||||
@@ -6,6 +6,8 @@ import { usePrevNext } from 'vitepress/dist/client/theme-default/composables/pre
|
||||
import VPIconEdit from 'vitepress/dist/client/theme-default/components/icons/VPIconEdit.vue'
|
||||
import VPLink from 'vitepress/dist/client/theme-default/components/VPLink.vue'
|
||||
import VPDocFooterLastUpdated from 'vitepress/dist/client/theme-default/components/VPDocFooterLastUpdated.vue'
|
||||
import CustomIcon from './CustomIcon.vue'
|
||||
import { Icons } from '@beeline/design-tokens/js/iconfont/icons'
|
||||
|
||||
const { theme, page, frontmatter } = useData()
|
||||
|
||||
@@ -43,14 +45,14 @@ const showFooter = computed(() => {
|
||||
<nav v-if="control.prev?.link || control.next?.link" class="prev-next">
|
||||
<div class="pager">
|
||||
<VPLink v-if="control.prev?.link" class="pager-link prev" :href="control.prev.link">
|
||||
<span class="desc" v-html="theme.docFooter?.prev || 'Previous page'"></span>
|
||||
<CustomIcon class="desc-prev" :icon="Icons.ArrowRight" />
|
||||
<span class="title" v-html="control.prev.text"></span>
|
||||
</VPLink>
|
||||
</div>
|
||||
<div class="pager">
|
||||
<VPLink v-if="control.next?.link" class="pager-link next" :href="control.next.link">
|
||||
<span class="desc" v-html="theme.docFooter?.next || 'Next page'"></span>
|
||||
<span class="title" v-html="control.next.text"></span>
|
||||
<CustomIcon class="desc-next" :icon="Icons.ArrowRight" />
|
||||
</VPLink>
|
||||
</div>
|
||||
</nav>
|
||||
@@ -59,7 +61,7 @@ const showFooter = computed(() => {
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.VPDocFooter {
|
||||
margin-top: 64px;
|
||||
margin-top: 40px;
|
||||
}
|
||||
|
||||
.edit-info {
|
||||
@@ -98,8 +100,6 @@ const showFooter = computed(() => {
|
||||
}
|
||||
|
||||
.prev-next {
|
||||
border-top: 1px solid var(--vp-c-divider);
|
||||
padding-top: 24px;
|
||||
display: grid;
|
||||
grid-row-gap: 8px;
|
||||
}
|
||||
@@ -115,10 +115,19 @@ const showFooter = computed(() => {
|
||||
display: block;
|
||||
border: 1px solid var(--vp-c-divider);
|
||||
border-radius: 8px;
|
||||
padding: 11px 16px 13px;
|
||||
padding: 10px 16px 10px 12px;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
transition: border-color 0.25s;
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
|
||||
color: #1a73e8;
|
||||
|
||||
&.next {
|
||||
padding: 10px 12px 10px 16px;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
}
|
||||
|
||||
.pager-link:hover {
|
||||
@@ -136,6 +145,14 @@ const showFooter = computed(() => {
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
color: var(--vp-c-text-2);
|
||||
|
||||
&-next {
|
||||
rotate: -270deg;
|
||||
}
|
||||
|
||||
&-prev {
|
||||
rotate: -90deg;
|
||||
}
|
||||
}
|
||||
|
||||
.title {
|
||||
|
||||
@@ -22,8 +22,7 @@ type ItemFeature = {
|
||||
const style = useCssModule()
|
||||
const classes = computed(() => ({
|
||||
[style.CustomFeature]: true,
|
||||
[style.CustomFeatureDisabled]: disabled || !link,
|
||||
[style.CustomFeatureWithScroll]: scrollTo && !disabled
|
||||
[style.CustomFeatureDisabled]: disabled || !link && !scrollTo,
|
||||
}))
|
||||
|
||||
const handleClick = (event: Event) => {
|
||||
@@ -51,7 +50,11 @@ const handleClick = (event: Event) => {
|
||||
</Component>
|
||||
<div :class="$style.CustomFeatureContainer">
|
||||
<div v-for="(item, i) in items" :key="i">
|
||||
<Component :is="!disabled && item.link ? VPLink : 'article'" v-bind="{ ...(!disabled && item.link && { href: item.link }) }">
|
||||
<Component
|
||||
:is="!disabled && item.link ? VPLink : 'article'"
|
||||
v-bind="{ ...(!disabled && item.link && { href: item.link }) }"
|
||||
:class="{ [style.CustomFeatureDisabled]: disabled || !item.link }"
|
||||
>
|
||||
<p :class="$style.CustomFeatureSubtitle">{{ item.title }}</p>
|
||||
</Component>
|
||||
</div>
|
||||
@@ -94,16 +97,12 @@ const handleClick = (event: Event) => {
|
||||
color: themes.$color-text-active;
|
||||
|
||||
&:hover {
|
||||
color: themes.$color-text-link !important;
|
||||
color: themes.$color-text-link;
|
||||
}
|
||||
|
||||
#{$el}Disabled & {
|
||||
color: themes.$color-text-disabled;
|
||||
}
|
||||
|
||||
#{$el}WithScroll & {
|
||||
color: themes.$color-text-active;
|
||||
}
|
||||
}
|
||||
|
||||
&Subtitle {
|
||||
|
||||
@@ -20,6 +20,7 @@ import {
|
||||
nextTick,
|
||||
onBeforeUnmount,
|
||||
onMounted,
|
||||
Raw,
|
||||
ref,
|
||||
shallowRef,
|
||||
watch,
|
||||
@@ -32,6 +33,8 @@ import { escapeRegExp } from 'vitepress/dist/client/shared'
|
||||
import { useData } from 'vitepress/dist/client/theme-default/composables/data'
|
||||
import { LRUCache } from 'vitepress/dist/client/theme-default/support/lru'
|
||||
import { createSearchTranslate } from 'vitepress/dist/client/theme-default/support/translation'
|
||||
import CustomIcon from './CustomIcon.vue';
|
||||
import { Icons } from '@beeline/design-tokens/js/iconfont/icons';
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'close'): void
|
||||
@@ -132,6 +135,7 @@ watchEffect(() => {
|
||||
const results: Ref<(SearchResult & Result)[]> = shallowRef([])
|
||||
|
||||
const enableNoResults = ref(false)
|
||||
const loadig = ref(true)
|
||||
|
||||
watch(filterText, () => {
|
||||
enableNoResults.value = false
|
||||
@@ -160,11 +164,7 @@ debouncedWatch(
|
||||
if (!index) return
|
||||
|
||||
// Search
|
||||
results.value = index
|
||||
.search(filterTextValue)
|
||||
.slice(0, 16) as (SearchResult & Result)[]
|
||||
enableNoResults.value = true
|
||||
|
||||
retrySearch(index, filterTextValue)
|
||||
// Highlighting
|
||||
const mods = showDetailedListValue
|
||||
? await Promise.all(results.value.map((r) => fetchExcerpt(r.id)))
|
||||
@@ -268,6 +268,16 @@ function focusSearchInput(select = true) {
|
||||
select && searchInput.value?.select()
|
||||
}
|
||||
|
||||
const retrySearch = (index: Raw<MiniSearch<Result>>, filter: string) => {
|
||||
if (!index) return
|
||||
|
||||
results.value = index
|
||||
.search(filter)
|
||||
.slice(0, 16) as (SearchResult & Result)[]
|
||||
|
||||
enableNoResults.value = true
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
focusSearchInput()
|
||||
})
|
||||
@@ -481,33 +491,6 @@ function formMarkRegex(terms: Set<string>) {
|
||||
class="search-input"
|
||||
/>
|
||||
<div class="search-actions">
|
||||
<button
|
||||
v-if="!disableDetailedView"
|
||||
class="toggle-layout-button"
|
||||
type="button"
|
||||
:class="{ 'detailed-list': showDetailedList }"
|
||||
:title="$t('modal.displayDetails')"
|
||||
@click="
|
||||
selectedIndex > -1 && (showDetailedList = !showDetailedList)
|
||||
"
|
||||
>
|
||||
<svg
|
||||
width="18"
|
||||
height="18"
|
||||
viewBox="0 0 24 24"
|
||||
aria-hidden="true"
|
||||
>
|
||||
<path
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M3 14h7v7H3zM3 3h7v7H3zm11 1h7m-7 5h7m-7 6h7m-7 5h7"
|
||||
/>
|
||||
</svg>
|
||||
</button>
|
||||
|
||||
<button
|
||||
class="clear-button"
|
||||
type="reset"
|
||||
@@ -515,26 +498,13 @@ function formMarkRegex(terms: Set<string>) {
|
||||
:title="$t('modal.resetButtonTitle')"
|
||||
@click="resetSearch"
|
||||
>
|
||||
<svg
|
||||
width="18"
|
||||
height="18"
|
||||
viewBox="0 0 24 24"
|
||||
aria-hidden="true"
|
||||
>
|
||||
<path
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M20 5H9l-7 7l7 7h11a2 2 0 0 0 2-2V7a2 2 0 0 0-2-2Zm-2 4l-6 6m0-6l6 6"
|
||||
/>
|
||||
</svg>
|
||||
<CustomIcon :icon="Icons.Close" size="large" style="padding: 12px 0;" />
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<ul
|
||||
v-if="!!results.length"
|
||||
ref="resultsEl"
|
||||
:id="results?.length ? 'localsearch-list' : undefined"
|
||||
:role="results?.length ? 'listbox' : undefined"
|
||||
@@ -561,29 +531,21 @@ function formMarkRegex(terms: Set<string>) {
|
||||
>
|
||||
<div>
|
||||
<div class="titles">
|
||||
<span class="title-icon">#</span>
|
||||
<span
|
||||
v-for="(t, index) in p.titles"
|
||||
:key="index"
|
||||
class="title"
|
||||
>
|
||||
<span class="text" v-html="t" />
|
||||
<svg width="18" height="18" viewBox="0 0 24 24">
|
||||
<path
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="m9 18l6-6l-6-6"
|
||||
/>
|
||||
</svg>
|
||||
<span class="text"> > </span>
|
||||
</span>
|
||||
<span class="title main">
|
||||
<span class="text" v-html="p.title" />
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<span v-html="p.title" />
|
||||
|
||||
<div v-if="showDetailedList" class="excerpt-wrapper">
|
||||
<div v-if="p.text" class="excerpt" inert>
|
||||
<div class="vp-doc" v-html="p.text" />
|
||||
@@ -594,65 +556,15 @@ function formMarkRegex(terms: Set<string>) {
|
||||
</div>
|
||||
</a>
|
||||
</li>
|
||||
<li
|
||||
v-if="filterText && !results.length && enableNoResults"
|
||||
class="no-results"
|
||||
>
|
||||
{{ $t('modal.noResultsText') }} "<strong>{{ filterText }}</strong
|
||||
>"
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div class="search-keyboard-shortcuts">
|
||||
<span>
|
||||
<kbd :aria-label="$t('modal.footer.navigateUpKeyAriaLabel')">
|
||||
<svg width="14" height="14" viewBox="0 0 24 24">
|
||||
<path
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M12 19V5m-7 7l7-7l7 7"
|
||||
/>
|
||||
</svg>
|
||||
</kbd>
|
||||
<kbd :aria-label="$t('modal.footer.navigateDownKeyAriaLabel')">
|
||||
<svg width="14" height="14" viewBox="0 0 24 24">
|
||||
<path
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M12 5v14m7-7l-7 7l-7-7"
|
||||
/>
|
||||
</svg>
|
||||
</kbd>
|
||||
{{ $t('modal.footer.navigateText') }}
|
||||
</span>
|
||||
<span>
|
||||
<kbd :aria-label="$t('modal.footer.selectKeyAriaLabel')">
|
||||
<svg width="14" height="14" viewBox="0 0 24 24">
|
||||
<g
|
||||
fill="none"
|
||||
stroke="currentcolor"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
>
|
||||
<path d="m9 10l-5 5l5 5" />
|
||||
<path d="M20 4v7a4 4 0 0 1-4 4H4" />
|
||||
</g>
|
||||
</svg>
|
||||
</kbd>
|
||||
{{ $t('modal.footer.selectText') }}
|
||||
</span>
|
||||
<span>
|
||||
<kbd :aria-label="$t('modal.footer.closeKeyAriaLabel')">esc</kbd>
|
||||
{{ $t('modal.footer.closeText') }}
|
||||
</span>
|
||||
</div>
|
||||
<ul
|
||||
v-else-if="filterText && !results.length && enableNoResults"
|
||||
class="no-results"
|
||||
>
|
||||
<p class="no-results-text">
|
||||
{{ $t('modal.noResultsText') }}
|
||||
</p>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</Teleport>
|
||||
@@ -675,16 +587,12 @@ function formMarkRegex(terms: Set<string>) {
|
||||
|
||||
.shell {
|
||||
position: relative;
|
||||
padding: 12px;
|
||||
padding: 24px;
|
||||
margin: 64px auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 16px;
|
||||
background: var(--vp-local-search-bg);
|
||||
width: min(100vw - 60px, 900px);
|
||||
height: min-content;
|
||||
max-height: min(100vh - 128px, 900px);
|
||||
border-radius: 6px;
|
||||
border-radius: 12px;
|
||||
}
|
||||
|
||||
@media (max-width: 767px) {
|
||||
@@ -698,7 +606,7 @@ function formMarkRegex(terms: Set<string>) {
|
||||
}
|
||||
|
||||
.search-bar {
|
||||
border: 1px solid var(--vp-c-divider);
|
||||
border: 1px solid rgb(32, 33, 35);
|
||||
border-radius: 12px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@@ -712,10 +620,6 @@ function formMarkRegex(terms: Set<string>) {
|
||||
}
|
||||
}
|
||||
|
||||
.search-bar:focus-within {
|
||||
border-color: var(--vp-c-brand-1);
|
||||
}
|
||||
|
||||
.search-icon {
|
||||
margin: 8px;
|
||||
}
|
||||
@@ -756,7 +660,7 @@ function formMarkRegex(terms: Set<string>) {
|
||||
}
|
||||
|
||||
.search-actions button {
|
||||
padding: 8px;
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
.search-actions button:not([disabled]):hover,
|
||||
@@ -802,27 +706,31 @@ function formMarkRegex(terms: Set<string>) {
|
||||
}
|
||||
|
||||
.results {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 6px;
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
overscroll-behavior: contain;
|
||||
border-radius: 12px;
|
||||
border: 1px solid rgba(25, 28, 52, 0.18);
|
||||
padding: 8px 0;
|
||||
max-height: min(100vh - 214px, 900px);
|
||||
box-shadow: 0px 6px 38px rgba(0, 0, 0, 0.16), 0px 0px 10px rgba(0, 0, 0, 0.08);
|
||||
|
||||
li:hover {
|
||||
background-color: rgba(25, 28, 52, 0.08);
|
||||
}
|
||||
}
|
||||
|
||||
.result {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
border-radius: 12px;
|
||||
transition: none;
|
||||
line-height: 1rem;
|
||||
border: solid 2px var(--vp-local-search-result-border);
|
||||
outline: none;
|
||||
min-height: 66px;
|
||||
}
|
||||
|
||||
.result > div {
|
||||
margin: 12px;
|
||||
margin: 12px 16px;
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
@@ -840,6 +748,13 @@ function formMarkRegex(terms: Set<string>) {
|
||||
position: relative;
|
||||
z-index: 1001;
|
||||
padding: 2px 0;
|
||||
font-size: 13px !important;
|
||||
line-height: 16px !important;
|
||||
}
|
||||
|
||||
:deep(mark) {
|
||||
background-color: transparent;
|
||||
color: none;
|
||||
}
|
||||
|
||||
.title {
|
||||
@@ -852,21 +767,10 @@ function formMarkRegex(terms: Set<string>) {
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.title-icon {
|
||||
opacity: 0.5;
|
||||
font-weight: 500;
|
||||
color: var(--vp-c-brand-1);
|
||||
}
|
||||
|
||||
.title svg {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.result.selected {
|
||||
--vp-local-search-result-bg: var(--vp-local-search-result-selected-bg);
|
||||
border-color: var(--vp-local-search-result-selected-border);
|
||||
}
|
||||
|
||||
.excerpt-wrapper {
|
||||
position: relative;
|
||||
}
|
||||
@@ -892,10 +796,7 @@ function formMarkRegex(terms: Set<string>) {
|
||||
|
||||
.titles :deep(mark),
|
||||
.excerpt :deep(mark) {
|
||||
background-color: var(--vp-local-search-highlight-bg);
|
||||
color: var(--vp-local-search-highlight-text);
|
||||
border-radius: 2px;
|
||||
padding: 0 2px;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.excerpt :deep(.vp-code-group) .tabs {
|
||||
@@ -932,12 +833,44 @@ function formMarkRegex(terms: Set<string>) {
|
||||
}
|
||||
|
||||
.no-results {
|
||||
font-size: 0.9rem;
|
||||
text-align: center;
|
||||
padding: 12px;
|
||||
padding: 28px 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 24px;
|
||||
align-items: center;
|
||||
z-index: 100;
|
||||
box-shadow: 0px 6px 38px rgba(0, 0, 0, 0.16), 0px 0px 10px rgba(0, 0, 0, 0.08);
|
||||
border-radius: 12px;
|
||||
border: 1px solid rgba(25, 28, 52, 0.18);
|
||||
background-color: rgb(255, 255, 255);
|
||||
}
|
||||
|
||||
.no-results-text {
|
||||
font-weight: 400;
|
||||
font-size: 17px;
|
||||
line-height: 22px;
|
||||
letter-spacing: 0.2px;
|
||||
color: rgba(25, 28, 52, 0.48);
|
||||
}
|
||||
|
||||
.no-results-button {
|
||||
border-radius: 12px;
|
||||
border: 1px solid rgba(25, 28, 52, 0.18);
|
||||
padding: 13px 20px;
|
||||
font-weight: 500;
|
||||
font-size: 17px;
|
||||
line-height: 22px;
|
||||
letter-spacing: 0.2px;
|
||||
color: rgba(9, 11, 22, 0.94);
|
||||
}
|
||||
|
||||
svg {
|
||||
flex: none;
|
||||
}
|
||||
|
||||
.text {
|
||||
font-size: 13px !important;
|
||||
line-height: 16px !important;
|
||||
color: rgba(25, 28, 52, 0.48);
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -12,6 +12,7 @@ import VPNavBarSearch from 'vitepress/dist/client/theme-default/components/VPNav
|
||||
import VPNavBarSocialLinks from 'vitepress/dist/client/theme-default/components/VPNavBarSocialLinks.vue'
|
||||
import CustomNavBarTitle from './CustomNavBarTitle.vue'
|
||||
import VPNavBarTranslations from 'vitepress/dist/client/theme-default/components/VPNavBarTranslations.vue'
|
||||
import CustomButton from './CustomButton.vue'
|
||||
|
||||
defineProps<{
|
||||
isScreenOpen: boolean
|
||||
@@ -27,6 +28,7 @@ const { hasLocalNav } = useLocalNav()
|
||||
const { frontmatter } = useData()
|
||||
|
||||
const classes = ref<Record<string, boolean>>({})
|
||||
const loginUrl = import.meta.env.VITE_LOGIN_URL
|
||||
|
||||
watchPostEffect(() => {
|
||||
classes.value = {
|
||||
@@ -55,14 +57,9 @@ watchPostEffect(() => {
|
||||
<div class="content">
|
||||
<div class="content-body">
|
||||
<slot name="nav-bar-content-before" />
|
||||
<VPNavBarSearch class="search" />
|
||||
<VPNavBarMenu class="menu" />
|
||||
<VPNavBarTranslations class="translations" />
|
||||
<VPNavBarAppearance class="appearance" />
|
||||
<VPNavBarSocialLinks class="social-links" />
|
||||
<VPNavBarExtra class="extra" />
|
||||
<slot name="nav-bar-content-after" />
|
||||
<VPNavBarHamburger class="hamburger" :active="isScreenOpen" @click="$emit('toggle-screen')" />
|
||||
<VPNavBarSearch class="search" />
|
||||
<!-- <CustomButton text="Войти" size="small" :href="loginUrl" /> -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -109,7 +106,7 @@ watchPostEffect(() => {
|
||||
|
||||
@media (min-width: 768px) {
|
||||
.wrapper {
|
||||
padding: 0 32px;
|
||||
padding: 0 24px;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -178,7 +175,7 @@ watchPostEffect(() => {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
padding-right: 32px;
|
||||
padding-left: var(--vp-sidebar-width);
|
||||
padding-left: 0px;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -191,7 +188,7 @@ watchPostEffect(() => {
|
||||
|
||||
.content-body {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
height: var(--vp-nav-height);
|
||||
transition: background-color 0.5s;
|
||||
@@ -225,6 +222,10 @@ watchPostEffect(() => {
|
||||
height: 24px;
|
||||
background-color: var(--vp-c-divider);
|
||||
content: "";
|
||||
font-weight: 500;
|
||||
font-size: 15px;
|
||||
line-height: 20px;
|
||||
letter-spacing: 0.2px;
|
||||
}
|
||||
|
||||
.menu + .appearance::before,
|
||||
@@ -255,4 +256,9 @@ watchPostEffect(() => {
|
||||
background-color: rgba(255, 255, 255, 0.2);
|
||||
}
|
||||
}
|
||||
|
||||
.search {
|
||||
justify-content: flex-end;
|
||||
margin-right: 24px;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -3,12 +3,16 @@ import type { DefaultTheme } from 'vitepress/theme'
|
||||
import { useData } from 'vitepress/dist/client/theme-default/composables/data'
|
||||
import { isActive } from 'vitepress/dist/client/shared'
|
||||
import VPLink from 'vitepress/dist/client/theme-default/components/VPLink.vue'
|
||||
import { computed, ref } from 'vue'
|
||||
|
||||
defineProps<{
|
||||
item: DefaultTheme.NavItemWithLink
|
||||
}>()
|
||||
|
||||
const { page } = useData()
|
||||
const textRef = ref<HTMLElement | null>(null)
|
||||
|
||||
const wrapperWidth = computed(() => textRef.value?.offsetWidth)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -20,22 +24,32 @@ const { page } = useData()
|
||||
page.relativePath,
|
||||
item.activeMatch || item.link,
|
||||
!!item.activeMatch
|
||||
)
|
||||
),
|
||||
disabled: !isActive(
|
||||
page.relativePath,
|
||||
item.activeMatch || item.link,
|
||||
!!item.activeMatch
|
||||
) && !item.link ? 'disabled' : '',
|
||||
}"
|
||||
:href="item.link"
|
||||
:target="item.target"
|
||||
:rel="item.rel"
|
||||
tabindex="0"
|
||||
>
|
||||
<span v-html="item.text"></span>
|
||||
<span
|
||||
ref="textRef"
|
||||
v-html="item.text"
|
||||
/>
|
||||
</VPLink>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
<style lang="scss" scoped>
|
||||
@use '@beeline/design-tokens/scss/tokens/globals/colors';
|
||||
|
||||
.VPNavBarMenuLink {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0 12px;
|
||||
padding: 0 24px;
|
||||
line-height: var(--vp-nav-height);
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
@@ -45,9 +59,32 @@ const { page } = useData()
|
||||
|
||||
.VPNavBarMenuLink.active {
|
||||
color: var(--color-text-active);
|
||||
|
||||
&::after {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
content: '';
|
||||
height: 4px;
|
||||
display: none;
|
||||
width: calc(v-bind(wrapperWidth) * 1px);
|
||||
border-top-left-radius: 12px;
|
||||
border-top-right-radius: 12px;
|
||||
background-color: colors.$color-background-brand;
|
||||
}
|
||||
|
||||
&.active {
|
||||
&::after {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.VPNavBarMenuLink:hover {
|
||||
.disabled {
|
||||
opacity: 0.45;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.VPNavBarMenuLink:hover:not(.disabled) {
|
||||
color: var(--color-text-active);
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -14,31 +14,22 @@ const $t = createSearchTranslate(defaultTranslations)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<button type="button" class="DocSearch DocSearch-Button CustomDocSearch-Button" :aria-label="$t('button.buttonAriaLabel')">
|
||||
<span class="DocSearch-Button-Container">
|
||||
<svg
|
||||
class="DocSearch-Search-Icon"
|
||||
width="20"
|
||||
height="20"
|
||||
viewBox="0 0 20 20"
|
||||
aria-label="search icon"
|
||||
>
|
||||
<path
|
||||
d="M14.386 14.386l4.0877 4.0877-4.0877-4.0877c-2.9418 2.9419-7.7115 2.9419-10.6533 0-2.9419-2.9418-2.9419-7.7115 0-10.6533 2.9418-2.9419 7.7115-2.9419 10.6533 0 2.9419 2.9418 2.9419 7.7115 0 10.6533z"
|
||||
stroke="currentColor"
|
||||
fill="none"
|
||||
fill-rule="evenodd"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
/>
|
||||
</svg>
|
||||
<span class="DocSearch-Button-Placeholder">{{ $t('button.buttonText') }}</span>
|
||||
</span>
|
||||
<span class="DocSearch-Button-Keys">
|
||||
<kbd class="DocSearch-Button-Key"></kbd>
|
||||
<kbd class="DocSearch-Button-Key">K</kbd>
|
||||
</span>
|
||||
</button>
|
||||
<svg
|
||||
class="DocSearch-Search-Icon"
|
||||
width="20"
|
||||
height="20"
|
||||
viewBox="0 0 20 20"
|
||||
aria-label="search icon"
|
||||
>
|
||||
<path
|
||||
d="M14.386 14.386l4.0877 4.0877-4.0877-4.0877c-2.9418 2.9419-7.7115 2.9419-10.6533 0-2.9419-2.9418-2.9419-7.7115 0-10.6533 2.9418-2.9419 7.7115-2.9419 10.6533 0 2.9419 2.9418 2.9419 7.7115 0 10.6533z"
|
||||
stroke="currentColor"
|
||||
fill="none"
|
||||
fill-rule="evenodd"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
/>
|
||||
</svg>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
@@ -65,156 +56,13 @@ const $t = createSearchTranslate(defaultTranslations)
|
||||
--docsearch-hit-shadow: none;
|
||||
}
|
||||
|
||||
.DocSearch-Button {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
border-radius: 12px;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
width: 48px;
|
||||
height: 55px;
|
||||
background: transparent;
|
||||
transition: border-color 0.25s;
|
||||
}
|
||||
|
||||
.DocSearch-Button:hover {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.DocSearch-Button:focus {
|
||||
outline: 1px dotted;
|
||||
outline: 5px auto -webkit-focus-ring-color;
|
||||
}
|
||||
|
||||
.DocSearch-Button:focus:not(:focus-visible) {
|
||||
outline: none !important;
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
.DocSearch-Button {
|
||||
justify-content: flex-start;
|
||||
border: 1px solid transparent;
|
||||
border-radius: 12px;
|
||||
padding: 0 10px 0 12px;
|
||||
width: 100%;
|
||||
height: 40px;
|
||||
background-color: var(--vp-c-bg-alt);
|
||||
}
|
||||
|
||||
.DocSearch-Button:hover {
|
||||
border-color: var(--vp-c-brand-1);
|
||||
background: var(--vp-c-bg-alt);
|
||||
}
|
||||
}
|
||||
|
||||
.DocSearch-Button .DocSearch-Button-Container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.DocSearch-Button .DocSearch-Search-Icon {
|
||||
.DocSearch-Search-Icon {
|
||||
position: relative;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
color: var(--vp-c-text-1);
|
||||
fill: currentColor;
|
||||
transition: color 0.5s;
|
||||
}
|
||||
|
||||
.DocSearch-Button:hover .DocSearch-Search-Icon {
|
||||
color: var(--vp-c-text-1);
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
.DocSearch-Button .DocSearch-Search-Icon {
|
||||
top: 1px;
|
||||
margin-right: 8px;
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
color: var(--vp-c-text-2);
|
||||
}
|
||||
}
|
||||
|
||||
.DocSearch-Button .DocSearch-Button-Placeholder {
|
||||
display: none;
|
||||
margin-top: 2px;
|
||||
padding: 0 16px 0 0;
|
||||
font-size: 13px;
|
||||
font-weight: 500;
|
||||
color: var(--vp-c-text-2);
|
||||
transition: color 0.5s;
|
||||
}
|
||||
|
||||
.DocSearch-Button:hover .DocSearch-Button-Placeholder {
|
||||
color: var(--vp-c-text-1);
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
.DocSearch-Button .DocSearch-Button-Placeholder {
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
|
||||
.DocSearch-Button .DocSearch-Button-Keys {
|
||||
/*rtl:ignore*/
|
||||
direction: ltr;
|
||||
display: none;
|
||||
min-width: auto;
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
.DocSearch-Button .DocSearch-Button-Keys {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
|
||||
.DocSearch-Button .DocSearch-Button-Key {
|
||||
display: block;
|
||||
margin: 2px 0 0 0;
|
||||
border: 1px solid var(--vp-c-divider);
|
||||
/*rtl:begin:ignore*/
|
||||
border-right: none;
|
||||
border-radius: 4px 0 0 4px;
|
||||
padding-left: 6px;
|
||||
/*rtl:end:ignore*/
|
||||
min-width: 0;
|
||||
width: auto;
|
||||
height: 22px;
|
||||
line-height: 22px;
|
||||
font-family: var(--vp-font-family-base);
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
transition: color 0.5s, border-color 0.5s;
|
||||
}
|
||||
|
||||
.DocSearch-Button .DocSearch-Button-Key + .DocSearch-Button-Key {
|
||||
/*rtl:begin:ignore*/
|
||||
border-right: 1px solid var(--vp-c-divider);
|
||||
border-left: none;
|
||||
border-radius: 0 4px 4px 0;
|
||||
padding-left: 2px;
|
||||
padding-right: 6px;
|
||||
/*rtl:end:ignore*/
|
||||
}
|
||||
|
||||
.DocSearch-Button .DocSearch-Button-Key:first-child {
|
||||
font-size: 0 !important;
|
||||
}
|
||||
|
||||
.DocSearch-Button .DocSearch-Button-Key:first-child:after {
|
||||
content: 'Ctrl';
|
||||
font-size: 12px;
|
||||
letter-spacing: normal;
|
||||
color: var(--docsearch-muted-color);
|
||||
}
|
||||
|
||||
.mac .DocSearch-Button .DocSearch-Button-Key:first-child:after {
|
||||
content: '\2318';
|
||||
}
|
||||
|
||||
.DocSearch-Button .DocSearch-Button-Key:first-child > * {
|
||||
display: none;
|
||||
margin: 8px;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -38,10 +38,10 @@ const target = computed(() =>
|
||||
:target="target"
|
||||
>
|
||||
<slot name="nav-bar-title-before" />
|
||||
<VPImage v-if="theme.logo" class="logo" :image="theme.logo" />
|
||||
<template v-if="theme.siteTitle">{{ theme.siteTitle }}</template>
|
||||
<template v-else-if="theme.siteTitle === undefined">{{ site.title }}</template>
|
||||
<slot name="nav-bar-title-after" />
|
||||
<VPImage v-if="theme.logo" class="logo" :image="theme.logo" />
|
||||
</a>
|
||||
</div>
|
||||
</template>
|
||||
@@ -53,10 +53,13 @@ const target = computed(() =>
|
||||
border-bottom: 1px solid transparent;
|
||||
width: 100%;
|
||||
height: var(--vp-nav-height);
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
color: var(--vp-c-text-1);
|
||||
font-size: 25px;
|
||||
font-weight: 500;
|
||||
line-height: 28px;
|
||||
color: var(--color-text-inactive);
|
||||
transition: opacity 0.25s;
|
||||
gap: 20px;
|
||||
margin-right: 24px;
|
||||
}
|
||||
|
||||
@media (min-width: 960px) {
|
||||
@@ -72,7 +75,6 @@ const target = computed(() =>
|
||||
}
|
||||
|
||||
:deep(.logo) {
|
||||
margin-right: 8px;
|
||||
height: var(--vp-nav-logo-height);
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -60,9 +60,8 @@ watch(
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
z-index: var(--vp-z-index-sidebar);
|
||||
padding: 32px 32px 96px 32px;
|
||||
width: 256px;
|
||||
max-width: 320px;
|
||||
padding: 0px 0px 96px 0px;
|
||||
width: 320px;
|
||||
background-color: var(--vp-sidebar-bg-color);
|
||||
opacity: 0;
|
||||
box-shadow: var(--vp-c-shadow-3);
|
||||
@@ -88,8 +87,6 @@ watch(
|
||||
@media (min-width: 960px) {
|
||||
.VPSidebar {
|
||||
padding-top: var(--vp-nav-height);
|
||||
// width: var(--vp-sidebar-width);
|
||||
// max-width: 100%;
|
||||
background-color: var(--vp-sidebar-bg-color);
|
||||
opacity: 1;
|
||||
visibility: visible;
|
||||
@@ -98,13 +95,6 @@ watch(
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 1440px) {
|
||||
.VPSidebar {
|
||||
// padding-left: max(32px, calc((100% - (var(--vp-layout-max-width) - 64px)) / 2));
|
||||
// width: calc((100% - (var(--vp-layout-max-width) - 64px)) / 2 + var(--vp-sidebar-width) - 32px);
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 960px) {
|
||||
.curtain {
|
||||
position: sticky;
|
||||
@@ -121,17 +111,14 @@ watch(
|
||||
|
||||
.nav {
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
.group + .group {
|
||||
border-top: 1px solid var(--vp-c-divider);
|
||||
padding-top: 10px;
|
||||
padding-top: 24px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
@media (min-width: 960px) {
|
||||
.group {
|
||||
padding-top: 10px;
|
||||
width: calc(var(--vp-sidebar-width) - 64px);
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
@@ -1,11 +1,329 @@
|
||||
.custom-block {
|
||||
padding: 24px;
|
||||
@use "@beeline/design-tokens/scss/tokens/globals/colors";
|
||||
@use "@beeline/design-tokens/scss/tokens/themes";
|
||||
@use '@beeline/design-tokens/scss/tokens/themes/theme-variables' as *;
|
||||
|
||||
&-title {
|
||||
font-size: 18px;
|
||||
line-height: 22px;
|
||||
font-weight: 500;
|
||||
letter-spacing: .2px;
|
||||
margin-bottom: 12px;
|
||||
.custom-block {
|
||||
padding: 24px;
|
||||
|
||||
&-title {
|
||||
font-size: 17px !important;
|
||||
line-height: 22px !important;
|
||||
font-weight: 700 !important;
|
||||
letter-spacing: .2px !important;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
&.tip a {
|
||||
color: #1a73e8;
|
||||
|
||||
&:hover {
|
||||
color: #1a73e8;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.custom-block {
|
||||
border: 1px solid transparent;
|
||||
border-radius: 8px;
|
||||
padding: 24px 24px 24px 64px;
|
||||
line-height: 24px;
|
||||
font-size: var(--vp-custom-block-font-size);
|
||||
color: var(--vp-c-text-2);
|
||||
|
||||
&.custom-block.details {
|
||||
padding: 0px;
|
||||
}
|
||||
}
|
||||
|
||||
.custom-block.info {
|
||||
border-color: var(--vp-custom-block-info-border);
|
||||
color: var(--vp-custom-block-info-text);
|
||||
background-color: var(--vp-custom-block-info-bg);
|
||||
}
|
||||
|
||||
.custom-block.info a,
|
||||
.custom-block.info code {
|
||||
color: var(--vp-c-brand-1);
|
||||
}
|
||||
|
||||
.custom-block.info a:hover,
|
||||
.custom-block.info a:hover > code {
|
||||
color: var(--vp-c-brand-2);
|
||||
}
|
||||
|
||||
.custom-block.info code {
|
||||
background-color: var(--vp-custom-block-info-code-bg);
|
||||
}
|
||||
|
||||
.custom-block.note {
|
||||
border-color: var(--vp-custom-block-note-border);
|
||||
color: var(--vp-custom-block-note-text);
|
||||
background-color: var(--vp-custom-block-note-bg);
|
||||
}
|
||||
|
||||
.custom-block.note a,
|
||||
.custom-block.note code {
|
||||
color: var(--vp-c-brand-1);
|
||||
}
|
||||
|
||||
.custom-block.note a:hover,
|
||||
.custom-block.note a:hover > code {
|
||||
color: var(--vp-c-brand-2);
|
||||
}
|
||||
|
||||
.custom-block.note code {
|
||||
background-color: var(--vp-custom-block-note-code-bg);
|
||||
}
|
||||
|
||||
.custom-block.tip {
|
||||
border-color: var(--vp-custom-block-tip-border);
|
||||
color: var(--vp-custom-block-tip-text);
|
||||
background-color: var(--vp-custom-block-tip-bg);
|
||||
|
||||
&::before {
|
||||
height: 24px;
|
||||
width: 24px;
|
||||
background-image: var(--vp-icon-clock);
|
||||
position: absolute;
|
||||
left: 24px;
|
||||
content: '';
|
||||
}
|
||||
}
|
||||
|
||||
.custom-block.tip a,
|
||||
.custom-block.tip code {
|
||||
color: var(--vp-c-tip-1);
|
||||
}
|
||||
|
||||
.custom-block.tip a:hover,
|
||||
.custom-block.tip a:hover > code {
|
||||
color: var(--vp-c-tip-2);
|
||||
}
|
||||
|
||||
.custom-block.tip code {
|
||||
background-color: var(--vp-custom-block-tip-code-bg);
|
||||
}
|
||||
|
||||
.custom-block.important {
|
||||
border-color: var(--vp-custom-block-important-border);
|
||||
color: var(--vp-custom-block-important-text);
|
||||
background-color: var(--vp-custom-block-important-bg);
|
||||
}
|
||||
|
||||
.custom-block.important a,
|
||||
.custom-block.important code {
|
||||
color: var(--vp-c-important-1);
|
||||
}
|
||||
|
||||
.custom-block.important a:hover,
|
||||
.custom-block.important a:hover > code {
|
||||
color: var(--vp-c-important-2);
|
||||
}
|
||||
|
||||
.custom-block.important code {
|
||||
background-color: var(--vp-custom-block-important-code-bg);
|
||||
}
|
||||
|
||||
.custom-block.warning {
|
||||
border-color: var(--vp-custom-block-warning-border);
|
||||
color: var(--vp-custom-block-warning-text);
|
||||
background-color: var(--vp-custom-block-warning-bg);
|
||||
|
||||
&::before {
|
||||
height: 24px;
|
||||
width: 24px;
|
||||
background-image: var(--vp-icon-info-circled);
|
||||
position: absolute;
|
||||
left: 24px;
|
||||
content: '';
|
||||
}
|
||||
}
|
||||
|
||||
.custom-block.warning a,
|
||||
.custom-block.warning code {
|
||||
color: $color-text-link;
|
||||
}
|
||||
|
||||
.custom-block.warning a:hover,
|
||||
.custom-block.warning a:hover > code {
|
||||
color: $color-text-link;
|
||||
}
|
||||
|
||||
.custom-block.warning code {
|
||||
background-color: var(--vp-custom-block-warning-code-bg);
|
||||
}
|
||||
|
||||
.custom-block.danger {
|
||||
border-color: var(--vp-custom-block-danger-border);
|
||||
color: var(--vp-custom-block-danger-text);
|
||||
background-color: var(--vp-custom-block-danger-bg);
|
||||
|
||||
&::before {
|
||||
height: 24px;
|
||||
width: 24px;
|
||||
background-image: var(--vp-icon-warning-triangle);
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 24px;
|
||||
}
|
||||
}
|
||||
|
||||
.custom-block.danger a,
|
||||
.custom-block.danger code {
|
||||
color: var(--vp-c-danger-1);
|
||||
}
|
||||
|
||||
.custom-block.danger a:hover,
|
||||
.custom-block.danger a:hover > code {
|
||||
color: var(--vp-c-danger-2);
|
||||
}
|
||||
|
||||
.custom-block.danger code {
|
||||
background-color: var(--vp-custom-block-danger-code-bg);
|
||||
}
|
||||
|
||||
.custom-block.caution {
|
||||
border-color: var(--vp-custom-block-caution-border);
|
||||
color: var(--vp-custom-block-caution-text);
|
||||
background-color: var(--vp-custom-block-caution-bg);
|
||||
}
|
||||
|
||||
.custom-block.caution a,
|
||||
.custom-block.caution code {
|
||||
color: var(--vp-c-caution-1);
|
||||
}
|
||||
|
||||
.custom-block.caution a:hover,
|
||||
.custom-block.caution a:hover > code {
|
||||
color: var(--vp-c-caution-2);
|
||||
}
|
||||
|
||||
.custom-block.caution code {
|
||||
background-color: var(--vp-custom-block-caution-code-bg);
|
||||
}
|
||||
|
||||
.custom-block.details {
|
||||
border-color: var(--vp-custom-block-details-border);
|
||||
color: var(--vp-custom-block-details-text);
|
||||
background-color: transparent;
|
||||
border-radius: 12px;
|
||||
border: 1px solid $color-border;
|
||||
|
||||
pre {
|
||||
border: none !important;
|
||||
|
||||
}
|
||||
|
||||
div {
|
||||
margin: 0 !important;
|
||||
}
|
||||
|
||||
&:open {
|
||||
&.custom-block.details summary {
|
||||
background-color: $color-background-base-hover;
|
||||
border-top-left-radius: 12px;
|
||||
border-top-right-radius: 12px;
|
||||
|
||||
&::before {
|
||||
background-image: var(--vp-icon-nav-arrow-up);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.custom-block.details a {
|
||||
color: var(--vp-c-brand-1);
|
||||
}
|
||||
|
||||
.custom-block.details a:hover,
|
||||
.custom-block.details a:hover > code {
|
||||
color: var(--vp-c-brand-2);
|
||||
}
|
||||
|
||||
.custom-block.details code {
|
||||
background-color: var(--vp-custom-block-details-code-bg);
|
||||
}
|
||||
|
||||
.custom-block-title {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.custom-block p + p {
|
||||
margin: 8px 0;
|
||||
}
|
||||
|
||||
.custom-block.details summary {
|
||||
margin: 0;
|
||||
padding: 24px;
|
||||
font-weight: 500;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
font-size: 19px;
|
||||
line-height: 24px;
|
||||
letter-spacing: 0.2px;
|
||||
display: block;
|
||||
|
||||
&::before {
|
||||
position: absolute;
|
||||
right: 24px;
|
||||
content: '';
|
||||
background-image: var(--vp-icon-nav-arrow-down);
|
||||
height: 24px;
|
||||
width: 24px;
|
||||
}
|
||||
}
|
||||
|
||||
.custom-block.details {
|
||||
h1, h2, h3, h4, h5, ul, p {
|
||||
margin: 0 24px;
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 24px !important;
|
||||
}
|
||||
|
||||
&:first-child {
|
||||
margin-top: 24px !important;
|
||||
}
|
||||
}
|
||||
|
||||
ol {
|
||||
padding: 0 24px;
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 24px !important;
|
||||
}
|
||||
|
||||
&:first-child {
|
||||
margin-top: 24px !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.custom-block.details summary + p {
|
||||
padding: 24px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.custom-block a {
|
||||
color: inherit;
|
||||
font-weight: 600;
|
||||
text-decoration: underline;
|
||||
text-underline-offset: 2px;
|
||||
transition: opacity 0.25s;
|
||||
}
|
||||
|
||||
.custom-block a:hover {
|
||||
opacity: 0.75;
|
||||
}
|
||||
|
||||
.custom-block code {
|
||||
font-size: var(--vp-custom-block-code-font-size);
|
||||
}
|
||||
|
||||
.custom-block.custom-block th,
|
||||
.custom-block.custom-block blockquote > p {
|
||||
font-size: var(--vp-custom-block-font-size);
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,10 +1,53 @@
|
||||
.VPDocAside {
|
||||
.outline-link {
|
||||
font-size: 16px;
|
||||
}
|
||||
@use '@beeline/design-tokens/scss/tokens/components/navigationDrawer';
|
||||
@use "@beeline/design-tokens/scss/tokens/globals/colors";
|
||||
|
||||
.outline-title {
|
||||
font-size: 17px;
|
||||
font-weight: 500;
|
||||
.VPDocAside {
|
||||
.outline-link {
|
||||
font-weight: 400;
|
||||
font-size: 15px;
|
||||
line-height: 18px;
|
||||
letter-spacing: 0.2px;
|
||||
padding-top: 8px;
|
||||
padding-bottom: 8px;
|
||||
white-space: unset;
|
||||
color: colors.$color-text-grey-inactive;
|
||||
}
|
||||
|
||||
.outline-link.active {
|
||||
font-weight: 500 !important;
|
||||
color: colors.$color-text-black-active;
|
||||
}
|
||||
|
||||
.outline-title {
|
||||
font-size: 15px;
|
||||
font-weight: 500;
|
||||
line-height: 18px;
|
||||
padding-bottom: 16px;
|
||||
color: colors.$color-text-black-active;
|
||||
}
|
||||
|
||||
.content {
|
||||
padding-left: 0px !important;
|
||||
border-left: 0px !important;
|
||||
|
||||
nav {
|
||||
border-left: 1px solid var(--vp-c-divider) !important;
|
||||
|
||||
.outline-link {
|
||||
padding-left: 20px !important;
|
||||
|
||||
&.active {
|
||||
padding-left: 16px !important;
|
||||
position: relative !important;
|
||||
left: -1px !important;
|
||||
border-left: navigationDrawer.$navigation-drawer-item-indicator-width solid
|
||||
navigationDrawer.$navigation-drawer-item-activated-indicator-color !important;
|
||||
|
||||
border-top-right-radius: navigationDrawer.$navigation-drawer-item-indicator-border-radius-topright !important;
|
||||
border-bottom-right-radius: navigationDrawer.$navigation-drawer-item-indicator-border-radius-bottomright !important;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,138 +1,566 @@
|
||||
@use "@beeline/design-tokens/scss/tokens/globals/colors";
|
||||
@use "@beeline/design-tokens/scss/tokens/themes";
|
||||
@use '@beeline/design-tokens/scss/tokens/themes/theme-variables' as *;
|
||||
|
||||
@mixin font_style($fontSize, $fontWeight, $lineHeight, $letterSpacing) {
|
||||
font-size: $fontSize;
|
||||
font-weight: $fontWeight;
|
||||
line-height: $lineHeight;
|
||||
letter-spacing: $letterSpacing;
|
||||
font-size: $fontSize;
|
||||
font-weight: $fontWeight;
|
||||
line-height: $lineHeight;
|
||||
letter-spacing: $letterSpacing;
|
||||
}
|
||||
|
||||
@mixin generate-numbered-list-styles($start, $end) {
|
||||
@for $counter from $start through $end {
|
||||
$counter-name: list + ' ' + ($counter - 1);
|
||||
ol[start*="#{$counter}"] {
|
||||
list-style-type: none;
|
||||
counter-reset: $counter-name;
|
||||
}
|
||||
@for $counter from $start through $end {
|
||||
$counter-name: list + ' ' + ($counter - 1);
|
||||
ol[start*="#{$counter}"] {
|
||||
list-style-type: none;
|
||||
counter-reset: $counter-name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.vp-doc {
|
||||
font-size: 17px;
|
||||
font-size: 17px;
|
||||
|
||||
// Titles
|
||||
h1 {
|
||||
@include font_style(44px, 500, 46px, 0.3px);
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
// Titles
|
||||
h1 {
|
||||
@include font_style(44px, 500, 56px, 0.3px);
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
h2 {
|
||||
@include font_style(34px, 400, 36px, 0.3px);
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
h2 {
|
||||
@include font_style(26px, 500, 32px, 0.2px);
|
||||
margin: 40px 0 24px;
|
||||
}
|
||||
|
||||
h3 {
|
||||
@include font_style(26px, 500, 32px, 0.2px);
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
h3 {
|
||||
@include font_style(26px, 500, 32px, 0.2px);
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
h4 {
|
||||
@include font_style(20px, 700, 28px, 0.2px);
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
h4 {
|
||||
@include font_style(20px, 700, 28px, 0.2px);
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
h5 {
|
||||
@include font_style(17px, 500, 22px, 0.2px);
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
h5 {
|
||||
@include font_style(17px, 500, 22px, 0.2px);
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
// Text
|
||||
ol {
|
||||
list-style-type: none;
|
||||
counter-reset: list;
|
||||
margin: 0 0 0 50px;
|
||||
padding: 0 0 5px 0;
|
||||
font-size: 16px;
|
||||
// Text
|
||||
ol {
|
||||
list-style-type: none;
|
||||
counter-reset: list;
|
||||
margin: 0 0 0 50px;
|
||||
padding: 0;
|
||||
font-size: 15px;
|
||||
|
||||
& > * + * {
|
||||
margin-top: 50px;
|
||||
}
|
||||
& > * + * {
|
||||
margin-top: 50px;
|
||||
}
|
||||
}
|
||||
|
||||
@include generate-numbered-list-styles(2, 50);
|
||||
|
||||
ol li {
|
||||
position: relative;
|
||||
padding: 8px 0 0 0;
|
||||
line-height: 18px;
|
||||
}
|
||||
|
||||
li + li {
|
||||
margin-top: 30px;
|
||||
}
|
||||
|
||||
ul li {
|
||||
padding-bottom: 0;
|
||||
padding-top: 0;
|
||||
margin-top: 8px;
|
||||
@include font_style(15px, 400, 18px, 0.2px);
|
||||
}
|
||||
|
||||
ol li:nth-last-of-type(n+2)::after {
|
||||
content: '';
|
||||
border-left: 1px solid rgb(201, 197, 197);
|
||||
position: absolute;
|
||||
line-height: 100%;
|
||||
left: -30px;
|
||||
top: 43px;
|
||||
bottom: -25px;
|
||||
}
|
||||
|
||||
ol li::before {
|
||||
content: counter(list);
|
||||
counter-increment: list;
|
||||
display: inline-flex;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: -48px;
|
||||
width: 35px;
|
||||
height: 35px;
|
||||
background-color: colors.$color-background-brand;
|
||||
color: themes.$color-text-active;
|
||||
@include font_style(15px, 400, 18px, 0.2px);
|
||||
border-radius: 50%;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
ul li:nth-last-of-type(n):after {
|
||||
content: none;
|
||||
}
|
||||
|
||||
ol ul li::before {
|
||||
counter-increment: list;
|
||||
content: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
ol li:last-child {
|
||||
margin-bottom: 40px;
|
||||
}
|
||||
|
||||
ul li:last-child {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
ol li p {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
p {
|
||||
@include font_style(15px, 400, 18px, 0.2px);
|
||||
margin: 24px 0;
|
||||
}
|
||||
|
||||
// Links
|
||||
a {
|
||||
color: #1a73e8;
|
||||
text-decoration: none;
|
||||
|
||||
&:hover, &:focus-visible, &:focus, &:active {
|
||||
color: #1a73e8;
|
||||
}
|
||||
|
||||
@include generate-numbered-list-styles(2, 50);
|
||||
|
||||
ol li {
|
||||
position: relative;
|
||||
padding: 5px 0 0 0;
|
||||
line-height: 1.4;
|
||||
&:visited {
|
||||
color: #7e00ed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
li + li {
|
||||
margin-top: 50px;
|
||||
// Tabs
|
||||
.plugin-tabs {
|
||||
border-radius: 12px;
|
||||
border: 1px solid $color-border;
|
||||
background-color: revert-layer !important;
|
||||
|
||||
&--tab {
|
||||
border-bottom: 1px solid transparent;
|
||||
}
|
||||
|
||||
&--content {
|
||||
padding: 24px !important;
|
||||
|
||||
.language- {
|
||||
border: none;
|
||||
padding: 0px !important;
|
||||
overflow-y: hidden !important;
|
||||
overflow-x: hidden !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ul li {
|
||||
padding-bottom: 0;
|
||||
padding-top: 0;
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
ol li:nth-last-of-type(n+2)::after {
|
||||
content: '';
|
||||
border-left: 1px solid rgb(201, 197, 197);
|
||||
position: absolute;
|
||||
line-height: 100%;
|
||||
left: -30px;
|
||||
top: 43px;
|
||||
bottom: -30px;
|
||||
}
|
||||
// Code
|
||||
.vp-doc :not(pre, h1, h2, h3, h4, h5, h6) > code {
|
||||
font-size: var(--vp-code-font-size);
|
||||
color: var(--vp-code-color);
|
||||
}
|
||||
|
||||
ol li::before {
|
||||
content: counter(list);
|
||||
counter-increment: list;
|
||||
display: inline-flex;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: -48px;
|
||||
width: 35px;
|
||||
height: 35px;
|
||||
background-color: #7e00ed;
|
||||
color: #fff;
|
||||
text-align: center;
|
||||
line-height: 25px;
|
||||
font-size: 16px;
|
||||
border-radius: 50%;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
.vp-doc :not(pre) > code {
|
||||
border-radius: 4px;
|
||||
padding: 3px 6px;
|
||||
background-color: var(--vp-code-bg);
|
||||
transition:
|
||||
color 0.25s,
|
||||
background-color 0.5s;
|
||||
}
|
||||
|
||||
ul li:nth-last-of-type(n):after {
|
||||
content: none;
|
||||
}
|
||||
.vp-doc a > code {
|
||||
color: var(--vp-code-link-color);
|
||||
}
|
||||
|
||||
ol ul li::before {
|
||||
counter-increment: list;
|
||||
content: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
.vp-doc a:hover > code {
|
||||
color: var(--vp-code-link-hover-color);
|
||||
}
|
||||
|
||||
ol li p {
|
||||
margin-top: 0;
|
||||
}
|
||||
.vp-doc h1 > code,
|
||||
.vp-doc h2 > code,
|
||||
.vp-doc h3 > code {
|
||||
font-size: 0.9em;
|
||||
}
|
||||
|
||||
p {
|
||||
line-height: 22px;
|
||||
}
|
||||
.vp-doc div[class*='language-'],
|
||||
.vp-block {
|
||||
position: relative;
|
||||
margin: 16px -24px;
|
||||
background-color: transparent;
|
||||
overflow-x: auto;
|
||||
transition: background-color 0.5s;
|
||||
}
|
||||
|
||||
// Links
|
||||
a {
|
||||
color: #1a73e8;
|
||||
@media (min-width: 640px) {
|
||||
.vp-doc div[class*='language-'],
|
||||
.vp-block {
|
||||
border-radius: 12px;
|
||||
margin: 16px 0;
|
||||
}
|
||||
}
|
||||
|
||||
&:hover, &:focus-visible, &:focus, &:active {
|
||||
color: #1a73e8;
|
||||
}
|
||||
@media (max-width: 639px) {
|
||||
.vp-doc li div[class*='language-'] {
|
||||
border-radius: 8px 0 0 8px;
|
||||
}
|
||||
}
|
||||
|
||||
&:visited {
|
||||
color: #7e00ed;
|
||||
}
|
||||
}
|
||||
}
|
||||
.vp-doc div[class*='language-'] + div[class*='language-'],
|
||||
.vp-doc div[class$='-api'] + div[class*='language-'],
|
||||
.vp-doc div[class*='language-'] + div[class$='-api'] > div[class*='language-'] {
|
||||
margin-top: -8px;
|
||||
}
|
||||
|
||||
.vp-doc [class*='language-'] pre,
|
||||
.vp-doc [class*='language-'] code {
|
||||
/*rtl:ignore*/
|
||||
direction: ltr;
|
||||
/*rtl:ignore*/
|
||||
text-align: left;
|
||||
white-space: pre;
|
||||
word-spacing: normal;
|
||||
word-break: normal;
|
||||
word-wrap: normal;
|
||||
-moz-tab-size: 4;
|
||||
-o-tab-size: 4;
|
||||
tab-size: 4;
|
||||
-webkit-hyphens: none;
|
||||
-moz-hyphens: none;
|
||||
-ms-hyphens: none;
|
||||
hyphens: none;
|
||||
}
|
||||
|
||||
.vp-doc [class*='language-'] pre {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
margin: 0;
|
||||
padding: 24px;
|
||||
overflow-x: auto;
|
||||
border-radius: 12px;
|
||||
border: 1px solid $color-border;
|
||||
}
|
||||
|
||||
.vp-doc [class*='language-'] code {
|
||||
display: block;
|
||||
padding: 0px;
|
||||
width: fit-content;
|
||||
min-width: 100%;
|
||||
line-height: var(--vp-code-line-height);
|
||||
font-size: var(--vp-code-font-size);
|
||||
color: var(--vp-code-color);
|
||||
transition: color 0.5s;
|
||||
}
|
||||
|
||||
.vp-doc [class*='language-'] code .highlighted {
|
||||
background-color: var(--vp-code-line-highlight-color);
|
||||
transition: background-color 0.5s;
|
||||
margin: 0 -24px;
|
||||
padding: 0 24px;
|
||||
width: calc(100% + 2 * 24px);
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.vp-doc [class*='language-'] code .highlighted.error {
|
||||
background-color: var(--vp-code-line-error-color);
|
||||
}
|
||||
|
||||
.vp-doc [class*='language-'] code .highlighted.warning {
|
||||
background-color: var(--vp-code-line-warning-color);
|
||||
}
|
||||
|
||||
.vp-doc [class*='language-'] code .diff {
|
||||
transition: background-color 0.5s;
|
||||
margin: 0 -24px;
|
||||
padding: 0 24px;
|
||||
width: calc(100% + 2 * 24px);
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.vp-doc [class*='language-'] code .diff::before {
|
||||
position: absolute;
|
||||
left: 10px;
|
||||
}
|
||||
|
||||
.vp-doc [class*='language-'] .has-focused-lines .line:not(.has-focus) {
|
||||
filter: blur(0.095rem);
|
||||
opacity: 0.4;
|
||||
transition:
|
||||
filter 0.35s,
|
||||
opacity 0.35s;
|
||||
}
|
||||
|
||||
.vp-doc [class*='language-'] .has-focused-lines .line:not(.has-focus) {
|
||||
opacity: 0.7;
|
||||
transition:
|
||||
filter 0.35s,
|
||||
opacity 0.35s;
|
||||
}
|
||||
|
||||
.vp-doc [class*='language-']:hover .has-focused-lines .line:not(.has-focus) {
|
||||
filter: blur(0);
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.vp-doc [class*='language-'] code .diff.remove {
|
||||
background-color: var(--vp-code-line-diff-remove-color);
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
.vp-doc [class*='language-'] code .diff.remove::before {
|
||||
content: '-';
|
||||
color: var(--vp-code-line-diff-remove-symbol-color);
|
||||
}
|
||||
|
||||
.vp-doc [class*='language-'] code .diff.add {
|
||||
background-color: var(--vp-code-line-diff-add-color);
|
||||
}
|
||||
|
||||
.vp-doc [class*='language-'] code .diff.add::before {
|
||||
content: '+';
|
||||
color: var(--vp-code-line-diff-add-symbol-color);
|
||||
}
|
||||
|
||||
.vp-doc div[class*='language-'].line-numbers-mode {
|
||||
/*rtl:ignore*/
|
||||
padding-left: 32px;
|
||||
}
|
||||
|
||||
.vp-doc .line-numbers-wrapper {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
/*rtl:ignore*/
|
||||
left: 0;
|
||||
z-index: 3;
|
||||
/*rtl:ignore*/
|
||||
border-right: 1px solid var(--vp-code-block-divider-color);
|
||||
padding-top: 20px;
|
||||
width: 32px;
|
||||
text-align: center;
|
||||
font-family: var(--vp-font-family-mono);
|
||||
line-height: var(--vp-code-line-height);
|
||||
font-size: var(--vp-code-font-size);
|
||||
color: var(--vp-code-line-number-color);
|
||||
transition:
|
||||
border-color 0.5s,
|
||||
color 0.5s;
|
||||
}
|
||||
|
||||
.vp-doc [class*='language-'] > button.copy {
|
||||
/*rtl:ignore*/
|
||||
direction: ltr;
|
||||
position: absolute;
|
||||
top: 12px;
|
||||
/*rtl:ignore*/
|
||||
right: 12px;
|
||||
z-index: 3;
|
||||
border: none;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
background-color: transparent;
|
||||
opacity: 1;
|
||||
cursor: pointer;
|
||||
background-image: var(--vp-icon-copy);
|
||||
background-position: 50%;
|
||||
background-size: 20px;
|
||||
background-repeat: no-repeat;
|
||||
transition:
|
||||
border-color 0.25s,
|
||||
background-color 0.25s,
|
||||
opacity 0.25s;
|
||||
}
|
||||
|
||||
.vp-doc [class*='language-']:hover > button.copy,
|
||||
.vp-doc [class*='language-'] > button.copy:focus {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.vp-doc [class*='language-'] > button.copy:hover,
|
||||
.vp-doc [class*='language-'] > button.copy.copied {
|
||||
border: none;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.vp-doc [class*='language-'] > button.copy.copied,
|
||||
.vp-doc [class*='language-'] > button.copy:hover.copied {
|
||||
/*rtl:ignore*/
|
||||
background-color: transparent;
|
||||
background-image: none;
|
||||
}
|
||||
|
||||
.vp-doc [class*='language-'] > button.copy.copied::before,
|
||||
.vp-doc [class*='language-'] > button.copy:hover.copied::before {
|
||||
position: relative;
|
||||
top: -1px;
|
||||
/*rtl:ignore*/
|
||||
transform: translateX(calc(-100% - 1px));
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
border: none;
|
||||
/*rtl:ignore*/
|
||||
border-right: 0;
|
||||
padding: 0 10px;
|
||||
width: fit-content;
|
||||
height: 40px;
|
||||
text-align: center;
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
color: var(--vp-code-copy-code-active-text);
|
||||
white-space: nowrap;
|
||||
content: '';
|
||||
}
|
||||
|
||||
.vp-doc [class*='language-'] > span.lang {
|
||||
position: absolute;
|
||||
top: 2px;
|
||||
/*rtl:ignore*/
|
||||
right: 8px;
|
||||
z-index: 2;
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
color: var(--vp-code-lang-color);
|
||||
transition:
|
||||
color 0.4s,
|
||||
opacity 0.4s;
|
||||
}
|
||||
|
||||
.vp-doc [class*='language-']:hover > button.copy + span.lang,
|
||||
.vp-doc [class*='language-'] > button.copy:focus + span.lang {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
// Banner
|
||||
.vp-doc .custom-block {
|
||||
margin: 40px 0;
|
||||
}
|
||||
|
||||
.vp-doc .custom-block p {
|
||||
margin: 8px 0;
|
||||
line-height: 18px;
|
||||
}
|
||||
|
||||
.vp-doc .custom-block p:first-child {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.vp-doc .custom-block div[class*='language-'] {
|
||||
margin: 8px 0;
|
||||
border-radius: 12px;
|
||||
}
|
||||
|
||||
.vp-doc .custom-block div[class*='language-'] code {
|
||||
font-weight: 400;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.vp-doc .custom-block .vp-code-group .tabs {
|
||||
margin: 0;
|
||||
border-radius: 8px 8px 0 0;
|
||||
}
|
||||
|
||||
// Table
|
||||
.vp-doc table {
|
||||
display: block;
|
||||
border-collapse: collapse;
|
||||
overflow-x: auto;
|
||||
border-radius: 12px;
|
||||
border: 1px solid $color-border;
|
||||
// width: 100%;
|
||||
margin: 24px 0;
|
||||
}
|
||||
|
||||
.vp-doc tr {
|
||||
border-top: hidden;
|
||||
transition: background-color 0.5s;
|
||||
}
|
||||
|
||||
.vp-doc tr:nth-child(2n) {
|
||||
background-color: var(--vp-c-bg-soft);
|
||||
}
|
||||
|
||||
.vp-doc th,
|
||||
.vp-doc td {
|
||||
padding: 18px 16px;
|
||||
padding: 18px 16px;
|
||||
width: 100vh;
|
||||
background-color: var(--vp-c-bg);
|
||||
border: none;
|
||||
}
|
||||
|
||||
.vp-doc tbody tr {
|
||||
border-top: 1px solid $color-border;
|
||||
|
||||
&:last-child{
|
||||
border-bottom: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
.vp-doc th {
|
||||
@include font_style(15px, 500, 20px, 0.2px);
|
||||
color: $color-text-active;
|
||||
background-color: var(--vp-c-bg);
|
||||
border-top: 1px solid $color-border;
|
||||
}
|
||||
|
||||
.vp-doc td {
|
||||
@include font_style(15px, 400, 18px, 0.2px);
|
||||
padding: 18px 16px;
|
||||
background-color: var(--vp-c-bg);
|
||||
border-right: hidden;
|
||||
border-left: hidden;
|
||||
color: $color-text-active;
|
||||
}
|
||||
|
||||
// Block
|
||||
.vp-doc .custom-block {
|
||||
margin: 16px 0;
|
||||
}
|
||||
|
||||
.vp-doc .custom-block p {
|
||||
margin: 8px 0;
|
||||
line-height: 24px;
|
||||
}
|
||||
|
||||
.vp-doc .custom-block p:first-child {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.vp-doc .custom-block div[class*='language-'] {
|
||||
margin: 40px 0;
|
||||
border-radius: 12px;
|
||||
|
||||
&.vp-doc .custom-block {
|
||||
margin: 0;
|
||||
border: none;
|
||||
}
|
||||
}
|
||||
|
||||
.vp-doc .custom-block div[class*='language-'] code {
|
||||
font-weight: 400;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.vp-doc .custom-block .vp-code-group .tabs {
|
||||
margin: 0;
|
||||
border-radius: 8px 8px 0 0;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,116 @@
|
||||
@use '@beeline/design-tokens/scss/tokens/components/navigationDrawer';
|
||||
@use '@beeline/design-tokens/scss/tokens/themes/theme-variables' as theme;
|
||||
@use '@/scss/helpers/media';
|
||||
|
||||
.VPSidebar {
|
||||
&Item {
|
||||
.text {
|
||||
font-size: 15px;
|
||||
}
|
||||
--vp-sidebar-bg-color: var(--vp-c-bg);
|
||||
}
|
||||
|
||||
.VPSidebar .VPSidebarItem .item {
|
||||
margin: 4px 0;
|
||||
}
|
||||
|
||||
.VPSidebar .VPSidebarItem .link {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.indicator {
|
||||
border-top-right-radius: navigationDrawer.$navigation-drawer-item-indicator-border-radius-topright !important;
|
||||
border-bottom-right-radius: navigationDrawer.$navigation-drawer-item-indicator-border-radius-bottomright !important;
|
||||
position: absolute !important;
|
||||
left: 0 !important;
|
||||
}
|
||||
|
||||
.VPSidebarItem.is-active > .item .link > .text {
|
||||
color: theme.$color-text-active !important;
|
||||
font-weight: 500 !important;
|
||||
line-height: 20px !important;
|
||||
}
|
||||
|
||||
.VPSidebarItem {
|
||||
.item {
|
||||
padding: 12px 32px !important;
|
||||
border-top-right-radius: 12px !important;
|
||||
border-bottom-right-radius: 12px !important;
|
||||
color: theme.$color-text-inactive;
|
||||
|
||||
&:hover {
|
||||
background-color: navigationDrawer.$navigation-drawer-item-hover-background-color !important;
|
||||
color: theme.$color-text-inactive;
|
||||
}
|
||||
}
|
||||
|
||||
&.is-active > .item > .indicator {
|
||||
border-left: navigationDrawer.$navigation-drawer-item-indicator-width solid
|
||||
navigationDrawer.$navigation-drawer-item-activated-indicator-color !important;
|
||||
}
|
||||
}
|
||||
|
||||
.VPSidebarItem.collapsible {
|
||||
.items {
|
||||
margin-left: 16px;
|
||||
|
||||
.item {
|
||||
padding: 12px 16px 12px 56px !important;
|
||||
border-top-left-radius: 12px !important;
|
||||
border-bottom-left-radius: 12px !important;
|
||||
}
|
||||
}
|
||||
|
||||
&.is-active,
|
||||
&.has-active {
|
||||
> .item {
|
||||
.indicator {
|
||||
display: block !important;
|
||||
border-left: navigationDrawer.$navigation-drawer-item-indicator-width solid
|
||||
navigationDrawer.$navigation-drawer-item-activated-indicator-color !important;
|
||||
}
|
||||
|
||||
.text {
|
||||
color: theme.$color-text-active !important;
|
||||
font-weight: 500 !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.items .VPSidebarItem.is-active > .item {
|
||||
background-color: navigationDrawer.$navigation-drawer-item-hover-background-color !important;
|
||||
|
||||
.text {
|
||||
color: theme.$color-text-active !important;
|
||||
font-weight: 500 !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.VPSidebarItem.collapsible .items .item .indicator {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.text {
|
||||
padding: 0px !important;
|
||||
font-weight: 400 !important;
|
||||
font-size: 15px !important;
|
||||
line-height: 18px !important;
|
||||
letter-spacing: 0.2px !important;
|
||||
|
||||
transition-property: all;
|
||||
transition-duration: 150ms;
|
||||
transition-timing-function: ease-in-out;
|
||||
color: theme.$color-text-inactive !important;
|
||||
}
|
||||
|
||||
.VPSidebarItem .items {
|
||||
border-left: 0px !important;
|
||||
}
|
||||
|
||||
.VPSidebarItem {
|
||||
padding-bottom: 0px !important;
|
||||
}
|
||||
|
||||
.VPLocalNav.has-sidebar {
|
||||
@include media.max(sm) {
|
||||
padding-left: 0px;
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,8 @@
|
||||
@use '@beeline/design-tokens/scss/font-face';
|
||||
@use "@beeline/design-tokens/scss/iconfont/iconfont" with (
|
||||
$font-path-iconfont: '../assets/fonts/iconfont'
|
||||
);
|
||||
@use "@beeline/design-tokens/scss/iconfont/icons";
|
||||
@use '@beeline/design-tokens/scss/tokens/themes/dark';
|
||||
@use '@beeline/design-tokens/scss/tokens/themes';
|
||||
|
||||
@@ -1,57 +0,0 @@
|
||||
@use "@beeline/design-tokens/scss/iconfont/iconfont" with (
|
||||
$font-path-iconfont: '/fonts/iconfont'
|
||||
);
|
||||
@use "@beeline/design-tokens/scss/iconfont/icons";
|
||||
|
||||
$font-path-beeline-sans: '/fonts/beeline-sans' !default;
|
||||
|
||||
@mixin beeline-sans-font($type, $weight, $style: normal) {
|
||||
@font-face {
|
||||
font-family: "Beeline Sans";
|
||||
src:url('#{$font-path-beeline-sans}/BeelineSans-#{$type}.woff2') format('woff2'),
|
||||
url('#{$font-path-beeline-sans}/BeelineSans-#{$type}.woff') format('woff'),
|
||||
url('#{$font-path-beeline-sans}/BeelineSans-#{$type}.ttf') format('truetype');
|
||||
font-weight: $weight;
|
||||
font-style: $style;
|
||||
}
|
||||
}
|
||||
|
||||
@mixin beeline-sans-font-pair($type, $weight) {
|
||||
@include beeline-sans-font($type, $weight);
|
||||
|
||||
}
|
||||
|
||||
@include beeline-sans-font-pair(Regular, 400);
|
||||
|
||||
@include beeline-sans-font-pair(Medium, 500);
|
||||
|
||||
@include beeline-sans-font-pair(Bold, 700);
|
||||
|
||||
@include beeline-sans-font-pair(Black, 900);
|
||||
|
||||
$font-path-roboto-mono: '/fonts/roboto-mono' !default;
|
||||
|
||||
@mixin roboto-mono-font($type, $weight, $style: normal) {
|
||||
@font-face {
|
||||
font-family: "Roboto Mono";
|
||||
src:url('#{$font-path-roboto-mono}/RobotoMono-#{$type}.woff2') format('woff2'),
|
||||
url('#{$font-path-roboto-mono}/RobotoMono-#{$type}.woff') format('woff'),
|
||||
url('#{$font-path-roboto-mono}/RobotoMono-#{$type}.ttf') format('truetype');
|
||||
font-weight: $weight;
|
||||
font-style: $style;
|
||||
}
|
||||
}
|
||||
|
||||
@mixin roboto-mono-font-pair($type, $weight) {
|
||||
@include roboto-mono-font($type, $weight);
|
||||
|
||||
}
|
||||
|
||||
@include roboto-mono-font-pair(Light, 300);
|
||||
|
||||
@include roboto-mono-font-pair(Regular, 400);
|
||||
|
||||
@include roboto-mono-font-pair(Medium, 500);
|
||||
|
||||
@include roboto-mono-font-pair(Bold, 700);
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
@forward "media";
|
||||
@@ -1,3 +1,5 @@
|
||||
@use "sass:map";
|
||||
|
||||
// @deprecated
|
||||
@mixin media($minWidth, $maxWidth) {
|
||||
@media (min-width: $minWidth) and (max-width: $maxWidth) {
|
||||
@@ -27,7 +29,7 @@ $breakpoints: (
|
||||
);
|
||||
|
||||
@mixin max($breakpoint) {
|
||||
$value: map-get($breakpoints, $breakpoint);
|
||||
$value: map.get($breakpoints, $breakpoint);
|
||||
|
||||
@if $value {
|
||||
@media (max-width: $value) {
|
||||
@@ -1,4 +1,3 @@
|
||||
@use "fonts";
|
||||
@use "design-system";
|
||||
@use "design-tokens";
|
||||
@use "vars";
|
||||
@use "components";
|
||||
@@ -111,7 +111,7 @@
|
||||
|
||||
:root {
|
||||
--vp-font-family-base: 'Beeline Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif;
|
||||
--vp-font-family-mono: 'Roboto Mono', monospace;
|
||||
--vp-font-family-mono: 'JetBrains Mono', monospace;
|
||||
|
||||
// Code
|
||||
// --vp-code-font-size: ;
|
||||
@@ -183,16 +183,18 @@
|
||||
--vp-custom-block-code-font-size: 17px;
|
||||
--vp-custom-block-tip-border: transparent;
|
||||
--vp-custom-block-tip-text: var(--vp-c-text-1);
|
||||
--vp-custom-block-tip-bg: #f1f1f3;
|
||||
--vp-custom-block-tip-bg: #f9f9f9;
|
||||
--vp-custom-block-tip-code-bg: var(--vp-c-brand-soft);
|
||||
--vp-custom-block-warning-bg: #fff4e1;
|
||||
--vp-custom-block-danger-bg: #ffecef;
|
||||
--vp-custom-block-warning-bg: #e3f2ff;
|
||||
--vp-custom-block-warning-icon: #1a73e8;
|
||||
--vp-custom-block-danger-bg: #fff4e1;
|
||||
--vp-custom-block-danger-icon: #ff9419;
|
||||
}
|
||||
|
||||
.dark {
|
||||
--vp-custom-block-warning-bg: #3d392a;
|
||||
--vp-custom-block-warning-bg: #132338;
|
||||
--vp-custom-block-tip-bg: #36383c;
|
||||
--vp-custom-block-danger-bg: #371313;
|
||||
--vp-custom-block-danger-bg: #3d392a;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -203,3 +205,12 @@
|
||||
--docsearch-primary-color: var(--vp-c-brand-1) !important;
|
||||
}
|
||||
|
||||
:root {
|
||||
--vp-icon-copy: url('../../../public/icons/copy.svg');
|
||||
--vp-icon-clock: url('../../../public/icons/clock.svg');
|
||||
--vp-icon-info-circled: url('../../../public/icons/info_circled.svg');
|
||||
--vp-icon-warning-triangle: url('../../../public/icons/warning_triangle.svg');
|
||||
--vp-icon-nav-arrow-down: url('../../../public/icons/nav_arrow_down.svg');
|
||||
--vp-icon-nav-arrow-up: url('../../../public/icons/nav_arrow_up.svg');
|
||||
--vp-sidebar-width: 320px;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,107 @@
|
||||
# Cloud Deckhouse Kubernetes
|
||||
|
||||
## Назначение сервиса
|
||||
|
||||
**Cloud Deckhouse Kubernetes** — это управляемый облачный сервис на базе платформы оркестрации контейнеров Kubernetes.
|
||||
|
||||
Сервис автоматизирует настройку:
|
||||
- серверов;
|
||||
- сети;
|
||||
- балансировщиков нагрузки;
|
||||
- механизмов отказоустойчивости.
|
||||
|
||||
Пользователю не нужно самостоятельно управлять инфраструктурой — кластер работает «из коробки».
|
||||
|
||||
> **Kubernetes** - это платформа для оркестрации контейнеров, которая автоматизирует развертывание, масштабирование и управление приложениями.
|
||||
|
||||
## Автоматизация сервис
|
||||
|
||||
**Cloud Deckhouse Kubernetes** самостоятельно выполняет следующие операции:
|
||||
|
||||
| Операция | Описание |
|
||||
|------------------------------|-------------------------------------------------------|
|
||||
| Управление ролями узлов | Назначает узлам роли master, frontend, system, worker |
|
||||
| Мониторинг компонентов | Отслеживает состояние всех частей платформы |
|
||||
| Восстановление после отказов | Автоматически перезапускает отказавшие узлы и поды |
|
||||
|
||||
## Архитектура и компоненты
|
||||
|
||||
Для стабильной работы сервиса используются три ключевых компонента:
|
||||
|
||||
- **Deckhouse** — платформа управления. Устанавливает, обновляет и настраивает кластер.
|
||||
- **etcd** — распределенное хранилище. Сохраняет состояние кластера и данные конфигурации.
|
||||
- **Балансировщики нагрузки** — единая точка входа. Направляют трафик к работающим приложениям.
|
||||
|
||||
## Доступ к приложениям
|
||||
|
||||
Подключение к приложениям внутри кластера выполняется через единую точку доступа. Подключаться к отдельным узлам не требуется.
|
||||
|
||||
## Управление и мониторинг
|
||||
|
||||
| Задача | Инструмент |
|
||||
|-------------------------------------------------|-----------------------|
|
||||
| Управление кластером и развертывание приложений | Веб-интерфейс Console |
|
||||
| Мониторинг состояния системы | Grafana |
|
||||
|
||||
## Отказоустойчивость
|
||||
|
||||
Кластер поставляется в отказоустойчивой архитектуре, которая обеспечивает:
|
||||
|
||||
- высокую доступность плоскости управления (control plane);
|
||||
- автоматическое восстановление узлов при отказах.
|
||||
|
||||
### Типы узлов кластера
|
||||
|
||||
Кластер состоит из следующих типов виртуальных серверов:
|
||||
|
||||
| Тип виртуального сервера | Количество узлов | Назначение |
|
||||
| ------------------------------- | ---------------- | -------------------- |
|
||||
| **Master-узлы (control plane)** | 3 | Обязательные узлы. На них работают управляющие компоненты кластера: API server, etcd, controller manager, scheduler. |
|
||||
| **System-узлы** | 2 | Служебные узлы. На них размещаются внутренние компоненты платформы Deckhouse, системы мониторинга (Prometheus, Grafana), логирования и другие вспомогательные сервисы, обеспечивающие работу кластера. |
|
||||
| **Frontend-узлы** | 2 | Узлы, предназначенные для обработки входящего трафика. На них работают Ingress-контроллеры и балансировщики нагрузки, которые принимают запросы из внешней сети и распределяют их между приложениями, запущенными на worker-узлах. |
|
||||
| **Worker-узлы** | от 1 и более | Узлы, на которых непосредственно выполняются пользовательские приложения в контейнерах. Именно здесь размещаются поды с сервисами и прикладными компонентами. |
|
||||
|
||||
::: info Примечание
|
||||
По умолчанию кластер работает в высокодоступном режиме. Выход из строя одного или двух master-узлов не приводит к потере управления кластером.
|
||||
:::
|
||||
|
||||
::: warning Важно
|
||||
Для тестовых сред возможна **одноузловая конфигурация control plane**. В этом случае отказ master-узла сделает кластер неуправляемым.
|
||||
:::
|
||||
|
||||
## Доступ к кластеру
|
||||
|
||||
Прямой доступ к серверам кластера (по SSH) не предоставляется.
|
||||
|
||||
Управление приложениями и ресурсами кластера возможно через:
|
||||
|
||||
- **kubectl** — командная строка;
|
||||
- **веб-интерфейс Console**;
|
||||
- **API Kubernetes**.
|
||||
|
||||
## Возможности сервиса
|
||||
|
||||
**Cloud Deckhouse Kubernetes** предоставляет возможности, позволяющие использовать Kubernetes без самостоятельного администрирования инфраструктуры.
|
||||
|
||||
Сервис обеспечивает:
|
||||
|
||||
- автоматическое управление кластером (установка, обновление, настройка);
|
||||
- высокую доступность control plane;
|
||||
- единую точку входа в приложения;
|
||||
- автоматическое восстановление при отказах;
|
||||
- веб-доступ к управлению кластером и мониторингу;
|
||||
- совместимость со стандартными инструментами (**kubectl**);
|
||||
- автоматическое масштабирование приложений;
|
||||
- блочные и сетевые хранилища для данных приложений (Persistent Volume).
|
||||
|
||||
## Сценарии использования
|
||||
|
||||
Сервис подходит для систем, где требуется надежная оркестрация контейнеров и упрощённое управление инфраструктурой.
|
||||
|
||||
Примеры использования:
|
||||
|
||||
- размещение production-приложений в контейнерах с высокими требованиями к доступности;
|
||||
- микросервисная архитектура с единой точкой управления кластером;
|
||||
- работа stateful-приложений (базы данных, очереди) с сохранением состояния;
|
||||
- быстрое развёртывание Kubernetes-кластера без ручной настройки сети, хранилищ и мониторинга;
|
||||
- администрирование через веб-интерфейс без прямого доступа к серверам.
|
||||
@@ -0,0 +1,238 @@
|
||||
# Подключение к сервису Deckhouse
|
||||
|
||||
В данном разделе описаны способы подключения к кластеру **Cloud Deckhouse Kubernetes**. Рассматривается работа с кластером через веб-интерфейс **Console**, а также управление через командную строку с использованием утилиты **kubectl** после генерации **kubeconfig**.
|
||||
|
||||
## Предварительные требования
|
||||
|
||||
После предоставления доступа к **сервису Cloud Deckhouse Kubernetes** пользователь получает возможность управлять кластером через веб-интерфейс **Console**.
|
||||
|
||||
**Console** - это встроенный веб-интерфейс платформы Deckhouse, предназначенный для упрощения взаимодействия с Kubernetes-кластером.
|
||||
|
||||
Он позволяет выполнять большинство операций, доступных в командной строке через **kubectl**, в визуальном режиме:
|
||||
- мониторинг состояния кластера;
|
||||
- управление узлами и модулями;
|
||||
- настройку безопасности и сети.
|
||||
|
||||
## Вход в Console
|
||||
|
||||
1. Откройте веб-браузер и перейдите по адресу, предоставленному для доступа к Console.
|
||||
|
||||
::: info Примечание
|
||||
URL-адрес направляется пользователю на электронную почту при предоставлении доступа.
|
||||
:::
|
||||
|
||||
2. На странице ввода учетных данных выполняется аутентификация при помощи логина и пароля;
|
||||
|
||||

|
||||
|
||||
3. После успешной аутентификации откроется главная страница веб-интерфейса Console.
|
||||
|
||||

|
||||
|
||||
## Основные разделы Console
|
||||
|
||||
В левой боковой панели веб-интерфейса Console расположены основные разделы для управления кластером:
|
||||
|
||||
| Раздел | Назначение |
|
||||
| ------------------ | -------------------------------------------------------------------------------------- |
|
||||
| **Deckhouse** | Управление платформой Deckhouse: обзор, обновления, модули, глобальные настройки |
|
||||
| **Проекты** | Управление проектами, шаблонами проектов и namespace (пространствами имён) |
|
||||
| **Узлы** | Управление узлами кластера: группы узлов, конфигурации, классы машин, статические узлы |
|
||||
| **Конфигурация** | Настройка Deschedulers и Priority Classes |
|
||||
| **Доступ** | Управление аутентификацией, сессиями пользователей, правами доступа (RBAC) |
|
||||
| **Сеть** | Настройка Egress-шлюзов, балансировки и управление сертификатами |
|
||||
| **Хранилище** | Управление Persistent Volume, классами хранилищ и снимками томов |
|
||||
| **Безопасность** | Настройка политик безопасности и операционных политик |
|
||||
| **Мониторинг** | Просмотр данных, дашбордов, активных алертов, настройка уведомлений и экспорт метрик |
|
||||
| **Журналирование** | Управление отправкой и сбором логов |
|
||||
|
||||
## Генерация kubeconfig через Console
|
||||
|
||||
Помимо управления через веб-интерфейс, Console позволяет сгенерировать файл **kubeconfig** для доступа к кластеру через **kubectl**.
|
||||
|
||||
1. На главной странице Console находится раздел «Инструменты» (Tools);
|
||||
2. Необходимо выбрать пункт «Генератор kubeconfig» (Generate kubeconfig);
|
||||
3. Нажимается кнопка генерации - система сгенерирует необходимые команды;
|
||||
4. Далее, нужно скопировать и выполнить в терминале команды, которые сгенерированы для пользовательской учётной записи.
|
||||
|
||||
::: info Примечание
|
||||
Сгенерированный **kubeconfig** уже содержит все необходимые параметры для подключения к API Kubernetes.
|
||||
:::
|
||||
|
||||
## Примеры простейших команд kubectl
|
||||
|
||||
После настройки **kubeconfig** управление кластером осуществляется через командную строку с помощью утилиты **kubectl**. Ниже приведены основные команды для начала работы.
|
||||
|
||||
### Проверка подключения к кластеру
|
||||
|
||||
```
|
||||
kubectl cluster-info
|
||||
```
|
||||
|
||||
**Пример вывода:**
|
||||
|
||||
```
|
||||
Kubernetes control plane is running at https://127.0.0.1:6445
|
||||
|
||||
To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.
|
||||
```
|
||||
|
||||
### Просмотр узлов кластера
|
||||
|
||||
```
|
||||
kubectl get nodes
|
||||
```
|
||||
|
||||
**Пример вывода:**
|
||||
|
||||
```
|
||||
NAME STATUS ROLES AGE VERSION
|
||||
cloud-frontend-0 Ready frontend 12d v1.32.10
|
||||
cloud-frontend-1 Ready frontend 12d v1.32.10
|
||||
cloud-master-0 Ready control-plane,master 12d v1.32.10
|
||||
cloud-master-1 Ready control-plane,master 12d v1.32.10
|
||||
cloud-master-2 Ready control-plane,master 12d v1.32.10
|
||||
cloud-system-0 Ready system 12d v1.32.10
|
||||
cloud-system-1 Ready system 12d v1.32.10
|
||||
cloud-worker-a374349e-zznfp-nkqr2 Ready worker 12d v1.32.10
|
||||
cloud-worker-a374349e-zznfp-rdpdz Ready worker 12d v1.32.10
|
||||
```
|
||||
|
||||
### Просмотр пространств имен
|
||||
|
||||
```
|
||||
kubectl get namespaces
|
||||
```
|
||||
|
||||
**Пример вывода:**
|
||||
|
||||
```
|
||||
NAME STATUS AGE
|
||||
d8-admission-policy-engine Active 12d
|
||||
d8-cert-manager Active 12d
|
||||
d8-chrony Active 12d
|
||||
d8-cloud-instance-manager Active 12d
|
||||
d8-cloud-provider-vcd Active 12d
|
||||
d8-cni-cilium Active 12d
|
||||
d8-console Active 12d
|
||||
d8-dashboard Active 12d
|
||||
d8-descheduler Active 12d
|
||||
d8-ingress-nginx Active 12d
|
||||
d8-local-path-provisioner Active 12d
|
||||
d8-log-shipper Active 12d
|
||||
d8-metallb Active 12d
|
||||
d8-monitoring Active 12d
|
||||
d8-multitenancy-manager Active 12d
|
||||
d8-observability Active 12d
|
||||
d8-operator-prometheus Active 12d
|
||||
d8-pod-reloader Active 12d
|
||||
d8-service-accounts Active 12d
|
||||
d8-snapshot-controller Active 12d
|
||||
d8-system Active 12d
|
||||
d8-upmeter Active 12d
|
||||
d8-user-authn Active 12d
|
||||
default Active 12d
|
||||
kube-node-lease Active 12d
|
||||
kube-public Active 12d
|
||||
kube-system Active 12d
|
||||
```
|
||||
|
||||
### Просмотр подов в конкретном namespace
|
||||
|
||||
```
|
||||
kubectl get pods -n d8-console
|
||||
```
|
||||
|
||||
**Пример вывода:**
|
||||
|
||||
```
|
||||
NAME READY STATUS RESTARTS AGE
|
||||
backend-546c7496f8-2nzx2 1/1 Running 0 3d7h
|
||||
backend-546c7496f8-nxqf4 1/1 Running 0 3d7h
|
||||
console-dex-authenticator-6b7d456445-7cg9p 2/2 Running 0 12d
|
||||
console-dex-authenticator-6b7d456445-ljjr8 2/2 Running 0 12d
|
||||
frontend-79cb59c94d-cf457 1/1 Running 0 3d7h
|
||||
frontend-79cb59c94d-rvlzk 1/1 Running 0 3d7h
|
||||
observability-gw-59c4fb6548-2lcqr 1/1 Running 0 3d7h
|
||||
observability-gw-59c4fb6548-9n6nb 1/1 Running 0 3d7h
|
||||
```
|
||||
|
||||
### Просмотр логов пода
|
||||
|
||||
```
|
||||
kubectl logs frontend-79cb59c94d-cf457 -n d8-console
|
||||
```
|
||||
|
||||
### Просмотр сервисов
|
||||
|
||||
```
|
||||
kubectl get services -n d8-console
|
||||
```
|
||||
|
||||
**Пример вывода:**
|
||||
|
||||
```
|
||||
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
|
||||
backend ClusterIP 10.222.4.60 <none> 8999/TCP 12d
|
||||
console-dex-authenticator ClusterIP 10.222.224.82 <none> 443/TCP 12d
|
||||
frontend ClusterIP 10.222.226.106 <none> 80/TCP 12d
|
||||
observability-gw ClusterIP None <none> 3000/TCP,8443/TCP 12d
|
||||
```
|
||||
|
||||
### Быстрое получение информации о ресурсах
|
||||
|
||||
```
|
||||
kubectl get all -n d8-console
|
||||
```
|
||||
|
||||
**Пример вывода:**
|
||||
|
||||
```
|
||||
NAME READY STATUS RESTARTS AGE
|
||||
pod/backend-546c7496f8-2nzx2 1/1 Running 0 3d7h
|
||||
pod/backend-546c7496f8-nxqf4 1/1 Running 0 3d7h
|
||||
pod/console-dex-authenticator-6b7d456445-7cg9p 2/2 Running 0 12d
|
||||
pod/console-dex-authenticator-6b7d456445-ljjr8 2/2 Running 0 12d
|
||||
pod/frontend-79cb59c94d-cf457 1/1 Running 0 3d7h
|
||||
pod/frontend-79cb59c94d-rvlzk 1/1 Running 0 3d7h
|
||||
pod/observability-gw-59c4fb6548-2lcqr 1/1 Running 0 3d7h
|
||||
pod/observability-gw-59c4fb6548-9n6nb 1/1 Running 0 3d7h
|
||||
|
||||
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
|
||||
service/backend ClusterIP 10.222.4.60 <none> 8999/TCP 12d
|
||||
service/console-dex-authenticator ClusterIP 10.222.224.82 <none> 443/TCP 12d
|
||||
service/frontend ClusterIP 10.222.226.106 <none> 80/TCP 12d
|
||||
service/observability-gw ClusterIP None <none> 3000/TCP,8443/TCP 12d
|
||||
|
||||
NAME READY UP-TO-DATE AVAILABLE AGE
|
||||
deployment.apps/backend 2/2 2 2 12d
|
||||
deployment.apps/console-dex-authenticator 2/2 2 2 12d
|
||||
deployment.apps/frontend 2/2 2 2 12d
|
||||
deployment.apps/observability-gw 2/2 2 2 12d
|
||||
|
||||
NAME DESIRED CURRENT READY AGE
|
||||
replicaset.apps/backend-546c7496f8 2 2 2 3d7h
|
||||
replicaset.apps/backend-69d8c6bd68 0 0 0 12d
|
||||
replicaset.apps/console-dex-authenticator-6b7d456445 2 2 2 12d
|
||||
replicaset.apps/console-dex-authenticator-74c97bf4d6 0 0 0 12d
|
||||
replicaset.apps/frontend-6b7ffb7bbd 0 0 0 9d
|
||||
replicaset.apps/frontend-79cb59c94d 2 2 2 3d7h
|
||||
replicaset.apps/frontend-79ccdfc56b 0 0 0 12d
|
||||
replicaset.apps/observability-gw-574cdfdd87 0 0 0 12d
|
||||
replicaset.apps/observability-gw-59c4fb6548 2 2 2 3d7h
|
||||
|
||||
|
||||
```
|
||||
### Получение справки
|
||||
|
||||
Для получение справки по любой команде используется флаг **--help**:
|
||||
|
||||
```
|
||||
kubectl get pods --help
|
||||
kubectl describe pod --help
|
||||
```
|
||||
### Просмотр подробной информации о конкретном ресурсе
|
||||
|
||||
```
|
||||
kubectl describe pod <имя-пода> -n <namespace>
|
||||
```
|
||||
|
After Width: | Height: | Size: 864 KiB |
|
After Width: | Height: | Size: 257 KiB |
@@ -0,0 +1,19 @@
|
||||
---
|
||||
section_links:
|
||||
- title: Обзор сервиса
|
||||
link: /PaaS/Deckhouse/about.md
|
||||
description: Обзор сервиса
|
||||
- title: Права и возможности пользователей
|
||||
link: /PaaS/Deckhouse/user-permissions.md
|
||||
description: Управление доступом и роли пользователей
|
||||
- title: Описание технических параметров
|
||||
link: /PaaS/Deckhouse/technical-parameters.md
|
||||
description: Параметры конфигурации сервиса Deckhouse
|
||||
- title: Подключение к сервису Deckhouse
|
||||
link: /PaaS/Deckhouse/connection.md
|
||||
description: Подключение и работа с сервисом Deckhouse
|
||||
---
|
||||
|
||||
# Cloud Deckhouse Kubernetes
|
||||
|
||||
В данном разделе представлена документация по управлемому сервису **Cloud Deckhouse Kubernetes** платформы Beeline Cloud.
|
||||
@@ -0,0 +1,120 @@
|
||||
# Описание технических параметров
|
||||
|
||||
Данный раздел содержит технические параметры **кластера Kubernetes** и порядок их первичной конфигурации.
|
||||
|
||||
Настройка параметров выполняется администратором облачного провайдера на этапе развертывания сервиса. Пользователь не может изменять их самостоятельно (исключение — конфигурация worker-узлов).
|
||||
|
||||
**Процедура согласования параметров:**
|
||||
|
||||
1. Клиент передает менеджеру список требуемых параметров.
|
||||
2. Администратор выполняет настройку по согласованным требованиям.
|
||||
|
||||
## Дисковое хранилище
|
||||
|
||||
Производительность приложений в Kubernetes зависит от скорости чтения и записи данных на диск. Тип хранилища определяет:
|
||||
|
||||
- **IOPS** (Input/Output Operations Per Second) — количество операций ввода-вывода в секунду;
|
||||
- **время отклика** (латентность).
|
||||
|
||||
::: info Примечание
|
||||
Чем выше IOPS, тем быстрее работают базы данных и другие диско-интенсивные приложения.
|
||||
:::
|
||||
|
||||
## Доступные типы хранилищ:
|
||||
|
||||
| Тип | Лимит IOPS |
|
||||
| ---------- | ------------------ |
|
||||
| Fast SAS | до 2 IOPS на 1 ГБ |
|
||||
| SSD | до 5 IOPS на 1 ГБ |
|
||||
| Fast SSD | до 10 IOPS на 1 ГБ |
|
||||
| Ultra NVMe | до 25 IOPS на 1 ГБ |
|
||||
|
||||
::: warning Важно
|
||||
После выбора типа диска необходимо указать объем дискового хранилища, который будет выделен под данные приложений (Persistent Volumes). **Минимальный объем - 50 ГБ.**
|
||||
:::
|
||||
|
||||
## Конфигурация вычислительных ресурсов
|
||||
|
||||
Вычислительные мощности кластера включают:
|
||||
|
||||
- процессорные ресурсы (vCPU);
|
||||
- оперативную память (RAM);
|
||||
- количество узлов.
|
||||
|
||||
### Узлы в кластере
|
||||
|
||||
Количество узлов определяет отказоустойчивость кластера и возможность распределять нагрузку между worker-узлами.
|
||||
|
||||
::: info Примечение
|
||||
Чем больше узлов, тем выше надежность и пропускная способность.
|
||||
:::
|
||||
|
||||
#### 1. Master-узлы (control plane)
|
||||
|
||||
Для обеспечения отказоустойчивости кластера **рекомендуется использовать не менее трех master-узлов**.
|
||||
|
||||
| Количество узлов | Результат |
|
||||
|------------------|-----------------------------------------------------------------------------------------------|
|
||||
| 3 и более | Обеспечивают кворум, безопасное обновление и отказоустойчивость. Большего числа не требуется. |
|
||||
| 2 | Недостаточно для кворума при отказе одного узла. |
|
||||
| 1 | Отказ узла приводит к полному сбою кластера. |
|
||||
|
||||
#### 2. System-узлы
|
||||
|
||||
Предназначены для запуска модулей Deckhouse.
|
||||
|
||||
**Рекомендация:** два узла. Это изолирует системные модули от пользовательских приложений.
|
||||
|
||||
#### 3. Frontend-узлы
|
||||
|
||||
Балансируют входящий трафик, на них работают Ingress-контроллеры.
|
||||
|
||||
**Рекомендация:** более одного узла.
|
||||
|
||||
**Требования к емкости:**
|
||||
|
||||
| Количество узлов | Требование к каждому узлу |
|
||||
|------------------|---------------------------------------------------|
|
||||
| 2 | Должен выдержать 100% нагрузки при отказе второго |
|
||||
| 3 | Должен выдержать увеличение нагрузки в 1.5 раза |
|
||||
|
||||
#### 4. Worker-узлы
|
||||
|
||||
На них выполняются пользовательские приложения.
|
||||
|
||||
- **Рекомендация:** от 1 узла.
|
||||
- **Управление:** пользователь может увеличивать максимальное количество узлов самостоятельно.
|
||||
|
||||
## Процессор (CPU)
|
||||
|
||||
**Процессор** - это вычислительная мощность, выделяемая каждому узлу кластера. Количество vCPU определяет, насколько быстро приложения смогут:
|
||||
|
||||
- обрабатывать запросы;
|
||||
- выполнять сложные вычисления;
|
||||
- обслуживать одновременные подключения.
|
||||
|
||||
**Диапазон**: от 2 до 24 vCPU на один узел.
|
||||
|
||||
## Оперативная память (RAM)
|
||||
|
||||
**Оперативная память** - влияет на производительность приложений. Данные в RAM обрабатываются без обращения к диску.
|
||||
|
||||
**Диапазон**: от 4 до 768 ГБ RAM на один узел.
|
||||
|
||||
## Доступ в интернет
|
||||
|
||||
При заказе сервиса выберите пропускную способность канала для доступа к кластеру из интернета.
|
||||
|
||||
**Доступные скорости**:
|
||||
|
||||
- 50 Мбит/с;
|
||||
- 100 Мбит/с;
|
||||
- 200 Мбит/с;
|
||||
- 300 Мбит/с;
|
||||
- 400 Мбит/с;
|
||||
- 500 Мбит/с;
|
||||
- 1000 Мбит/с (1 Гбит/с).
|
||||
|
||||
::: info Примечание
|
||||
Для выбранного канала предоставляется **статический белый IP-адрес**.
|
||||
:::
|
||||
@@ -0,0 +1,83 @@
|
||||
# Права и возможности пользователей
|
||||
|
||||
При развертывании сервиса Cloud Deckhouse Kubernetes создается учетная запись с уровнем доступа **SuperAdmin**. Этот уровень предоставляет расширенные права на управление кластером Kubernetes.
|
||||
|
||||
**SuperAdmin** получает полный контроль над своими приложениями и ресурсами в пределах выделенного кластера или пространства имен (namespace).
|
||||
|
||||
## Ограничения доступа SuperAdmin
|
||||
|
||||
SuperAdmin **не имеет доступа** к следующим компонентам:
|
||||
|
||||
- инфраструктурный уровень (гипервизоры, физические серверы, сетевое оборудование);
|
||||
- управление компонентами платформы Deckhouse на уровне всего кластера;
|
||||
- master-узлы, system-узлы и frontend-узлы;
|
||||
- изменение конфигурации платформы Deckhouse и её глобальных модулей.
|
||||
|
||||
## Доступные действия
|
||||
|
||||
### Управление пространствами имен (Namespaces)
|
||||
|
||||
SuperAdmin может управлять пространствами имен:
|
||||
|
||||
- создавать новые namespace;
|
||||
- удалять namespace (все ресурсы внутри удаляются);
|
||||
- просматривать список всех namespace;
|
||||
- устанавливать метки (labels) и аннотации для namespace.
|
||||
|
||||
### Управление рабочими нагрузками
|
||||
|
||||
SuperAdmin имеет полный контроль над подами, развёртываниями и другими ресурсами приложений:
|
||||
|
||||
- создавать, обновлять и удалять Deployment, StatefulSet, DaemonSet;
|
||||
- создавать, обновлять и удалять Pod;
|
||||
- просматривать логи подов (`kubectl logs`);
|
||||
- подключаться к выполняющемуся контейнеру (`kubectl exec`);
|
||||
- масштабировать развертывания (увеличивать или уменьшать количество реплик);
|
||||
- обновлять версии образов контейнеров;
|
||||
- удалять поды (в том числе принудительно);
|
||||
- просматривать события (events) в namespace.
|
||||
|
||||
### Управление сетевым доступом (Services & Ingress)
|
||||
|
||||
SuperAdmin может настраивать способы доступа к приложениям как внутри кластера, так и из внешней сети:
|
||||
|
||||
SuperAdmin может настраивать способы доступа к приложениям внутри кластера и из внешней сети:
|
||||
|
||||
- создавать, изменять и удалять Service (типы: ClusterIP, NodePort, LoadBalancer);
|
||||
- создавать, изменять и удалять Ingress-правила для маршрутизации входящего трафика;
|
||||
- настраивать порты и селекторы для сервисов;
|
||||
- просматривать список сервисов и их конечных точек (endpoints).
|
||||
|
||||
### Управление хранилищем (Storage)
|
||||
|
||||
SuperAdmin может создавать и использовать тома для хранения данных приложений:
|
||||
|
||||
- создавать Persistent Volume Claim (PVC);
|
||||
- удалять PVC (освобождать дисковое пространство);
|
||||
- просматривать список PVC и их статусов;
|
||||
- использовать PVC в подах (монтировать тома).
|
||||
|
||||
### Управление конфигурацией (ConfigMaps & Secrets)
|
||||
|
||||
SuperAdmin может создавать и изменять конфигурационные данные и секреты для приложений:
|
||||
|
||||
- создавать, изменять и удалять ConfigMap;
|
||||
- создавать, изменять и удалять Secrets (например, для хранения токенов, паролей или ключей);
|
||||
- монтировать ConfigMap и Secrets в поды в виде переменных окружения или файлов.
|
||||
|
||||
### Мониторинг и наблюдаемость
|
||||
|
||||
SuperAdmin имеет доступ к метрикам и логам своих приложений:
|
||||
|
||||
- просматривать метрики приложений в Grafana;
|
||||
- просматривать логи через `kubectl logs` или интерфейс сбора логов (Loki);
|
||||
- просматривать дашборды с информацией о потреблении ресурсов (CPU, RAM, Storage) своими приложениями;
|
||||
- просматривать события Kubernetes (events) для диагностики проблем.
|
||||
|
||||
### Управление доступом (RBAC)
|
||||
|
||||
SuperAdmin может управлять правами других пользователей в рамках своего пространства имен:
|
||||
|
||||
- создавать и удалять учетные записи (ServiceAccount);
|
||||
- назначать роли (Role, RoleBinding) другим пользователям в пределах своего namespace;
|
||||
- ограничивать доступ к отдельным ресурсам.
|
||||
@@ -0,0 +1,144 @@
|
||||
# Параметры конфигурации IPsec-соединения
|
||||
|
||||
В данном разделе приведены параметры конфигурации IPsec-соединения, используемого для организации защищенного канала связи между инфраструктурой заказчика и кластерами. Материал описывает настройки этапов установки соединения и передачи данных, включая методы аутентификации, алгоритмы шифрования и хеширования, группы Диффи-Хеллмана, а также параметры времени жизни ключей.
|
||||
|
||||
Ниже приведены основные параметры, задаваемые при развертывании кластера Kafka. Часть параметров определяется клиентом на этапе заказа услуги, часть - фиксирована и не подлежит изменению.
|
||||
|
||||
## Данные о конфигурации IPSEC
|
||||
|
||||
Параметры подключения (имя туннеля, устройство, публичный IP-адрес) заполняются вручную на основании информации, предоставленной заказчиком.
|
||||
|
||||
#### Версия IKE (Internet Key Exchange)
|
||||
|
||||
Версия IKE выбирается из выпадающего списка, который содержит в себе два параметра - **v1** и **v2**.
|
||||
|
||||
- **IKE v1** - более ранняя версия протокола;
|
||||
- **IKE v2** - более современная версия (обеспечивает более устойчивое соединение и гибкую обработку ошибок).
|
||||
|
||||
Рекомендуется использовать **IKE v2**, если оборудование заказчика это поддерживает.
|
||||
|
||||
## Метод аутентификации
|
||||
|
||||
Метод аутентификации выбирается вручную из выпадающего списка, который содержит два варианта:
|
||||
|
||||
- **PSK (Pre-Shared Key)** - метод аутентификации, при котором используется заранее согласованный общий ключ;
|
||||
- **Certificate** - аутентификация с использованием цифровых сертификатов.
|
||||
|
||||
## Этап 1 - установка защищенного соединения
|
||||
|
||||
#### Hash
|
||||
|
||||
Определяет алгоритм хеширования **для защиты управляющего канала**.
|
||||
|
||||
Данный параметр заполняется вручную из выпадающего списка следующего содержания:
|
||||
|
||||
- **SHA 1** - Формирует хеш длиной 160 бит, имеет коллизии (уязвимости), в современных системах считается устаревшим, используется только для совместимости со старым оборудованием;
|
||||
- **SHA 2 - 256** - Формирует хеш длиной 256 бит, существенно более устойчив к атакам, оптимальный баланс между безопасностью и производительностью, а также, на сегодняшний день, является стандартом по умолчанию в большинстве систем;
|
||||
- **SHA 2 - 384** - Длина хеша составляет 384 бита, имеет повышенную криптостойкость, требует больше вычислительных ресурсов, чем SHA-1 и SHA 2-256. Используется в средах с повышенными требованиями к безопасности;
|
||||
- **SHA 2 - 512** - Длина хеша составляет 512 бит, осуществляет самый высокий уровень стойкости из перечисленных, а также создает большую нагрузку на процессор. Обычно применяется в системах с повышенными требованиями к криптографии.
|
||||
|
||||
#### Шифрование
|
||||
|
||||
Определяет **алгоритм симметричного шифрования.**
|
||||
|
||||
Данный параметр заполняется вручную из выпадающего списка следующего содержания:
|
||||
|
||||
- **AES 128** - имеет 128-битный ключ, обеспечивает быстрое шифрование, имеет достаточный уровень безопасности для большинства задач;
|
||||
- **AES 256** - имеет 256-битный ключ, обеспечивает более высокую криптостойкость, оказывает немного большую нагрузку на CPU;
|
||||
- **AES GCM 12** / **AES GCM 192** / **AES GCM 256** - данные алгоритмы совмещают шифрование и контроль целостности, обладают более современным режимом работы, считаются более эффективными по производительности, а также рекомендуются в современных конфигурациях. Разница между этими тремя алгоритмами лишь в длине ключа.
|
||||
|
||||
#### DH Group - группа Деффи Хеллмана
|
||||
|
||||
Механизм Diffie-Hellman используется **для безопасной генерации общего секретного ключа** между сторонами туннеля без передачи этого ключа по сети.
|
||||
Чем выше номер группы и длина ключа - тем выше криптографическая стойкость соединения.
|
||||
|
||||
Данный параметр так же содержит в себе выпадающий список, состоящий из следующих значений:
|
||||
- **group 2**;
|
||||
- **group 5**;
|
||||
- **group 14**;
|
||||
- **group 15**;
|
||||
- **group 16**;
|
||||
- **group 19**;
|
||||
- **group 20**;
|
||||
- **group 21**.
|
||||
|
||||
#### IKE Mode (только для IKEv1)
|
||||
|
||||
Параметр IKE Mode **определяет способ установления соединения** на этапе 1 при использовании протокола IKEv1.
|
||||
|
||||
Доступны два режима: **Main** и **Aggressive**. Они отличаются количеством сообщений при установке соединения и уровнем защиты идентификационных данных.
|
||||
- Main Mode - является стандартным и более безопасным режимом работы IKEv1.
|
||||
- Aggressive Mode - упрощённый и ускоренный режим установления соединения. (более низкий уровень защиты данных)
|
||||
|
||||
#### Время жизни
|
||||
|
||||
Определяет, как долго действуют согласованные ключи в рамках первой фазы.
|
||||
|
||||
- Рекомендуемое значение: 86400 секунд (24 часа);
|
||||
- После истечения времени выполняется повторная генерация ключей.
|
||||
|
||||
|
||||
## Этап 2 - передача данных
|
||||
|
||||
Этап 2 IPsec-соединения отвечает за шифрование и защиту пользовательского трафика после того, как защищённый канал был установлен на этапе 1. Этот этап регулирует передачу данных между сторонами через безопасный туннель, который обеспечивает конфиденциальность и целостность данных.
|
||||
|
||||
#### Hash
|
||||
|
||||
Аналогично этапу 1, параметр Hash используется **для защиты целостности передаваемых данных**. Он обеспечивает проверку, что данные не были изменены при передаче.
|
||||
|
||||
Содержит элементы для выбора:
|
||||
|
||||
- **SHA 1**;
|
||||
- **SHA 2 - 256**;
|
||||
- **SHA 2 - 384**;
|
||||
- **SHA 2 - 512**.
|
||||
|
||||
#### Шифрование
|
||||
|
||||
Этап 2 отвечает за **шифрование пользовательского трафика**. Это важнейший параметр, который защищает данные при их передаче по сети.
|
||||
|
||||
Доступны следующие алгоритмы:
|
||||
|
||||
- **AES 128**;
|
||||
- **AES 256**;
|
||||
- **AES GCM 128**;
|
||||
- **AES GCM 192**;
|
||||
- **AES GCM 256**.
|
||||
|
||||
#### PFS
|
||||
|
||||
**Enable perfect forward secrecy (PFS)** - параметр, активирующий генерацию нового ключа на этапе 2. При включенном PFS группа DH будет такая же как и на 1-й фазе. Данный параметр представлен в виде чекбокса.
|
||||
|
||||
При его включении:
|
||||
|
||||
- На этапе 2 выполняется дополнительный обмен ключами Diffie-Hellman;
|
||||
- Для каждой новой IPsec-сессии формируется новый независимый криптографический секрет;
|
||||
- Ключи шифрования пользовательского трафика не зависят от ключей этапа 1.
|
||||
|
||||
#### DH Group - группа Деффи Хеллмана
|
||||
|
||||
Группа DH **определяет параметры обмена ключами** между сторонами. Чем выше номер группы, тем выше криптографическая стойкость и безопасность обмена.
|
||||
|
||||
Данный параметр так же содержит в себе выпадающий список, состоящий из следующих значений:
|
||||
|
||||
- **group 2**;
|
||||
- **group 5**;
|
||||
- **group 14**;
|
||||
- **group 15**;
|
||||
- **group 16**;
|
||||
- **group 19**;
|
||||
- **group 20**;
|
||||
- **group 21**.
|
||||
|
||||
#### Время жизни (в секундах)
|
||||
|
||||
Определяет, как долго действуют согласованные ключи в рамках второй фазы.
|
||||
|
||||
- Рекомендуемое значение: 3600 секунд (1 час).
|
||||
- После истечения времени выполняется повторная генерация ключей.
|
||||
|
||||
#### Префиксы локальной сети заказчика
|
||||
|
||||
Этот параметр определяет, какие сети на стороне заказчика будут маршрутизироваться через IPsec-туннель.
|
||||
|
||||
Префиксы задаются в формате `192.168.1.0/24`, который позволяет указать диапазон IP-адресов.
|
||||
@@ -0,0 +1,25 @@
|
||||
---
|
||||
section_links:
|
||||
- title: Назначение сервиса
|
||||
link: /PaaS/PostgreSQL/about.md
|
||||
description: Конфигурации и возможности сервиса
|
||||
- title: Параметры кластера PostgreSQL
|
||||
link: /PaaS/PostgreSQL/cluster-parameter.md
|
||||
description: Технические параметры кластера PostgreSQL
|
||||
- title: Схема подключения
|
||||
link: /PaaS/PostgreSQL/connection.md
|
||||
description: Общая схема подключения к Cloud PostgreSQL
|
||||
- title: Возможности пользователя
|
||||
link: /PaaS/PostgreSQL/user-capabilities.md
|
||||
description: Возможности пользователя при создании сервиса
|
||||
- title: Веб-интерфейс Grafana
|
||||
link: /PaaS/PostgreSQL/grafana.md
|
||||
description: Инструкция по работе с Grafana
|
||||
- title: Веб-интерфейс PgAdmin
|
||||
link: /PaaS/PostgreSQL/pgadmin.md
|
||||
description: Инструкция по работе с PgAdmin
|
||||
---
|
||||
|
||||
# Cloud PostgreSQL
|
||||
|
||||
В данном разделе представлена документация по управляемому сервису **Cloud PostgreSQL** платформы Beeline Cloud.
|
||||
@@ -0,0 +1,87 @@
|
||||
# Cloud PostgreSQL
|
||||
|
||||
## Назначение сервиса
|
||||
|
||||
**Cloud PostgreSQL** - это управляемый облачный сервис реляционной базы данных PostgreSQL. Он позволяет развернуть и использовать отказоустойчивый кластер базы данных без необходимости самостоятельно настраивать серверы, репликацию и механизмы отказоустойчивости.
|
||||
|
||||
PostgreSQL - это современная система управления базами данных, которая поддерживает стандарт SQL и используется для хранения и обработки данных приложений.
|
||||
|
||||
В **Cloud PostgreSQL** все основные операции по управлению кластером выполняются автоматически.
|
||||
|
||||
Сервис самостоятельно:
|
||||
- управляет ролями серверов базы данных (основной сервер и реплики);
|
||||
- отслеживает состояние узлов;
|
||||
- автоматически переключает основной сервер при сбоях.
|
||||
|
||||
Для обеспечения стабильной работы сервиса используется несколько инфраструктурных компонентов:
|
||||
- **Patroni** - управляет кластером PostgreSQL и автоматическим переключением при отказах;
|
||||
- **etcd** - хранит состояние кластера и обеспечивает согласованность работы узлов;
|
||||
- **HAProxy** - обеспечивает единую точку подключения и распределяет клиентские подключения между узлами.
|
||||
|
||||
Подключение к базе данных выполняется через прокси-узлы сервиса. Пользователю не требуется подключаться к отдельным серверам кластера — все операции производятся через единую точку доступа.
|
||||
|
||||
Для управления базами данных и пользователями доступен [web-интерфейс **pgAdmin**](./pgadmin.md), позволяющий выполнять администрирование непосредственно через браузер.
|
||||
|
||||
## Конфигурации кластера
|
||||
|
||||
Сервис **Cloud PostgreSQL** поддерживает версии СУБД с 13 по 17 включительно.
|
||||
|
||||
Кластер предоставляется в архитектуре Primary–Standby, которая обеспечивает:
|
||||
|
||||
- синхронную репликацию данных;
|
||||
- повышенную отказоустойчивость.
|
||||
|
||||
В рамках данной конфигурации создаётся кластер из виртуальных серверов, включающий:
|
||||
|
||||
- **Primary** (основной сервер) — обязательный узел, на котором выполняются операции записи данных;
|
||||
- **Replica** (реплики) — дополнительные узлы (от 0 до 4), создаваемые по желанию пользователя.
|
||||
|
||||
Реплики являются полноценными участниками кластера PostgreSQL и могут использоваться для выполнения запросов, не изменяющих данные (например, SELECT).
|
||||
|
||||
В многоузловой конфигурации серверы кластера размещаются на разных физических хостах гипервизора, что повышает устойчивость сервиса к отказам оборудования.
|
||||
|
||||
## Режимы репликации
|
||||
|
||||
По умолчанию фиксация изменений выполняется в **синхронном режиме**. Это означает, что операция записи считается завершённой только после того, как данные будут зафиксированы как на основном сервере, так и на одной из реплик.
|
||||
|
||||
Если в кластере настроено несколько реплик, синхронный режим применяется только к одной из них. Остальные реплики работают в асинхронном режиме — изменения передаются на них без ожидания подтверждения.
|
||||
|
||||
При необходимости режим репликации может быть изменён на полностью **асинхронный**. В этом случае изменения сначала фиксируются на основном сервере, а затем передаются на реплики с задержкой.
|
||||
|
||||
## Доступ к серверам и оптимизация соединений
|
||||
|
||||
Прямой доступ к серверам кластера (например, по протоколу SSH) не предоставляется. Пользователь взаимодействует с базой данных исключительно через точки подключения, предоставленные сервисом.
|
||||
|
||||
На каждом узле кластера установлен пулер соединений **PgBouncer**, который может использоваться для ускорения работы приложений за счёт оптимизации подключений к базе данных.
|
||||
|
||||
::: warning Примечание
|
||||
|
||||
Использование PgBouncer не является обязательным - подключение возможно как напрямую к PostgreSQL, так и через пулер, а также одновременно обоими способами.
|
||||
|
||||
:::
|
||||
|
||||
## Возможности сервиса
|
||||
|
||||
**Cloud PostgreSQL** предоставляет набор возможностей, позволяющих использовать PostgreSQL в облаке без необходимости самостоятельного администрирования инфраструктуры.
|
||||
|
||||
Сервис обеспечивает:
|
||||
|
||||
- автоматическое управление кластером PostgreSQL;
|
||||
- высокую доступность за счёт репликации и автоматического переключения primary-узла;
|
||||
- единую точку подключения к базе данных через прокси;
|
||||
- автоматическое переключение при отказе узлов кластера без вмешательства пользователя;
|
||||
- web-доступ к управлению базами данных и пользователями через pgAdmin;
|
||||
- совместимость со стандартными клиентскими инструментами PostgreSQL;
|
||||
- возможность установки расширений PostgreSQL в базу данных.
|
||||
|
||||
## Сценарии использования сервиса
|
||||
|
||||
**Cloud PostgreSQL** подходит для использования в системах, где требуется надёжное хранение данных и упрощённое управление инфраструктурой базы данных.
|
||||
|
||||
Сервис может применяться в следующих сценариях:
|
||||
|
||||
- размещение production-баз данных с высокими требованиями к доступности;
|
||||
- использование PostgreSQL в микросервисной архитектуре с единой точкой подключения к базе данных;
|
||||
- хранение критичных данных с минимальным временем простоя при отказах инфраструктуры;
|
||||
- быстрое развёртывание PostgreSQL-кластера без необходимости ручной настройки репликации и failover;
|
||||
- администрирование баз данных через веб-интерфейс без прямого доступа к серверам кластера.
|
||||
@@ -0,0 +1,81 @@
|
||||
# Описание технических параметров
|
||||
|
||||
Данный раздел содержит технические параметры кластера PostgreSQL и порядок их первичной конфигурации.
|
||||
|
||||
Настройка указанных параметров выполняется администратором облачного провайдера на этапе развёртывания сервиса. Пользователь не имеет прямого доступа к их самостоятельной установке.
|
||||
|
||||
Перед созданием кластера клиент предоставляет перечень требуемых параметров менеджеру. Администратор облачного провайдера выполняет конфигурацию в соответствии с согласованными требованиями.
|
||||
|
||||
## Выбор типа и размера дискового хранилища
|
||||
|
||||
Производительность базы данных напрямую зависит от скорости, с которой она может читать и записывать данные на диск. При заказе кластера необходимо выбрать тип дискового хранилища, который определит максимальную скорость работы (IOPS) и время отклика.
|
||||
|
||||
**IOPS (Input/Output Operations Per Second)** — количество операций чтения или записи, которые диск может выполнить за секунду. Чем выше этот показатель, тем быстрее база данных обрабатывает запросы.
|
||||
|
||||
## Доступные типы хранилищ:
|
||||
|
||||
| Название | Лимит IOPS |
|
||||
| -------------- | ------------------ |
|
||||
| **Fast SAS** | до 2 IOPS на 1 ГБ |
|
||||
| **SSD** | до 5 IOPS на 1 ГБ |
|
||||
| **Fast SSD** | до 10 IOPS на 1 ГБ |
|
||||
| **Ultra NVMe** | до 25 IOPS на 1 ГБ |
|
||||
|
||||
::: warning Примечание
|
||||
|
||||
После выбора типа диска необходимо указать объем дискового хранилища, который будет выделен под данные кластера PostgreSQL. Минимальный объем - 50 ГБ.
|
||||
|
||||
:::
|
||||
|
||||
## Конфигурация вычислительных ресурсов
|
||||
|
||||
В данном разделе определяются вычислительные мощности кластера: процессорные ресурсы, оперативная память и количество серверов (нод), из которых будет состоять кластер PostgreSQL.
|
||||
|
||||
#### Количество нод в кластере
|
||||
|
||||
Количество нод определяет отказоустойчивость кластера и возможность распределять запросы на чтение между репликами. Чем больше нод, тем выше надёжность и производительность операций чтения.
|
||||
|
||||
Количество нод выбирается в диапазоне **от 1 до 5**.
|
||||
|
||||
#### Процессор (CPU)
|
||||
|
||||
Процессор — это вычислительная мощность, выделяемая каждой ноде кластера. Количество vCPU определяет, насколько быстро база данных сможет:
|
||||
|
||||
- обрабатывать запросы;
|
||||
- выполнять сложные операции (сортировки, объединения таблиц);
|
||||
- обслуживать одновременные подключения.
|
||||
|
||||
Доступный диапазон: **от 2 до 24 vCPU** на ноду.
|
||||
|
||||
#### Оперативная память (RAM)
|
||||
|
||||
Оперативная память — один из ключевых ресурсов для производительности базы данных. Данные, помещающиеся в RAM, обрабатываются максимально быстро, без обращения к диску.
|
||||
|
||||
Доступный диапазон: **от 4 до 768 ГБ RAM** на ноду.
|
||||
|
||||
#### Доступ в интернет
|
||||
|
||||
При заказе сервиса можно выбрать пропускную способность канала связи, через который будет осуществляться доступ к кластеру PostgreSQL из сети интернет.
|
||||
|
||||
**Доступные варианты скорости:**
|
||||
- 50 Мбит/с;
|
||||
- 100 Мбит/с;
|
||||
- 200 Мбит/с;
|
||||
- 300 Мбит/с;
|
||||
- 400 Мбит/с;
|
||||
- 500 Мбит/с;
|
||||
- 1000 Мбит/с (1 Гбит/с).
|
||||
|
||||
::: warning Примечание
|
||||
|
||||
Для выбранного канала предоставляется статический белый IP-адрес.
|
||||
|
||||
:::
|
||||
|
||||
## Сетевой доступ к кластеру
|
||||
|
||||
Для организации защищенного подключения к кластеру Kafka доступны стандартные механизмы, используемые во всех сервисах платформы:
|
||||
- **IPsec-подключение** - организация защищенного туннеля между инфраструктурой и кластером PostgreSQL. Подробнее см. [раздел IPsec](../IPSEC.md);
|
||||
- **Interconnection** - прямое сетевое соединение между сервисами внутри платформы без выхода в интернет. Подробнее см. раздел Interconnection.
|
||||
|
||||
Выбор конкретного способа подключения зависит от архитектуры приложений и требований к безопасности.
|
||||
@@ -0,0 +1,88 @@
|
||||
# Общая схема подключения
|
||||
|
||||
Подключение к кластеру **Cloud PostgreSQL** осуществляется через прокси-сервер. Клиентские подключения принимаются прокси, который маршрутизирует трафик к соответствующим узлам кластера (master или replica) в зависимости от выбранного порта.
|
||||
|
||||
Прокси является единой точкой входа для всех клиентских подключений и принимает входящие соединения от приложений, административных инструментов и пользователей.
|
||||
|
||||
В зависимости от выбранного порта прокси автоматически направляет трафик:
|
||||
- **на активный primary-узел** - для операций чтения и записи
|
||||
- **на реплики** - для операций только чтения
|
||||
|
||||
::: warning Примечание
|
||||
Прямое подключение к отдельным узлам базы данных **не используется и не предоставляется**. Взаимодействие с кластером всегда выполняется **через прокси-сервер**.
|
||||
:::
|
||||
|
||||
## Подключение к базе данных
|
||||
|
||||
Для подключения к базе данных необходимо использовать IP-адрес прокси-сервера, который предоставляется после заказа услуги.
|
||||
|
||||
Этот IP-адрес является единой точкой входа для работы с кластером PostgreSQL. Все подключения к базе данных - как из приложений, так и из клиентских инструментов - выполняются через него.
|
||||
|
||||
Использование других IP-адресов или попытка прямого подключения к отдельным узлам кластера не предусмотрены.
|
||||
|
||||
## Доступные порты
|
||||
|
||||
Для разных типов нагрузки используются разные порты:
|
||||
|
||||
|Порт |Назначение |
|
||||
|------|-----------------------------------------|
|
||||
|5432 |Primary (чтение и запись) |
|
||||
|15432 |Replica (только чтение) |
|
||||
|6432 |Primary через PgBouncer (чтение и запись)|
|
||||
|16432 |Replica через PgBouncer (только чтение) |
|
||||
|
||||
#### Особенности работы портов
|
||||
|
||||
- Порты **для чтения и записи** (5432, 6432) всегда направляют трафик на активный primary-узел. При смене primary переключение происходит автоматически;
|
||||
- Порты **только для чтения** (15432, 16432) направляют трафик на активные реплики. Если реплик несколько, нагрузка распределяется между ними по принципу round-robin;
|
||||
- Если в кластере **отсутствуют реплики**, порты для чтения не используются - подключение по ним не устанавливается.
|
||||
|
||||
#### Рекомендации по выбору порта
|
||||
|
||||
- Для OLTP-нагрузки и большого количества соединений рекомендуется использовать **порты PgBouncer (6432 или 16432)**;
|
||||
- Для операций записи используйте **master-порты (5432 или 6432)**;
|
||||
- Для read-only запросов можно использовать **replica-порты (15432 или 16432)**.
|
||||
|
||||
## Доступ к pgAdmin
|
||||
|
||||
Для администрирования базы данных используется [web-интерфейс pgAdmin](./pgadmin.md).
|
||||
Доступ осуществляется по DNS-имени, которое нужно прописать локально в инфраструктуре откуда будет происходить доступ к web-интерфейсу сервиса:
|
||||
`10.X.X.4 <domain>.cloud-pg.dfcloud.ru`
|
||||
|
||||
После добавления записи pgAdmin будет доступен по адресу:
|
||||
`https://<domain>.cloud-pg.dfcloud.ru`
|
||||
|
||||
Авторизация выполняется с использованием учётных данных, предоставленных вместе с доступом к сервису.
|
||||
|
||||
::: warning Примечание
|
||||
|
||||
- подключение к базе данных возможно только через указанный прокси-IP;
|
||||
- в интерфейсе pgAdmin уже добавлен сервер базы данных, созданный для данной инсталляции. Для подключения требуется ввести пароль от учётной записи базы данных;
|
||||
- pgAdmin предназначен для администрирования и не рекомендуется для выполнения тяжёлых или длительных запросов в production-среде.
|
||||
|
||||
:::
|
||||
|
||||
## Примеры подключения к PostgreSQL
|
||||
|
||||
Подключение к primary:
|
||||
`psql -h 10.X.X.4 -p 5432 -U <username> -d <database>`
|
||||
|
||||
Подключение через PgBouncer:
|
||||
`psql -h 10.X.X.4 -p 6432 -U <username> -d <database>`
|
||||
|
||||
#### Подключение через DBeaver / DataGrip
|
||||
|
||||
При создании подключения укажите:
|
||||
- Host: 10.X.X.4;
|
||||
- Port: 5432 или 6432;
|
||||
- Database: `<database>`;
|
||||
- User / Password: согласно выданным доступам;
|
||||
- Тип подключения: PostgreSQL.
|
||||
|
||||
#### Пример строки подключения
|
||||
|
||||
Primary:
|
||||
`postgresql://<username>:<password>@10.X.X.4:5432/<database>`
|
||||
|
||||
Через PgBouncer:
|
||||
`postgresql://<username>:<password>@10.X.X.4:6432/<database>`
|
||||
@@ -0,0 +1,104 @@
|
||||
# Grafana
|
||||
|
||||
## Инструкция по работе с метриками
|
||||
|
||||
Доступ к метрикам кластера предоставляется после запроса соответствующих прав. После получения доступа можно перейти в систему мониторинга по ссылке: https://metrics.dfcloud.ru. После перехода по ссылке будет представлена главная страница Grafana.
|
||||
|
||||
Для просмотра метрик кластера PostgreSQL выполните следующие шаги:
|
||||
|
||||
1. В левом боковом меню нажмите **Dashboard**;
|
||||
2. В списке доступных дашбордов выберите **папку Cloud PostgreSQL**;
|
||||
3. Внутри папки выберите **дашборд Cloud PostgreSQL** — в нём отображаются все метрики кластера.
|
||||
|
||||
## Управление отображаемыми данными
|
||||
|
||||
В верхней части дашборда доступны селекторы для настройки отображения:
|
||||
|
||||
- **InstallationID** - выбор одного опеределенного кластера;
|
||||
- **Cluster node name** - выбор конкретного нода кластера, в котором значения графиков меняются в зависимости от выбранного хоста (селектор влияет на все графики, кроме блока Patroni);
|
||||
- **Database** - выбор базы данных, по которым отображаются метрики;
|
||||
- **Lock table** - выбор типа блокировки для отображения (применим не для всех графиков).
|
||||
|
||||
## Метрики PostgreSQL
|
||||
|
||||
Метрики отображают ключевые параметры конфигурации и текущие показатели работы экземпляра PostgreSQL.
|
||||
|
||||
| Наименование метрики | Описание метрики |
|
||||
| ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| **Version** | Показывает текущую версию PostgreSQL, установленную на кластере. |
|
||||
| **Current fetch data** | Объем данных, извлеченных из базы за текущий период (операции чтения). |
|
||||
| **Current insert data** | Объем данных, вставленных в базу (операции записи новых данных). |
|
||||
| **Current update data** | Объем данных, обновленных в базе. |
|
||||
| **Seq Page Cost** | Стоимость последовательного чтения страницы данных. Влияет на выбор плана запроса: чем выше значение, тем реже оптимизатор будет выбирать последовательное сканирование таблиц. |
|
||||
| **Random Page Cost** | Стоимость чтения случайной страницы данных. Низкое значение говорит о том, что в системе используются быстрые диски, и оптимизатор будет чаще выбирать доступ по индексам. |
|
||||
| **Max Connections** | Максимальное количество одновременных подключений к базе данных, разрешенное на сервере. |
|
||||
| **Shared Buffers** | Объем оперативной памяти, выделенный под кэш данных PostgreSQL. Здесь хранятся часто используемые данные для ускорения доступа к ним. |
|
||||
| **Effective Cache** | Предполагаемый размер системного кэша файлов. Используется оптимизатором для оценки вероятности нахождения данных в кэше операционной системы. |
|
||||
| **Maintenance Work Mem** | Объем памяти для выполнения операций обслуживания. |
|
||||
| **Work Mem** | Объем памяти, выделяемый для внутренних сортировок и хеш-таблиц при выполнении запросов (на каждую операцию). |
|
||||
| **Max WAL Size** | Максимальный размер журнала предзаписи, после достижения которого запускается процесс контрольной точки (checkpoint). |
|
||||
| **Max Worker Processes** | Максимальное количество фоновых процессов, которые могут быть запущены в системе. |
|
||||
| **Max Parallel Workers** | Максимальное количество параллельных процессов, которые могут быть задействованы при выполнении одного запроса. |
|
||||
|
||||
## Метрики Database Stats
|
||||
|
||||
Метрики отображают текущую нагрузку и состояние баз данных в кластере PostgreSQL. Данные метрики позволяют:
|
||||
- оценить эффективность работы баз данных;
|
||||
- отследить скачки нагрузки;
|
||||
- своевременно среагировать на потенциальные проблемы до того, как они повлияют на работу приложений.
|
||||
|
||||
| Наименование | Описание |
|
||||
|---------------------------| -------------------|
|
||||
| **Average CPU Usage** | Показывает время, затраченное на выполнение пользовательских и системных задач, а также, насколько интенсивно используются вычислительные ресурсы сервера базы данных. |
|
||||
| **Average Memory Usage** | Средний объем оперативной памяти, используемой процессами PostgreSQL за 5-минутные интервалы. Показывает, сколько памяти потребляет база данных в процессе работы. |
|
||||
| **Open File Descriptors** | Количество открытых файловых дескрипторов процессами PostgreSQL. Метрика показывает среднее (Mean), последнее (Last), максимальное (Max) и минимальное (Min) значение за интервал. |
|
||||
| **Active sessions** | Показывает, сколько в данный момент выполняется запросов к PostgreSQL. Метрика показывает среднее (Mean), последнее (Last), максимальное (Max) значение. |
|
||||
| **Transcations** | Количество транзакций в базах данных кластера. Метрика разделена на два типа операций: commits (успешно завершенные транзакции) и rollbacks (откаченные транзакции). |
|
||||
| **Update data** | Объем данных, обновленных в базах данных кластера. Показывает, сколько данных было изменено в результате выполнения операций UPDATE. |
|
||||
| **Fetch data (SELECT)** | Объем данных, извлеченных из базы с помощью запросов SELECT. Показывает, сколько данных было считано из базы в результате операций чтения. |
|
||||
| **Insert data** | Объем данных, вставленных в базы данных кластера. Показывает, сколько данных было добавлено в результате выполнения операций INSERT. |
|
||||
| **Lock tables** | Количество блокировок таблиц в базах данных кластера. Показывает, сколько раз таблицы были заблокированы для выполнения операций.<br>AccessShareLock - это блокировка, которая возникает, когда кто-то читает данные из таблицы (делает SELECT). Данная блокировка не мешает операциям чтения, но не дает удалить в этот момент таблицу или изменить ее структуру. |
|
||||
| **Return data** | Объем данных, возвращаемых клиенту в результате выполнения запросов. Показывает, сколько данных было отправлено обратно клиенту после обработки запросов в базе. |
|
||||
| **Idle sessions** | Количество бездействующих сессий подключения к базе данных. Показывает, сколько открытых подключений в данный момент не выполняют никаких запросов и просто ждут. |
|
||||
| **Delete data** | Объем данных, удаленных из базы данных в результате выполнения операций DELETE. Показывает, сколько данных было удалено из таблиц. |
|
||||
| **Cache Hit Rate** | Показывает процент запросов к данным, которые были удовлетворены из кэша (оперативной памяти), без обращения к диску. Показывает, насколько эффективно используется кэш PostgreSQL. |
|
||||
| **Buffers (bgwriter)** | Метрика, показывающая активность фонового процесса записи, который занимается синхронизацией данных из оперативной памяти на диск. |
|
||||
| **Conflicts/Deadlocks** | Метрика, отслеживающая две проблемы при работе с базой данных: конфликты восстановления и взаимоблокировки. |
|
||||
| **Temp File (Bytes)** | Объем данных, записанных во временные файлы при выполнении запросов в базах данных. PostgreSQL создает временные файлы на диске, когда для выполнения запроса не хватает оперативной памяти. |
|
||||
| **Checkpoint Stats** | Метрика, показывающая время, затрачиваемое на выполнение checkpoints в PostgreSQL, где: <br>- **write_time** - время, затраченное на запись данных на диск во время checkpoint (сколько миллисекунд ушло на запись файлов).<br>- **sync_time** - время, затраченное на синхронизацию файлов с диском (чтобы данные гарантированно сохранились). |
|
||||
|
||||
## Метрики Patroni
|
||||
|
||||
Метрик отображают состояние и конфигурацию кластера PostgreSQL под управлением Patroni. Эти метрики позволяют контролировать отказоустойчивость кластера, отслеживать переключения мастера и убеждаться, что репликация работает штатно.
|
||||
|
||||
| Наименование | Описание |
|
||||
|------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| **Patroni Leader** | Метрика, которая показывает, какая нода в кластере PostgreSQL в данный момент является master-сервером, принимающим запросы на запись. |
|
||||
| **Patroni Replica** | Метрика, которая показывает, какие узлы кластера PostgreSQL в данный момент выполняют роль реплики. |
|
||||
| **Sync Standby** | Метрика, которая показывает, какая из реплик в кластере PostgreSQL назначена синхронной. |
|
||||
| **PostgreSQL WAL Replay** | Метрика, которая показывает, включена ли на узлах кластера синхронизация данных через WAL. |
|
||||
| **PostgreSQL Pending Restart** | Метрика, которая показывает, требуется ли перезагрузка PostgreSQL на узлах кластера после изменения конфигурационных параметров. |
|
||||
| **Patroni Primary Node** | Метрика, которая показывает, какой узел в кластере PostgreSQL в данный момент является основным и принимает запросы на запись. |
|
||||
| **Patroni Secondary Nodes** | Метрика, которая показывает, какие узлы кластера PostgreSQL в определенные моменты времени выполняли роль реплик. |
|
||||
| **Replicas Received WAL Location** | Метрика, показывающая объем журналов предзаписи (WAL), полученных каждой репликой кластера. |
|
||||
| **Primary WAL Location** | Метрика, показывающая объем журналов предзаписи (WAL), на основном сервере кластера PostgreSQL. |
|
||||
| **Replicas Replayed WAL Location** | Метрика, показывающая объем журналов предзаписи (WAL), которые были не просто получены, а уже применены на репликах кластера. |
|
||||
| **WAL Replay Paused** | Метрика, которая отслеживает, не приостановлен ли процесс применения WAL-журналов на узлах кластера. Если передача или применение WAL-файлов останавливается, на графике происходит скачок. |
|
||||
|
||||
## Метрики Hosts
|
||||
|
||||
Блок Hosts управляется селектором **Cluster node name**. Метрики отображают состояние и ресурсы серверов, на которых развернут кластер PostgreSQL. Данные метрики позволяют оценить, хватает ли серверу ресурсов для текущей нагрузки, и своевременно обнаружить проблемы с производительностью или нехваткой места на дисках.
|
||||
|
||||
| Наименование | Описание |
|
||||
| -------------------------------|-------------------------------------------------------------------------------------------------------------------------------|
|
||||
| **CPU Busy** | Метрика, показывающая общую загруженность всех процессорных ядер на сервере, где работает PostgreSQL. |
|
||||
| **RAM Used** | Метрика, показывающая процент оперативной памяти, который занят на сервере всеми процессами. |
|
||||
| **CPU Cores** | Метрика, показывающая общее количество процессорных ядер, доступных на сервере, где работает PostgreSQL. |
|
||||
| **RAM Total** | Метрика, показывающая общий объем оперативной памяти, установленный на сервере. |
|
||||
| **DB Disk Total** | Метрика, показывающая общий объем дискового пространства, выделенного для хранения данных базы данных PostgreSQL на сервере. |
|
||||
| **CPU Basic** | Метрика, которая показывает детальную разбивку загрузки процессора по типам выполняемых задач. Она позволяет увидеть, на что именно тратится процессорное время на сервере. |
|
||||
| **Memory Basic** | Метрика, которая показывает детальную разбивку использования оперативной памяти на сервере, а также информацию о SWAP. |
|
||||
| **Disk IOps** | Метрика, показывающая количество операций чтения и записи, выполняемых на диске сервера в секунду. |
|
||||
| **Disk Space Used Basic** | Метрика, показывающая процент занятого дискового пространства на всех подключенных файловых системах сервера. |
|
||||
| **Disk R/W Data** | Показывает объем данных в байтах, читаемых с диска и записываемых на диск в секунду. |
|
||||
| **Filesystem space available** | Метрика, показывающая объем свободного дискового пространства на файловой системе сервера. |
|
||||
@@ -0,0 +1,67 @@
|
||||
# PgAdmin
|
||||
|
||||
После предоставления доступа к сервису **Cloud PostgreSQL** пользователь получает возможность управлять базами данных через веб-интерфейс **pgAdmin**. Ниже приведена инструкция по входу в систему и выполнению основных операций.
|
||||
|
||||
## Вход в pgAdmin
|
||||
|
||||
1. Откройте веб-браузер и перейдите по адресу, предоставленному для доступа к pgAdmin;
|
||||
2. На странице авторизации введите **логин и пароль от pgAdmin**;
|
||||
> Учетные данные направляются пользователю на электронную почту при предоставлении доступа.
|
||||
3. После входа в систему в левой панели навигации откройте раздел **Servers**;
|
||||
4. Выберите предварительно настроенный сервер с названием **PostgreSQL**;
|
||||
5. В открывшемся окне введите пароль;
|
||||
> Важно: на данном этапе необходимо указать **пароль учетной записи базы данных**, а не пароль от pgAdmin.
|
||||
6. Нажмите **ОК**.
|
||||
|
||||
После успешной аутентификации станет доступен веб-интерфейс СУБД PostgreSQL.
|
||||
|
||||
## Реплики и параметры конфигураций
|
||||
|
||||
pgAdmin позволяет осуществлять мониторинг реплик, входящих в состав кластера. Чтобы просмотреть список реплик необходимо открыть раздел **Replica nodes** в панели навигации.
|
||||
|
||||
|
||||
### Просмотр состояния репликаций
|
||||
|
||||
Чтобы проверить состояние репликации:
|
||||
1. Выберите нужную реплику в разделе **Replica nodes**;
|
||||
2. Перейдите в подраздел **Replication**;
|
||||
3. Откройте пункт **Replication stats**;
|
||||
4. Разверните раздел **Подробности** - в нем отображаются все параметры и текущее состояние репликации.
|
||||
|
||||
Вкладка **Replication** позволяет определить, выполняется ли передача данных на дополнительные узлы кластера.
|
||||
|
||||
### Просмотр конфигураций реплики
|
||||
|
||||
Чтобы просмотреть **параметры конфигурации PostgreSQL**, применённые к конкретной реплике, перейдите в раздел **Конфигурация**, расположенный в блоке **Replica nodes**.
|
||||
|
||||
Раздел **Конфигурация** содержит следующие параметры:
|
||||
- **Имя** - наименование конфигурационного параметра;
|
||||
- **Категория** - логическая группа параметра;
|
||||
- **Значение** - текущее установленное значение;
|
||||
- **Единицы** - единицы измерения (если применимо);
|
||||
- **Описание** - краткое пояснение назначения параметра.
|
||||
> Вкладка **Конфигурация** предназначена для просмотра текущих настроек реплики.
|
||||
|
||||
## Базы данных
|
||||
|
||||
### Просмотр существующих баз данных:
|
||||
|
||||
Чтобы просмотреть существующие базы данных, откройте раздел Базы данных в левой панели навигации. В этом разделе отображается перечень всех созданных баз.
|
||||
|
||||
### Создание новой базы данных:
|
||||
|
||||
1. Щелкните правой кнопкой мыши по разделу **Базы данных**;
|
||||
2. В контекстном меню выберите **Создать**, затем - **База данных**;
|
||||
3. Заполните обязательные поля в открывшейся форме;
|
||||
4. Нажмите **Сохранить**.
|
||||
|
||||
## Роли входа / группы
|
||||
|
||||
В разделе **Роли входа/группы** отображается список пользователей (ролей), имеющих доступ к базам данных кластера.
|
||||
|
||||
### Создание новой роли:
|
||||
|
||||
1. Щелкните правой кнопкой мыши по разделу **Роли входа/группы**;
|
||||
2. Выберите **Создать**, затем - **Роль входа/группы**;
|
||||
3. Заполните необходимые параметры в форме создания роли;
|
||||
4. Нажмите **Сохранить**.
|
||||
@@ -0,0 +1,119 @@
|
||||
# Возможности пользователя
|
||||
|
||||
Данный раздел описывает права, которые предоставляются пользователю PostgreSQL при создании сервиса **Cloud PostgreSQL**, а также перечень административных операций, доступных ему для самостоятельного выполнения.
|
||||
|
||||
При развертывании сервиса автоматически создаётся пользователь базы данных с преднастроенными атрибутами и привилегиями. Эти права позволяют заказчику самостоятельно управлять своими базами данных, ролями и пользователями в рамках созданного экземпляра PostgreSQL.
|
||||
|
||||
|
||||
## Общая информация о пользователе
|
||||
|
||||
При инициализации сервиса автоматически создаётся пользователь:
|
||||
|
||||
```nginx
|
||||
client
|
||||
```
|
||||
|
||||
Данный пользователь является основной учётной записью для административной работы в рамках предоставленного экземпляра PostgreSQL.
|
||||
|
||||
Он предназначен для самостоятельного управления в пределах выданных привилегий:
|
||||
- базами данных;
|
||||
- ролями;
|
||||
- правами доступа.
|
||||
|
||||
|
||||
## Выданные права и ограничения
|
||||
|
||||
Пользователю `client` назначается набор атрибутов и привилегий, позволяющих выполнять административные операции в рамках своего экземпляра базы данных.
|
||||
|
||||
#### Атрибуты роли
|
||||
|
||||
Пользователь создаётся со следующими атрибутами:
|
||||
- `CREATEDB` — разрешено создание и удаление баз данных;
|
||||
- `CREATEROLE` — разрешено создание ролей и пользователей, а также управление их.
|
||||
|
||||
Атрибут `SUPERUSER` пользователю не предоставляется. Соответственно, доступ к системным операциям уровня кластера и настройкам сервера отсутствует.
|
||||
|
||||
#### Права на системную базу postgres:
|
||||
|
||||
К стандартной базе данных `postgres` пользователю предоставлено только право подключения — `CONNECT`
|
||||
|
||||
**Иные привилегии (создание объектов, изменение схем и т.д.) на данную базу не выдаются.**
|
||||
|
||||
|
||||
## Мониторинг и системные представления
|
||||
|
||||
Для выполнения базовых задач мониторинга пользователю дополнительно предоставлены:
|
||||
- членство в роли `pg_monitor`;
|
||||
- право `SELECT` на системное представление:
|
||||
```sql
|
||||
pg_catalog.pg_stat_replication
|
||||
```
|
||||
|
||||
Доступ к системной информации предоставляется исключительно **в режиме чтения**. Изменение системных представлений и параметров сервера недоступно.
|
||||
|
||||
|
||||
## Изменение пароля
|
||||
|
||||
После первого подключения к базе данных пользователь `client` обязан выполнить изменения пароля.
|
||||
|
||||
Изменить пароля можно:
|
||||
- в открытом виде (с передачей нового значения пароля);
|
||||
- с указанием заранее сгенерированного хэша.
|
||||
|
||||
На сервере используется алгоритм шифрования паролей:
|
||||
|
||||
```
|
||||
scram-sha-256
|
||||
```
|
||||
|
||||
При использовании **SCRAM** применяется следующий формат хэша:
|
||||
|
||||
```
|
||||
$<iterations>:<salt>$<storedkey>:<serverkey>
|
||||
```
|
||||
|
||||
| Операция | Описание | Команда SQL |
|
||||
|----------|----------|-------------|
|
||||
|Смена пароля в открытом виде | Для смены пароля в открытом виде | ```ALTER USER client WITH PASSWORD 'new_strong_password';``` |
|
||||
|Смена пароля с указанием хэша | Рекомендуется использовать сложный уникальный пароль, соответствующий требованиям информационной безопасности, и хранить его в защищённом хранилище | ```ALTER USER client WITH ENCRYPTED PASSWORD '$4096:...';``` |
|
||||
|Создание новой базы данных | Для создания базы данных | ```CREATE DATABASE app_db;``` |
|
||||
|Создание базы данных с указанием владельца | Пользователь, указанный как владелец, будет иметь полный контроль над базой данных, включая права на её удаление и изменение. По умолчанию владельцем создаваемой базы данных является пользователь, который её создает | ```CREATE DATABASE app_db OWNER client;``` |
|
||||
|
||||
|
||||
## Создание пользователей и ролей
|
||||
|
||||
Пользователь `client` имеет право создавать новые роли и пользователей для приложений, а также управлять их правами доступа.
|
||||
|
||||
| Операция | Описание | Команда SQL |
|
||||
|----------|----------|-------------|
|
||||
|Создание роли без логина | Для входа в базу данных (например, для организации прав доступа) | ```CREATE ROLE app_role; ```|
|
||||
|Создание пользователя с паролем | Для создания пользователя с паролем. После выполнения этой команды новый пользователь `app_user` будет иметь возможность входа в базу данных, используя указанный пароль. | ```CREATE USER app_user WITH PASSWORD 'app_password';``` |
|
||||
|Назначение роли пользователю | Для назначения роли пользователю. Данная команда позволяет управлять правами пользователя в рамках определённой роли. После выполнения этой команды пользователь `app_user` станет членом роли `app_role`, и будет наследовать все права, связанные с этой ролью. | ```GRANT app_role TO app_user; ``` |
|
||||
|
||||
|
||||
## Управление правами доступа
|
||||
|
||||
После создания пользователей и ролей необходимо назначить им соответствующие права доступа.
|
||||
|
||||
| Операция | Описание | Команда SQL |
|
||||
|----------|----------|-------------|
|
||||
|Передача владельца базы данных | Для передачи прав владения базой данных другому пользователю. После выполнения этой команды база данных `app_db` будет принадлежать пользователю `app_user`, и он будет иметь полный контроль над ней.| ```ALTER DATABASE app_db OWNER TO app_user;``` |
|
||||
|Выдача прав на подключение к базе данных | Для предоставления прав к подключению к базе данных. После выполнения этой команды пользователь может `app_user` подключаться к базе данных `app_db`. | ```GRANT CONNECT ON DATABASE app_db TO app_user;```|
|
||||
|Предоставление прав на схему public | Для предоставления прав на использование схемы `public`. После выполнения этой команды пользователь `app_user` может использовать объекты в схеме `public`, а также создавать новые объекты внутри неё. | ```GRANT USAGE, CREATE ON SCHEMA public TO app_user;```|
|
||||
|Предоставление прав на существующие таблицы | Для предоставления доступа пользователю к существующим таблицам в схеме `public`. После выполнения этой команды пользователь `app_user` может выполнять операции чтения, вставки, обновления и удаления данных в существующих таблицах схемы `public`.| ```GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO app_user;``` |
|
||||
|Предоставление прав на будущие таблицы | Если необходимо автоматически предоставить пользователю права на новые таблицы, создаваемые в схеме `public`. После выполнения этой команды все будущие таблицы, создаваемые в схеме `public`, будут автоматически иметь права для пользователя `app_user` на чтение, вставку, обновление и удаление данных. | ```ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO app_user;```|
|
||||
|
||||
|
||||
## Мониторинг репликации
|
||||
|
||||
Пользователь `client` имеет доступ к системным представлениям для мониторинга состояния репликации в кластере PostgreSQL.
|
||||
|
||||
| Операция | Описание | Команда SQL |
|
||||
|----------|----------|-------------|
|
||||
|Просмотр состояния репликации | Для просмотра текущего статуса репликации. Этот запрос возвращает информацию о всех репликах, подключённых к основному (primary) серверу. |```SELECT * FROM pg_stat_replication;```|
|
||||
|
||||
::: warning Ограничения доступа реплкации
|
||||
|
||||
Пользователь `client` имеет доступ к данным в представлении `pg_stat_replication` только в режиме **read-only**. Это означает, что он может просматривать состояние репликации, но не может изменять или вмешиваться в процесс репликации.
|
||||
|
||||
:::
|
||||
@@ -0,0 +1,12 @@
|
||||
---
|
||||
section_links:
|
||||
- title: Cloud PostgreSQL
|
||||
link: /PaaS/PostgreSQL/PostgreSQL-index.md
|
||||
description: Обзор сервиса PostgreSQL
|
||||
- title: Deckhouse
|
||||
link: /PaaS/Deckhouse/index.md
|
||||
description: Обзор сервиса Deckhouse Kubernetes
|
||||
- title: IPSEC
|
||||
link: /PaaS/IPSEC.md
|
||||
description: Параметры конфигурации IPSEC
|
||||
---
|
||||
@@ -1,10 +0,0 @@
|
||||
---
|
||||
section_links:
|
||||
- title: Управление ключевыми парами
|
||||
link: /admin/ssh.md
|
||||
description: Добавление SSH-ключей для подключения к виртуальным машинам
|
||||
---
|
||||
|
||||
# Аккаунт Beeline Cloud
|
||||
|
||||
Аккаунт Beeline Cloud создается при [регистрации пользователя](../start/getting-started.md#1-регистрация-в-beeline-cloud) в Beeline Cloud. С помощью аккаунта можно управлять профилем пользователя.
|
||||
@@ -1,13 +0,0 @@
|
||||
# Матрица региональной доступности
|
||||
|
||||
Регион доступности — это один или несколько центров обработки данных (ЦОД), в которых могут быть размещены компоненты облачной инфраструктуры.
|
||||
|
||||
| Регион | Статус | Гипервизор | Процессор | HDD| SSD | NVME|
|
||||
|:---:|:---:|:---:|:---:|:---:|:---:|:---:|
|
||||
| **ДатаФорт 1** | Доступен | OpenStack | Intel® Xeon® Gold 6248R | ✘ | ✘ | ✅ |
|
||||
|
||||
Условные обозначения:
|
||||
|
||||
✅ — есть возможность выдачи ресурсов.
|
||||
|
||||
✘ — нет возможности выдачи ресурсов.
|
||||
@@ -0,0 +1,12 @@
|
||||
---
|
||||
section_links:
|
||||
- title: Управление ключевыми парами
|
||||
link: /admin/ssh.md
|
||||
description: Добавление SSH-ключей для подключения к виртуальным машинам
|
||||
---
|
||||
|
||||
# Администрирование
|
||||
|
||||
При [регистрации пользователя](../start/getting-started.md#1-регистрация-в-beeline-cloud) в Beeline Cloud создается аккаунт и проект в Beeline Cloud.
|
||||
|
||||
С помощью аккаунта можно управлять профилем пользователя - добавлять SSH-ключи, чтобы подключаться к виртуальным машинам без ввода пароля.
|
||||
|
||||
@@ -1,40 +0,0 @@
|
||||
# Квоты и лимиты
|
||||
|
||||
Ограничения включают в себя лимиты и квоты на потребление ресурсов в проекте.
|
||||
|
||||
Квоты ограничивают потребление ресурсов в проекте. В проекте на каждый ресурс выделяется квота, не превышающая лимит.
|
||||
|
||||
После создания проекту становятся доступны базовые квоты. Для них установлены значения по умолчанию.
|
||||
|
||||
**Базовые квоты**
|
||||
|
||||
| Название квоты | Количество |
|
||||
|---------------------|------------|
|
||||
| Количество виртуальных ВМов | 3 штуки|
|
||||
| ЦПУ | 200 |
|
||||
| ОЗУ | 200 Гбайт |
|
||||
| Хранилище NVME | 5000 Гбайт |
|
||||
| Объектное хранилище | 100 Гбайт |
|
||||
|
||||
## Просмотр квот проекта
|
||||
|
||||
1. Перейдите в консоль управления.
|
||||
2. В шапке выберите **Проекты**.
|
||||
3. Откроется список проектов, в которых вы являетесь участником.
|
||||
4. Нажмите на имя нужного проекта.
|
||||
5. Откройте раздел **Обзор**.
|
||||
|
||||
## Редактирование квот проекта
|
||||
|
||||
::: tip Информация
|
||||
Изменить квоты проекта может пользователь с ролью **Владелец проекта**.
|
||||
:::
|
||||
|
||||
1. Перейдите в консоль управления.
|
||||
2. В шапке выберите **Проекты**.
|
||||
3. Откроется список проектов, в которых вы являетесь участником.
|
||||
4. Нажмите на имя нужного проекта.
|
||||
5. Откройте раздел **Обзор**.
|
||||
6. В правом верхнем углу нажмите **Изменить квоты**.
|
||||
7. Увеличите или уменьшите квоты для ресурсов.
|
||||
8. Нажмите **Сохранить**.
|
||||
@@ -1,49 +0,0 @@
|
||||
# Управление проектами
|
||||
|
||||
Проект — это структурная единица публичного облака, в которой содержатся ресурсы: виртуальные машины, хранилища, IP-адреса и др.
|
||||
|
||||
Ресурсы могут быть вычислительными и аппаратными.
|
||||
|
||||
Вычислительные ресурсы:
|
||||
- оперативная память (ОЗУ);
|
||||
- ядра процессора (ЦПУ);
|
||||
- локальные диски;
|
||||
- сетевые диски;
|
||||
- IP-адреса.
|
||||
|
||||
Аппаратные ресурсы (ВМы, сети, диски) размещены в центрах обработки данных (ЦОД). Каждый дата-центр разделен на модули. Модули оснащены независимыми системами электропитания и охлаждения.
|
||||
|
||||
При получении доступа в публичное облако текущий пользователь становится менеджера проектов. Менеджер проектов может создавать новые проекты, в которых он получает роль владельца проекта. Владелец проекта может добавлять пользователей в проект, назначая им роли.
|
||||
|
||||
Доступ к проекту осуществляется из консоли управления.
|
||||
|
||||
## Создать проект
|
||||
|
||||
1. Перейдите в консоль управления.
|
||||
2. Нажмите кнопку **Создать → Проект** в правом верхнем углу.
|
||||
3. Заполните информацию о проекте:
|
||||
- **Название**: введите наименование проекта.
|
||||
- **Идентификатор**: введите идентификатор проекта:
|
||||
- допустимы строчные и прописные буквы латинского алфавита, цифры и дефис;
|
||||
- длина не более 64 символов;
|
||||
- не должно начинаться или заканчиваться дефисом.
|
||||
- **Описание**: введите краткое описание проекта.
|
||||
4. Нажмите **Создать**.
|
||||
|
||||
## Изменить имя проекта
|
||||
|
||||
::: tip Информация
|
||||
Изменить имя и описание проекта может только пользователь с ролью **Владелец проекта**.
|
||||
:::
|
||||
|
||||
1. Перейдите в консоль управления.
|
||||
2. В шапке выберите **Проекты**.
|
||||
3. Откроется список проектов, в которых вы являетесь участником.
|
||||
4. Нажмите на имя нужного проекта.
|
||||
5. Откройте раздел **Настройки → Основное**.
|
||||
6. Измените имя, описание проекта.
|
||||
7. Нажмите **Сохранить**.
|
||||
|
||||
## Удаление проекта
|
||||
|
||||
Функциональность не предусмотрена в публичном облаке.
|
||||
@@ -1,49 +0,0 @@
|
||||
# Ролевая модель
|
||||
|
||||
Управление проектом основано на ролевой модели.
|
||||
|
||||
**Базовые роли**
|
||||
|
||||
В проекте предусмотрен базовый набор ролей:
|
||||
|
||||
- **Владелец продукта** — управление пользователями проекта, просмотр ресурсов.
|
||||
- **DevOps-инженер** — управление инфраструктурой, стандартное администрирование ОС UNIX по протоколу ssh и права управления виртуальными ВМами и дисками в консоли управления.
|
||||
|
||||
## Матрица ролей
|
||||
|
||||
| Действие | Владелец проекта | DevOps-инженер |
|
||||
|---|---|---|
|
||||
| Обзор проекта<br> (квоты и количество использованных ресурсов)| ✅ | ✅ |
|
||||
| ВМы: обзор | ✅ | ✅ |
|
||||
| ВМы: мониторинг | ✅ | ✅ |
|
||||
| ВМы: создать ВМ |✘ | ✅ |
|
||||
| ВМы: подключить диск | ✘ | ✅ |
|
||||
| ВМы: отключить диск | ✘ | ✅ |
|
||||
| ВМы: добавить диск | ✘ | ✅ |
|
||||
| ВМы: теги | ✘ |✅ |
|
||||
| ВМы: масштабирование ВМа | ✘ | ✅ |
|
||||
| ВМы: выключить ВМ | ✘ | ✅ |
|
||||
| ВМы: включить ВМ | ✘ | ✅ |
|
||||
| ВМы: перезагрузить ВМ | ✘ | ✅ |
|
||||
| ВМы: принудительно перезагрузить ВМ | ✘ | ✅ |
|
||||
| ВМы: удалить ВМ | ✘ | ✅ |
|
||||
| ВМы: группы размещения | ✘ | ✅ |
|
||||
| ВМы: IP-адреса | ✘ | ✅ |
|
||||
| Диски: просмотр дисков | ✅ | ✅ |
|
||||
| Диски: добавление дискового пространства | ✘ | ✅ |
|
||||
| Диски: удалить диск| ✘ | ✅ |
|
||||
| Объектное хранилище: просмотр| ✅ | ✅ |
|
||||
| Объектное хранилище: добавить хранилище | ✘ | ✅ |
|
||||
| Объектное хранилище: удалить хранилище | ✘ | ✅|
|
||||
| DNS: добавить зону | ✘ | ✅ |
|
||||
| DNS: редактировать зону | ✘ | ✅ |
|
||||
| DNS: удалить зону |✘ | ✅ |
|
||||
| Настройки проекта: просмотр| ✅ | ✅ |
|
||||
| Настройки проекта: изменить описание проекта |✅ | ✘ |
|
||||
| Участники: просмотр | ✅ | ✅ |
|
||||
| Участники: добавить участника | ✅ | ✘ |
|
||||
| Участники: удалить участника | ✅ | ✘ |
|
||||
| Участники: назначить роль | ✅| ✘ |
|
||||
| Квоты: просмотр | ✅ | ✅ |
|
||||
| Веб-обработчики | ✘ | ✅ |
|
||||
| Наблюдаемость | ✅ | ✅ |
|
||||
@@ -10,7 +10,7 @@ SSH-ключ добавляется на этапе [создания вирту
|
||||
|
||||
## Добавить SSH-ключ
|
||||
|
||||
1. Войдите в [личный кабинет](https://lk.cloud.beeline.ru/).
|
||||
1. Войдите в [личный кабинет](https://console.cloud.beeline.ru/).
|
||||
2. Перейдите в профиль пользователя в правом верхнем углу.
|
||||
3. Перейдите в раздел **SSH-ключи**.
|
||||
4. Нажмите **Добавить ключ**.
|
||||
@@ -31,14 +31,14 @@ SSH-ключ добавляется на этапе [создания вирту
|
||||
|
||||
## Посмотреть SSH-ключи
|
||||
|
||||
1. Войдите в [личный кабинет](https://lk.cloud.beeline.ru/).
|
||||
1. Войдите в [личный кабинет](https://console.cloud.beeline.ru/).
|
||||
2. Перейдите в профиль пользователя в правом верхнем углу.
|
||||
3. Перейдите в раздел **SSH-ключи**.
|
||||
4. В таблице показаны SSH-ключи пользователя.
|
||||
|
||||
## Изменить название SSH-ключа
|
||||
|
||||
1. Войдите в [личный кабинет](https://lk.cloud.beeline.ru/).
|
||||
1. Войдите в [личный кабинет](https://console.cloud.beeline.ru/).
|
||||
2. Перейдите в профиль пользователя в правом верхнем углу.
|
||||
3. Перейдите в раздел **SSH-ключи**.
|
||||
4. Выберите нужный ключ.
|
||||
@@ -48,7 +48,7 @@ SSH-ключ добавляется на этапе [создания вирту
|
||||
|
||||
## Удалить SSH-ключ
|
||||
|
||||
1. Войдите в [личный кабинет](https://lk.cloud.beeline.ru/).
|
||||
1. Войдите в [личный кабинет](https://console.cloud.beeline.ru/).
|
||||
2. Перейдите в профиль пользователя в правом верхнем углу.
|
||||
3. Перейдите в раздел **SSH-ключи**.
|
||||
4. Выберите нужный ключ.
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
# Управление пользователями в проекте
|
||||
|
||||
В консоли управления можно добавлять пользователей, управлять ролями пользователей в проекте. Один пользователей может участвовать в нескольких проектах и иметь в них разные роли.
|
||||
|
||||
::: tip Информация
|
||||
Добавлять и удалять пользователей, изменять права пользователей в проекте может только владелец проекта.
|
||||
:::
|
||||
|
||||
## Добавить пользователя
|
||||
|
||||
1. Перейдите в консоль управления.
|
||||
2. Откройте **Настройки → Участники**.
|
||||
3. Нажмите **Добавить пользователя**.
|
||||
4. Найдите пользователя по ФИО или email.
|
||||
5. Назначьте [роль](../admin/roles.md) пользователю.
|
||||
6. Нажмите **Добавить**.
|
||||
|
||||
## Назначить права пользователю
|
||||
|
||||
Каждому пользователю проекта должна быть выдана хотя бы одна роль. У пользователя может быть несколько ролей в одном проекте.
|
||||
|
||||
1. Перейдите в консоль управления.
|
||||
2. Откройте **Настройки → Участники**.
|
||||
3. Найдите пользователя.
|
||||
4. Нажмите ⠇ в строке с именем пользователя и выберите **Редактировать**.
|
||||
5. Назначьте [роль](../admin/roles.md) пользователю: установите флажок напротив роли.
|
||||
6. Нажмите **Сохранить**.
|
||||
|
||||
Права на существующие ОС применятся в течение 10 минут.
|
||||
|
||||
## Отозвать права у пользователя
|
||||
|
||||
1. Перейдите в консоль управления.
|
||||
2. Откройте **Настройки → Участники**.
|
||||
3. Найдите пользователя.
|
||||
4. Нажмите ⠇ в строке с именем пользователя и выберите **Редактировать**.
|
||||
5. Отзовите роль у пользователя: уберите флажок напротив роли. Оставьте пользователю хотя бы одну роль в проекте.
|
||||
6. Нажмите кнопку **Сохранить**.
|
||||
|
||||
## Удалить пользователя
|
||||
|
||||
1. Перейдите в консоль управления.
|
||||
2. Откройте **Настройки → Участники**.
|
||||
3. Найдите пользователя.
|
||||
4. Нажмите ⠇ в строке с именем пользователя и выберите **Удалить**.
|
||||
|
||||
Пользователь будет удален из списка участников проекта. Ресурсы проекта станут недоступны пользователю.
|
||||
|
Before Width: | Height: | Size: 347 KiB After Width: | Height: | Size: 347 KiB |
|
Before Width: | Height: | Size: 325 KiB After Width: | Height: | Size: 325 KiB |
|
Before Width: | Height: | Size: 199 KiB After Width: | Height: | Size: 199 KiB |
@@ -1,38 +0,0 @@
|
||||
@use '@beeline/design-tokens/scss/tokens/themes' as *;
|
||||
|
||||
:root {
|
||||
--app-navbar-height: #{$app-navbar-height};
|
||||
}
|
||||
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
html,
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
html {
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
#app {
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
html.dark-theme {
|
||||
background-color: $color-background-base;
|
||||
color: $color-text-active;
|
||||
}
|
||||
|
||||
a:visited {
|
||||
color: $color-text-active !important;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
text-decoration: none !important;
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
@import 'variables';
|
||||
@import 'base';
|
||||
@import 'form';
|
||||
@import 'helpers';
|
||||
@import 'components';
|
||||
@@ -1,3 +0,0 @@
|
||||
// Navbar
|
||||
$app-navbar-height: 3.5rem;
|
||||
$app-header-height: 64px;
|
||||
@@ -1,122 +0,0 @@
|
||||
@use '@beeline/design-tokens/scss/tokens/themes' as *;
|
||||
@use '@beeline/design-tokens/scss/tokens/components/fab' as *;
|
||||
@use '@beeline/design-tokens/scss/tokens/components/button' as *;
|
||||
@use '@beeline/design-tokens/scss/tokens/globals' as *;
|
||||
@use '@beeline/design-tokens/scss/mixin';
|
||||
|
||||
@mixin fab_button {
|
||||
background-color: $button-overlay-background-color;
|
||||
padding-left: $button-only-text-small-padding-horizontal;
|
||||
padding-right: $button-only-text-small-padding-horizontal;
|
||||
letter-spacing: $button-small-text-font-letter-spacing;
|
||||
line-height: $button-small-text-font-line-height;
|
||||
font-size: $button-small-text-font-size;
|
||||
height: $button-small-height;
|
||||
color: $button-overlay-text-color;
|
||||
box-shadow: none;
|
||||
border: 1px solid $button-outline-border-color;
|
||||
border-radius: $button-border-radius;
|
||||
|
||||
&:hover {
|
||||
cursor: pointer;
|
||||
background-color: $button-overlay-background-color-hover;
|
||||
}
|
||||
}
|
||||
|
||||
.app-fab {
|
||||
height: $fab-standard-height;
|
||||
width: $fab-standard-width;
|
||||
position: fixed;
|
||||
z-index: 50;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
border: 0;
|
||||
padding: $fab-standard-padding;
|
||||
letter-spacing: $fab-text-font-letter-spacing;
|
||||
line-height: $fab-text-font-line-height;
|
||||
font-size: $fab-text-font-size;
|
||||
font-weight: $fab-text-font-weight;
|
||||
box-shadow: $fab-shadow;
|
||||
background-color: $color-background-inverse;
|
||||
color: $color-text-active-inverse;
|
||||
cursor: pointer;
|
||||
|
||||
&__icon {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
// background-color: $fab-hover-background-color;
|
||||
}
|
||||
|
||||
&--focused {
|
||||
border-color: $fab-focused-border-color;
|
||||
border-width: $fab-focused-border-width;
|
||||
}
|
||||
|
||||
&--mini {
|
||||
height: $fab-mini-height;
|
||||
width: $fab-mini-width;
|
||||
border-radius: $fab-mini-border-radius;
|
||||
padding: $fab-mini-padding;
|
||||
}
|
||||
|
||||
&--extended {
|
||||
height: $fab-extended-height;
|
||||
border-radius: $fab-extended-border-radius;
|
||||
padding-right: $fab-extended-padding-right;
|
||||
padding-left: $fab-extended-padding-left;
|
||||
|
||||
& &__icon {
|
||||
margin-right: $fab-extended-icon-spacing;
|
||||
}
|
||||
}
|
||||
|
||||
.app-fab--extended.app-fab--mini {
|
||||
height: $fab-mini-height;
|
||||
}
|
||||
|
||||
&--disabled {
|
||||
opacity: $fab-disabled-opacity;
|
||||
}
|
||||
}
|
||||
|
||||
.app-fab-dialog {
|
||||
position: fixed;
|
||||
bottom: 44px;
|
||||
right: 0;
|
||||
// background-color: $color-background-medium;
|
||||
background-color: transparent;
|
||||
// border-radius: 12px;
|
||||
padding: 1rem;
|
||||
// border: 1px solid $color-border;
|
||||
// min-width: 300px;
|
||||
// box-shadow: $elevation-medium;
|
||||
|
||||
.icon-contained {
|
||||
display: inline-flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
background-color: $color-status-neutral-background;
|
||||
color: $color-status-neutral;
|
||||
border-radius: 12px;
|
||||
}
|
||||
|
||||
#feedback_button {
|
||||
@include fab_button();
|
||||
}
|
||||
|
||||
#bug_button {
|
||||
@include fab_button();
|
||||
line-height: 38px;
|
||||
}
|
||||
|
||||
a#bug_button,
|
||||
a#bug_button:visited,
|
||||
a#bug_button:active {
|
||||
color: $button-overlay-text-color !important;
|
||||
}
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
@import 'fab';
|
||||
@@ -1 +0,0 @@
|
||||
@use '@beeline/design-tokens/scss/tokens/components/formfield' as formfield;
|
||||
@@ -1,104 +0,0 @@
|
||||
@use '@beeline/design-tokens/scss/tokens/components/textarea' as *;
|
||||
@use '@beeline/design-tokens/scss/tokens/components/formfield';
|
||||
@use '@beeline/design-tokens/scss/tokens/themes';
|
||||
|
||||
.textarea-field {
|
||||
$px: 16px;
|
||||
|
||||
display: block;
|
||||
width: 100%;
|
||||
position: relative;
|
||||
padding: $textarea-without-label-medium-text-margin-top $px $textarea-text-margin-bottom;
|
||||
height: $textarea-without-label-medium-height;
|
||||
background: formfield.$formfield-background-color;
|
||||
border: formfield.$formfield-border-width formfield.$formfield-border-style formfield.$formfield-border-color;
|
||||
border-radius: formfield.$formfield-border-radius;
|
||||
|
||||
& &__label {
|
||||
position: absolute;
|
||||
top: $textarea-with-label-text-margin-top;
|
||||
left: $px;
|
||||
transition: font-size 300ms ease-out;
|
||||
color: formfield.$formfield-label-color;
|
||||
}
|
||||
|
||||
& textarea {
|
||||
height: $textarea-medium-text-height;
|
||||
width: 100%;
|
||||
outline: none;
|
||||
border: none;
|
||||
box-shadow: none;
|
||||
resize: none;
|
||||
background-color: transparent;
|
||||
color: themes.$color-text-active;
|
||||
}
|
||||
|
||||
& &__resizer {
|
||||
position: absolute;
|
||||
bottom: $textarea-resizer-margin-bottom;
|
||||
right: $textarea-resizer-margin-right;
|
||||
rotate: -45deg;
|
||||
width: 1em;
|
||||
height: 1em;
|
||||
|
||||
&:hover {
|
||||
cursor: nwse-resize;
|
||||
}
|
||||
|
||||
&::before {
|
||||
content: '';
|
||||
display: flex;
|
||||
background-color: darkslategrey;
|
||||
width: 10px;
|
||||
height: 1px;
|
||||
}
|
||||
|
||||
&::after {
|
||||
content: '';
|
||||
display: flex;
|
||||
position: relative;
|
||||
right: -3px;
|
||||
bottom: -2px;
|
||||
background-color: darkslategrey;
|
||||
width: 4px;
|
||||
height: 1px;
|
||||
}
|
||||
}
|
||||
|
||||
&.textarea-field--with-label {
|
||||
height: $textarea-with-label-medium-height;
|
||||
padding-top: $textarea-with-label-text-margin-top;
|
||||
|
||||
&.textarea-field--floated .textarea-field__label {
|
||||
top: $textarea-medium-label-floated-margin-top;
|
||||
line-height: $textarea-small-label-floated-font-line-height;
|
||||
font-size: $textarea-small-label-floated-font-size;
|
||||
}
|
||||
|
||||
&.textarea-field--small {
|
||||
height: $textarea-with-label-small-height;
|
||||
padding-top: $textarea-small-label-margin-top;
|
||||
top: $textarea-small-label-floated-margin-top;
|
||||
|
||||
& .textarea-field__label {
|
||||
font-size: $textarea-small-label-font-size;
|
||||
font-weight: $textarea-small-label-font-weight;
|
||||
letter-spacing: $textarea-small-label-font-letter-spacing;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.textarea-field--focused {
|
||||
border-color: formfield.$formfield-border-color-focus;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
&.textarea-field--small {
|
||||
padding-top: $textarea-without-label-small-text-margin-top;
|
||||
height: $textarea-without-label-small-height;
|
||||
|
||||
& textarea {
|
||||
height: $textarea-small-text-height;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,70 +0,0 @@
|
||||
@use '@beeline/design-tokens/scss/tokens/components/textfield' as *;
|
||||
@use '@beeline/design-tokens/scss/tokens/globals';
|
||||
@use '@beeline/design-tokens/scss/tokens/themes' as theme;
|
||||
|
||||
.textfield {
|
||||
display: block;
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: globals.$size-control-height-medium;
|
||||
border: globals.$size-border-width-regular solid transparent;
|
||||
padding-top: $textfield-without-label-medium-text-margin-vertical;
|
||||
padding-bottom: $textfield-without-label-medium-text-margin-vertical;
|
||||
background-color: theme.$color-control-background;
|
||||
border-radius: 12px; // globals.$size-border-radius-x6;
|
||||
|
||||
&:hover {
|
||||
background-color: theme.$color-control-background-hover;
|
||||
}
|
||||
|
||||
// input
|
||||
input {
|
||||
outline: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
// label
|
||||
&--with-label {
|
||||
// padding-top: $textfield-with-label-medium-text-margin-top;
|
||||
// padding-bottom: $textfield-with-label-medium-text-margin-bottom;
|
||||
}
|
||||
|
||||
&__label {
|
||||
// padding-top: $textfield-medium-label-margin-top;
|
||||
|
||||
&.textfield__label--floated {
|
||||
// padding-top: $textfield-medium-label-margin-top-floated;
|
||||
}
|
||||
}
|
||||
|
||||
// small
|
||||
&--small {
|
||||
height: globals.$size-control-height-small;
|
||||
}
|
||||
|
||||
// large
|
||||
&--large {
|
||||
height: globals.$size-control-height-large;
|
||||
padding-top: $textfield-without-label-large-text-margin-vertical;
|
||||
padding-bottom: $textfield-without-label-large-text-margin-vertical;
|
||||
|
||||
&.textfield--with-label {
|
||||
padding-top: $textfield-with-label-large-text-margin-top;
|
||||
padding-bottom: $textfield-with-label-large-text-margin-bottom;
|
||||
}
|
||||
|
||||
.textfield__label {
|
||||
padding-top: $textfield-large-label-margin-top;
|
||||
|
||||
&.textfield__label--floated {
|
||||
padding-top: $textfield-large-label-margin-top-floated;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// states
|
||||
&--focused {
|
||||
border-color: theme.$color-border-focus;
|
||||
background-color: theme.$color-background-base;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
@use '@beeline/design-tokens/scss/tokens/themes' as *;
|
||||
|
||||
.app-bg-status-error {
|
||||
background-color: $color-status-error-background;
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
.app-cursor-pointer {
|
||||
cursor: pointer;
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
@import 'text';
|
||||
@import 'color';
|
||||
@import 'media';
|
||||
@import 'common';
|
||||
@@ -1,80 +0,0 @@
|
||||
@use '@beeline/design-tokens/scss/tokens/themes' as theme;
|
||||
@use 'src/assets/scss/app/mixins' as mixins;
|
||||
|
||||
@mixin truncate {
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
@mixin truncate-lines($lines: 2) {
|
||||
display: -webkit-box;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-line-clamp: $lines;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.app-text-active {
|
||||
color: theme.$color-text-active;
|
||||
}
|
||||
|
||||
.app-text-inactive {
|
||||
color: theme.$color-text-inactive;
|
||||
}
|
||||
|
||||
// styles for hyperlinks
|
||||
.app-link {
|
||||
color: theme.$color-text-active;
|
||||
|
||||
&:hover {
|
||||
color: theme.$color-text-active;
|
||||
}
|
||||
}
|
||||
|
||||
.app-text-caption {
|
||||
@include mixins.text-caption;
|
||||
}
|
||||
|
||||
.app-text-truncate {
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
// Sizes
|
||||
.app-text-size-subtitle-3 {
|
||||
font-size: 15px;
|
||||
line-height: 20px;
|
||||
font-weight: 500;
|
||||
letter-spacing: 0.2px;
|
||||
}
|
||||
|
||||
.app-text-size-body-3 {
|
||||
font-size: 15px;
|
||||
line-height: 18px;
|
||||
letter-spacing: 0.2px;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
// Colors
|
||||
.app-text-color-caption {
|
||||
color: theme.$color-text-inactive;
|
||||
}
|
||||
.app-text-warning {
|
||||
color: theme.$color-status-warning;
|
||||
}
|
||||
.app-text-info {
|
||||
color: theme.$color-status-info;
|
||||
}
|
||||
.app-text-error {
|
||||
color: theme.$color-status-error;
|
||||
}
|
||||
.app-text-success {
|
||||
color: theme.$color-status-success;
|
||||
}
|
||||
|
||||
// Breaks
|
||||
.app-break-keep-all {
|
||||
word-break: keep-all;
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
@import 'spinner';
|
||||
@@ -1,6 +0,0 @@
|
||||
@use 'src/assets/scss/app/variables' as v;
|
||||
|
||||
.app-loading-screen {
|
||||
display: block;
|
||||
height: calc(100vh - v.$app-header-height);
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
@forward 'text';
|
||||