diff --git a/.flake8 b/.flake8 deleted file mode 100644 index 7f0a5e6..0000000 --- a/.flake8 +++ /dev/null @@ -1,23 +0,0 @@ -[flake8] -max-line-length=88 -count=True -show-source=False -statistics=True -exclude=.git, __pycache__, hyperglass/api/examples/*.py, hyperglass/compat/_sshtunnel.py, test.py -filename=*.py -per-file-ignores= - hyperglass/main.py:E402 - # Disable classmethod warning for validator decorators - hyperglass/models/*.py:N805,E0213,R0903,E501,C0301 - hyperglass/models/api/*.py:N805,E0213,R0903,E501,C0301 - hyperglass/models/commands/*.py:N805,E0213,R0903,E501,C0301 - hyperglass/parsing/models/*.py:N805,E0213,R0903 - hyperglass/configuration/models/*.py:N805,E0213,R0903,E501,C0301 - # Disable unused import warning for modules - hyperglass/*/__init__.py:F401 - hyperglass/models/*/__init__.py:F401 -ignore=W503,C0330,R504,D202,S403,S301,S404 -select=B, BLK, C, D, E, F, I, II, N, P, PIE, S, R, W -disable-noqa=False -hang-closing=False -max-complexity=10 diff --git a/.github/workflows/backend.yml b/.github/workflows/backend.yml deleted file mode 100644 index 861ea83..0000000 --- a/.github/workflows/backend.yml +++ /dev/null @@ -1,48 +0,0 @@ -name: Backend Testing -on: [push, pull_request] - -jobs: - backend: - name: Backend Tests - strategy: - fail-fast: false - matrix: - node-version: [14.x] - redis-version: [5, 6] - poetry-version: [1.1.4] - python-version: [3.6, 3.8] - os: [ubuntu-20.04] - runs-on: ${{ matrix.os }} - - steps: - - name: Git Checkout - uses: actions/checkout@v2 - - - name: Install Python - uses: actions/setup-python@v2 - with: - python-version: ${{ matrix.python-version }} - - - name: Install Poetry - uses: abatilo/actions-poetry@v2.0.0 - with: - poetry-version: ${{ matrix.poetry-version }} - - - name: Install Node - uses: actions/setup-node@v1 - with: - node-version: ${{ matrix.node-version }} - - - name: Start Redis - uses: supercharge/redis-github-action@1.1.0 - with: - redis-version: ${{ matrix.redis-version }} - - - name: Install Python Dependencies - run: poetry install - - - name: Run Flake8 - run: poetry run flake8 hyperglass - - - name: Run hyperglass - run: '.tests/ga-backend-app.sh' diff --git a/.github/workflows/frontend.yml b/.github/workflows/frontend.yml deleted file mode 100644 index d727ba7..0000000 --- a/.github/workflows/frontend.yml +++ /dev/null @@ -1,35 +0,0 @@ -name: Frontend Testing -on: [push, pull_request] - -jobs: - frontend: - name: Frontend Tests - strategy: - fail-fast: false - matrix: - node-version: [14.x] - os: [ubuntu-20.04] - runs-on: ${{ matrix.os }} - env: - working-directory: ./hyperglass/ui - steps: - - name: Git Checkout - uses: actions/checkout@v2 - - - name: Install Node - uses: actions/setup-node@v2 - with: - node-version: ${{ matrix.node-version }} - - - name: Install Dependencies - working-directory: ${{ env.working-directory }} - run: yarn install - - - name: TypeScript - run: ./.tests/pre-commit-frontend.sh --typescript - - - name: ESLint - run: ./.tests/pre-commit-frontend.sh --eslint - - - name: Prettier - run: ./.tests/pre-commit-frontend.sh --prettier diff --git a/.github/workflows/installer.yml b/.github/workflows/installer.yml deleted file mode 100644 index 2ed684e..0000000 --- a/.github/workflows/installer.yml +++ /dev/null @@ -1,18 +0,0 @@ -name: Installer Testing -on: [push, pull_request] - -jobs: - installer: - name: Installer Tests - strategy: - fail-fast: false - matrix: - os: [ubuntu-20.04] - runs-on: ${{ matrix.os }} - - steps: - - name: Git Checkout - uses: actions/checkout@v2 - - - name: Run hyperglass - run: "sudo bash ./install.sh" diff --git a/.github/workflows/release-pypi.yml b/.github/workflows/release-pypi.yml deleted file mode 100644 index d82381b..0000000 --- a/.github/workflows/release-pypi.yml +++ /dev/null @@ -1,37 +0,0 @@ -name: Release to PyPI -on: - release: - types: [published] - -jobs: - release: - name: Release to PyPI - strategy: - fail-fast: false - matrix: - python-version: [3.6] - poetry-version: [1.1.4] - os: [ubuntu-latest] - runs-on: ubuntu-latest - - steps: - - name: Git Checkout - uses: actions/checkout@v2 - - - name: Install Python - uses: actions/setup-python@v2 - with: - python-version: ${{ matrix.python-version }} - - - name: Install Poetry - uses: abatilo/actions-poetry@v2.0.0 - with: - poetry-version: ${{ matrix.poetry-version }} - - - name: Build hyperglass - run: | - poetry config pypi-token.pypi ${{ secrets.PYPI_API_TOKEN }} - poetry build - - - name: Publish hyperglass release - run: poetry publish diff --git a/.isort.cfg b/.isort.cfg deleted file mode 100644 index 536022e..0000000 --- a/.isort.cfg +++ /dev/null @@ -1,14 +0,0 @@ -[settings] -skip_glob = hyperglass/api/examples/*.py -line_length = 88 -indent = ' ' -include_trailing_comma = True -multi_line_output = 3 -balanced_wrapping = True -length_sort = True -force_single_line = False -import_heading_stdlib = Standard Library -import_heading_thirdparty = Third Party -import_heading_firstparty = Project -import_heading_localfolder = Local -known_third_party = starlette,fastapi,inquirer \ No newline at end of file diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml deleted file mode 100644 index 3891142..0000000 --- a/.pre-commit-config.yaml +++ /dev/null @@ -1,37 +0,0 @@ -repos: - - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v2.3.0 - hooks: - - id: flake8 - stages: - - commit - - repo: local - hooks: - - id: typescript - name: TypeScript - files: 'hyperglass/ui/*' - exclude: 'hyperglass/ui/node_modules|hyperglass/ui/.next' - stages: - - commit - entry: ./.tests/pre-commit-frontend.sh --typescript - language: script - - repo: local - hooks: - - id: eslint - name: ESLint - files: 'hyperglass/ui/*' - exclude: 'hyperglass/ui/node_modules|hyperglass/ui/.next' - stages: - - commit - entry: ./.tests/pre-commit-frontend.sh --eslint - language: script - - repo: local - hooks: - - id: prettier - name: Prettier - files: 'hyperglass/ui/*' - exclude: 'hyperglass/ui/node_modules|hyperglass/ui/.next' - stages: - - commit - entry: ./.tests/pre-commit-frontend.sh --prettier - language: script diff --git a/.tests/app/setup.sh b/.tests/app/setup.sh deleted file mode 100755 index 4f4cc87..0000000 --- a/.tests/app/setup.sh +++ /dev/null @@ -1,52 +0,0 @@ -#!/usr/bin/env bash - -echo "[INFO] Starting Redis..." -redis-server & - -cd /tmp/hyperglass - -echo "[INFO] Starting setup..." -poetry run hyperglass setup -d -echo "[SUCCESS] Setup completed." -sleep 2 - -echo "listen_address: 127.0.0.1" >> /root/hyperglass/hyperglass.yaml - -echo "[INFO] Starting UI build." -poetry run hyperglass build-ui - -if [[ ! $? == 0 ]]; then - echo "[ERROR] Failed to start hyperglass." - exit 1 -else - echo "[SUCCESS] UI build completed." -fi - -echo "[INFO] Starting hyperglass..." -poetry run hyperglass start &> /var/log/hyperglassci.log & -sleep 180 - -if [[ ! $? == 0 ]]; then - echo "[ERROR] Failed to start hyperglass." - exit 1 -else - echo "[SUCCESS] Started hyperglass." -fi - -echo "[INFO] Running HTTP test..." - -STATUS=$(curl -s -o /dev/null -w "%{http_code}" http://127.0.0.1:8001) - -echo "[INFO] Status code: $STATUS" - -if [[ ! $? == 0 ]]; then - echo "[ERROR] HTTP test failed." - exit 1 -elif [[ ! "$STATUS" == "200" ]]; then - echo "[ERROR] HTTP test failed. Startup log:" - cat /var/log/hyperglassci.log - exit 1 -fi - -echo "[SUCCESS] Tests ran successfully." -exit 0 \ No newline at end of file diff --git a/.tests/app/ubuntu/Dockerfile b/.tests/app/ubuntu/Dockerfile deleted file mode 100644 index 73bd15e..0000000 --- a/.tests/app/ubuntu/Dockerfile +++ /dev/null @@ -1,31 +0,0 @@ -FROM ubuntu:bionic as base -ENV LC_ALL=C.UTF-8 -ENV LANG=C.UTF-8 -WORKDIR /tmp -RUN apt-get update \ - && apt-get install -y git curl net-tools \ - && curl -sL https://deb.nodesource.com/setup_14.x | bash - \ - && curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - \ - && echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list \ - && apt-get update \ - && apt-get install -y python3 python3-pip python3-venv redis-server nodejs yarn \ - # && curl -sSL https://raw.githubusercontent.com/python-poetry/poetry/master/get-poetry.py | python3 \ - # - # Pinning Poetry installer to this specific version. As of 2020 07 24, the script from master - # fails to install due to Python 2's executable matching first. See #2106 - # - && curl -sSL https://raw.githubusercontent.com/python-poetry/poetry/e70ee3112ab06374dfef4ab84e6dded2382cc7dd/get-poetry.py | python3 \ - && python3 --version \ - && echo "NodeJS $(node --version)" \ - && echo "Yarn $(yarn --version)" -COPY ./ /tmp/hyperglass -ENV PATH=$PATH:/root/.poetry/bin - -FROM base as install -WORKDIR /tmp/hyperglass -RUN poetry install --no-ansi - -FROM install as setup -WORKDIR /tmp/hyperglass -COPY .tests/app/setup.sh /tmp/setup.sh -RUN ls -lsah /tmp \ No newline at end of file diff --git a/.tests/ga-backend-app.sh b/.tests/ga-backend-app.sh deleted file mode 100755 index 5bea96f..0000000 --- a/.tests/ga-backend-app.sh +++ /dev/null @@ -1,61 +0,0 @@ -#!/usr/bin/env bash - -LOG_FILE="$HOME/hyperglass-ci.log" - -export POETRY_HYPERGLASS_UI_BUILD_TIMEOUT="600" -echo "[INFO] Set build timeout to $POETRY_HYPERGLASS_UI_BUILD_TIMEOUT seconds" - -echo "[INFO] Starting setup..." -poetry run hyperglass setup -d &> $LOG_FILE -echo "[SUCCESS] Setup completed." -sleep 2 - -echo "[INFO] Copying devices.yaml file..." -cp ./hyperglass/examples/devices.yaml $HOME/hyperglass/devices.yaml - -echo "[INFO] Setting listen_address..." -echo "listen_address: 127.0.0.1" >> $HOME/hyperglass/hyperglass.yaml - -echo "[INFO] Starting UI build." -poetry run hyperglass build-ui &> $LOG_FILE - -if [[ ! $? == 0 ]]; then - echo "[ERROR] Failed to build hyperglass ui." - cat /tmp/hyperglass.log - cat $LOG_FILE - exit 1 -else - echo "[SUCCESS] UI build completed." -fi - -echo "[INFO] Starting hyperglass..." -poetry run hyperglass start &> $LOG_FILE & -sleep 120 - -if [[ ! $? == 0 ]]; then - echo "[ERROR] Failed to start hyperglass." - cat /tmp/hyperglass.log - cat $LOG_FILE - exit 1 -else - echo "[SUCCESS] Started hyperglass." -fi - -echo "[INFO] Running HTTP test..." - -STATUS=$(curl -s -o /dev/null -w "%{http_code}" http://127.0.0.1:8001) - -echo "[INFO] Status code: $STATUS" - -if [[ ! $? == 0 ]]; then - echo "[ERROR] HTTP test failed." - exit 1 -elif [[ ! "$STATUS" == "200" ]]; then - echo "[ERROR] HTTP test failed." - cat /tmp/hyperglass.log - cat $LOG_FILE - exit 1 -fi - -echo "[SUCCESS] Tests ran successfully." -exit 0 diff --git a/.tests/install/ubuntu/Dockerfile b/.tests/install/ubuntu/Dockerfile deleted file mode 100644 index 2afb057..0000000 --- a/.tests/install/ubuntu/Dockerfile +++ /dev/null @@ -1,5 +0,0 @@ -FROM ubuntu:bionic as base -WORKDIR /tmp -COPY .tests/install/ubuntu/setup.sh /tmp/init.sh -COPY ./install.sh /tmp/install.sh -RUN bash /tmp/init.sh \ No newline at end of file diff --git a/.tests/install/ubuntu/setup.sh b/.tests/install/ubuntu/setup.sh deleted file mode 100755 index 23b9fbe..0000000 --- a/.tests/install/ubuntu/setup.sh +++ /dev/null @@ -1,17 +0,0 @@ -#!/usr/bin/env bash - -echo "[INFO] Disabling multiverse repos..." -sed -i -e '/multiverse/s/^#*/#\ /g' /etc/apt/sources.list -cat /etc/apt/sources.list - -echo "[INFO] Updating package repos..." -apt-get update &> /dev/null - -echo "[INFO] Installing apt-utils..." -apt-get install -y apt-utils > /dev/null - -echo "[INFO] Installing base dependencies..." -apt-get install -y curl git gnupg dialog build-essential > /dev/null - -echo '[SUCCESS] Completed build' -exit 0 \ No newline at end of file diff --git a/.tests/pre-commit-frontend.sh b/.tests/pre-commit-frontend.sh deleted file mode 100755 index e23a434..0000000 --- a/.tests/pre-commit-frontend.sh +++ /dev/null @@ -1,38 +0,0 @@ -#!/usr/bin/env bash - -UI_DIR="$(pwd)/hyperglass/ui" - -check_typescript () { - cd $UI_DIR - node_modules/.bin/tsc --noEmit -} - -check_eslint () { - cd $UI_DIR - node_modules/.bin/eslint . --ext .ts --ext .tsx -} - -check_prettier () { - cd $UI_DIR - node_modules/.bin/prettier -c . -} - -for arg in "$@" -do - if [ "$arg" == "--typescript" ] - then - check_typescript - exit $? - elif [ "$arg" == "--eslint" ] - then - check_eslint - exit $? - elif [ "$arg" == "--prettier" ] - then - check_prettier - exit $? - else - echo "Arguments --typescript, --eslint, or --prettier required." - exit 1 - fi -done diff --git a/cmd/cmd.go b/cmd/cmd.go new file mode 100644 index 0000000..ef7a313 --- /dev/null +++ b/cmd/cmd.go @@ -0,0 +1,47 @@ +package cmd + +import ( + "github.com/k0kubun/pp/v3" + "github.com/spf13/cobra" + "github.com/thatmattlove/hyperglass/core/api" + "github.com/thatmattlove/hyperglass/core/infrastructure/database" + "github.com/thatmattlove/hyperglass/core/migrations" + "github.com/thatmattlove/hyperglass/core/system" +) + +func start(cmd *cobra.Command, args []string) { + cobra.CheckErr(api.Start()) +} + +func settings(cmd *cobra.Command, args []string) { + db, err := database.New() + cobra.CheckErr(err) + settings := db.Settings() + pp.Print(settings) +} + +func initializeCmd() { + err := system.InitializeDirs() + cobra.CheckErr(err) + err = migrations.AutoMigrate() + cobra.CheckErr(err) +} + +func Main() error { + initializeCmd() + root := &cobra.Command{ + Use: "hyperglass", + Short: "hyperglass is the network looking glass that tries to make the internet better.", + } + root.AddCommand(&cobra.Command{ + Use: "start", + Short: "Start hyperglass", + Run: start, + }) + root.AddCommand(&cobra.Command{ + Use: "settings", + Short: "Show hyperglass settings", + Run: settings, + }) + return root.Execute() +} diff --git a/core/api/api.go b/core/api/api.go new file mode 100644 index 0000000..53d13c5 --- /dev/null +++ b/core/api/api.go @@ -0,0 +1,25 @@ +package api + +import ( + "fmt" + + "github.com/gofiber/fiber/v2" + "github.com/thatmattlove/hyperglass/core/controllers" + "github.com/thatmattlove/hyperglass/core/infrastructure/database" +) + +func Start() (err error) { + db, err := database.New() + if err != nil { + return + } + settings := db.Settings() + config := fiber.Config{ + ServerHeader: "hyperglass", + AppName: fmt.Sprintf("%s Looking Glass", settings.OrganizationName), + Network: "tcp", + } + app := fiber.New(config) + app.Post("/api/query", controllers.QueryController) + return app.Listen(":8080") +} diff --git a/core/connections/ssh/auth.go b/core/connections/ssh/auth.go new file mode 100644 index 0000000..cbc0165 --- /dev/null +++ b/core/connections/ssh/auth.go @@ -0,0 +1,63 @@ +package terminal + +import ( + "fmt" + + "github.com/melbahja/goph" +) + +type AuthMethod int + +const ( + AUTH_PASSWORD AuthMethod = 0 + AUTH_KEY AuthMethod = 1 +) + +type PasswordAuth struct { + Password string +} + +type KeyAuth struct { + Key string + KeyPassword string +} + +type AuthOptions struct { + Method AuthMethod + Username string + Password string + Key string + KeyPassword string +} + +func (a *PasswordAuth) Backend() (*goph.Auth, error) { + auth := goph.Password(a.Password) + return &auth, nil +} + +func (a *KeyAuth) Backend() (*goph.Auth, error) { + auth, err := goph.Key(a.Key, a.KeyPassword) + return &auth, err +} + +type Auth interface { + Backend() (*goph.Auth, error) +} + +func NewSSHAuth(opts *AuthOptions) (Auth, error) { + switch opts.Method { + case AUTH_PASSWORD: + auth := &PasswordAuth{ + Password: opts.Password, + } + return auth, nil + case AUTH_KEY: + auth := &KeyAuth{ + Key: opts.Key, + KeyPassword: opts.KeyPassword, + } + return auth, nil + default: + return nil, fmt.Errorf("unsupported SSH auth method '%d'", opts.Method) + } +} diff --git a/core/connections/ssh/ssh.go b/core/connections/ssh/ssh.go new file mode 100644 index 0000000..8d188fb --- /dev/null +++ b/core/connections/ssh/ssh.go @@ -0,0 +1,80 @@ +package terminal + +import ( + "log" + "time" + + "github.com/melbahja/goph" + "golang.org/x/crypto/ssh" +) + +type Connection struct { + Auth *Auth + Address string + Port uint + Client *goph.Client +} + +type ConnectionOptions struct { + Method AuthMethod + Address string + Port uint + Username string + Password string + Key string + KeyPassword string + Timeout time.Duration +} + +func (conn *Connection) Run(cmd string) (res string, err error) { + defer conn.Client.Close() + b, err := conn.Client.Run(cmd) + if err != nil { + return + } + res = string(b) + return +} + +func NewConnection(opts *ConnectionOptions) (*Connection, error) { + sshAuth, err := NewSSHAuth(&AuthOptions{ + Method: opts.Method, + Username: opts.Username, + Password: opts.Password, + Key: opts.Key, + KeyPassword: opts.KeyPassword, + }) + if err != nil { + return nil, err + } + + auth, err := sshAuth.Backend() + if err != nil { + return nil, err + } + cfg := &goph.Config{ + Auth: *auth, + Addr: opts.Address, + Port: opts.Port, + User: opts.Username, + Timeout: opts.Timeout, + BannerCallback: func(msg string) error { + log.Println(msg) + return nil + }, + Callback: ssh.InsecureIgnoreHostKey(), + } + + client, err := goph.NewConn(cfg) + if err != nil { + return nil, err + } + + connection := &Connection{ + Auth: &sshAuth, + Address: opts.Address, + Port: opts.Port, + Client: client, + } + return connection, nil +} diff --git a/core/controllers/query.go b/core/controllers/query.go new file mode 100644 index 0000000..98ed6d2 --- /dev/null +++ b/core/controllers/query.go @@ -0,0 +1,30 @@ +package controllers + +import ( + "github.com/go-playground/validator/v10" + "github.com/gofiber/fiber/v2" + "github.com/thatmattlove/hyperglass/core/entities" + "github.com/thatmattlove/hyperglass/core/interfaces" +) + +func QueryController(ctx *fiber.Ctx) error { + var query *entities.QueryRequest + err := ctx.BodyParser(&query) + if err != nil { + return err + } + validate := validator.New() + err = validate.Struct(query) + if err != nil { + return err + } + iface, err := interfaces.NewQueryInterface(ctx, query) + if err != nil { + return err + } + res, err := iface.Query() + if err != nil { + return err + } + return ctx.Status(200).JSON(res) +} diff --git a/core/entities/query.go b/core/entities/query.go new file mode 100644 index 0000000..520c82f --- /dev/null +++ b/core/entities/query.go @@ -0,0 +1,18 @@ +package entities + +import "time" + +type QueryRequest struct { + Devices []uint `json:"devices" validate:"min=1"` + Target string `json:"target" validate:"cidr|ip"` + Type string `json:"type" validate:"required"` +} + +type PlainQueryResponse struct { + Random string `json:"random" validate:"required"` + Cached bool `json:"cached" validate:"boolean"` + Runtime float64 `json:"runtime" validate:"required"` + Timestamp time.Time `json:"timestamp" validate:"required"` + Format string `json:"format" validate:"oneof=application/json text/plain"` + Output string `json:"output" validate:"required"` +} diff --git a/core/infrastructure/cache/cache.go b/core/infrastructure/cache/cache.go new file mode 100644 index 0000000..ca88977 --- /dev/null +++ b/core/infrastructure/cache/cache.go @@ -0,0 +1,87 @@ +package cache + +import ( + "os" + "path" + + "go.etcd.io/bbolt" +) + +type Cache struct { + File *os.File + Backend *bbolt.DB + Bucket []byte +} + +func (c *Cache) Get(key string) (value string, err error) { + err = c.Transaction(func(db *bbolt.DB) error { + err = db.View(func(tx *bbolt.Tx) error { + b := tx.Bucket(c.Bucket) + v := b.Get([]byte(key)) + value = string(v) + return nil + }) + return err + }) + return +} + +func (c *Cache) Set(key, value string) (err error) { + return c.Transaction(func(db *bbolt.DB) error { + return db.Update(func(tx *bbolt.Tx) error { + b := tx.Bucket(c.Bucket) + return b.Put([]byte(key), []byte(value)) + }) + }) +} + +func (c *Cache) Transaction(cb func(db *bbolt.DB) error) (err error) { + db, err := bbolt.Open(c.File.Name(), 0666, nil) + if err != nil { + return + } + + defer db.Close() + defer c.File.Close() + return cb(db) +} + +func (c *Cache) Destroy(name string) (err error) { + err = c.Backend.Close() + if err != nil { + return + } + err = os.Remove(c.File.Name()) + return +} + +func New(name string) (c *Cache, err error) { + cacheDir, err := os.MkdirTemp("", "hyperglass-cache-*") + if err != nil { + return + } + cacheFile, err := os.Create(path.Join(cacheDir, "hyperglass.cache")) + if err != nil { + return + } + db, err := bbolt.Open(cacheFile.Name(), 0666, nil) + if err != nil { + return + } + defer db.Close() + defer cacheFile.Close() + bucket := []byte(name) + err = db.Update(func(tx *bbolt.Tx) (err error) { + _, err = tx.CreateBucket(bucket) + return + }) + if err != nil { + return + } + c = &Cache{ + Backend: db, + File: cacheFile, + Bucket: bucket, + } + return +} diff --git a/core/infrastructure/cache/cache_test.go b/core/infrastructure/cache/cache_test.go new file mode 100644 index 0000000..9faa966 --- /dev/null +++ b/core/infrastructure/cache/cache_test.go @@ -0,0 +1,28 @@ +package cache_test + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/thatmattlove/hyperglass/core/infrastructure/cache" +) + +func Test_Cache(t *testing.T) { + name := "test" + c, err := cache.New(name) + assert.NoError(t, err) + + t.Run("get/set values", func(t *testing.T) { + key := "test-key" + value := "test-value" + err := c.Set(key, value) + assert.NoError(t, err) + valueC, err := c.Get(key) + assert.NoError(t, err) + assert.Equal(t, value, valueC) + }) + t.Cleanup(func() { + err := c.Destroy(name) + assert.NoError(t, err) + }) +} diff --git a/core/infrastructure/database/database.go b/core/infrastructure/database/database.go new file mode 100644 index 0000000..b2967ea --- /dev/null +++ b/core/infrastructure/database/database.go @@ -0,0 +1,43 @@ +package database + +import ( + "os" + "path" + + "github.com/thatmattlove/hyperglass/core/models/settings" + "github.com/thatmattlove/hyperglass/core/system" + "gorm.io/driver/sqlite" + "gorm.io/gorm" +) + +type IDB struct { + File string + DB *gorm.DB +} + +func (idb *IDB) Settings() (settings *settings.Settings) { + idb.DB.Limit(1).Find(&settings) + return +} + +func New() (idb *IDB, err error) { + appDir, err := system.GetAppDir() + if err != nil { + return + } + dbFile := path.Join(appDir, "hyperglass.db") + if _, err = os.Stat(dbFile); os.IsNotExist(err) { + _, err = os.Create(dbFile) + if err != nil { + return + } + } + db, err := gorm.Open(sqlite.Open(dbFile), &gorm.Config{ + DisableForeignKeyConstraintWhenMigrating: true, + }) + idb = &IDB{ + File: dbFile, + DB: db, + } + return +} diff --git a/core/interfaces/query.go b/core/interfaces/query.go new file mode 100644 index 0000000..898c87f --- /dev/null +++ b/core/interfaces/query.go @@ -0,0 +1,36 @@ +package interfaces + +import ( + "time" + + "github.com/go-playground/validator/v10" + "github.com/gofiber/fiber/v2" + "github.com/thatmattlove/hyperglass/core/entities" +) + +type QueryInterface struct { + Ctx *fiber.Ctx + Request *entities.QueryRequest +} + +func (qi *QueryInterface) Query() (res any, err error) { + res = &entities.PlainQueryResponse{ + Random: "random string", + Cached: false, + Runtime: 30, + Timestamp: time.Now(), + Format: "text/plain", + Output: "some output", + } + validate := validator.New() + err = validate.Struct(res) + return +} + +func NewQueryInterface(ctx *fiber.Ctx, req *entities.QueryRequest) (iface *QueryInterface, err error) { + iface = &QueryInterface{ + Ctx: ctx, + Request: req, + } + return +} diff --git a/core/migrations/auto.go b/core/migrations/auto.go new file mode 100644 index 0000000..4edcc83 --- /dev/null +++ b/core/migrations/auto.go @@ -0,0 +1,39 @@ +package migrations + +import ( + "errors" + + "github.com/thatmattlove/hyperglass/core/infrastructure/database" + "github.com/thatmattlove/hyperglass/core/models" + "github.com/thatmattlove/hyperglass/core/models/settings" + "gorm.io/gorm" +) + +func AutoMigrate() (err error) { + db, err := database.New() + if err != nil { + return + } + err = db.DB.AutoMigrate( + settings.Logging{}, + settings.Message{}, + models.Group{}, + models.Credential{}, + models.Device{}, + models.Proxy{}, + ) + if err != nil { + return + } + if err = db.DB.AutoMigrate(&settings.Settings{}); err == nil && db.DB.Migrator().HasTable(&settings.Settings{}) { + if err := db.DB.First(&settings.Settings{}).Error; errors.Is(err, gorm.ErrRecordNotFound) { + s, err := settings.Seed() + if err != nil { + return err + } + tx := db.DB.Create(s) + return tx.Error + } + } + return +} diff --git a/core/models/common.go b/core/models/common.go new file mode 100644 index 0000000..11be6b8 --- /dev/null +++ b/core/models/common.go @@ -0,0 +1,11 @@ +package models + +import "gorm.io/gorm" + +type Model struct { + // ID uuid.UUID `gorm:"primaryKey; unique; type:uuid; column:id; default:uuid_generate_v4()"` + // CreatedAt time.Time + // UpdatedAt time.Time + // DeletedAt *time.Time `sql:"index"` + gorm.Model +} diff --git a/core/models/credential.go b/core/models/credential.go new file mode 100644 index 0000000..f9516dd --- /dev/null +++ b/core/models/credential.go @@ -0,0 +1,15 @@ +package models + +import ( + "database/sql" +) + +type Credential struct { + Model + Username string + Mode uint `gorm:"default:1"` + Password sql.NullString + Key sql.NullString + Devices []Device + Proxies []Proxy +} diff --git a/core/models/device.go b/core/models/device.go new file mode 100644 index 0000000..9d51c7c --- /dev/null +++ b/core/models/device.go @@ -0,0 +1,20 @@ +package models + +import ( + "github.com/google/uuid" +) + +type Device struct { + Model + Name string + Description string + Address string + Port uint + Platform string + GroupID uuid.UUID + Group Group + CredentialID uuid.UUID + Credential Credential + ProxyID *uuid.UUID + Proxy *Proxy +} diff --git a/core/models/group.go b/core/models/group.go new file mode 100644 index 0000000..0c3b324 --- /dev/null +++ b/core/models/group.go @@ -0,0 +1,7 @@ +package models + +type Group struct { + Model + Name string + Devices []Device +} diff --git a/core/models/proxy.go b/core/models/proxy.go new file mode 100644 index 0000000..5108e87 --- /dev/null +++ b/core/models/proxy.go @@ -0,0 +1,18 @@ +package models + +import ( + "github.com/google/uuid" +) + +type Proxy struct { + Model + Name string + Address string + CredentialID uuid.UUID + Credential Credential + Devices []Device +} + +func (Proxy) TableName() string { + return "proxies" +} diff --git a/core/models/settings/logging.go b/core/models/settings/logging.go new file mode 100644 index 0000000..a4f97c2 --- /dev/null +++ b/core/models/settings/logging.go @@ -0,0 +1,44 @@ +package settings + +import ( + "database/sql" + + "code.cloudfoundry.org/bytefmt" + "github.com/thatmattlove/hyperglass/core/system" + "gorm.io/gorm" +) + +const ( + LOG_FORMAT_JSON string = "json" + LOG_FORMAT_TEXT string = "text" +) + +type Logging struct { + gorm.Model + Directory string + Format string + MaxSize uint64 + EnableSyslog sql.NullBool `gorm:"default:false"` + SyslogHost *string + SyslogPort *int + EnableHTTP sql.NullBool `gorm:"default:false"` + HTTPHost *string + SettingsID uint +} + +func SeedLogging() (logging Logging, err error) { + loggingDir, err := system.GetLogDir() + if err != nil { + return + } + defaultLogSize, err := bytefmt.ToBytes("50MB") + if err != nil { + return + } + logging = Logging{ + Directory: loggingDir, + Format: LOG_FORMAT_TEXT, + MaxSize: defaultLogSize, + } + return +} diff --git a/core/models/settings/messages.go b/core/models/settings/messages.go new file mode 100644 index 0000000..e4e7bd7 --- /dev/null +++ b/core/models/settings/messages.go @@ -0,0 +1,49 @@ +package settings + +import "gorm.io/gorm" + +type Message struct { + gorm.Model + Name string + Value string + SettingsID uint +} + +const ( + MESSAGE_MissingField string = "MissingField" + MESSAGE_TargetNotAllowed string = "TargetNotAllowed" + MESSAGE_FeatureNotEnabled string = "FeatureNotEnabled" + MESSAGE_InvalidInput string = "InvalidInput" + MESSAGE_InvalidField string = "InvalidField" + MESSAGE_UnknownError string = "UnknownError" + MESSAGE_RequestTimeout string = "RequestTimeout" + MESSAGE_ConnectionError string = "ConnectionError" + MESSAGE_AuthenticationError string = "AuthenticationError" + MESSAGE_ResponseParsingFailure string = "ResponseParsingFailure" + MESSAGE_EmptyResponse string = "EmptyResponse" +) + +var DefaultMessages map[string]string = map[string]string{ + MESSAGE_MissingField: "{.Value} must be specified.", + MESSAGE_TargetNotAllowed: "{.Value} is not allowed.", + MESSAGE_FeatureNotEnabled: "{.Value} is not enabled.", + MESSAGE_InvalidInput: "{.Value} is invalid.", + MESSAGE_InvalidField: "{.Value} is an invalid {.Type}", + MESSAGE_UnknownError: "Something went wrong.", + MESSAGE_RequestTimeout: "Request timed out.", + MESSAGE_ConnectionError: "Error connecting to {.Value}: {.Error}", + MESSAGE_AuthenticationError: "Error authenticating to {.Value}: {.Error}", + MESSAGE_ResponseParsingFailure: "Error reading response.", + MESSAGE_EmptyResponse: "The query completed, but no results were found.", +} + +func SeedMessages() (messages []Message) { + for n, v := range DefaultMessages { + msg := Message{ + Name: n, + Value: v, + } + messages = append(messages, msg) + } + return +} diff --git a/core/models/settings/settings.go b/core/models/settings/settings.go new file mode 100644 index 0000000..3965f04 --- /dev/null +++ b/core/models/settings/settings.go @@ -0,0 +1,25 @@ +package settings + +import "gorm.io/gorm" + +type Settings struct { + gorm.Model + RequestTimeout int `gorm:"default:90"` + OrganizationName string `gorm:"default:Beloved Hyperglass User"` + UITitle string `gorm:"default:hyperglass"` + UIDescription string `gorm:"Network Looking Glass"` + Messages []Message + Logging Logging +} + +func Seed() (settings *Settings, err error) { + logging, err := SeedLogging() + if err != nil { + return + } + settings = &Settings{ + Messages: SeedMessages(), + Logging: logging, + } + return +} diff --git a/core/system/dirs.go b/core/system/dirs.go new file mode 100644 index 0000000..1cf89ad --- /dev/null +++ b/core/system/dirs.go @@ -0,0 +1,77 @@ +package system + +import ( + "os" + "path" + "runtime" +) + +func GetLogDir() (loggingDir string, err error) { + loggingDir = "/var/log/hyperglass" + switch runtime.GOOS { + case "windows": + var userDir string + userDir, err = os.UserHomeDir() + if err != nil { + return + } + loggingDir = path.Join(userDir, "AppData", "Local", "hyperglass", "logs") + case "darwin": + var userDir string + userDir, err = os.UserHomeDir() + if err != nil { + return + } + loggingDir = path.Join(userDir, "Library", "Logs", "hyperglass") + } + return +} + +func GetAppDir() (appDir string, err error) { + appDir = "/etc/hyperglass" + configDir, err := os.UserConfigDir() + if err != nil { + return + } + switch runtime.GOOS { + case "windows": + appDir = path.Join(configDir, "hyperglass") + case "darwin": + appDir = path.Join(configDir, "hyperglass") + } + return +} + +func InitializeDirs() (err error) { + logDir, err := GetLogDir() + if err != nil { + return + } + appDir, err := GetAppDir() + if err != nil { + return + } + _, err = os.Stat(logDir) + if err != nil { + if os.IsNotExist(err) { + err = os.Mkdir(logDir, 0755) + if err != nil { + return + } + return + } + return + } + _, err = os.Stat(appDir) + if err != nil { + if os.IsNotExist(err) { + err = os.Mkdir(appDir, 0755) + if err != nil { + return + } + return + } + return + } + return +} diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..b053d91 --- /dev/null +++ b/go.mod @@ -0,0 +1,52 @@ +module github.com/thatmattlove/hyperglass + +go 1.20 + +require ( + code.cloudfoundry.org/bytefmt v0.0.0-20230612151507-41ef4d1f67a4 + github.com/go-playground/validator/v10 v10.14.1 + github.com/gofiber/fiber/v2 v2.48.0 + github.com/google/uuid v1.3.0 + github.com/k0kubun/pp/v3 v3.2.0 + github.com/spf13/cobra v1.7.0 + github.com/stretchr/testify v1.8.3 + github.com/twitchtv/twirp v8.1.3+incompatible + go.etcd.io/bbolt v1.3.7 + google.golang.org/protobuf v1.26.0 + gorm.io/driver/sqlite v1.5.2 + gorm.io/gorm v1.25.2 +) + +require ( + github.com/andybalholm/brotli v1.0.5 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/gabriel-vasile/mimetype v1.4.2 // indirect + github.com/go-playground/locales v0.14.1 // indirect + github.com/go-playground/universal-translator v0.18.1 // indirect + github.com/inconshreveable/mousetrap v1.1.0 // indirect + github.com/jinzhu/inflection v1.0.0 // indirect + github.com/jinzhu/now v1.1.5 // indirect + github.com/klauspost/compress v1.16.3 // indirect + github.com/kr/fs v0.1.0 // indirect + github.com/kr/pretty v0.3.1 // indirect + github.com/leodido/go-urn v1.2.4 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.19 // indirect + github.com/mattn/go-runewidth v0.0.14 // indirect + github.com/mattn/go-sqlite3 v1.14.17 // indirect + github.com/melbahja/goph v1.3.1 // indirect + github.com/pkg/errors v0.9.1 // indirect + github.com/pkg/sftp v1.13.5 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/rivo/uniseg v0.2.0 // indirect + github.com/spf13/pflag v1.0.5 // indirect + github.com/valyala/bytebufferpool v1.0.0 // indirect + github.com/valyala/fasthttp v1.48.0 // indirect + github.com/valyala/tcplisten v1.0.0 // indirect + golang.org/x/crypto v0.7.0 // indirect + golang.org/x/net v0.10.0 // indirect + golang.org/x/sys v0.10.0 // indirect + golang.org/x/text v0.9.0 // indirect + gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..0bd8def --- /dev/null +++ b/go.sum @@ -0,0 +1,152 @@ +code.cloudfoundry.org/bytefmt v0.0.0-20230612151507-41ef4d1f67a4 h1:9G5F8zgma5v0GdDvNz6iZwwJp3RS/z0SY/aHGfVwvTo= +code.cloudfoundry.org/bytefmt v0.0.0-20230612151507-41ef4d1f67a4/go.mod h1:wYHCXH/gI19ujoFVuMkY48qPpPCoHLKBKXPkn67h/Yc= +github.com/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/cCs= +github.com/andybalholm/brotli v1.0.5/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= +github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU= +github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA= +github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0= +github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= +github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= +github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= +github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= +github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= +github.com/go-playground/validator/v10 v10.14.1 h1:9c50NUPC30zyuKprjL3vNZ0m5oG+jU0zvx4AqHGnv4k= +github.com/go-playground/validator/v10 v10.14.1/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU= +github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= +github.com/gofiber/fiber/v2 v2.48.0 h1:cRVMCb9aUJDsyHxGFLwz/sGzDggdailZZyptU9F9cU0= +github.com/gofiber/fiber/v2 v2.48.0/go.mod h1:xqJgfqrc23FJuqGOW6DVgi3HyZEm2Mn9pRqUb2kHSX8= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 h1:yAJXTCF9TqKcTiHJAE8dj7HMvPfh66eeA2JYW7eFpSE= +github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= +github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= +github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= +github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ= +github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= +github.com/k0kubun/pp/v3 v3.2.0 h1:h33hNTZ9nVFNP3u2Fsgz8JXiF5JINoZfFq4SvKJwNcs= +github.com/k0kubun/pp/v3 v3.2.0/go.mod h1:ODtJQbQcIRfAD3N+theGCV1m/CBxweERz2dapdz1EwA= +github.com/klauspost/compress v1.16.3 h1:XuJt9zzcnaz6a16/OU53ZjWp/v7/42WcR5t2a0PcNQY= +github.com/klauspost/compress v1.16.3/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= +github.com/kr/fs v0.1.0 h1:Jskdu9ieNAYnjxsi0LbQp1ulIKZV1LAFgK1tWhpZgl8= +github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q= +github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= +github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU= +github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/mattn/go-sqlite3 v1.14.17 h1:mCRHCLDUBXgpKAqIKsaAaAsrAlbkeomtRFKXh2L6YIM= +github.com/mattn/go-sqlite3 v1.14.17/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= +github.com/melbahja/goph v1.3.1 h1:FxFevAwCCpLkM4WBmnVVxcJBcBz6lKQpsN5biV2hA6w= +github.com/melbahja/goph v1.3.1/go.mod h1:uG+VfK2Dlhk+O32zFrRlc3kYKTlV6+BtvPWd/kK7U68= +github.com/onsi/ginkgo/v2 v2.9.2 h1:BA2GMJOtfGAfagzYtrAlufIP0lq6QERkFmHLMLPwFSU= +github.com/onsi/gomega v1.27.4 h1:Z2AnStgsdSayCMDiCU42qIz+HLqEPcgiOCXjAU/w+8E= +github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/sftp v1.13.5 h1:a3RLUqkyjYRtBTZJZ1VRrKbN3zhuPLlUc3sphVz81go= +github.com/pkg/sftp v1.13.5/go.mod h1:wHDZ0IZX6JcBYRK1TH9bcVq8G7TLpVHYIGJRFnmPfxg= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= +github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= +github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I= +github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0= +github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY= +github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/twitchtv/twirp v8.1.3+incompatible h1:+F4TdErPgSUbMZMwp13Q/KgDVuI7HJXP61mNV3/7iuU= +github.com/twitchtv/twirp v8.1.3+incompatible/go.mod h1:RRJoFSAmTEh2weEqWtpPE3vFK5YBhA6bqp2l1kfCC5A= +github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= +github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= +github.com/valyala/fasthttp v1.48.0 h1:oJWvHb9BIZToTQS3MuQ2R3bJZiNSa2KiNdeI8A+79Tc= +github.com/valyala/fasthttp v1.48.0/go.mod h1:k2zXd82h/7UZc3VOdJ2WaUqt1uZ/XpXAfE9i+HBC3lA= +github.com/valyala/tcplisten v1.0.0 h1:rBHj/Xf+E1tRGZyWIWwJDiRY0zc1Js+CV5DqwacVSA8= +github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +go.etcd.io/bbolt v1.3.7 h1:j+zJOnnEjF/kyHlDDgGnVL/AIqIJPq8UoB2GSNfkUfQ= +go.etcd.io/bbolt v1.3.7/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= +golang.org/x/crypto v0.7.0 h1:AvwMYaRytfdeVt3u6mLaxYtErKYjxA2OXjJ1HHq6t3A= +golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M= +golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA= +golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE= +golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.7.0 h1:W4OVu8VVOaIO0yzWMNdepAulS7YfoS3Zabrm8DOXXU4= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gorm.io/driver/sqlite v1.5.2 h1:TpQ+/dqCY4uCigCFyrfnrJnrW9zjpelWVoEVNy5qJkc= +gorm.io/driver/sqlite v1.5.2/go.mod h1:qxAuCol+2r6PannQDpOP1FP6ag3mKi4esLnB/jHed+4= +gorm.io/gorm v1.25.2 h1:gs1o6Vsa+oVKG/a9ElL3XgyGfghFfkKA2SInQaCyMho= +gorm.io/gorm v1.25.2/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k= diff --git a/hooks.sh b/hooks.sh deleted file mode 100755 index 34d35d9..0000000 --- a/hooks.sh +++ /dev/null @@ -1,24 +0,0 @@ -#!/usr/bin/env bash - -function isort_all () { - isort -y hyperglass/*.py - if [[ ! $? == 0 ]]; then - exit 1 - fi - isort -y hyperglass/**/*.py - if [[ ! $? == 0 ]]; then - exit 1 - fi -} - -function validate_examples () { - python3 ./validate_examples.py - if [[ ! $? == 0 ]]; then - exit 1 - fi -} - -# isort_all -validate_examples - -exit 0 \ No newline at end of file diff --git a/hyperglass/.gitignore b/hyperglass/.gitignore deleted file mode 100644 index 9aa4ea5..0000000 --- a/hyperglass/.gitignore +++ /dev/null @@ -1,10 +0,0 @@ -.DS_Store -.sass-cache/ -.flask_cache -.flask_cache/* -gunicorn_config.py -gunicorn_dev_config.py -test.py -__pycache__/ -*_old -certs/ diff --git a/hyperglass/__init__.py b/hyperglass/__init__.py deleted file mode 100644 index d19fd10..0000000 --- a/hyperglass/__init__.py +++ /dev/null @@ -1,52 +0,0 @@ -"""hyperglass is a modern, customizable network looking glass written in Python 3. - -https://github.com/thatmattlove/hyperglass - -The Clear BSD License - -Copyright (c) 2021 Matthew Love -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted (subject to the limitations in the disclaimer -below) provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - * Neither the name of the copyright holder nor the names of its - contributors may be used to endorse or promote products derived from this - software without specific prior written permission. - -NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY -THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND -CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A -PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR -CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR -BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER -IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. -""" - -# Third Party -import uvloop - -# Project -from hyperglass.util import set_app_path -from hyperglass.constants import METADATA - -# Find hyperglass application directory. -set_app_path() - -# Use Uvloop for performance. -uvloop.install() - -__name__, __version__, __author__, __copyright__, __license__ = METADATA diff --git a/hyperglass/api/__init__.py b/hyperglass/api/__init__.py deleted file mode 100644 index 3221802..0000000 --- a/hyperglass/api/__init__.py +++ /dev/null @@ -1,271 +0,0 @@ -"""hyperglass REST API & Web UI.""" - -# Standard Library -import sys -from typing import List -from pathlib import Path - -# Third Party -from fastapi import FastAPI -from fastapi.exceptions import ValidationError, RequestValidationError -from starlette.responses import JSONResponse -from starlette.exceptions import HTTPException as StarletteHTTPException -from fastapi.openapi.utils import get_openapi -from starlette.staticfiles import StaticFiles -from starlette.middleware.cors import CORSMiddleware - -# Project -from hyperglass.log import log -from hyperglass.util import cpu_count -from hyperglass.constants import TRANSPORT_REST, __version__ -from hyperglass.api.events import on_startup, on_shutdown -from hyperglass.api.routes import ( - docs, - info, - query, - queries, - routers, - communities, - import_certificate, -) -from hyperglass.exceptions import HyperglassError -from hyperglass.configuration import URL_DEV, STATIC_PATH, params, devices -from hyperglass.api.error_handlers import ( - app_handler, - http_handler, - default_handler, - validation_handler, -) -from hyperglass.models.api.response import ( - QueryError, - InfoResponse, - QueryResponse, - RoutersResponse, - CommunityResponse, - SupportedQueryResponse, -) - -WORKING_DIR = Path(__file__).parent -EXAMPLES_DIR = WORKING_DIR / "examples" - -UI_DIR = STATIC_PATH / "ui" -CUSTOM_DIR = STATIC_PATH / "custom" -IMAGES_DIR = STATIC_PATH / "images" - -EXAMPLE_DEVICES_PY = EXAMPLES_DIR / "devices.py" -EXAMPLE_QUERIES_PY = EXAMPLES_DIR / "queries.py" -EXAMPLE_QUERY_PY = EXAMPLES_DIR / "query.py" -EXAMPLE_DEVICES_CURL = EXAMPLES_DIR / "devices.sh" -EXAMPLE_QUERIES_CURL = EXAMPLES_DIR / "queries.sh" -EXAMPLE_QUERY_CURL = EXAMPLES_DIR / "query.sh" - -ASGI_PARAMS = { - "host": str(params.listen_address), - "port": params.listen_port, - "debug": params.debug, - "workers": cpu_count(2), -} -DOCS_PARAMS = {} -if params.docs.enable: - DOCS_PARAMS.update({"openapi_url": params.docs.openapi_uri}) - if params.docs.mode == "redoc": - DOCS_PARAMS.update({"docs_url": None, "redoc_url": params.docs.uri}) - elif params.docs.mode == "swagger": - DOCS_PARAMS.update({"docs_url": params.docs.uri, "redoc_url": None}) - -for directory in (UI_DIR, IMAGES_DIR): - if not directory.exists(): - log.warning("Directory '{d}' does not exist, creating...", d=str(directory)) - directory.mkdir() - -# Main App Definition -app = FastAPI( - debug=params.debug, - title=params.site_title, - description=params.site_description, - version=__version__, - default_response_class=JSONResponse, - **DOCS_PARAMS, -) - -# Add Event Handlers -for startup in on_startup: - app.add_event_handler("startup", startup) - -for shutdown in on_shutdown: - app.add_event_handler("shutdown", shutdown) - -# HTTP Error Handler -app.add_exception_handler(StarletteHTTPException, http_handler) - -# Backend Application Error Handler -app.add_exception_handler(HyperglassError, app_handler) - -# Request Validation Error Handler -app.add_exception_handler(RequestValidationError, validation_handler) - -# App Validation Error Handler -app.add_exception_handler(ValidationError, validation_handler) - -# Uncaught Error Handler -app.add_exception_handler(Exception, default_handler) - - -def _custom_openapi(): - """Generate custom OpenAPI config.""" - openapi_schema = get_openapi( - title=params.docs.title.format(site_title=params.site_title), - version=__version__, - description=params.docs.description, - routes=app.routes, - ) - openapi_schema["info"]["x-logo"] = { - "url": "/images/light" + params.web.logo.light.suffix - } - - query_samples = [] - queries_samples = [] - devices_samples = [] - - with EXAMPLE_QUERY_CURL.open("r") as e: - example = e.read() - query_samples.append( - {"lang": "cURL", "source": example % str(params.docs.base_url)} - ) - - with EXAMPLE_QUERY_PY.open("r") as e: - example = e.read() - query_samples.append( - {"lang": "Python", "source": example % str(params.docs.base_url)} - ) - - with EXAMPLE_DEVICES_CURL.open("r") as e: - example = e.read() - queries_samples.append( - {"lang": "cURL", "source": example % str(params.docs.base_url)} - ) - with EXAMPLE_DEVICES_PY.open("r") as e: - example = e.read() - queries_samples.append( - {"lang": "Python", "source": example % str(params.docs.base_url)} - ) - - with EXAMPLE_QUERIES_CURL.open("r") as e: - example = e.read() - devices_samples.append( - {"lang": "cURL", "source": example % str(params.docs.base_url)} - ) - - with EXAMPLE_QUERIES_PY.open("r") as e: - example = e.read() - devices_samples.append( - {"lang": "Python", "source": example % str(params.docs.base_url)} - ) - - openapi_schema["paths"]["/api/query/"]["post"]["x-code-samples"] = query_samples - openapi_schema["paths"]["/api/devices"]["get"]["x-code-samples"] = devices_samples - openapi_schema["paths"]["/api/queries"]["get"]["x-code-samples"] = queries_samples - - app.openapi_schema = openapi_schema - return app.openapi_schema - - -CORS_ORIGINS = params.cors_origins.copy() -if params.developer_mode: - CORS_ORIGINS.append(URL_DEV) - -# CORS Configuration -app.add_middleware( - CORSMiddleware, - allow_origins=CORS_ORIGINS, - allow_methods=["GET", "POST", "OPTIONS"], - allow_headers=["*"], -) - -app.add_api_route( - path="/api/info", - endpoint=info, - methods=["GET"], - response_model=InfoResponse, - response_class=JSONResponse, - summary=params.docs.info.summary, - description=params.docs.info.description, - tags=[params.docs.info.title], -) - -app.add_api_route( - path="/api/devices", - endpoint=routers, - methods=["GET"], - response_model=List[RoutersResponse], - response_class=JSONResponse, - summary=params.docs.devices.summary, - description=params.docs.devices.description, - tags=[params.docs.devices.title], -) - -app.add_api_route( - path="/api/communities", - endpoint=communities, - methods=["GET"], - response_model=List[CommunityResponse], - summary=params.docs.communities.summary, - tags=[params.docs.communities.title], -) - -app.add_api_route( - path="/api/queries", - endpoint=queries, - methods=["GET"], - response_class=JSONResponse, - response_model=List[SupportedQueryResponse], - summary=params.docs.queries.summary, - description=params.docs.queries.description, - tags=[params.docs.queries.title], -) - -app.add_api_route( - path="/api/query/", - endpoint=query, - methods=["POST"], - summary=params.docs.query.summary, - description=params.docs.query.description, - responses={ - 400: {"model": QueryError, "description": "Request Content Error"}, - 422: {"model": QueryError, "description": "Request Format Error"}, - 500: {"model": QueryError, "description": "Server Error"}, - }, - response_model=QueryResponse, - tags=[params.docs.query.title], - response_class=JSONResponse, -) - -# Enable certificate import route only if a device using -# hyperglass-agent is defined. -if [n for n in devices.all_nos if n in TRANSPORT_REST]: - app.add_api_route( - path="/api/import-agent-certificate/", - endpoint=import_certificate, - methods=["POST"], - include_in_schema=False, - ) - -if params.docs.enable: - app.add_api_route(path=params.docs.uri, endpoint=docs, include_in_schema=False) - app.openapi = _custom_openapi - log.debug("API Docs config: {}", app.openapi()) - -app.mount("/images", StaticFiles(directory=IMAGES_DIR), name="images") -app.mount("/custom", StaticFiles(directory=CUSTOM_DIR), name="custom") -app.mount("/", StaticFiles(directory=UI_DIR, html=True), name="ui") - - -def start(**kwargs): - """Start the web server with Uvicorn ASGI.""" - # Third Party - import uvicorn - - try: - uvicorn.run("hyperglass.api:app", **ASGI_PARAMS, **kwargs) - except KeyboardInterrupt: - sys.exit(0) diff --git a/hyperglass/api/error_handlers.py b/hyperglass/api/error_handlers.py deleted file mode 100644 index d2ac9bd..0000000 --- a/hyperglass/api/error_handlers.py +++ /dev/null @@ -1,40 +0,0 @@ -"""API Error Handlers.""" - -# Third Party -from starlette.responses import JSONResponse - -# Project -from hyperglass.configuration import params - - -async def default_handler(request, exc): - """Handle uncaught errors.""" - return JSONResponse( - {"output": params.messages.general, "level": "danger", "keywords": []}, - status_code=500, - ) - - -async def http_handler(request, exc): - """Handle web server errors.""" - return JSONResponse( - {"output": exc.detail, "level": "danger", "keywords": []}, - status_code=exc.status_code, - ) - - -async def app_handler(request, exc): - """Handle application errors.""" - return JSONResponse( - {"output": exc.message, "level": exc.level, "keywords": exc.keywords}, - status_code=exc.status_code, - ) - - -async def validation_handler(request, exc): - """Handle Pydantic validation errors raised by FastAPI.""" - error = exc.errors()[0] - return JSONResponse( - {"output": error["msg"], "level": "error", "keywords": error["loc"]}, - status_code=422, - ) diff --git a/hyperglass/api/events.py b/hyperglass/api/events.py deleted file mode 100644 index 418010a..0000000 --- a/hyperglass/api/events.py +++ /dev/null @@ -1,16 +0,0 @@ -"""API Events.""" - -# Project -from hyperglass.cache import AsyncCache -from hyperglass.configuration import REDIS_CONFIG, params - - -async def check_redis() -> bool: - """Ensure Redis is running before starting server.""" - cache = AsyncCache(db=params.cache.database, **REDIS_CONFIG) - await cache.test() - return True - - -on_startup = (check_redis,) -on_shutdown = () diff --git a/hyperglass/api/examples/devices.py b/hyperglass/api/examples/devices.py deleted file mode 100644 index e6ec88d..0000000 --- a/hyperglass/api/examples/devices.py +++ /dev/null @@ -1,6 +0,0 @@ -# Third Party -import httpx - -request = httpx.get("%s/api/devices") - -print(request.json()) diff --git a/hyperglass/api/examples/devices.sh b/hyperglass/api/examples/devices.sh deleted file mode 100644 index cf94cb2..0000000 --- a/hyperglass/api/examples/devices.sh +++ /dev/null @@ -1 +0,0 @@ -curl %s/api/devices \ No newline at end of file diff --git a/hyperglass/api/examples/queries.py b/hyperglass/api/examples/queries.py deleted file mode 100644 index b44b0fa..0000000 --- a/hyperglass/api/examples/queries.py +++ /dev/null @@ -1,6 +0,0 @@ -# Third Party -import httpx - -request = httpx.get("%s/api/queries") - -print(request.json()) diff --git a/hyperglass/api/examples/queries.sh b/hyperglass/api/examples/queries.sh deleted file mode 100644 index b89af31..0000000 --- a/hyperglass/api/examples/queries.sh +++ /dev/null @@ -1 +0,0 @@ -curl %s/api/queries \ No newline at end of file diff --git a/hyperglass/api/examples/query.py b/hyperglass/api/examples/query.py deleted file mode 100644 index 3b75ddf..0000000 --- a/hyperglass/api/examples/query.py +++ /dev/null @@ -1,13 +0,0 @@ -# Third Party -import httpx - -query = { - "query_location": "router01", - "query_type": "bgp_route", - "query_vrf": "default", - "query_target": "1.1.1.0/24", -} - -request = httpx.post("%s/api/query/", data=query) - -print(request.json().get("output")) diff --git a/hyperglass/api/examples/query.sh b/hyperglass/api/examples/query.sh deleted file mode 100644 index ec41f6c..0000000 --- a/hyperglass/api/examples/query.sh +++ /dev/null @@ -1,7 +0,0 @@ -curl -X POST %s/api/query/ -d \ - '{ - "query_location": "router01", - "query_type": "bgp_route", - "query_vrf": "default", - "query_target": "1.1.1.0/24" - }' \ No newline at end of file diff --git a/hyperglass/api/fake_output.py b/hyperglass/api/fake_output.py deleted file mode 100644 index 1c7ffed..0000000 --- a/hyperglass/api/fake_output.py +++ /dev/null @@ -1,174 +0,0 @@ -"""Return fake, static data for development purposes.""" - -# Standard Library -from typing import Dict, Union - -PLAIN = r""" -BGP routing table entry for 4.0.0.0/9, version 1017877672 -BGP Bestpath: deterministic-med -Paths: (10 available, best #9, table default) - Advertised to update-groups: - 50 - 1299 3356, (aggregated by 3356 4.69.130.24) - 216.250.230.1 (metric 2000) from 216.250.230.1 (216.250.230.1) - Origin IGP, metric 0, localpref 100, weight 100, valid, internal, atomic-aggregate - Community: 1299:25000 14525:0 14525:40 14525:601 14525:1021 14525:2840 14525:3003 14525:4002 14525:9003 - 1299 3356, (aggregated by 3356 4.69.130.24), (received-only) - 216.250.230.1 (metric 2000) from 216.250.230.1 (216.250.230.1) - Origin IGP, metric 0, localpref 150, valid, internal, atomic-aggregate - Community: 1299:25000 14525:0 14525:40 14525:601 14525:1021 14525:2840 14525:3003 14525:4002 14525:9003 - 1299 3356, (aggregated by 3356 4.69.130.184) - 199.34.92.9 (metric 1000) from 199.34.92.9 (199.34.92.9) - Origin IGP, metric 0, localpref 100, weight 100, valid, internal, atomic-aggregate - Community: 1299:25000 14525:0 14525:40 14525:601 14525:1021 14525:2840 14525:3001 14525:4001 14525:9003 - 1299 3356, (aggregated by 3356 4.69.130.184), (received-only) - 199.34.92.9 (metric 1000) from 199.34.92.9 (199.34.92.9) - Origin IGP, metric 0, localpref 150, valid, internal, atomic-aggregate - Community: 1299:25000 14525:0 14525:40 14525:601 14525:1021 14525:2840 14525:3001 14525:4001 14525:9003 - 174 3356, (aggregated by 3356 4.69.130.4) - 199.34.92.10 (metric 1000) from 199.34.92.10 (199.34.92.10) - Origin IGP, metric 0, localpref 100, weight 100, valid, internal, atomic-aggregate - Community: 174:21000 174:22013 14525:0 14525:40 14525:601 14525:1021 14525:2840 14525:3001 14525:4001 14525:9001 - 174 3356, (aggregated by 3356 4.69.130.4), (received-only) - 199.34.92.10 (metric 1000) from 199.34.92.10 (199.34.92.10) - Origin IGP, metric 0, localpref 150, valid, internal, atomic-aggregate - Community: 174:21000 174:22013 14525:0 14525:40 14525:601 14525:1021 14525:2840 14525:3001 14525:4001 14525:9001 - 209 3356, (aggregated by 3356 4.69.130.2) - 199.34.92.5 (metric 101) from 199.34.92.5 (199.34.92.5) - Origin IGP, metric 8006570, localpref 150, weight 200, valid, internal, atomic-aggregate - Community: 209:88 209:888 3356:0 3356:3 3356:100 3356:123 3356:575 3356:2011 14525:0 14525:40 14525:1021 14525:2840 14525:3002 14525:4003 14525:9005 - 209 3356, (aggregated by 3356 4.69.130.2), (received-only) - 199.34.92.5 (metric 101) from 199.34.92.5 (199.34.92.5) - Origin IGP, metric 8006570, localpref 150, valid, internal, atomic-aggregate - Community: 209:88 209:888 3356:0 3356:3 3356:100 3356:123 3356:575 3356:2011 14525:0 14525:40 14525:1021 14525:2840 14525:3002 14525:4003 14525:9005 - 6939 3356, (aggregated by 3356 4.69.130.4) - 184.105.247.177 from 184.105.247.177 (216.218.252.234) - Origin IGP, localpref 150, weight 200, valid, external, atomic-aggregate, best - Community: 6939:7016 6939:8840 6939:9001 14525:0 14525:40 14525:1021 14525:2840 14525:3002 14525:4003 14525:9002 - 6939 3356, (aggregated by 3356 4.69.130.4), (received-only) - 184.105.247.177 from 184.105.247.177 (216.218.252.234) - Origin IGP, localpref 100, valid, external, atomic-aggregate - Community: 6939:7016 6939:8840 6939:9001 -""" # noqa: W291,E501 - -ROUTES = [ - { - "prefix": "1.1.1.0/24", - "active": True, - "age": 1025337, - "weight": 170, - "med": 0, - "local_preference": 175, - "as_path": [1299, 13335], - "communities": [ - "1299:35000", - "14525:0", - "14525:41", - "14525:600", - "14525:1021", - "14525:2840", - "14525:3001", - "14525:4001", - "14525:9003", - ], - "next_hop": "62.115.189.136", - "source_as": 13335, - "source_rid": "141.101.72.1", - "peer_rid": "2.255.254.43", - "rpki_state": 1, - }, - { - "prefix": "1.1.1.0/24", - "active": False, - "age": 1584622, - "weight": 200, - "med": 0, - "local_preference": 250, - "as_path": [13335], - "communities": [ - "14525:0", - "14525:20", - "14525:600", - "14525:1021", - "14525:2840", - "14525:3002", - "14525:4003", - "14525:9009", - ], - "next_hop": "", - "source_as": 13335, - "source_rid": "172.68.129.1", - "peer_rid": "199.34.92.5", - "rpki_state": 3, - }, - { - "prefix": "1.1.1.0/24", - "active": False, - "age": 982517, - "weight": 200, - "med": 0, - "local_preference": 250, - "as_path": [13335], - "communities": [ - "14525:0", - "14525:20", - "14525:600", - "14525:1021", - "14525:2840", - "14525:3002", - "14525:4003", - "14525:9009", - ], - "next_hop": "", - "source_as": 13335, - "source_rid": "172.68.129.1", - "peer_rid": "199.34.92.6", - "rpki_state": 3, - }, - { - "prefix": "1.1.1.0/24", - "active": False, - "age": 1000101, - "weight": 200, - "med": 0, - "local_preference": 250, - "as_path": [13335], - "communities": [ - "13335:10014", - "13335:19000", - "13335:20050", - "13335:20500", - "13335:20530", - "14525:0", - "14525:20", - "14525:600", - "14525:1021", - "14525:2840", - "14525:3003", - "14525:4002", - "14525:9009", - ], - "next_hop": "", - "source_as": 13335, - "source_rid": "141.101.73.1", - "peer_rid": "216.250.230.2", - "rpki_state": 3, - }, -] - -STRUCTURED = { - "vrf": "default", - "count": len(ROUTES), - "routes": ROUTES, - "winning_weight": "high", -} - - -async def fake_output(structured: bool) -> Union[str, Dict]: - """Bypass the standard execution process and return static, fake output.""" - output = PLAIN - - if structured: - output = STRUCTURED - - return output diff --git a/hyperglass/api/routes.py b/hyperglass/api/routes.py deleted file mode 100644 index 9f5b41b..0000000 --- a/hyperglass/api/routes.py +++ /dev/null @@ -1,266 +0,0 @@ -"""API Routes.""" - -# Standard Library -import os -import json -import time -from datetime import datetime - -# Third Party -from fastapi import HTTPException, BackgroundTasks -from starlette.requests import Request -from fastapi.openapi.docs import get_redoc_html, get_swagger_ui_html - -# Project -from hyperglass.log import log -from hyperglass.cache import AsyncCache -from hyperglass.encode import jwt_decode -from hyperglass.external import Webhook, bgptools -from hyperglass.api.tasks import process_headers, import_public_key -from hyperglass.constants import __version__ -from hyperglass.exceptions import HyperglassError -from hyperglass.models.api import Query, EncodedRequest -from hyperglass.configuration import REDIS_CONFIG, params, devices -from hyperglass.execution.main import execute - -# Local -from .fake_output import fake_output - -APP_PATH = os.environ["hyperglass_directory"] - - -async def send_webhook(query_data: Query, request: Request, timestamp: datetime): - """If webhooks are enabled, get request info and send a webhook. - - Args: - query_data (Query): Valid query - request (Request): Starlette/FastAPI request - - Returns: - int: Returns 1 regardless of result - """ - try: - if params.logging.http is not None: - headers = await process_headers(headers=request.headers) - - if headers.get("x-real-ip") is not None: - host = headers["x-real-ip"] - elif headers.get("x-forwarded-for") is not None: - host = headers["x-forwarded-for"] - else: - host = request.client.host - - network_info = await bgptools.network_info(host) - - async with Webhook(params.logging.http) as hook: - - await hook.send( - query={ - **query_data.export_dict(pretty=True), - "headers": headers, - "source": host, - "network": network_info.get(host, {}), - "timestamp": timestamp, - } - ) - except Exception as err: - log.error( - "Error sending webhook to {}: {}", params.logging.http.provider, str(err) - ) - - -async def query(query_data: Query, request: Request, background_tasks: BackgroundTasks): - """Ingest request data pass it to the backend application to perform the query.""" - - timestamp = datetime.utcnow() - background_tasks.add_task(send_webhook, query_data, request, timestamp) - - # Initialize cache - cache = AsyncCache(db=params.cache.database, **REDIS_CONFIG) - log.debug("Initialized cache {}", repr(cache)) - - # Use hashed query_data string as key for for k/v cache store so - # each command output value is unique. - cache_key = query_data.digest() - - # Define cache entry expiry time - cache_timeout = params.cache.timeout - - log.debug("Cache Timeout: {}", cache_timeout) - log.info("Starting query execution for query {}", query_data.summary) - - cache_response = await cache.get_dict(cache_key, "output") - - json_output = False - - if query_data.device.structured_output and query_data.query_type in ( - "bgp_route", - "bgp_community", - "bgp_aspath", - ): - json_output = True - - cached = False - runtime = 65535 - if cache_response: - log.debug("Query {} exists in cache", cache_key) - - # If a cached response exists, reset the expiration time. - await cache.expire(cache_key, seconds=cache_timeout) - - cached = True - runtime = 0 - timestamp = await cache.get_dict(cache_key, "timestamp") - - elif not cache_response: - log.debug("No existing cache entry for query {}", cache_key) - log.debug( - "Created new cache key {} entry for query {}", cache_key, query_data.summary - ) - - timestamp = query_data.timestamp - - starttime = time.time() - - if params.fake_output: - # Return fake, static data for development purposes, if enabled. - cache_output = await fake_output(json_output) - else: - # Pass request to execution module - cache_output = await execute(query_data) - - endtime = time.time() - elapsedtime = round(endtime - starttime, 4) - log.debug("Query {} took {} seconds to run.", cache_key, elapsedtime) - - if cache_output is None: - raise HyperglassError(message=params.messages.general, alert="danger") - - # Create a cache entry - if json_output: - raw_output = json.dumps(cache_output) - else: - raw_output = str(cache_output) - await cache.set_dict(cache_key, "output", raw_output) - await cache.set_dict(cache_key, "timestamp", timestamp) - await cache.expire(cache_key, seconds=cache_timeout) - - log.debug("Added cache entry for query: {}", cache_key) - - runtime = int(round(elapsedtime, 0)) - - # If it does, return the cached entry - cache_response = await cache.get_dict(cache_key, "output") - response_format = "text/plain" - - if json_output: - response_format = "application/json" - - log.debug("Cache match for {}:\n{}", cache_key, cache_response) - log.success("Completed query execution for query {}", query_data.summary) - - return { - "output": cache_response, - "id": cache_key, - "cached": cached, - "runtime": runtime, - "timestamp": timestamp, - "format": response_format, - "random": query_data.random(), - "level": "success", - "keywords": [], - } - - -async def import_certificate(encoded_request: EncodedRequest): - """Import a certificate from hyperglass-agent.""" - - # Try to match the requested device name with configured devices - log.debug( - "Attempting certificate import for device '{}'", devices[encoded_request.device] - ) - try: - matched_device = devices[encoded_request.device] - except AttributeError: - raise HTTPException( - detail=f"Device {str(encoded_request.device)} not found", status_code=404 - ) - - try: - # Decode JSON Web Token - decoded_request = await jwt_decode( - payload=encoded_request.encoded, - secret=matched_device.credential.password.get_secret_value(), - ) - except HyperglassError as decode_error: - raise HTTPException(detail=str(decode_error), status_code=400) - - try: - # Write certificate to file - import_public_key( - app_path=APP_PATH, - device_name=matched_device._id, - keystring=decoded_request, - ) - except RuntimeError as err: - raise HyperglassError(str(err), level="danger") - - log.info("Added public key for {}", encoded_request.device) - return { - "output": f"Added public key for {encoded_request.device}", - "level": "success", - "keywords": [encoded_request.device], - } - - -async def docs(): - """Serve custom docs.""" - if params.docs.enable: - docs_func_map = {"swagger": get_swagger_ui_html, "redoc": get_redoc_html} - docs_func = docs_func_map[params.docs.mode] - return docs_func( - openapi_url=params.docs.openapi_url, title=params.site_title + " - API Docs" - ) - else: - raise HTTPException(detail="Not found", status_code=404) - - -async def routers(): - """Serve list of configured routers and attributes.""" - return [ - d.dict( - include={ - "name": ..., - "network": ..., - "display_name": ..., - "vrfs": {-1: {"name", "display_name"}}, - } - ) - for d in devices.objects - ] - - -async def communities(): - """Serve list of configured communities if mode is select.""" - if params.queries.bgp_community.mode != "select": - raise HTTPException(detail="BGP community mode is not select", status_code=404) - - return [c.export_dict() for c in params.queries.bgp_community.communities] - - -async def queries(): - """Serve list of enabled query types.""" - return params.queries.list - - -async def info(): - """Serve general information about this instance of hyperglass.""" - return { - "name": params.site_title, - "organization": params.org_name, - "primary_asn": int(params.primary_asn), - "version": f"hyperglass {__version__}", - } - - -endpoints = [query, docs, routers, info] diff --git a/hyperglass/api/tasks.py b/hyperglass/api/tasks.py deleted file mode 100644 index 1761d4f..0000000 --- a/hyperglass/api/tasks.py +++ /dev/null @@ -1,51 +0,0 @@ -"""Tasks to be executed from web API.""" - -# Standard Library -from typing import Dict, Union -from pathlib import Path - -# Third Party -from httpx import Headers - - -def import_public_key( - app_path: Union[Path, str], device_name: str, keystring: str -) -> bool: - """Import a public key for hyperglass-agent.""" - if not isinstance(app_path, Path): - app_path = Path(app_path) - - cert_dir = app_path / "certs" - - if not cert_dir.exists(): - cert_dir.mkdir() - - if not cert_dir.exists(): - raise RuntimeError(f"Failed to create certs directory at {str(cert_dir)}") - - filename = f"{device_name}.pem" - cert_file = cert_dir / filename - - with cert_file.open("w+") as file: - file.write(str(keystring)) - - with cert_file.open("r") as file: - read_file = file.read().strip() - if not keystring == read_file: - raise RuntimeError("Wrote key, but written file did not match input key") - - return True - - -async def process_headers(headers: Headers) -> Dict: - """Filter out unwanted headers and return as a dictionary.""" - headers = dict(headers) - header_keys = ( - "user-agent", - "referer", - "accept-encoding", - "accept-language", - "x-real-ip", - "x-forwarded-for", - ) - return {k: headers.get(k) for k in header_keys} diff --git a/hyperglass/cache/__init__.py b/hyperglass/cache/__init__.py deleted file mode 100644 index 04c3efd..0000000 --- a/hyperglass/cache/__init__.py +++ /dev/null @@ -1,7 +0,0 @@ -"""Redis cache handlers.""" - -# Project -from hyperglass.cache.aio import AsyncCache -from hyperglass.cache.sync import SyncCache - -__all__ = ("AsyncCache", "SyncCache") diff --git a/hyperglass/cache/aio.py b/hyperglass/cache/aio.py deleted file mode 100644 index 84025b7..0000000 --- a/hyperglass/cache/aio.py +++ /dev/null @@ -1,148 +0,0 @@ -"""Asyncio Redis cache handler.""" - -# Standard Library -import json -import time -import pickle -import asyncio -from typing import Any, Dict - -# Third Party -from aredis import StrictRedis as AsyncRedis -from aredis.pubsub import PubSub as AsyncPubSub -from aredis.exceptions import RedisError - -# Project -from hyperglass.cache.base import BaseCache -from hyperglass.exceptions import HyperglassError - - -class AsyncCache(BaseCache): - """Asynchronous Redis cache handler.""" - - def __init__(self, *args, **kwargs): - """Initialize Redis connection.""" - super().__init__(*args, **kwargs) - - password = self.password - if password is not None: - password = password.get_secret_value() - - self.instance: AsyncRedis = AsyncRedis( - db=self.db, - host=self.host, - port=self.port, - password=password, - decode_responses=self.decode_responses, - **self.redis_args, - ) - - async def test(self): - """Send an echo to Redis to ensure it can be reached.""" - try: - await self.instance.echo("hyperglass test") - except RedisError as err: - err_msg = str(err) - if not err_msg and hasattr(err, "__context__"): - # Some Redis exceptions are raised without a message - # even if they are raised from another exception that - # does have a message. - err_msg = str(err.__context__) - - if "auth" in err_msg.lower(): - raise HyperglassError( - "Authentication to Redis server {server} failed.".format( - server=repr(self) - ), - level="danger", - ) from None - else: - raise HyperglassError( - "Unable to connect to Redis server {server}".format( - server=repr(self) - ), - level="danger", - ) from None - - async def get(self, *args: str) -> Any: - """Get item(s) from cache.""" - if len(args) == 1: - raw = await self.instance.get(args[0]) - else: - raw = await self.instance.mget(args) - return self.parse_types(raw) - - async def get_dict(self, key: str, field: str = "") -> Any: - """Get hash map (dict) item(s).""" - if not field: - raw = await self.instance.hgetall(key) - else: - raw = await self.instance.hget(key, field) - - return self.parse_types(raw) - - async def set(self, key: str, value: str) -> bool: - """Set cache values.""" - return await self.instance.set(key, value) - - async def set_dict(self, key: str, field: str, value: str) -> bool: - """Set hash map (dict) values.""" - success = False - - if isinstance(value, Dict): - value = json.dumps(value) - else: - value = str(value) - - response = await self.instance.hset(key, field, value) - - if response in (0, 1): - success = True - - return success - - async def wait(self, pubsub: AsyncPubSub, timeout: int = 30, **kwargs) -> Any: - """Wait for pub/sub messages & return posted message.""" - now = time.time() - timeout = now + timeout - - while now < timeout: - - message = await pubsub.get_message(ignore_subscribe_messages=True, **kwargs) - - if message is not None and message["type"] == "message": - data = message["data"] - return self.parse_types(data) - - await asyncio.sleep(0.01) - now = time.time() - - return None - - async def pubsub(self) -> AsyncPubSub: - """Provide an aredis.pubsub.Pubsub instance.""" - return self.instance.pubsub() - - async def pub(self, key: str, value: str) -> None: - """Publish a value.""" - await asyncio.sleep(1) - await self.instance.publish(key, value) - - async def clear(self) -> None: - """Clear the cache.""" - await self.instance.flushdb() - - async def delete(self, *keys: str) -> None: - """Delete a cache key.""" - await self.instance.delete(*keys) - - async def expire(self, *keys: str, seconds: int) -> None: - """Set timeout of key in seconds.""" - for key in keys: - await self.instance.expire(key, seconds) - - async def get_config(self) -> Dict: - """Get picked config object from cache.""" - - pickled = await self.instance.get("HYPERGLASS_CONFIG") - return pickle.loads(pickled) diff --git a/hyperglass/cache/base.py b/hyperglass/cache/base.py deleted file mode 100644 index 87fa43f..0000000 --- a/hyperglass/cache/base.py +++ /dev/null @@ -1,66 +0,0 @@ -"""Base Redis cache handler.""" - -# Standard Library -import re -import json -from typing import Any, Optional - -# Third Party -from pydantic import SecretStr - - -class BaseCache: - """Redis cache handler.""" - - def __init__( - self, - db: int, - host: str = "localhost", - port: int = 6379, - password: Optional[SecretStr] = None, - decode_responses: bool = True, - **kwargs: Any, - ) -> None: - """Initialize Redis connection.""" - self.db: int = db - self.host: str = str(host) - self.port: int = port - self.password: Optional[SecretStr] = password - self.decode_responses: bool = decode_responses - self.redis_args: dict = kwargs - - def __repr__(self) -> str: - """Represent class state.""" - return "HyperglassCache(db={}, host={}, port={}, password={})".format( - self.db, self.host, self.port, self.password - ) - - def parse_types(self, value: str) -> Any: - """Parse a string to standard python types.""" - - def parse_string(str_value: str): - - is_float = (re.compile(r"^(\d+\.\d+)$"), float) - is_int = (re.compile(r"^(\d+)$"), int) - is_bool = (re.compile(r"^(True|true|False|false)$"), bool) - is_none = (re.compile(r"^(None|none|null|nil|\(nil\))$"), lambda v: None) - is_jsonable = (re.compile(r"^[\{\[].*[\}\]]$"), json.loads) - - for pattern, factory in (is_float, is_int, is_bool, is_none, is_jsonable): - if isinstance(str_value, str) and bool(re.match(pattern, str_value)): - str_value = factory(str_value) - break - return str_value - - if isinstance(value, str): - value = parse_string(value) - elif isinstance(value, bytes): - value = parse_string(value.decode("utf-8")) - elif isinstance(value, list): - value = [parse_string(i) for i in value] - elif isinstance(value, tuple): - value = tuple(parse_string(i) for i in value) - elif isinstance(value, dict): - value = {k: self.parse_types(v) for k, v in value.items()} - - return value diff --git a/hyperglass/cache/sync.py b/hyperglass/cache/sync.py deleted file mode 100644 index 085fa82..0000000 --- a/hyperglass/cache/sync.py +++ /dev/null @@ -1,147 +0,0 @@ -"""Non-asyncio Redis cache handler.""" - -# Standard Library -import json -import time -import pickle -from typing import Any, Dict - -# Third Party -from redis import Redis as SyncRedis -from redis.client import PubSub as SyncPubsSub -from redis.exceptions import RedisError - -# Project -from hyperglass.cache.base import BaseCache -from hyperglass.exceptions import HyperglassError - - -class SyncCache(BaseCache): - """Synchronous Redis cache handler.""" - - def __init__(self, *args, **kwargs): - """Initialize Redis connection.""" - super().__init__(*args, **kwargs) - - password = self.password - if password is not None: - password = password.get_secret_value() - - self.instance: SyncRedis = SyncRedis( - db=self.db, - host=self.host, - port=self.port, - password=password, - decode_responses=self.decode_responses, - **self.redis_args, - ) - - def test(self): - """Send an echo to Redis to ensure it can be reached.""" - try: - self.instance.echo("hyperglass test") - except RedisError as err: - err_msg = str(err) - if not err_msg and hasattr(err, "__context__"): - # Some Redis exceptions are raised without a message - # even if they are raised from another exception that - # does have a message. - err_msg = str(err.__context__) - - if "auth" in err_msg.lower(): - raise HyperglassError( - "Authentication to Redis server {server} failed.".format( - server=repr(self) - ), - level="danger", - ) from None - else: - raise HyperglassError( - "Unable to connect to Redis server {server}".format( - server=repr(self) - ), - level="danger", - ) from None - - def get(self, *args: str) -> Any: - """Get item(s) from cache.""" - if len(args) == 1: - raw = self.instance.get(args[0]) - else: - raw = self.instance.mget(args) - return self.parse_types(raw) - - def get_dict(self, key: str, field: str = "") -> Any: - """Get hash map (dict) item(s).""" - if not field: - raw = self.instance.hgetall(key) - else: - raw = self.instance.hget(key, str(field)) - - return self.parse_types(raw) - - def set(self, key: str, value: str) -> bool: - """Set cache values.""" - return self.instance.set(key, str(value)) - - def set_dict(self, key: str, field: str, value: str) -> bool: - """Set hash map (dict) values.""" - success = False - - if isinstance(value, Dict): - value = json.dumps(value) - else: - value = str(value) - - response = self.instance.hset(key, str(field), value) - - if response in (0, 1): - success = True - - return success - - def wait(self, pubsub: SyncPubsSub, timeout: int = 30, **kwargs) -> Any: - """Wait for pub/sub messages & return posted message.""" - now = time.time() - timeout = now + timeout - - while now < timeout: - - message = pubsub.get_message(ignore_subscribe_messages=True, **kwargs) - - if message is not None and message["type"] == "message": - data = message["data"] - return self.parse_types(data) - - time.sleep(0.01) - now = time.time() - - return None - - def pubsub(self) -> SyncPubsSub: - """Provide a redis.client.Pubsub instance.""" - return self.instance.pubsub() - - def pub(self, key: str, value: str) -> None: - """Publish a value.""" - time.sleep(1) - self.instance.publish(key, value) - - def clear(self) -> None: - """Clear the cache.""" - self.instance.flushdb() - - def delete(self, *keys: str) -> None: - """Delete a cache key.""" - self.instance.delete(*keys) - - def expire(self, *keys: str, seconds: int) -> None: - """Set timeout of key in seconds.""" - for key in keys: - self.instance.expire(key, seconds) - - def get_config(self) -> Dict: - """Get picked config object from cache.""" - - pickled = self.instance.get("HYPERGLASS_CONFIG") - return pickle.loads(pickled) diff --git a/hyperglass/cli/__init__.py b/hyperglass/cli/__init__.py deleted file mode 100644 index 86ab7f8..0000000 --- a/hyperglass/cli/__init__.py +++ /dev/null @@ -1,6 +0,0 @@ -"""hyperglass cli module.""" - -# Project -from hyperglass.cli.commands import hg - -CLI = hg diff --git a/hyperglass/cli/commands.py b/hyperglass/cli/commands.py deleted file mode 100644 index dfdbd4c..0000000 --- a/hyperglass/cli/commands.py +++ /dev/null @@ -1,205 +0,0 @@ -"""CLI Command definitions.""" - -# Standard Library -import sys -from pathlib import Path - -# Third Party -from click import group, option, help_option - -# Project -from hyperglass.util import cpu_count - -# Local -from .echo import error, label, success, warning, cmd_help -from .util import build_ui -from .static import LABEL, CLI_HELP, E -from .installer import Installer -from .formatting import HelpColorsGroup, HelpColorsCommand, random_colors - -# Define working directory -WORKING_DIR = Path(__file__).parent - -supports_color = "utf" in sys.getfilesystemencoding().lower() - - -def _print_version(ctx, param, value): - # Project - from hyperglass import __version__ - - if not value or ctx.resilient_parsing: - return - label("hyperglass version: {v}", v=__version__) - ctx.exit() - - -@group( - cls=HelpColorsGroup, - help=CLI_HELP, - context_settings={"help_option_names": ["-h", "--help"], "color": supports_color}, - help_headers_color=LABEL, - help_options_custom_colors=random_colors( - "build-ui", "start", "secret", "setup", "system-info", "clear-cache" - ), -) -@option( - "-v", - "--version", - is_flag=True, - callback=_print_version, - expose_value=False, - is_eager=True, - help=cmd_help(E.NUMBERS, "hyperglass version", supports_color), -) -@help_option( - "-h", - "--help", - help=cmd_help(E.FOLDED_HANDS, "Show this help message", supports_color), -) -def hg(): - """Initialize Click Command Group.""" - pass - - -@hg.command( - "build-ui", help=cmd_help(E.BUTTERFLY, "Create a new UI build", supports_color) -) -@option("-t", "--timeout", required=False, default=180, help="Timeout in seconds") -def build_frontend(timeout): - """Create a new UI build.""" - return build_ui(timeout) - - -@hg.command( # noqa: C901 - "start", - help=cmd_help(E.ROCKET, "Start web server", supports_color), - cls=HelpColorsCommand, - help_options_custom_colors=random_colors("-b", "-d", "-w"), -) -@option("-b", "--build", is_flag=True, help="Render theme & build frontend assets") -@option( - "-d", - "--direct", - is_flag=True, - default=False, - help="Start hyperglass directly instead of through process manager", -) -@option( - "-w", - "--workers", - type=int, - required=False, - default=0, - help=f"Number of workers. By default, calculated from CPU cores [{cpu_count(2)}]", -) -def start(build, direct, workers): # noqa: C901 - """Start web server and optionally build frontend assets.""" - # Project - from hyperglass.api import start as uvicorn_start - from hyperglass.main import start - - kwargs = {} - if workers != 0: - kwargs["workers"] = workers - - try: - - if build: - build_complete = build_ui(timeout=180) - - if build_complete and not direct: - start(**kwargs) - elif build_complete and direct: - uvicorn_start(**kwargs) - - if not build and not direct: - start(**kwargs) - - elif not build and direct: - uvicorn_start(**kwargs) - - except (KeyboardInterrupt, SystemExit) as err: - error_message = str(err) - if (len(error_message)) > 1: - warning(str(err)) - error("Stopping hyperglass due to keyboard interrupt.") - - -@hg.command( - "secret", - help=cmd_help(E.LOCK, "Generate agent secret", supports_color), - cls=HelpColorsCommand, - help_options_custom_colors=random_colors("-l"), -) -@option( - "-l", "--length", "length", default=32, help="Number of characters [default: 32]" -) -def generate_secret(length): - """Generate secret for hyperglass-agent. - - Arguments: - length {int} -- Length of secret - """ - # Standard Library - import secrets - - gen_secret = secrets.token_urlsafe(length) - label("Secret: {s}", s=gen_secret) - - -@hg.command( - "setup", - help=cmd_help(E.TOOLBOX, "Run the setup wizard", supports_color), - cls=HelpColorsCommand, - help_options_custom_colors=random_colors("-d"), -) -@option( - "-d", - "--use-defaults", - "unattended", - default=False, - is_flag=True, - help="Use hyperglass defaults (requires no input)", -) -def setup(unattended): - """Define application directory, move example files, generate systemd service.""" - - installer = Installer(unattended=unattended) - installer.install() - - success( - """Completed hyperglass installation. -After adding your hyperglass.yaml file, you should run the `hyperglass build-ui` command.""" # noqa: E501 - ) - - -@hg.command( - "system-info", - help=cmd_help( - E.THERMOMETER, " Get system information for a bug report", supports_color - ), - cls=HelpColorsCommand, -) -def get_system_info(): - """Get CPU, Memory, Disk, Python, & hyperglass version.""" - # Project - from hyperglass.cli.util import system_info - - system_info() - - -@hg.command( - "clear-cache", - help=cmd_help(E.SOAP, "Clear the Redis cache", supports_color), - cls=HelpColorsCommand, -) -def clear_cache(): - """Clear the Redis Cache.""" - # Project - from hyperglass.util import sync_clear_redis_cache - - try: - sync_clear_redis_cache() - success("Cleared Redis Cache") - except RuntimeError as err: - error(str(err)) diff --git a/hyperglass/cli/echo.py b/hyperglass/cli/echo.py deleted file mode 100644 index 63d0755..0000000 --- a/hyperglass/cli/echo.py +++ /dev/null @@ -1,142 +0,0 @@ -"""Helper functions for CLI message printing.""" -# Standard Library -import re - -# Third Party -from click import echo, style - -# Project -from hyperglass.cli.static import CMD_HELP, Message -from hyperglass.cli.exceptions import CliError - - -def cmd_help(emoji="", help_text="", supports_color=False): - """Print formatted command help.""" - if supports_color: - help_str = emoji + style(help_text, **CMD_HELP) - else: - help_str = help_text - return help_str - - -def _base_formatter(_text, _state, _callback, *args, **kwargs): - """Format text block, replace template strings with keyword arguments. - - Arguments: - state {dict} -- Text format attributes - label {dict} -- Keyword format attributes - text {[type]} -- Text to format - callback {function} -- Callback function - - Returns: - {str|ClickException} -- Formatted output - """ - fmt = Message(_state) - - if _callback is None: - _callback = style - - nargs = () - for i in args: - if not isinstance(i, str): - nargs += (str(i),) - else: - nargs += (i,) - - for k, v in kwargs.items(): - if not isinstance(v, str): - v = str(v) - kwargs[k] = style(v, **fmt.kw) - - text_all = re.split(r"(\{\w+\})", _text) - text_all = [style(i, **fmt.msg) for i in text_all] - text_all = [i.format(*nargs, **kwargs) for i in text_all] - - if fmt.emoji: - text_all.insert(0, fmt.emoji) - - text_fmt = "".join(text_all) - - return _callback(text_fmt) - - -def info(text, *args, **kwargs): - """Generate formatted informational text. - - Arguments: - text {str} -- Text to format - callback {callable} -- Callback function (default: {echo}) - - Returns: - {str} -- Informational output - """ - return _base_formatter(_state="info", _text=text, _callback=echo, *args, **kwargs) - - -def error(text, *args, **kwargs): - """Generate formatted exception. - - Arguments: - text {str} -- Text to format - callback {callable} -- Callback function (default: {echo}) - - Raises: - ClickException: Raised after formatting - """ - raise _base_formatter(text, "error", CliError, *args, **kwargs) - - -def success(text, *args, **kwargs): - """Generate formatted success text. - - Arguments: - text {str} -- Text to format - callback {callable} -- Callback function (default: {echo}) - - Returns: - {str} -- Success output - """ - return _base_formatter( - _state="success", _text=text, _callback=echo, *args, **kwargs - ) - - -def warning(text, *args, **kwargs): - """Generate formatted warning text. - - Arguments: - text {str} -- Text to format - callback {callable} -- Callback function (default: {echo}) - - Returns: - {str} -- Warning output - """ - return _base_formatter( - _state="warning", _text=text, _callback=echo, *args, **kwargs - ) - - -def label(text, *args, **kwargs): - """Generate formatted info text with accented labels. - - Arguments: - text {str} -- Text to format - callback {callable} -- Callback function (default: {echo}) - - Returns: - {str} -- Label output - """ - return _base_formatter(_state="label", _text=text, _callback=echo, *args, **kwargs) - - -def status(text, *args, **kwargs): - """Generate formatted status text. - - Arguments: - text {str} -- Text to format - callback {callable} -- Callback function (default: {echo}) - - Returns: - {str} -- Status output - """ - return _base_formatter(_state="status", _text=text, _callback=echo, *args, **kwargs) diff --git a/hyperglass/cli/exceptions.py b/hyperglass/cli/exceptions.py deleted file mode 100644 index 3b44806..0000000 --- a/hyperglass/cli/exceptions.py +++ /dev/null @@ -1,15 +0,0 @@ -"""hyperglass CLI custom exceptions.""" - -# Third Party -from click import ClickException, echo -from click._compat import get_text_stderr - - -class CliError(ClickException): - """Custom exception to exclude the 'Error:' prefix from echos.""" - - def show(self, file=None): - """Exclude 'Error:' prefix from raised exceptions.""" - if file is None: - file = get_text_stderr() - echo(self.format_message()) diff --git a/hyperglass/cli/formatting.py b/hyperglass/cli/formatting.py deleted file mode 100644 index 22b58bd..0000000 --- a/hyperglass/cli/formatting.py +++ /dev/null @@ -1,178 +0,0 @@ -"""Help formatting. - -https://github.com/click-contrib/click-help-colors -MIT License - -Copyright (c) 2016 Roman Tonkonozhko - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -""" - -# Standard Library -import random - -# Third Party -import click - - -def random_colors(*commands): - """From tuple of commands, generate random but unique colors.""" - colors = ["blue", "green", "red", "yellow", "magenta", "cyan", "white"] - num_colors = len(colors) - num_commands = len(commands) - - if num_commands >= num_colors: - colors += colors - - unique_colors = random.sample(colors, num_commands) - commands_fmt = {} - for i, cmd in enumerate(commands): - commands_fmt.update({cmd: {"fg": unique_colors[i], "bold": True}}) - commands_fmt.update({"--help": {"fg": "white"}}) - return commands_fmt - - -class HelpColorsFormatter(click.HelpFormatter): - """Click help formatting plugin. See file docstring for license. - - Modified from original copy to support click.style() instead of - direct ANSII string formatting. - """ - - def __init__( - self, - headers_color=None, - options_color=None, - options_custom_colors=None, - *args, - **kwargs - ): - """Initialize help formatter. - - Keyword Arguments: - headers_color {dict} -- click.style() paramters for header - options_color {dict} -- click.style() paramters for options - options_custom_colors {dict} -- click.style() paramters for options by name - """ - self.headers_color = headers_color or {} - self.options_color = options_color or {} - self.options_custom_colors = options_custom_colors or {} - - super().__init__(indent_increment=3, *args, **kwargs) - - def _pick_color(self, option_name): - """Filter options and pass relevant click.style() options for command.""" - opt = option_name.split()[0].strip(",") - color = {} - if self.options_custom_colors and opt in self.options_custom_colors.keys(): - color = self.options_custom_colors[opt] - else: - color = self.options_color - return color - - def write_usage(self, prog, args="", prefix="Usage: "): - """Write Usage: section.""" - prefix_fmt = click.style(prefix, **self.headers_color) - super().write_usage(prog, args, prefix=prefix_fmt) - - def write_heading(self, heading): - """Write Heading section.""" - heading_fmt = click.style(heading, **self.headers_color) - super().write_heading(heading_fmt) - - def write_dl(self, rows, **kwargs): - """Write Options section.""" - colorized_rows = [ - (click.style(row[0], **self._pick_color(row[0])), row[1]) for row in rows - ] - super().write_dl(colorized_rows, **kwargs) - - -class HelpColorsMixin: - """Click help formatting plugin. See file docstring for license. - - Modified from original copy to support click.style() instead of - direct ANSII string formatting. - """ - - def __init__( - self, - help_headers_color=None, - help_options_color=None, - help_options_custom_colors=None, - *args, - **kwargs - ): - """Initialize help mixin.""" - self.help_headers_color = help_headers_color or {} - self.help_options_color = help_options_color or {} - self.help_options_custom_colors = help_options_custom_colors or {} - super().__init__(*args, **kwargs) - - def get_help(self, ctx): - """Format help.""" - formatter = HelpColorsFormatter( - width=ctx.terminal_width, - max_width=ctx.max_content_width, - headers_color=self.help_headers_color, - options_color=self.help_options_color, - options_custom_colors=self.help_options_custom_colors, - ) - self.format_help(ctx, formatter) - return formatter.getvalue().rstrip("\n") - - -class HelpColorsGroup(HelpColorsMixin, click.Group): - """Click help formatting plugin. See file docstring for license. - - Modified from original copy to support click.style() instead of - direct ANSII string formatting. - """ - - def __init__(self, *args, **kwargs): - """Initialize group formatter.""" - super().__init__(*args, **kwargs) - - def command(self, *args, **kwargs): - """Set command values.""" - kwargs.setdefault("cls", HelpColorsCommand) - kwargs.setdefault("help_headers_color", self.help_headers_color) - kwargs.setdefault("help_options_color", self.help_options_color) - kwargs.setdefault("help_options_custom_colors", self.help_options_custom_colors) - return super().command(*args, **kwargs) - - def group(self, *args, **kwargs): - """Set group values.""" - kwargs.setdefault("cls", HelpColorsGroup) - kwargs.setdefault("help_headers_color", self.help_headers_color) - kwargs.setdefault("help_options_color", self.help_options_color) - kwargs.setdefault("help_options_custom_colors", self.help_options_custom_colors) - return super().group(*args, **kwargs) - - -class HelpColorsCommand(HelpColorsMixin, click.Command): - """Click help formatting plugin. See file docstring for license. - - Modified from original copy to support click.style() instead of - direct ANSII string formatting. - """ - - def __init__(self, *args, **kwargs): - """Initialize command formatter.""" - super().__init__(*args, **kwargs) diff --git a/hyperglass/cli/installer.py b/hyperglass/cli/installer.py deleted file mode 100644 index a9e2976..0000000 --- a/hyperglass/cli/installer.py +++ /dev/null @@ -1,114 +0,0 @@ -"""Install hyperglass.""" - -# Standard Library -import os -import shutil -from filecmp import dircmp -from pathlib import Path - -# Third Party -import inquirer - -# Local -from .echo import error, success, warning -from .util import create_dir - -USER_PATH = Path.home() / "hyperglass" -ROOT_PATH = Path("/etc/hyperglass/") -ASSET_DIR = Path(__file__).parent.parent / "images" -IGNORED_FILES = [".DS_Store"] - -INSTALL_PATHS = [ - inquirer.List( - "install_path", - message="Choose a directory for hyperglass", - choices=[USER_PATH, ROOT_PATH], - ) -] - - -def prompt_for_path() -> str: - """Recursively prompt the user for an app path until one is provided.""" - - answer = inquirer.prompt(INSTALL_PATHS) - - if answer is None: - warning("A directory for hyperglass is required") - answer = prompt_for_path() - - return answer["install_path"] - - -class Installer: - """Install hyperglass.""" - - def __init__(self, unattended: bool): - """Initialize installer.""" - - self.unattended = unattended - - def install(self) -> None: - """Complete the installation.""" - - self.app_path = self._get_app_path() - self._scaffold() - self._migrate_static_assets() - - def _get_app_path(self) -> Path: - """Find the app path from env variables or a prompt.""" - - if self.unattended: - return USER_PATH - - app_path = os.environ.get("HYPERGLASS_PATH", None) - - if app_path is None: - app_path = prompt_for_path() - - return app_path - - def _scaffold(self) -> None: - """Create the file structure necessary for hyperglass to run.""" - - ui_dir = self.app_path / "static" / "ui" - images_dir = self.app_path / "static" / "images" - favicon_dir = images_dir / "favicons" - custom_dir = self.app_path / "static" / "custom" - - create_dir(self.app_path) - - for path in (ui_dir, images_dir, favicon_dir, custom_dir): - create_dir(path, parents=True) - - def _migrate_static_assets(self) -> bool: - """Synchronize the project assets with the installation assets.""" - - target_dir = self.app_path / "static" / "images" - - if not target_dir.exists(): - shutil.copytree(ASSET_DIR, target_dir) - - # Compare the contents of the project's asset directory (considered - # the source of truth) with the installation directory. If they do - # not match, delete the installation directory's asset directory and - # re-copy it. - compare_initial = dircmp(ASSET_DIR, target_dir, ignore=IGNORED_FILES) - - if not compare_initial.left_list == compare_initial.right_list: - shutil.rmtree(target_dir) - shutil.copytree(ASSET_DIR, target_dir) - - # Re-compare the source and destination directory contents to - # ensure they match. - compare_post = dircmp(ASSET_DIR, target_dir, ignore=IGNORED_FILES) - - if not compare_post.left_list == compare_post.right_list: - error( - "Files in {a} do not match files in {b}", - a=str(ASSET_DIR), - b=str(target_dir), - ) - return False - - success("Migrated assets from {a} to {b}", a=str(ASSET_DIR), b=str(target_dir)) - return True diff --git a/hyperglass/cli/static.py b/hyperglass/cli/static.py deleted file mode 100644 index 624c511..0000000 --- a/hyperglass/cli/static.py +++ /dev/null @@ -1,127 +0,0 @@ -"""Static string definitions.""" -# Third Party -import click - - -class Char: - """Helper class for single-character strings.""" - - def __init__(self, char): - """Set instance character.""" - self.char = char - - def __getitem__(self, i): - """Subscription returns the instance's character * n.""" - return self.char * i - - def __str__(self): - """Stringify the instance character.""" - return str(self.char) - - def __repr__(self): - """Stringify the instance character for representation.""" - return str(self.char) - - def __add__(self, other): - """Addition method for string concatenation.""" - return str(self.char) + str(other) - - -class Emoji: - """Helper class for unicode emoji.""" - - BUTTERFLY = "\U0001F98B " - CHECK = "\U00002705 " - INFO = "\U00002755 " - ERROR = "\U0000274C " - WARNING = "\U000026A0\U0000FE0F " - TOOLBOX = "\U0001F9F0 " - NUMBERS = "\U0001F522 " - FOLDED_HANDS = "\U0001F64F " - ROCKET = "\U0001F680 " - SPARKLES = "\U00002728 " - PAPERCLIP = "\U0001F4CE " - KEY = "\U0001F511 " - LOCK = "\U0001F512 " - CLAMP = "\U0001F5DC " - BOOKS = "\U0001F4DA " - THERMOMETER = "\U0001F321 " - SOAP = "\U0001F9FC " - - -WS = Char(" ") -NL = Char("\n") -CL = Char(":") -E = Emoji() - -CLI_HELP = ( - click.style("hyperglass", fg="magenta", bold=True) - + WS[1] - + click.style("Command Line Interface", fg="white") -) - -# Click Style Helpers -SUCCESS = {"fg": "green", "bold": True} -WARNING = {"fg": "yellow"} -ERROR = {"fg": "red", "bold": True} -LABEL = {"fg": "white"} -INFO = {"fg": "blue", "bold": True} -STATUS = {"fg": "black"} -VALUE = {"fg": "magenta", "bold": True} -CMD_HELP = {"fg": "white"} - - -class Message: - """Helper class for single-character strings.""" - - colors = { - "warning": "yellow", - "success": "green", - "error": "red", - "info": "blue", - "status": "black", - "label": "white", - } - label_colors = { - "warning": "yellow", - "success": "green", - "error": "red", - "info": "blue", - "status": "black", - "label": "magenta", - } - emojis = { - "warning": E.WARNING, - "success": E.CHECK, - "error": E.ERROR, - "info": E.INFO, - "status": "", - "label": "", - } - - def __init__(self, state): - """Set instance character.""" - self.state = state - self.color = self.colors[self.state] - self.label_color = self.label_colors[self.state] - - @property - def msg(self): - """Click style attributes for message text.""" - return {"fg": self.color} - - @property - def kw(self): - """Click style attributes for keywords.""" - return {"fg": self.label_color, "bold": True, "underline": True} - - @property - def emoji(self): - """Match emoji from state.""" - return self.emojis[self.state] - - def __repr__(self): - """Stringify the instance character for representation.""" - return "Message(msg={m}, kw={k}, emoji={e})".format( - m=self.msg, k=self.kw, e=self.emoji - ) diff --git a/hyperglass/cli/util.py b/hyperglass/cli/util.py deleted file mode 100644 index 1a6759a..0000000 --- a/hyperglass/cli/util.py +++ /dev/null @@ -1,181 +0,0 @@ -"""CLI utility functions.""" - -# Standard Library -import os -from pathlib import Path - -# Third Party -from click import echo, style - -# Project -from hyperglass.cli.echo import info, error, status, success -from hyperglass.cli.static import CL, NL, WS, E - -PROJECT_ROOT = Path(__file__).parent.parent - - -def async_command(func) -> None: - """Decororator for to make async functions runable from synchronous code.""" - # Standard Library - import asyncio - from functools import update_wrapper - - func = asyncio.coroutine(func) - - def wrapper(*args, **kwargs): - loop = asyncio.get_event_loop() - return loop.run_until_complete(func(*args, **kwargs)) - - return update_wrapper(wrapper, func) - - -def start_web_server(start, params): - """Start web server.""" - msg_start = "Starting hyperglass web server on" - msg_uri = "http://" - msg_host = str(params["host"]) - msg_port = str(params["port"]) - msg_len = len("".join([msg_start, WS[1], msg_uri, msg_host, CL[1], msg_port])) - try: - echo( - NL[1] - + WS[msg_len + 8] - + E.ROCKET - + NL[1] - + E.CHECK - + style(msg_start, fg="green", bold=True) - + WS[1] - + style(msg_uri, fg="white") - + style(msg_host, fg="blue", bold=True) - + style(CL[1], fg="white") - + style(msg_port, fg="magenta", bold=True) - + WS[1] - + E.ROCKET - + NL[1] - + WS[1] - + NL[1] - ) - start() - - except Exception as e: - error("Failed to start web server: {e}", e=e) - - -def build_ui(timeout: int) -> None: - """Create a new UI build.""" - try: - # Project - from hyperglass.configuration import CONFIG_PATH, params, frontend_params - from hyperglass.util.frontend import build_frontend - from hyperglass.compat._asyncio import aiorun - except ImportError as e: - error("Error importing UI builder: {e}", e=e) - - status("Starting new UI build with a {t} second timeout...", t=timeout) - - if params.developer_mode: - dev_mode = "development" - else: - dev_mode = "production" - - try: - build_success = aiorun( - build_frontend( - dev_mode=params.developer_mode, - dev_url=f"http://localhost:{str(params.listen_port)}/", - prod_url="/api/", - params=frontend_params, - force=True, - app_path=CONFIG_PATH, - ) - ) - if build_success: - success("Completed UI build in {m} mode", m=dev_mode) - - except Exception as e: - error("Error building UI: {e}", e=e) - - return True - - -def create_dir(path, **kwargs) -> bool: - """Validate and attempt to create a directory, if it does not exist.""" - - # If input path is not a path object, try to make it one - if not isinstance(path, Path): - try: - path = Path(path) - except TypeError: - error("{p} is not a valid path", p=path) - - # If path does not exist, try to create it - if not path.exists(): - try: - path.mkdir(**kwargs) - except PermissionError: - error( - "{u} does not have permission to create {p}. Try running with sudo?", - u=os.getlogin(), - p=path, - ) - - # Verify the path was actually created - if path.exists(): - success("Created {p}", p=path) - - # If the path already exists, inform the user - elif path.exists(): - info("{p} already exists", p=path) - - return True - - -def write_to_file(file, data) -> bool: - """Write string data to a file.""" - try: - with file.open("w+") as f: - f.write(data.strip()) - except PermissionError: - error( - "{u} does not have permission to write to {f}. Try running with sudo?", - u=os.getlogin(), - f=file, - ) - if not file.exists(): - error("Error writing file {f}", f=file) - elif file.exists(): - success("Wrote systemd file {f}", f=file) - return True - - -def system_info() -> None: - """Create a markdown table of various system information.""" - # Project - from hyperglass.util.system_info import get_system_info - - data = get_system_info() - - def _code(val): - return f"`{str(val)}`" - - def _bold(val): - return f"**{str(val)}**" - - md_table_lines = ("| Metric | Value |", "| :----- | :---- |") - - for title, metric in data.items(): - value, mod = metric - - title = _bold(title) - - if mod == "code": - value = _code(value) - - md_table_lines += (f"| {title} | {value} |",) - - md_table = "\n".join(md_table_lines) - - info("Please copy & paste this table in your bug report:\n") - echo(md_table + "\n") - - return None diff --git a/hyperglass/compat/__init__.py b/hyperglass/compat/__init__.py deleted file mode 100644 index 0352479..0000000 --- a/hyperglass/compat/__init__.py +++ /dev/null @@ -1 +0,0 @@ -"""Functions for maintaining compatability with older Python versions or libraries.""" diff --git a/hyperglass/compat/_asyncio.py b/hyperglass/compat/_asyncio.py deleted file mode 100644 index 8cfeed9..0000000 --- a/hyperglass/compat/_asyncio.py +++ /dev/null @@ -1,118 +0,0 @@ -"""Functions for maintaining asyncio compatability with other versions of Python.""" - -# Standard Library -import sys -import asyncio -import weakref - -try: - # Standard Library - from asyncio import get_running_loop -except ImportError: - # Standard Library - from asyncio.events import _get_running_loop as get_running_loop - -RUNNING_PYTHON_VERSION = sys.version_info - -# _patch_loop, _patched_run, and _cancel_all_tasks are taken directly -# from github.com/nickdavis: -# https://gist.github.com/nickdavies/4a37c6cd9dcc7041fddd2d2a81cee383 - -# These functions are a backport of the functionality added in -# Python 3.7 to support asyncio.run(), which is used in several areas -# of hyperglass. Because the LTS version of Ubuntu at this time (18.04) -# still ships with Python 3.6, compatibility with Python 3.6 is the -# goal. - - -def _patch_loop(loop): - tasks = weakref.WeakSet() - - task_factory = [None] - - def _set_task_factory(factory): - task_factory[0] = factory - - def _get_task_factory(): - return task_factory[0] - - def _safe_task_factory(loop, coro): - if task_factory[0] is None: - task = asyncio.Task(coro, loop=loop) - if task._source_traceback: - del task._source_traceback[-1] - else: - task = task_factory[0](loop, coro) - tasks.add(task) - return task - - loop.set_task_factory(_safe_task_factory) - loop.set_task_factory = _set_task_factory - loop.get_task_factory = _get_task_factory - - return tasks - - -def _cancel_all_tasks(loop, tasks): - to_cancel = [task for task in tasks if not task.done()] - - if not to_cancel: - return - - for task in to_cancel: - task.cancel() - - loop.run_until_complete( - asyncio.gather(*to_cancel, loop=loop, return_exceptions=True) - ) - - for task in to_cancel: - if task.cancelled(): - continue - if task.exception() is not None: - loop.call_exception_handler( - { - "message": "unhandled exception during asyncio.run() shutdown", - "exception": task.exception(), - "task": task, - } - ) - - -def _patched_run(main, *, debug=False): - try: - loop = get_running_loop() - except RuntimeError: - loop = None - - if loop is not None: - raise RuntimeError("asyncio.run() cannot be called from a running event loop") - - if not asyncio.iscoroutine(main): - raise ValueError("a coroutine was expected, got {!r}".format(main)) - - loop = asyncio.new_event_loop() - tasks = _patch_loop(loop) - - try: - asyncio.set_event_loop(loop) - loop.set_debug(debug) - return loop.run_until_complete(main) - finally: - try: - _cancel_all_tasks(loop, tasks) - loop.run_until_complete(loop.shutdown_asyncgens()) - finally: - asyncio.set_event_loop(None) - loop.close() - - -# If local system's python version is at least 3.6, use the backported -# asyncio runner. -if RUNNING_PYTHON_VERSION >= (3, 6): - aiorun = _patched_run - -# If the local system's python version is at least 3.7, use the standard -# library's asyncio.run() -elif RUNNING_PYTHON_VERSION >= (3, 7): - aiorun = asyncio.run diff --git a/hyperglass/compat/_sshtunnel.py b/hyperglass/compat/_sshtunnel.py deleted file mode 100644 index 59ff3a6..0000000 --- a/hyperglass/compat/_sshtunnel.py +++ /dev/null @@ -1,1619 +0,0 @@ -"""Initiate SSH tunnels via a remote gateway. - -Copyright (c) 2014-2019 Pahaz Blinov - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -*sshtunnel* - Initiate SSH tunnels via a remote gateway. - -``sshtunnel`` works by opening a port forwarding SSH connection in the -background, using threads. - -The connection(s) are closed when explicitly calling the -:meth:`SSHTunnelForwarder.stop` method or using it as a context. -""" - -# Standard Library -import os -import sys -import queue -import socket -import getpass -import logging -import argparse -import warnings -import threading -import socketserver -from select import select -from binascii import hexlify - -# Third Party -import paramiko - -# Project -from hyperglass.log import log -from hyperglass.configuration import params - -if params.debug: - logging.getLogger("paramiko").setLevel(logging.DEBUG) - -log.bind(logger_name="paramiko") - -TUNNEL_TIMEOUT = 1.0 #: Timeout (seconds) for tunnel connection -_DAEMON = False #: Use daemon threads in connections -_CONNECTION_COUNTER = 1 -_LOCK = threading.Lock() - -DEPRECATIONS = { - "ssh_address": "ssh_address_or_host", - "ssh_host": "ssh_address_or_host", - "ssh_private_key": "ssh_pkey", - "raise_exception_if_any_forwarder_have_a_problem": "mute_exceptions", -} - -if os.name == "posix": - DEFAULT_SSH_DIRECTORY = "~/.ssh" - UnixStreamServer = socketserver.UnixStreamServer -else: - DEFAULT_SSH_DIRECTORY = "~/ssh" - UnixStreamServer = socketserver.TCPServer - -#: Path of optional ssh configuration file -SSH_CONFIG_FILE = os.path.join(DEFAULT_SSH_DIRECTORY, "config") - -######################## -# # -# Utils # -# # -######################## - - -def check_host(host): - assert isinstance(host, str), "IP is not a string ({0})".format(type(host).__name__) - - -def check_port(port): - assert isinstance(port, int), "PORT is not a number" - assert port >= 0, "PORT < 0 ({0})".format(port) - - -def check_address(address): - """Check if the format of the address is correct. - - Arguments: - address (tuple): - (``str``, ``int``) representing an IP address and port, - respectively - - .. note:: - alternatively a local ``address`` can be a ``str`` when working - with UNIX domain sockets, if supported by the platform - Raises: - ValueError: - raised when address has an incorrect format - - Example: - >>> check_address(('127.0.0.1', 22)) - """ - if isinstance(address, tuple): - check_host(address[0]) - check_port(address[1]) - elif isinstance(address, str): - if os.name != "posix": - raise ValueError("Platform does not support UNIX domain sockets") - if not ( - os.path.exists(address) or os.access(os.path.dirname(address), os.W_OK) - ): - raise ValueError( - "ADDRESS not a valid socket domain socket ({0})".format(address) - ) - else: - raise ValueError( - "ADDRESS is not a tuple, string, or character buffer " - "({0})".format(type(address).__name__) - ) - - -def check_addresses(address_list, is_remote=False): - """ - Check if the format of the addresses is correct - - Arguments: - address_list (list[tuple]): - Sequence of (``str``, ``int``) pairs, each representing an IP - address and port respectively - - .. note:: - when supported by the platform, one or more of the elements in - the list can be of type ``str``, representing a valid UNIX - domain socket - - is_remote (boolean): - Whether or not the address list - Raises: - AssertionError: - raised when ``address_list`` contains an invalid element - ValueError: - raised when any address in the list has an incorrect format - - Example: - - >>> check_addresses([('127.0.0.1', 22), ('127.0.0.1', 2222)]) - """ - assert all(isinstance(x, (tuple, str)) for x in address_list) - if is_remote and any(isinstance(x, str) for x in address_list): - raise AssertionError("UNIX domain sockets not allowed for remote" "addresses") - - for address in address_list: - check_address(address) - - -def address_to_str(address): - if isinstance(address, tuple): - return "{0[0]}:{0[1]}".format(address) - return str(address) - - -def get_connection_id(): - global _CONNECTION_COUNTER - with _LOCK: - uid = _CONNECTION_COUNTER - _CONNECTION_COUNTER += 1 - return uid - - -def _remove_none_values(dictionary): - """ Remove dictionary keys whose value is None.""" - return list(map(dictionary.pop, [i for i in dictionary if dictionary[i] is None])) - - -######################## -# # -# Errors # -# # -######################## - - -class BaseSSHTunnelForwarderError(Exception): - """ Exception raised by :class:`SSHTunnelForwarder` errors """ - - def __init__(self, *args, **kwargs): - self.value = kwargs.pop("value", args[0] if args else "") - - def __str__(self): - return self.value - - -class HandlerSSHTunnelForwarderError(BaseSSHTunnelForwarderError): - """ Exception for Tunnel forwarder errors """ - - pass - - -######################## -# # -# Handlers # -# # -######################## - - -class _ForwardHandler(socketserver.BaseRequestHandler): - """ Base handler for tunnel connections """ - - remote_address = None - ssh_transport = None - logger = None - info = None - - def _redirect(self, chan): - while chan.active: - rqst, _, _ = select([self.request, chan], [], [], 5) - if self.request in rqst: - data = self.request.recv(1024) - if not data: - break - self.logger.trace( - ">>> OUT {0} send to {1}: {2} >>>".format( - self.info, self.remote_address, hexlify(data) - ), - ) - chan.sendall(data) - if chan in rqst: # else - if not chan.recv_ready(): - break - data = chan.recv(1024) - self.logger.trace( - "<<< IN {0} recv: {1} <<<".format(self.info, hexlify(data)), - ) - self.request.sendall(data) - - def handle(self): - uid = get_connection_id() - self.info = "#{0} <-- {1}".format( - uid, self.client_address or self.server.local_address - ) - src_address = self.request.getpeername() - if not isinstance(src_address, tuple): - src_address = ("dummy", 12345) - try: - chan = self.ssh_transport.open_channel( - kind="direct-tcpip", - dest_addr=self.remote_address, - src_addr=src_address, - timeout=TUNNEL_TIMEOUT, - ) - except paramiko.SSHException: - chan = None - if chan is None: - msg = "{0} to {1} was rejected by the SSH server".format( - self.info, self.remote_address - ) - self.logger.trace(msg) - raise HandlerSSHTunnelForwarderError(msg) - - self.logger.trace("{0} connected".format(self.info)) - try: - self._redirect(chan) - except socket.error: - # Sometimes a RST is sent and a socket error is raised, treat this - # exception. It was seen that a 3way FIN is processed later on, so - # no need to make an ordered close of the connection here or raise - # the exception beyond this point... - self.logger.trace("{0} sending RST".format(self.info)) - except Exception as e: - self.logger.trace("{0} error: {1}".format(self.info, repr(e))) - finally: - chan.close() - self.request.close() - self.logger.trace("{0} connection closed.".format(self.info)) - - -class _ForwardServer(socketserver.TCPServer): # Not Threading - """ - Non-threading version of the forward server - """ - - allow_reuse_address = True # faster rebinding - - def __init__(self, *args, **kwargs): - self.logger = kwargs.pop("logger") or log - self.tunnel_ok = queue.Queue() - socketserver.TCPServer.__init__(self, *args, **kwargs) - - def handle_error(self, request, client_address): - (exc_class, exc, tb) = sys.exc_info() - self.logger.error( - "Could not establish connection from {0} to remote " "side of the tunnel", - request.getsockname(), - ) - self.tunnel_ok.put(False) - - @property - def local_address(self): - return self.server_address - - @property - def local_host(self): - return self.server_address[0] - - @property - def local_port(self): - return self.server_address[1] - - @property - def remote_address(self): - return self.RequestHandlerClass.remote_address - - @property - def remote_host(self): - return self.RequestHandlerClass.remote_address[0] - - @property - def remote_port(self): - return self.RequestHandlerClass.remote_address[1] - - -class _ThreadingForwardServer(socketserver.ThreadingMixIn, _ForwardServer): - """ - Allow concurrent connections to each tunnel - """ - - # If True, cleanly stop threads created by ThreadingMixIn when quitting - daemon_threads = _DAEMON - - -class _UnixStreamForwardServer(UnixStreamServer): - """ - Serve over UNIX domain sockets (does not work on Windows) - """ - - def __init__(self, *args, **kwargs): - self.logger = kwargs.pop("logger") or log - self.tunnel_ok = queue.Queue() - UnixStreamServer.__init__(self, *args, **kwargs) - - @property - def local_address(self): - return self.server_address - - @property - def local_host(self): - return None - - @property - def local_port(self): - return None - - @property - def remote_address(self): - return self.RequestHandlerClass.remote_address - - @property - def remote_host(self): - return self.RequestHandlerClass.remote_address[0] - - @property - def remote_port(self): - return self.RequestHandlerClass.remote_address[1] - - -class _ThreadingUnixStreamForwardServer( - socketserver.ThreadingMixIn, _UnixStreamForwardServer -): - """ - Allow concurrent connections to each tunnel - """ - - # If True, cleanly stop threads created by ThreadingMixIn when quitting - daemon_threads = _DAEMON - - -class SSHTunnelForwarder: - """ - **SSH tunnel class** - - - Initialize a SSH tunnel to a remote host according to the input - arguments - - - Optionally: - + Read an SSH configuration file (typically ``~/.ssh/config``) - + Load keys from a running SSH agent (i.e. Pageant, GNOME Keyring) - - Raises: - - :class:`.BaseSSHTunnelForwarderError`: - raised by SSHTunnelForwarder class methods - - :class:`.HandlerSSHTunnelForwarderError`: - raised by tunnel forwarder threads - - .. note:: - Attributes ``mute_exceptions`` and - ``raise_exception_if_any_forwarder_have_a_problem`` - (deprecated) may be used to silence most exceptions raised - from this class - - Keyword Arguments: - - ssh_address_or_host (tuple or str): - IP or hostname of ``REMOTE GATEWAY``. It may be a two-element - tuple (``str``, ``int``) representing IP and port respectively, - or a ``str`` representing the IP address only - - .. versionadded:: 0.0.4 - - ssh_config_file (str): - SSH configuration file that will be read. If explicitly set to - ``None``, parsing of this configuration is omitted - - Default: :const:`SSH_CONFIG_FILE` - - .. versionadded:: 0.0.4 - - ssh_host_key (str): - Representation of a line in an OpenSSH-style "known hosts" - file. - - ``REMOTE GATEWAY``'s key fingerprint will be compared to this - host key in order to prevent against SSH server spoofing. - Important when using passwords in order not to accidentally - do a login attempt to a wrong (perhaps an attacker's) machine - - ssh_username (str): - Username to authenticate as in ``REMOTE SERVER`` - - Default: current local user name - - ssh_password (str): - Text representing the password used to connect to ``REMOTE - SERVER`` or for unlocking a private key. - - .. note:: - Avoid coding secret password directly in the code, since this - may be visible and make your service vulnerable to attacks - - ssh_port (int): - Optional port number of the SSH service on ``REMOTE GATEWAY``, - when `ssh_address_or_host`` is a ``str`` representing the - IP part of ``REMOTE GATEWAY``'s address - - Default: 22 - - ssh_pkey (str or paramiko.PKey): - **Private** key file name (``str``) to obtain the public key - from or a **public** key (:class:`paramiko.pkey.PKey`) - - ssh_private_key_password (str): - Password for an encrypted ``ssh_pkey`` - - .. note:: - Avoid coding secret password directly in the code, since this - may be visible and make your service vulnerable to attacks - - ssh_proxy (socket-like object or tuple): - Proxy where all SSH traffic will be passed through. - It might be for example a :class:`paramiko.proxy.ProxyCommand` - instance. - See either the :class:`paramiko.transport.Transport`'s sock - parameter documentation or ``ProxyCommand`` in ``ssh_config(5)`` - for more information. - - It is also possible to specify the proxy address as a tuple of - type (``str``, ``int``) representing proxy's IP and port - - .. note:: - Ignored if ``ssh_proxy_enabled`` is False - - .. versionadded:: 0.0.5 - - ssh_proxy_enabled (boolean): - Enable/disable SSH proxy. If True and user's - ``ssh_config_file`` contains a ``ProxyCommand`` directive - that matches the specified ``ssh_address_or_host``, - a :class:`paramiko.proxy.ProxyCommand` object will be created where - all SSH traffic will be passed through - - Default: ``True`` - - .. versionadded:: 0.0.4 - - local_bind_address (tuple): - Local tuple in the format (``str``, ``int``) representing the - IP and port of the local side of the tunnel. Both elements in - the tuple are optional so both ``('', 8000)`` and - ``('10.0.0.1', )`` are valid values - - Default: ``('0.0.0.0', RANDOM_PORT)`` - - .. versionchanged:: 0.0.8 - Added the ability to use a UNIX domain socket as local bind - address - - local_bind_addresses (list[tuple]): - In case more than one tunnel is established at once, a list - of tuples (in the same format as ``local_bind_address``) - can be specified, such as [(ip1, port_1), (ip_2, port2), ...] - - Default: ``[local_bind_address]`` - - .. versionadded:: 0.0.4 - - remote_bind_address (tuple): - Remote tuple in the format (``str``, ``int``) representing the - IP and port of the remote side of the tunnel. - - remote_bind_addresses (list[tuple]): - In case more than one tunnel is established at once, a list - of tuples (in the same format as ``remote_bind_address``) - can be specified, such as [(ip1, port_1), (ip_2, port2), ...] - - Default: ``[remote_bind_address]`` - - .. versionadded:: 0.0.4 - - allow_agent (boolean): - Enable/disable load of keys from an SSH agent - - Default: ``True`` - - .. versionadded:: 0.0.8 - - host_pkey_directories (list): - Look for pkeys in folders on this list, for example ['~/.ssh']. - - Default: ``None`` (disabled) - - .. versionadded:: 0.1.4 - - compression (boolean): - Turn on/off transport compression. By default compression is - disabled since it may negatively affect interactive sessions - - Default: ``False`` - - .. versionadded:: 0.0.8 - - logger (logging.Logger): - logging instance for sshtunnel and paramiko - - Default: :class:`logging.Logger` instance with a single - :class:`logging.StreamHandler` handler and - :const:`DEFAULT_LOGLEVEL` level - - .. versionadded:: 0.0.3 - - mute_exceptions (boolean): - Allow silencing :class:`BaseSSHTunnelForwarderError` or - :class:`HandlerSSHTunnelForwarderError` exceptions when enabled - - Default: ``False`` - - .. versionadded:: 0.0.8 - - set_keepalive (float): - Interval in seconds defining the period in which, if no data - was sent over the connection, a *'keepalive'* packet will be - sent (and ignored by the remote host). This can be useful to - keep connections alive over a NAT - - Default: 0.0 (no keepalive packets are sent) - - .. versionadded:: 0.0.7 - - threaded (boolean): - Allow concurrent connections over a single tunnel - - Default: ``True`` - - .. versionadded:: 0.0.3 - - ssh_address (str): - Superseded by ``ssh_address_or_host``, tuple of type (str, int) - representing the IP and port of ``REMOTE SERVER`` - - .. deprecated:: 0.0.4 - - ssh_host (str): - Superseded by ``ssh_address_or_host``, tuple of type - (str, int) representing the IP and port of ``REMOTE SERVER`` - - .. deprecated:: 0.0.4 - - ssh_private_key (str or paramiko.PKey): - Superseded by ``ssh_pkey``, which can represent either a - **private** key file name (``str``) or a **public** key - (:class:`paramiko.pkey.PKey`) - - .. deprecated:: 0.0.8 - - raise_exception_if_any_forwarder_have_a_problem (boolean): - Allow silencing :class:`BaseSSHTunnelForwarderError` or - :class:`HandlerSSHTunnelForwarderError` exceptions when set to - False - - Default: ``True`` - - .. versionadded:: 0.0.4 - - .. deprecated:: 0.0.8 (use ``mute_exceptions`` instead) - - Attributes: - - tunnel_is_up (dict): - Describe whether or not the other side of the tunnel was reported - to be up (and we must close it) or not (skip shutting down that - tunnel) - - .. note:: - This attribute should not be modified - - .. note:: - When :attr:`.skip_tunnel_checkup` is disabled or the local bind - is a UNIX socket, the value will always be ``True`` - - **Example**:: - - {('127.0.0.1', 55550): True, # this tunnel is up - ('127.0.0.1', 55551): False} # this one isn't - - where 55550 and 55551 are the local bind ports - - skip_tunnel_checkup (boolean): - Disable tunnel checkup (default for backwards compatibility). - - .. versionadded:: 0.1.0 - - """ - - skip_tunnel_checkup = True - daemon_forward_servers = _DAEMON #: flag tunnel threads in daemon mode - daemon_transport = _DAEMON #: flag SSH transport thread in daemon mode - - def local_is_up(self, target): - """ - Check if a tunnel is up (remote target's host is reachable on TCP - target's port) - - Arguments: - target (tuple): - tuple of type (``str``, ``int``) indicating the listen IP - address and port - Return: - boolean - - .. deprecated:: 0.1.0 - Replaced by :meth:`.check_tunnels()` and :attr:`.tunnel_is_up` - """ - try: - check_address(target) - except ValueError: - self.logger.warning( - "Target must be a tuple (IP, port), where IP " - 'is a string (i.e. "192.168.0.1") and port is ' - "an integer (i.e. 40000). Alternatively " - "target can be a valid UNIX domain socket." - ) - return False - - if self.skip_tunnel_checkup: # force tunnel check at this point - self.skip_tunnel_checkup = False - self.check_tunnels() - self.skip_tunnel_checkup = True # roll it back - return self.tunnel_is_up.get(target, True) - - def _make_ssh_forward_handler_class(self, remote_address_): - """ - Make SSH Handler class - """ - - class Handler(_ForwardHandler): - remote_address = remote_address_ - ssh_transport = self._transport - logger = self.logger - - return Handler - - def _make_ssh_forward_server_class(self, remote_address_): - return _ThreadingForwardServer if self._threaded else _ForwardServer - - def _make_unix_ssh_forward_server_class(self, remote_address_): - return ( - _ThreadingUnixStreamForwardServer - if self._threaded - else _UnixStreamForwardServer - ) - - def _make_ssh_forward_server(self, remote_address, local_bind_address): - """ - Make SSH forward proxy Server class - """ - _Handler = self._make_ssh_forward_handler_class(remote_address) - try: - if isinstance(local_bind_address, str): - forward_maker_class = self._make_unix_ssh_forward_server_class - else: - forward_maker_class = self._make_ssh_forward_server_class - _Server = forward_maker_class(remote_address) - ssh_forward_server = _Server( - local_bind_address, _Handler, logger=self.logger, - ) - - if ssh_forward_server: - ssh_forward_server.daemon_threads = self.daemon_forward_servers - self._server_list.append(ssh_forward_server) - self.tunnel_is_up[ssh_forward_server.server_address] = False - else: - self._raise( - BaseSSHTunnelForwarderError, - "Problem setting up ssh {0} <> {1} forwarder. You can " - "suppress this exception by using the `mute_exceptions`" - "argument".format( - address_to_str(local_bind_address), - address_to_str(remote_address), - ), - ) - except IOError: - self._raise( - BaseSSHTunnelForwarderError, - "Couldn't open tunnel {0} <> {1} might be in use or " - "destination not reachable".format( - address_to_str(local_bind_address), address_to_str(remote_address) - ), - ) - - def __init__( - self, - ssh_address_or_host=None, - ssh_config_file=SSH_CONFIG_FILE, - ssh_host_key=None, - ssh_password=None, - ssh_pkey=None, - ssh_private_key_password=None, - ssh_proxy=None, - ssh_proxy_enabled=True, - ssh_username=None, - local_bind_address=None, - local_bind_addresses=None, - logger=None, - mute_exceptions=False, - remote_bind_address=None, - remote_bind_addresses=None, - set_keepalive=0.0, - threaded=True, # old version False - compression=None, - allow_agent=True, # look for keys from an SSH agent - host_pkey_directories=None, # look for keys in ~/.ssh - gateway_timeout=None, - *args, - **kwargs, # for backwards compatibility - ): - self.logger = logger or log - self.ssh_host_key = ssh_host_key - self.set_keepalive = set_keepalive - self._server_list = [] # reset server list - self.tunnel_is_up = {} # handle tunnel status - self._threaded = threaded - self.is_alive = False - self.gateway_timeout = gateway_timeout - # Check if deprecated arguments ssh_address or ssh_host were used - for deprecated_argument in ["ssh_address", "ssh_host"]: - ssh_address_or_host = self._process_deprecated( - ssh_address_or_host, deprecated_argument, kwargs - ) - # other deprecated arguments - ssh_pkey = self._process_deprecated(ssh_pkey, "ssh_private_key", kwargs) - - self._raise_fwd_exc = ( - self._process_deprecated( - None, "raise_exception_if_any_forwarder_have_a_problem", kwargs - ) - or not mute_exceptions - ) - - if isinstance(ssh_address_or_host, tuple): - check_address(ssh_address_or_host) - (ssh_host, ssh_port) = ssh_address_or_host - else: - ssh_host = ssh_address_or_host - ssh_port = kwargs.pop("ssh_port", None) - - if kwargs: - raise ValueError("Unknown arguments: {0}".format(kwargs)) - - # remote binds - self._remote_binds = self._get_binds( - remote_bind_address, remote_bind_addresses, is_remote=True - ) - # local binds - self._local_binds = self._get_binds(local_bind_address, local_bind_addresses) - self._local_binds = self._consolidate_binds( - self._local_binds, self._remote_binds - ) - - ( - self.ssh_host, - self.ssh_username, - ssh_pkey, # still needs to go through _consolidate_auth - self.ssh_port, - self.ssh_proxy, - self.compression, - ) = self._read_ssh_config( - ssh_host, - ssh_config_file, - ssh_username, - ssh_pkey, - ssh_port, - ssh_proxy if ssh_proxy_enabled else None, - compression, - self.logger, - ) - - (self.ssh_password, self.ssh_pkeys) = self._consolidate_auth( - ssh_password=ssh_password, - ssh_pkey=ssh_pkey, - ssh_pkey_password=ssh_private_key_password, - allow_agent=allow_agent, - host_pkey_directories=host_pkey_directories, - logger=self.logger, - ) - - check_host(self.ssh_host) - check_port(self.ssh_port) - - self.logger.info( - "Connecting to gateway: {h}:{p} as user '{u}', timeout {t}", - h=self.ssh_host, - p=self.ssh_port, - u=self.ssh_username, - t=self.gateway_timeout, - ) - - self.logger.debug("Concurrent connections allowed: {0}", self._threaded) - - @staticmethod - def _read_ssh_config( - ssh_host, - ssh_config_file, - ssh_username=None, - ssh_pkey=None, - ssh_port=None, - ssh_proxy=None, - compression=None, - logger=log, - ): - """Read ssh_config_file. - - Read ssh_config_file and try to look for user (ssh_username), - identityfile (ssh_pkey), port (ssh_port) and proxycommand - (ssh_proxy) entries for ssh_host - """ - ssh_config = paramiko.SSHConfig() - if not ssh_config_file: # handle case where it's an empty string - ssh_config_file = None - - # Try to read SSH_CONFIG_FILE - try: - # open the ssh config file - with open(os.path.expanduser(ssh_config_file), "r") as f: - ssh_config.parse(f) - # looks for information for the destination system - hostname_info = ssh_config.lookup(ssh_host) - # gather settings for user, port and identity file - # last resort: use the 'login name' of the user - ssh_username = ssh_username or hostname_info.get("user") - ssh_pkey = ssh_pkey or hostname_info.get("identityfile", [None])[0] - ssh_host = hostname_info.get("hostname") - ssh_port = ssh_port or hostname_info.get("port") - - proxycommand = hostname_info.get("proxycommand") - ssh_proxy = ssh_proxy or ( - paramiko.ProxyCommand(proxycommand) if proxycommand else None - ) - if compression is None: - compression = hostname_info.get("compression", "") - compression = True if compression.upper() == "YES" else False - except IOError: - logger.warning( - "Could not read SSH configuration file: {f}", f=ssh_config_file - ) - except (AttributeError, TypeError): # ssh_config_file is None - logger.info("Skipping loading of ssh configuration file") - finally: - return ( - ssh_host, - ssh_username or getpass.getuser(), - ssh_pkey, - int(ssh_port) if ssh_port else 22, # fallback value - ssh_proxy, - compression, - ) - - @staticmethod - def get_agent_keys(logger=log): - """Load public keys from any available SSH agent. - - Arguments: - logger (Optional[logging.Logger]) - - Return: - list - """ - paramiko_agent = paramiko.Agent() - agent_keys = paramiko_agent.get_keys() - - logger.info("{k} keys loaded from agent", k=len(agent_keys)) - - return list(agent_keys) - - @staticmethod - def get_keys(logger=log, host_pkey_directories=None, allow_agent=False): - """Load public keys from any available SSH agent or local .ssh directory. - - Arguments: - logger (Optional[logging.Logger]) - - host_pkey_directories (Optional[list[str]]): - List of local directories where host SSH pkeys in the format - "id_*" are searched. For example, ['~/.ssh'] - - .. versionadded:: 0.1.0 - - allow_agent (Optional[boolean]): - Whether or not load keys from agent - - Default: False - - Return: - list - """ - keys = SSHTunnelForwarder.get_agent_keys(logger=logger) if allow_agent else [] - - if host_pkey_directories is not None: - paramiko_key_types = { - "rsa": paramiko.RSAKey, - "dsa": paramiko.DSSKey, - "ecdsa": paramiko.ECDSAKey, - "ed25519": paramiko.Ed25519Key, - } - for directory in host_pkey_directories or [DEFAULT_SSH_DIRECTORY]: - for keytype in paramiko_key_types.keys(): - ssh_pkey_expanded = os.path.expanduser( - os.path.join(directory, "id_{}".format(keytype)) - ) - if os.path.isfile(ssh_pkey_expanded): - ssh_pkey = SSHTunnelForwarder.read_private_key_file( - pkey_file=ssh_pkey_expanded, - logger=logger, - key_type=paramiko_key_types[keytype], - ) - if ssh_pkey: - keys.append(ssh_pkey) - - logger.info("{k} keys loaded from host directory", k=len(keys)) - - return keys - - @staticmethod - def _consolidate_binds(local_binds, remote_binds): - """Fill local_binds with defaults. - - Fill local_binds with defaults when no value/s were specified, - leaving paramiko to decide in which local port the tunnel will be open. - """ - count = len(remote_binds) - len(local_binds) - if count < 0: - raise ValueError( - "Too many local bind addresses " - "(local_bind_addresses > remote_bind_addresses)" - ) - local_binds.extend([("0.0.0.0", 0) for x in range(count)]) - return local_binds - - @staticmethod - def _consolidate_auth( - ssh_password=None, - ssh_pkey=None, - ssh_pkey_password=None, - allow_agent=True, - host_pkey_directories=None, - logger=log, - ): - """Get sure authentication information is in place. - - ``ssh_pkey`` may be of classes: - - ``str`` - in this case it represents a private key file; public - key will be obtained from it - - ``paramiko.Pkey`` - it will be transparently added to loaded keys - """ - ssh_loaded_pkeys = SSHTunnelForwarder.get_keys( - logger=logger, - host_pkey_directories=host_pkey_directories, - allow_agent=allow_agent, - ) - - if isinstance(ssh_pkey, str): - ssh_pkey_expanded = os.path.expanduser(ssh_pkey) - if os.path.exists(ssh_pkey_expanded): - ssh_pkey = SSHTunnelForwarder.read_private_key_file( - pkey_file=ssh_pkey_expanded, - pkey_password=ssh_pkey_password or ssh_password, - logger=logger, - ) - else: - logger.warning("Private key file not found: {k}", k=ssh_pkey) - - if isinstance(ssh_pkey, paramiko.pkey.PKey): - ssh_loaded_pkeys.insert(0, ssh_pkey) - - if not ssh_password and not ssh_loaded_pkeys: - raise ValueError("No password or public key available!") - return (ssh_password, ssh_loaded_pkeys) - - def _raise(self, exception=BaseSSHTunnelForwarderError, reason=None): - if self._raise_fwd_exc: - raise exception(reason) - else: - self.logger.error(repr(exception(reason))) - - def _get_transport(self): - """Return the SSH transport to the remote gateway.""" - if self.ssh_proxy: - if isinstance(self.ssh_proxy, paramiko.proxy.ProxyCommand): - proxy_repr = repr(self.ssh_proxy.cmd[1]) - else: - proxy_repr = repr(self.ssh_proxy) - self.logger.debug("Connecting via proxy: {0}".format(proxy_repr)) - _socket = self.ssh_proxy - else: - _socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - if isinstance(_socket, socket.socket): - _socket.settimeout(self.gateway_timeout) - _socket.connect((self.ssh_host, self.ssh_port)) - transport = paramiko.Transport(_socket) - transport.set_keepalive(self.set_keepalive) - transport.use_compression(compress=self.compression) - transport.daemon = self.daemon_transport - - return transport - - def _create_tunnels(self): - """Create SSH tunnels on top of a transport to the remote gateway.""" - if not self.is_active: - try: - self._connect_to_gateway() - except socket.gaierror: # raised by paramiko.Transport - msg = "Could not resolve IP address for {0}, aborting!".format( - self.ssh_host - ) - self.logger.error(msg) - return - except (paramiko.SSHException, socket.error) as e: - template = "Could not connect to gateway {0}:{1} : {2}" - msg = template.format(self.ssh_host, self.ssh_port, e.args[0]) - self.logger.error(msg) - return - for (rem, loc) in zip(self._remote_binds, self._local_binds): - try: - self._make_ssh_forward_server(rem, loc) - except BaseSSHTunnelForwarderError as e: - msg = "Problem setting SSH Forwarder up: {0}".format(e.value) - self.logger.error(msg) - - @staticmethod - def _get_binds(bind_address, bind_addresses, is_remote=False): - addr_kind = "remote" if is_remote else "local" - - if not bind_address and not bind_addresses: - if is_remote: - raise ValueError( - "No {0} bind addresses specified. Use " - "'{0}_bind_address' or '{0}_bind_addresses'" - " argument".format(addr_kind) - ) - else: - return [] - elif bind_address and bind_addresses: - raise ValueError( - "You can't use both '{0}_bind_address' and " - "'{0}_bind_addresses' arguments. Use one of " - "them.".format(addr_kind) - ) - if bind_address: - bind_addresses = [bind_address] - if not is_remote: - # Add random port if missing in local bind - for (i, local_bind) in enumerate(bind_addresses): - if isinstance(local_bind, tuple) and len(local_bind) == 1: - bind_addresses[i] = (local_bind[0], 0) - check_addresses(bind_addresses, is_remote) - return bind_addresses - - @staticmethod - def _process_deprecated(attrib, deprecated_attrib, kwargs): - """Processes optional deprecate arguments.""" - - if deprecated_attrib not in DEPRECATIONS: - raise ValueError( - "{0} not included in deprecations list".format(deprecated_attrib) - ) - if deprecated_attrib in kwargs: - warnings.warn( - "'{0}' is DEPRECATED use '{1}' instead".format( - deprecated_attrib, DEPRECATIONS[deprecated_attrib] - ), - DeprecationWarning, - ) - if attrib: - raise ValueError( - "You can't use both '{0}' and '{1}'. " - "Please only use one of them".format( - deprecated_attrib, DEPRECATIONS[deprecated_attrib] - ) - ) - else: - return kwargs.pop(deprecated_attrib) - return attrib - - @staticmethod - def read_private_key_file(pkey_file, pkey_password=None, key_type=None, logger=log): - """Get SSH Public key from a private key file, given an optional password. - - Arguments: - pkey_file (str): - File containing a private key (RSA, DSS or ECDSA) - Keyword Arguments: - pkey_password (Optional[str]): - Password to decrypt the private key - logger (Optional[logging.Logger]) - Return: - paramiko.Pkey - """ - ssh_pkey = None - for pkey_class in ( - (key_type,) - if key_type - else ( - paramiko.RSAKey, - paramiko.DSSKey, - paramiko.ECDSAKey, - paramiko.Ed25519Key, - ) - ): - try: - ssh_pkey = pkey_class.from_private_key_file( - pkey_file, password=pkey_password - ) - - logger.debug( - "Private key file ({k0}, {k1}) successfully loaded", - k0=pkey_file, - k1=pkey_class, - ) - - break - except paramiko.PasswordRequiredException: - - logger.error("Password is required for key {k}", k=pkey_file) - - break - except paramiko.SSHException: - logger.debug( - "Private key file ({k0}) could not be loaded as type {k1} or bad password", - k0=pkey_file, - k1=pkey_class, - ) - - return ssh_pkey - - def _check_tunnel(self, _srv): - """Check if tunnel is already established.""" - if self.skip_tunnel_checkup: - self.tunnel_is_up[_srv.local_address] = True - return - - self.logger.info("Checking tunnel to: {a}", a=_srv.remote_address) - - if isinstance(_srv.local_address, str): # UNIX stream - s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) - else: - s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - s.settimeout(TUNNEL_TIMEOUT) - try: - # Windows raises WinError 10049 if trying to connect to 0.0.0.0 - connect_to = ( - ("127.0.0.1", _srv.local_port) - if _srv.local_host == "0.0.0.0" - else _srv.local_address - ) - s.connect(connect_to) - self.tunnel_is_up[_srv.local_address] = _srv.tunnel_ok.get( - timeout=TUNNEL_TIMEOUT * 1.1 - ) - self.logger.debug("Tunnel to {0} is DOWN".format(_srv.remote_address)) - except socket.error: - self.logger.debug("Tunnel to {0} is DOWN".format(_srv.remote_address)) - self.tunnel_is_up[_srv.local_address] = False - - except queue.Empty: - self.logger.debug("Tunnel to {0} is UP".format(_srv.remote_address)) - self.tunnel_is_up[_srv.local_address] = True - finally: - s.close() - - def check_tunnels(self): - """Check that if all tunnels are established and populates. - - :attr:`.tunnel_is_up` - """ - for _srv in self._server_list: - self._check_tunnel(_srv) - - def start(self): - """Start the SSH tunnels.""" - if self.is_alive: - self.logger.warning("Already started!") - return - self._create_tunnels() - if not self.is_active: - self._raise( - BaseSSHTunnelForwarderError, - reason="Could not establish session to SSH gateway", - ) - for _srv in self._server_list: - thread = threading.Thread( - target=self._serve_forever_wrapper, - args=(_srv,), - name="Srv-{0}".format(address_to_str(_srv.local_port)), - ) - thread.daemon = self.daemon_forward_servers - thread.start() - self._check_tunnel(_srv) - self.is_alive = any(self.tunnel_is_up.values()) - if not self.is_alive: - self._raise( - HandlerSSHTunnelForwarderError, - "An error occurred while opening tunnels.", - ) - - def stop(self): - """Shut the tunnel down. - - .. note:: This **had** to be handled with care before ``0.1.0``: - - - if a port redirection is opened - - the destination is not reachable - - we attempt a connection to that tunnel (``SYN`` is sent and - acknowledged, then a ``FIN`` packet is sent and never - acknowledged... weird) - - we try to shutdown: it will not succeed until ``FIN_WAIT_2`` and - ``CLOSE_WAIT`` time out. - - .. note:: - Handle these scenarios with :attr:`.tunnel_is_up`: if False, server - ``shutdown()`` will be skipped on that tunnel - """ - self.logger.info("Closing all open connections...") - opened_address_text = ( - ", ".join((address_to_str(k.local_address) for k in self._server_list)) - or "None" - ) - self.logger.debug("Listening tunnels: " + opened_address_text) - self._stop_transport() - self._server_list = [] # reset server list - self.tunnel_is_up = {} # reset tunnel status - - def close(self): - """Stop the an active tunnel, alias to :meth:`.stop`.""" - self.stop() - - def restart(self): - """Restart connection to the gateway and tunnels.""" - self.stop() - self.start() - - def _connect_to_gateway(self): - """Open connection to SSH gateway. - - - First try with all keys loaded from an SSH agent (if allowed) - - Then with those passed directly or read from ~/.ssh/config - - As last resort, try with a provided password - """ - for key in self.ssh_pkeys: - self.logger.debug( - "Trying to log in with key: {0}".format(hexlify(key.get_fingerprint())) - ) - try: - self._transport = self._get_transport() - self._transport.connect( - hostkey=self.ssh_host_key, username=self.ssh_username, pkey=key - ) - if self._transport.is_alive: - return - except paramiko.AuthenticationException: - self.logger.debug("Authentication error") - self._stop_transport() - - if self.ssh_password: # avoid conflict using both pass and pkey - self.logger.debug( - "Trying to log in with password: {0}".format( - "*" * len(self.ssh_password) - ) - ) - try: - self._transport = self._get_transport() - self._transport.connect( - hostkey=self.ssh_host_key, - username=self.ssh_username, - password=self.ssh_password, - ) - if self._transport.is_alive: - return - except paramiko.AuthenticationException: - self.logger.debug("Authentication error") - self._stop_transport() - - self.logger.error("Could not open connection to gateway") - - def _serve_forever_wrapper(self, _srv, poll_interval=0.1): - """Wrapper for the server created for a SSH forward.""" - self.logger.info( - "Opening tunnel: {0} <> {1}".format( - address_to_str(_srv.local_address), address_to_str(_srv.remote_address) - ) - ) - _srv.serve_forever(poll_interval) # blocks until finished - - self.logger.info( - "Tunnel: {0} <> {1} released".format( - address_to_str(_srv.local_address), address_to_str(_srv.remote_address) - ) - ) - - def _stop_transport(self): - """Close the underlying transport when nothing more is needed.""" - - try: - self._check_is_started() - except (BaseSSHTunnelForwarderError, HandlerSSHTunnelForwarderError) as e: - self.logger.warning(e) - for _srv in self._server_list: - tunnel = _srv.local_address - if self.tunnel_is_up[tunnel]: - self.logger.info("Shutting down tunnel {0}".format(tunnel)) - _srv.shutdown() - _srv.server_close() - # clean up the UNIX domain socket if we're using one - if isinstance(_srv, _UnixStreamForwardServer): - try: - os.unlink(_srv.local_address) - except Exception as e: - self.logger.error( - "Unable to unlink socket {0}: {1}".format( - self.local_address, repr(e) - ) - ) - self.is_alive = False - if self.is_active: - self._transport.close() - self._transport.stop_thread() - self.logger.debug("Transport is closed") - - @property - def local_bind_port(self): - - # BACKWARDS COMPATIBILITY - self._check_is_started() - if len(self._server_list) != 1: - raise BaseSSHTunnelForwarderError( - "Use .local_bind_ports property for more than one tunnel" - ) - return self.local_bind_ports[0] - - @property - def local_bind_host(self): - - # BACKWARDS COMPATIBILITY - self._check_is_started() - if len(self._server_list) != 1: - raise BaseSSHTunnelForwarderError( - "Use .local_bind_hosts property for more than one tunnel" - ) - return self.local_bind_hosts[0] - - @property - def local_bind_address(self): - - # BACKWARDS COMPATIBILITY - self._check_is_started() - if len(self._server_list) != 1: - raise BaseSSHTunnelForwarderError( - "Use .local_bind_addresses property for more than one tunnel" - ) - return self.local_bind_addresses[0] - - @property - def local_bind_ports(self): - """Return a list containing the ports of local side of the TCP tunnels.""" - - self._check_is_started() - return [ - _server.local_port - for _server in self._server_list - if _server.local_port is not None - ] - - @property - def local_bind_hosts(self): - """Return a list containing the IP addresses listening for the tunnels.""" - self._check_is_started() - return [ - _server.local_host - for _server in self._server_list - if _server.local_host is not None - ] - - @property - def local_bind_addresses(self): - """Return a list of (IP, port) pairs for the local side of the tunnels.""" - self._check_is_started() - return [_server.local_address for _server in self._server_list] - - @property - def tunnel_bindings(self): - """Return a dictionary containing the active local<>remote tunnel_bindings.""" - return dict( - (_server.remote_address, _server.local_address) - for _server in self._server_list - if self.tunnel_is_up[_server.local_address] - ) - - @property - def is_active(self): - """ Return True if the underlying SSH transport is up """ - if "_transport" in self.__dict__ and self._transport.is_active(): - return True - return False - - def _check_is_started(self): - if not self.is_active: # underlying transport not alive - msg = "Server is not started. Please .start() first!" - raise BaseSSHTunnelForwarderError(msg) - if not self.is_alive: - msg = "Tunnels are not started. Please .start() first!" - raise HandlerSSHTunnelForwarderError(msg) - - def __str__(self): - credentials = { - "password": self.ssh_password, - "pkeys": [ - (key.get_name(), hexlify(key.get_fingerprint())) - for key in self.ssh_pkeys - ] - if any(self.ssh_pkeys) - else None, - } - _remove_none_values(credentials) - template = os.linesep.join( - [ - "{0} object", - "ssh gateway: {1}:{2}", - "proxy: {3}", - "username: {4}", - "authentication: {5}", - "hostkey: {6}", - "status: {7}started", - "keepalive messages: {8}", - "tunnel connection check: {9}", - "concurrent connections: {10}allowed", - "compression: {11}requested", - "logging level: {12}", - "local binds: {13}", - "remote binds: {14}", - ] - ) - return template.format( - self.__class__, - self.ssh_host, - self.ssh_port, - self.ssh_proxy.cmd[1] if self.ssh_proxy else "no", - self.ssh_username, - credentials, - self.ssh_host_key if self.ssh_host_key else "not checked", - "" if self.is_alive else "not ", - "disabled" - if not self.set_keepalive - else "every {0} sec".format(self.set_keepalive), - "disabled" if self.skip_tunnel_checkup else "enabled", - "" if self._threaded else "not ", - "" if self.compression else "not ", - os.environ.get("HYPERGLASS_LOG_LEVEL") or "INFO", - self._local_binds, - self._remote_binds, - ) - - def __repr__(self): - return self.__str__() - - def __enter__(self): - try: - self.start() - return self - except KeyboardInterrupt: - self.__exit__() - - def __exit__(self, *args): - self._stop_transport() - - -def open_tunnel(*args, **kwargs): - """Open an SSH Tunnel, wrapper for :class:`SSHTunnelForwarder`. - - Arguments: - destination (Optional[tuple]): - SSH server's IP address and port in the format - (``ssh_address``, ``ssh_port``) - - Keyword Arguments: - debug_level (Optional[int or str]): - log level for :class:`logging.Logger` instance, i.e. ``DEBUG`` - - skip_tunnel_checkup (boolean): - Enable/disable the local side check and populate - :attr:`~SSHTunnelForwarder.tunnel_is_up` - - Default: True - - .. versionadded:: 0.1.0 - - block_on_close (boolean): - Wait until all connections are done during close by changing the - value of :attr:`~SSHTunnelForwarder.block_on_close` - - Default: True - - .. note:: - A value of ``debug_level`` set to 1 == ``TRACE`` enables tracing mode - .. note:: - See :class:`SSHTunnelForwarder` for keyword arguments - - **Example**:: - - from sshtunnel import open_tunnel - - with open_tunnel(SERVER, - ssh_username=SSH_USER, - ssh_port=22, - ssh_password=SSH_PASSWORD, - remote_bind_address=(REMOTE_HOST, REMOTE_PORT), - local_bind_address=('', LOCAL_PORT)) as server: - def do_something(port): - pass - - print("LOCAL PORTS:", server.local_bind_port) - - do_something(server.local_bind_port) - """ - # Attach a console handler to the logger or create one if not passed - kwargs["logger"] = kwargs.get("logger") or log - - ssh_address_or_host = kwargs.pop("ssh_address_or_host", None) - # Check if deprecated arguments ssh_address or ssh_host were used - for deprecated_argument in ["ssh_address", "ssh_host"]: - ssh_address_or_host = SSHTunnelForwarder._process_deprecated( - ssh_address_or_host, deprecated_argument, kwargs - ) - - ssh_port = kwargs.pop("ssh_port", 22) - skip_tunnel_checkup = kwargs.pop("skip_tunnel_checkup", True) - block_on_close = kwargs.pop("block_on_close", _DAEMON) - if not args: - if isinstance(ssh_address_or_host, tuple): - args = (ssh_address_or_host,) - else: - args = ((ssh_address_or_host, ssh_port),) - forwarder = SSHTunnelForwarder(*args, **kwargs) - forwarder.skip_tunnel_checkup = skip_tunnel_checkup - forwarder.daemon_forward_servers = not block_on_close - forwarder.daemon_transport = not block_on_close - return forwarder - - -def _bindlist(input_str): - """Define type of data expected for remote and local bind address lists. - - Returns a tuple (ip_address, port) whose elements are (str, int) - """ - try: - ip_port = input_str.split(":") - if len(ip_port) == 1: - _ip = ip_port[0] - _port = None - else: - (_ip, _port) = ip_port - if not _ip and not _port: - raise AssertionError - elif not _port: - _port = "22" # default port if not given - return _ip, int(_port) - except ValueError: - raise argparse.ArgumentTypeError( - "Address tuple must be of type IP_ADDRESS:PORT" - ) - except AssertionError: - raise argparse.ArgumentTypeError("Both IP:PORT can't be missing!") diff --git a/hyperglass/configuration/.gitignore b/hyperglass/configuration/.gitignore deleted file mode 100644 index 4ecc56a..0000000 --- a/hyperglass/configuration/.gitignore +++ /dev/null @@ -1,5 +0,0 @@ -.DS_Store -*.toml -*.yaml -*.test -configuration_old \ No newline at end of file diff --git a/hyperglass/configuration/__init__.py b/hyperglass/configuration/__init__.py deleted file mode 100644 index 073a8a1..0000000 --- a/hyperglass/configuration/__init__.py +++ /dev/null @@ -1,14 +0,0 @@ -"""hyperglass Configuration.""" - -# Local -from .main import ( - URL_DEV, - URL_PROD, - CONFIG_PATH, - STATIC_PATH, - REDIS_CONFIG, - params, - devices, - commands, - frontend_params, -) diff --git a/hyperglass/configuration/main.py b/hyperglass/configuration/main.py deleted file mode 100644 index c26493b..0000000 --- a/hyperglass/configuration/main.py +++ /dev/null @@ -1,376 +0,0 @@ -"""Import configuration files and returns default values if undefined.""" - -# Standard Library -import os -import json -from typing import Dict, List -from pathlib import Path - -# Third Party -import yaml - -# Project -from hyperglass.log import ( - log, - set_log_level, - enable_file_logging, - enable_syslog_logging, -) -from hyperglass.util import set_app_path, set_cache_env, current_log_level -from hyperglass.defaults import CREDIT, DEFAULT_DETAILS -from hyperglass.constants import ( - SUPPORTED_QUERY_TYPES, - PARSED_RESPONSE_FIELDS, - __version__, -) -from hyperglass.exceptions import ConfigError, ConfigMissing -from hyperglass.util.files import check_path -from hyperglass.models.commands import Commands -from hyperglass.models.config.params import Params -from hyperglass.models.config.devices import Devices - -# Local -from .markdown import get_markdown -from .validation import validate_config, validate_nos_commands - -set_app_path(required=True) - -CONFIG_PATH = Path(os.environ["hyperglass_directory"]) -log.info("Configuration directory: {d}", d=str(CONFIG_PATH)) - -# Project Directories -WORKING_DIR = Path(__file__).resolve().parent -CONFIG_FILES = ( - ("hyperglass.yaml", False), - ("devices.yaml", True), - ("commands.yaml", False), -) - - -def _check_config_files(directory: Path): - """Verify config files exist and are readable.""" - - files = () - - for file in CONFIG_FILES: - file_name, required = file - file_path = directory / file_name - - checked = check_path(file_path) - - if checked is None and required: - raise ConfigMissing(missing_item=str(file_path)) - - if checked is None and not required: - log.warning( - "'{f}' was not found, but is not required to run hyperglass. " - + "Defaults will be used.", - f=str(file_path), - ) - files += (checked,) - - return files - - -STATIC_PATH = CONFIG_PATH / "static" - -CONFIG_MAIN, CONFIG_DEVICES, CONFIG_COMMANDS = _check_config_files(CONFIG_PATH) - - -def _config_required(config_path: Path) -> Dict: - try: - with config_path.open("r") as cf: - config = yaml.safe_load(cf) - - except (yaml.YAMLError, yaml.MarkedYAMLError) as yaml_error: - raise ConfigError(str(yaml_error)) - - if config is None: - log.critical("{} appears to be empty", str(config_path)) - raise ConfigMissing(missing_item=config_path.name) - - return config - - -def _config_optional(config_path: Path) -> Dict: - - config = {} - - if config_path is None: - return config - - else: - try: - with config_path.open("r") as cf: - config = yaml.safe_load(cf) or {} - - except (yaml.YAMLError, yaml.MarkedYAMLError) as yaml_error: - raise ConfigError(error_msg=str(yaml_error)) - - return config - - -user_config = _config_optional(CONFIG_MAIN) - -# Read raw debug value from config to enable debugging quickly. -set_log_level(logger=log, debug=user_config.get("debug", True)) - -# Map imported user configuration to expected schema. -log.debug("Unvalidated configuration from {}: {}", CONFIG_MAIN, user_config) -params = validate_config(config=user_config, importer=Params) - -# Re-evaluate debug state after config is validated -log_level = current_log_level(log) - -if params.debug and log_level != "debug": - set_log_level(logger=log, debug=True) -elif not params.debug and log_level == "debug": - set_log_level(logger=log, debug=False) - -# Map imported user commands to expected schema. -_user_commands = _config_optional(CONFIG_COMMANDS) -log.debug("Unvalidated commands from {}: {}", CONFIG_COMMANDS, _user_commands) -commands = validate_config(config=_user_commands, importer=Commands.import_params) - -# Map imported user devices to expected schema. -_user_devices = _config_required(CONFIG_DEVICES) -log.debug("Unvalidated devices from {}: {}", CONFIG_DEVICES, _user_devices) -devices = validate_config(config=_user_devices.get("routers", []), importer=Devices) - -# Validate commands are both supported and properly mapped. -validate_nos_commands(devices.all_nos, commands) - -# Set cache configurations to environment variables, so they can be -# used without importing this module (Gunicorn, etc). -set_cache_env(db=params.cache.database, host=params.cache.host, port=params.cache.port) - -# Set up file logging once configuration parameters are initialized. -enable_file_logging( - logger=log, - log_directory=params.logging.directory, - log_format=params.logging.format, - log_max_size=params.logging.max_size, -) - -# Set up syslog logging if enabled. -if params.logging.syslog is not None and params.logging.syslog.enable: - enable_syslog_logging( - logger=log, - syslog_host=params.logging.syslog.host, - syslog_port=params.logging.syslog.port, - ) - -if params.logging.http is not None and params.logging.http.enable: - log.debug("HTTP logging is enabled") - -# Perform post-config initialization string formatting or other -# functions that require access to other config levels. E.g., -# something in 'params.web.text' needs to be formatted with a value -# from params. -try: - params.web.text.subtitle = params.web.text.subtitle.format( - **params.dict(exclude={"web", "queries", "messages"}) - ) - - # If keywords are unmodified (default), add the org name & - # site_title. - if Params().site_keywords == params.site_keywords: - params.site_keywords = sorted( - {*params.site_keywords, params.org_name, params.site_title} - ) - -except KeyError: - pass - - -def _build_frontend_devices(): - """Build filtered JSON structure of devices for frontend. - - Schema: - { - "device.name": { - "display_name": "device.display_name", - "vrfs": [ - "Global", - "vrf.display_name" - ] - } - } - - Raises: - ConfigError: Raised if parsing/building error occurs. - - Returns: - {dict} -- Frontend devices - """ - frontend_dict = {} - for device in devices.objects: - if device.name in frontend_dict: - frontend_dict[device.name].update( - { - "network": device.network.display_name, - "display_name": device.display_name, - "vrfs": [ - { - "id": vrf.name, - "display_name": vrf.display_name, - "default": vrf.default, - "ipv4": True if vrf.ipv4 else False, # noqa: IF100 - "ipv6": True if vrf.ipv6 else False, # noqa: IF100 - } - for vrf in device.vrfs - ], - } - ) - elif device.name not in frontend_dict: - frontend_dict[device.name] = { - "network": device.network.display_name, - "display_name": device.display_name, - "vrfs": [ - { - "id": vrf.name, - "display_name": vrf.display_name, - "default": vrf.default, - "ipv4": True if vrf.ipv4 else False, # noqa: IF100 - "ipv6": True if vrf.ipv6 else False, # noqa: IF100 - } - for vrf in device.vrfs - ], - } - if not frontend_dict: - raise ConfigError(error_msg="Unable to build network to device mapping") - return frontend_dict - - -def _build_networks() -> List[Dict]: - """Build filtered JSON Structure of networks & devices for Jinja templates.""" - networks = [] - _networks = list(set({device.network.display_name for device in devices.objects})) - - for _network in _networks: - network_def = {"display_name": _network, "locations": []} - for device in devices.objects: - if device.network.display_name == _network: - network_def["locations"].append( - { - "_id": device._id, - "name": device.name, - "network": device.network.display_name, - "vrfs": [ - { - "_id": vrf._id, - "display_name": vrf.display_name, - "default": vrf.default, - "ipv4": True if vrf.ipv4 else False, # noqa: IF100 - "ipv6": True if vrf.ipv6 else False, # noqa: IF100 - } - for vrf in device.vrfs - ], - } - ) - networks.append(network_def) - - if not networks: - raise ConfigError(error_msg="Unable to build network to device mapping") - return networks - - -content_params = json.loads( - params.json(include={"primary_asn", "org_name", "site_title", "site_description"}) -) - - -def _build_vrf_help() -> Dict: - """Build a dict of vrfs as keys, help content as values.""" - all_help = {} - for vrf in devices.vrf_objects: - - vrf_help = {} - for command in SUPPORTED_QUERY_TYPES: - cmd = getattr(vrf.info, command) - if cmd.enable: - help_params = {**content_params, **cmd.params.dict()} - - if help_params["title"] is None: - command_params = getattr(params.queries, command) - help_params[ - "title" - ] = f"{vrf.display_name}: {command_params.display_name}" - - md = get_markdown( - config_path=cmd, - default=DEFAULT_DETAILS[command], - params=help_params, - ) - - vrf_help.update( - { - command: { - "content": md, - "enable": cmd.enable, - "params": help_params, - } - } - ) - - all_help.update({vrf._id: vrf_help}) - - return all_help - - -content_greeting = get_markdown( - config_path=params.web.greeting, - default="", - params={"title": params.web.greeting.title}, -) - -content_vrf = _build_vrf_help() - -content_credit = CREDIT.format(version=__version__) - -networks = _build_networks() -frontend_devices = _build_frontend_devices() -_include_fields = { - "cache": {"show_text", "timeout"}, - "debug": ..., - "developer_mode": ..., - "primary_asn": ..., - "request_timeout": ..., - "org_name": ..., - "google_analytics": ..., - "site_title": ..., - "site_description": ..., - "site_keywords": ..., - "web": ..., - "messages": ..., -} -_frontend_params = params.dict(include=_include_fields) - - -_frontend_params["web"]["logo"]["light_format"] = params.web.logo.light.suffix -_frontend_params["web"]["logo"]["dark_format"] = params.web.logo.dark.suffix - -_frontend_params.update( - { - "hyperglass_version": __version__, - "queries": {**params.queries.map, "list": params.queries.list}, - "networks": networks, - "parsed_data_fields": PARSED_RESPONSE_FIELDS, - "content": { - "credit": content_credit, - "vrf": content_vrf, - "greeting": content_greeting, - }, - } -) -frontend_params = _frontend_params - -URL_DEV = f"http://localhost:{str(params.listen_port)}/" -URL_PROD = "/api/" - -REDIS_CONFIG = { - "host": str(params.cache.host), - "port": params.cache.port, - "decode_responses": True, - "password": params.cache.password, -} diff --git a/hyperglass/configuration/markdown.py b/hyperglass/configuration/markdown.py deleted file mode 100644 index 873e671..0000000 --- a/hyperglass/configuration/markdown.py +++ /dev/null @@ -1,61 +0,0 @@ -"""Markdown processing utility functions.""" - -# Project -from hyperglass.log import log - - -def _get_file(path_obj): - """Read a file. - - Arguments: - path_obj {Path} -- Path to file. - - Returns: - {str} -- File contents - """ - with path_obj.open("r") as raw_file: - return raw_file.read() - - -def format_markdown(content, params): - """Format content with config parameters. - - Arguments: - content {str} -- Unformatted content - - Returns: - {str} -- Formatted content - """ - try: - fmt = content.format(**params) - except KeyError: - fmt = content - return fmt - - -def get_markdown(config_path, default, params): - """Get markdown file if specified, or use default. - - Format the content with config parameters. - - Arguments: - config_path {object} -- content config - default {str} -- default content - - Returns: - {str} -- Formatted content - """ - log.trace(f"Getting Markdown content for '{params['title']}'") - - if config_path.enable and config_path.file is not None: - md = _get_file(config_path.file) - else: - md = default - - log.trace(f"Unformatted Content for '{params['title']}':\n{md}") - - md_fmt = format_markdown(md, params) - - log.trace(f"Formatted Content for '{params['title']}':\n{md_fmt}") - - return md_fmt diff --git a/hyperglass/configuration/validation.py b/hyperglass/configuration/validation.py deleted file mode 100644 index 900cb93..0000000 --- a/hyperglass/configuration/validation.py +++ /dev/null @@ -1,50 +0,0 @@ -"""Post-Validation Validation. - -Some validations need to occur across multiple config files. -""" -# Standard Library -from typing import Dict, List, Union, Callable - -# Third Party -from pydantic import ValidationError - -# Project -from hyperglass.log import log -from hyperglass.models import HyperglassModel -from hyperglass.constants import TRANSPORT_REST, SUPPORTED_STRUCTURED_OUTPUT -from hyperglass.exceptions import ConfigError, ConfigInvalid -from hyperglass.models.commands import Commands - - -def validate_nos_commands(all_nos: List[str], commands: Commands) -> bool: - """Ensure defined devices have associated commands.""" - custom_commands = commands.dict().keys() - - for nos in all_nos: - valid = False - if nos in (*SUPPORTED_STRUCTURED_OUTPUT, *TRANSPORT_REST, *custom_commands): - valid = True - - if not valid: - raise ConfigError( - '"{nos}" is used on a device, ' - + 'but no command profile for "{nos}" is defined.', - nos=nos, - ) - - return True - - -def validate_config(config: Union[Dict, List], importer: Callable) -> HyperglassModel: - """Validate a config dict against a model.""" - validated = None - try: - if isinstance(config, Dict): - validated = importer(**config) - elif isinstance(config, List): - validated = importer(config) - except ValidationError as err: - log.error(str(err)) - raise ConfigInvalid(err.errors()) from None - - return validated diff --git a/hyperglass/console.py b/hyperglass/console.py deleted file mode 100755 index a1a7aed..0000000 --- a/hyperglass/console.py +++ /dev/null @@ -1,8 +0,0 @@ -#!/usr/bin/env python3 -"""hyperglass CLI management tool.""" - -# Project -from hyperglass.cli import CLI - -if __name__ == "__main__": - CLI() diff --git a/hyperglass/constants.py b/hyperglass/constants.py deleted file mode 100644 index 85584b9..0000000 --- a/hyperglass/constants.py +++ /dev/null @@ -1,89 +0,0 @@ -"""Constant definitions used throughout the application.""" - -# Standard Library -from datetime import datetime - -__name__ = "hyperglass" -__version__ = "1.0.4" -__author__ = "Matt Love" -__copyright__ = f"Copyright {datetime.now().year} Matthew Love" -__license__ = "BSD 3-Clause Clear License" - -METADATA = (__name__, __version__, __author__, __copyright__, __license__) - -MIN_PYTHON_VERSION = (3, 6) - -MIN_NODE_VERSION = 14 - -TARGET_FORMAT_SPACE = ("huawei", "huawei_vrpv8") - -TARGET_JUNIPER_ASPATH = ("juniper", "juniper_junos") - -SUPPORTED_STRUCTURED_OUTPUT = ("juniper", "arista_eos") - -STATUS_CODE_MAP = {"warning": 400, "error": 400, "danger": 500} - -DNS_OVER_HTTPS = { - "google": "https://dns.google/resolve", - "cloudflare": "https://cloudflare-dns.com/dns-query", -} - -PARSED_RESPONSE_FIELDS = ( - ("Prefix", "prefix", "left"), - ("Active", "active", None), - ("RPKI State", "rpki_state", "center"), - ("AS Path", "as_path", "left"), - ("Next Hop", "next_hop", "left"), - ("Origin", "source_as", None), - ("Weight", "weight", "center"), - ("Local Preference", "local_preference", "center"), - ("MED", "med", "center"), - ("Communities", "communities", "center"), - ("Originator", "source_rid", "right"), - ("Peer", "peer_rid", "right"), - ("Age", "age", "right"), -) - -SUPPORTED_QUERY_FIELDS = ("query_location", "query_type", "query_target", "query_vrf") -SUPPORTED_QUERY_TYPES = ( - "bgp_route", - "bgp_community", - "bgp_aspath", - "ping", - "traceroute", -) - -FUNC_COLOR_MAP = { - "primary": "cyan", - "secondary": "blue", - "success": "green", - "warning": "yellow", - "error": "orange", - "danger": "red", -} - -TRANSPORT_REST = ("frr_legacy", "bird_legacy") - -SCRAPE_HELPERS = { - "arista": "arista_eos", - "ios": "cisco_ios", - "juniper_junos": "juniper", - "junos": "juniper", - "mikrotik": "mikrotik_routeros", - "tsnr": "tnsr", -} - -DRIVER_MAP = { - # TODO: Troubleshoot Arista with Scrapli, broken after upgrading to 2021.1.30. - # "arista_eos": "scrapli", # noqa: E800 - "bird": "scrapli", - "cisco_ios": "scrapli", - "cisco_xe": "scrapli", - "cisco_xr": "scrapli", - "cisco_nxos": "scrapli", - "juniper": "scrapli", - "tnsr": "scrapli", - "frr": "scrapli", - "frr_legacy": "hyperglass_agent", - "bird_legacy": "hyperglass_agent", -} diff --git a/hyperglass/defaults.py b/hyperglass/defaults.py deleted file mode 100644 index b4a299a..0000000 --- a/hyperglass/defaults.py +++ /dev/null @@ -1,83 +0,0 @@ -"""Constant store for large default values.""" - -CREDIT = """ -Powered by [**hyperglass**](https://hyperglass.dev) version {version}. \ -Source code licensed [_BSD 3-Clause Clear_](https://hyperglass.dev/docs/license/). -""" - -DEFAULT_TERMS = """ -By using {site_title}, you agree to be bound by the following terms of use: - -All queries executed on this page are logged for analysis and troubleshooting. \ -Users are prohibited from automating queries, or attempting to process queries in \ -bulk. This service is provided on a best effort basis, and {org_name} \ -makes no availability or performance warranties or guarantees whatsoever. -""" - -DEFAULT_DETAILS = { - "bgp_aspath": """ -{site_title} accepts the following `AS_PATH` regular expression patterns: - -| Expression | Match | -| :------------------- | :-------------------------------------------- | -| `_65000$` | Originated by 65000 | -| `^65000_` | Received from 65000 | -| `_65000_` | Via 65000 | -| `_65000_65001_` | Via 65000 and 65001 | -| `_65000(_.+_)65001$` | Anything from 65001 that passed through 65000 | -""", - "bgp_community": """ -{site_title} makes use of the following BGP communities: - -| Community | Description | -| :-------- | :---------- | -| `65000:1` | Example 1 | -| `65000:2` | Example 2 | -| `65000:3` | Example 3 | -""", - "bgp_route": """ -Performs BGP table lookup based on IPv4/IPv6 prefix. -""", - "ping": """ -Sends 5 ICMP echo requests to the target. -""", - "traceroute": """ -Performs UDP Based traceroute to the target. \ -For information about how to interpret traceroute results, [click here]\ -(https://hyperglass.dev/traceroute_nanog.pdf). -""", -} - -DEFAULT_HELP = """ -##### BGP Route - -Performs BGP table lookup based on IPv4/IPv6 prefix. - ---- - -##### BGP Community - -Performs BGP table lookup based on [Extended](https://tools.ietf.org/html/rfc4360) \ -or [Large](https://tools.ietf.org/html/rfc8195) community value. - ---- - -##### BGP AS Path - -Performs BGP table lookup based on `AS_PATH` regular expression. - ---- - -##### Ping - -Sends 5 ICMP echo requests to the target. - ---- - -##### Traceroute - -Performs UDP Based traceroute to the target. - -For information about how to interpret traceroute results, [click here]\ -(https://hyperglass.dev/traceroute_nanog.pdf). -""" diff --git a/hyperglass/encode.py b/hyperglass/encode.py deleted file mode 100644 index 3b476ac..0000000 --- a/hyperglass/encode.py +++ /dev/null @@ -1,32 +0,0 @@ -"""Handle JSON Web Token Encoding & Decoding.""" - -# Standard Library -import datetime - -# Third Party -import jwt - -# Project -from hyperglass.exceptions import RestError - - -async def jwt_decode(payload: str, secret: str) -> str: - """Decode & validate an encoded JSON Web Token (JWT).""" - try: - decoded = jwt.decode(payload, secret, algorithm="HS256") - decoded = decoded["payload"] - return decoded - except (KeyError, jwt.PyJWTError) as exp: - raise RestError(str(exp)) from None - - -async def jwt_encode(payload: str, secret: str, duration: int) -> str: - """Encode a query to a JSON Web Token (JWT).""" - token = { - "payload": payload, - "nbf": datetime.datetime.utcnow(), - "iat": datetime.datetime.utcnow(), - "exp": datetime.datetime.utcnow() + datetime.timedelta(seconds=duration), - } - encoded = jwt.encode(token, secret, algorithm="HS256").decode("utf-8") - return encoded diff --git a/hyperglass/examples/commands.yaml b/hyperglass/examples/commands.yaml deleted file mode 100644 index e69de29..0000000 diff --git a/hyperglass/examples/devices.yaml b/hyperglass/examples/devices.yaml deleted file mode 100644 index 7775004..0000000 --- a/hyperglass/examples/devices.yaml +++ /dev/null @@ -1,89 +0,0 @@ ---- -routers: - - name: sfo_router01 - address: 10.0.0.1 - network: - name: primary - display_name: Main Network - credential: - username: user1 - password: secret1 - display_name: San Francisco, CA - port: 22 - nos: cisco_ios - vrfs: - - name: default - display_name: Global - ipv4: - source_address: 192.0.2.1 - access_list: - - network: 10.0.0.0/8 - action: deny - - network: 192.168.0.0/16 - action: deny - - network: 172.16.0.0/12 - action: deny - - network: 0.0.0.0/0 - action: permit - ge: 8 - le: 24 - ipv6: - source_address: 2001:db8::1 - access_list: - - network: ::/0 - action: permit - ge: 32 - le: 64 - - name: customer_a - display_name: Customer A - ipv4: - source_address: 192.168.1.1 - access_list: - - network: 192.0.2.0/24 - action: deny - - network: 10.0.0.0/8 - action: permit - ipv6: null - proxy: null - - name: atl_router01 - address: 10.0.0.2 - network: - name: secondary - display_name: That Other Network - credential: - username: user2 - password: secret2 - display_name: Atlanta, GA - port: 22 - nos: juniper - vrfs: - - name: default - display_name: Global - ipv4: - source_address: 192.0.2.2 - access_list: - - network: 10.0.0.0/8 - action: deny - - network: 192.168.0.0/16 - action: deny - - network: 172.16.0.0/12 - action: deny - - network: 0.0.0.0/0 - action: permit - ge: 8 - le: 24 - ipv6: - source_address: 2001:db8::2 - access_list: - - network: ::/0 - action: permit - ge: 32 - le: 64 - proxy: - name: server01 - address: 10.11.6.204 - port: 22 - credential: - username: user1 - password: secret1 - nos: linux_ssh diff --git a/hyperglass/examples/hyperglass.yaml b/hyperglass/examples/hyperglass.yaml deleted file mode 100644 index e69de29..0000000 diff --git a/hyperglass/exceptions.py b/hyperglass/exceptions.py deleted file mode 100644 index 8aee847..0000000 --- a/hyperglass/exceptions.py +++ /dev/null @@ -1,190 +0,0 @@ -"""Custom exceptions for hyperglass.""" - -# Standard Library -import json as _json -from typing import Dict, List, Union, Optional - -# Project -from hyperglass.log import log -from hyperglass.constants import STATUS_CODE_MAP - - -def validation_error_message(*errors: Dict) -> str: - """Parse errors return from pydantic.ValidationError.errors().""" - - errs = ("\n",) - - for err in errors: - loc = " → ".join(str(loc) for loc in err["loc"]) - errs += (f'Field: {loc}\n Error: {err["msg"]}\n',) - - return "\n".join(errs) - - -class HyperglassError(Exception): - """hyperglass base exception.""" - - def __init__( - self, - message: str = "", - level: str = "warning", - keywords: Optional[List[str]] = None, - ) -> None: - """Initialize the hyperglass base exception class.""" - self._message = message - self._level = level - self._keywords = keywords or [] - if self._level == "warning": - log.error(repr(self)) - elif self._level == "danger": - log.critical(repr(self)) - else: - log.info(repr(self)) - - def __str__(self) -> str: - """Return the instance's error message.""" - return self._message - - def __repr__(self) -> str: - """Return the instance's severity & error message in a string.""" - return f"[{self.level.upper()}] {self._message}" - - def dict(self) -> Dict: - """Return the instance's attributes as a dictionary.""" - return { - "message": self._message, - "level": self._level, - "keywords": self._keywords, - } - - def json(self) -> str: - """Return the instance's attributes as a JSON object.""" - return _json.dumps(self.__dict__()) - - @property - def message(self) -> str: - """Return the instance's `message` attribute.""" - return self._message - - @property - def level(self) -> str: - """Return the instance's `level` attribute.""" - return self._level - - @property - def keywords(self) -> List[str]: - """Return the instance's `keywords` attribute.""" - return self._keywords - - @property - def status_code(self) -> int: - """Return HTTP status code based on level level.""" - return STATUS_CODE_MAP.get(self._level, 500) - - -class _UnformattedHyperglassError(HyperglassError): - """Base exception class for freeform error messages.""" - - _level = "warning" - - def __init__( - self, unformatted_msg: str = "", level: Optional[str] = None, **kwargs - ) -> None: - """Format error message with keyword arguments.""" - self._message = unformatted_msg.format(**kwargs) - self._level = level or self._level - self._keywords = list(kwargs.values()) - super().__init__( - message=self._message, level=self._level, keywords=self._keywords - ) - - -class _PredefinedHyperglassError(HyperglassError): - _message = "undefined" - _level = "warning" - - def __init__(self, level: Optional[str] = None, **kwargs) -> None: - self._fmt_msg = self._message.format(**kwargs) - self._level = level or self._level - self._keywords = list(kwargs.values()) - super().__init__( - message=self._fmt_msg, level=self._level, keywords=self._keywords - ) - - -class ConfigInvalid(HyperglassError): - """Raised when a config item fails type or option validation.""" - - def __init__(self, errors: List[str]) -> None: - """Parse Pydantic ValidationError.""" - - super().__init__(message=validation_error_message(*errors)) - - -class ConfigError(_UnformattedHyperglassError): - """Raised for generic user-config issues.""" - - -class ConfigMissing(_PredefinedHyperglassError): - """Raised when a required config file or item is missing or undefined.""" - - _message = ( - "{missing_item} is missing or undefined and is required to start " - "hyperglass. Please consult the installation documentation." - ) - - -class ScrapeError(_UnformattedHyperglassError): - """Raised when a scrape/netmiko error occurs.""" - - _level = "danger" - - -class AuthError(_UnformattedHyperglassError): - """Raised when authentication to a device fails.""" - - _level = "danger" - - -class RestError(_UnformattedHyperglassError): - """Raised upon a rest API client error.""" - - _level = "danger" - - -class DeviceTimeout(_UnformattedHyperglassError): - """Raised when the connection to a device times out.""" - - _level = "danger" - - -class InputInvalid(_UnformattedHyperglassError): - """Raised when input validation fails.""" - - -class InputNotAllowed(_UnformattedHyperglassError): - """Raised when input validation fails due to a configured check.""" - - -class ResponseEmpty(_UnformattedHyperglassError): - """Raised when hyperglass can connect to the device but the response is empty.""" - - -class UnsupportedDevice(_UnformattedHyperglassError): - """Raised when an input NOS is not in the supported NOS list.""" - - -class ParsingError(_UnformattedHyperglassError): - """Raised when there is a problem parsing a structured response.""" - - def __init__( - self, unformatted_msg: Union[List[Dict], str], level: str = "danger", **kwargs, - ) -> None: - """Format error message with keyword arguments.""" - if isinstance(unformatted_msg, list): - self._message = validation_error_message(*unformatted_msg) - else: - self._message = unformatted_msg.format(**kwargs) - self._level = level or self._level - self._keywords = list(kwargs.values()) - super().__init__(self._message, level=self._level, keywords=self._keywords) diff --git a/hyperglass/execution/__init__.py b/hyperglass/execution/__init__.py deleted file mode 100644 index ec33dd5..0000000 --- a/hyperglass/execution/__init__.py +++ /dev/null @@ -1,5 +0,0 @@ -"""Validate, construct, execute queries. - -Constructs SSH commands or API call parameters based on front end -input, executes the commands/calls, returns the output to front end. -""" diff --git a/hyperglass/execution/drivers/__init__.py b/hyperglass/execution/drivers/__init__.py deleted file mode 100644 index 73a6ada..0000000 --- a/hyperglass/execution/drivers/__init__.py +++ /dev/null @@ -1,7 +0,0 @@ -"""Individual transport driver classes & subclasses.""" - -# Local -from .agent import AgentConnection -from ._common import Connection -from .ssh_netmiko import NetmikoConnection -from .ssh_scrapli import ScrapliConnection diff --git a/hyperglass/execution/drivers/_common.py b/hyperglass/execution/drivers/_common.py deleted file mode 100644 index 14b425a..0000000 --- a/hyperglass/execution/drivers/_common.py +++ /dev/null @@ -1,81 +0,0 @@ -"""Base Connection Class.""" - -# Standard Library -from typing import Dict, Union, Sequence - -# Project -from hyperglass.log import log -from hyperglass.models.api import Query -from hyperglass.parsing.nos import scrape_parsers, structured_parsers -from hyperglass.parsing.common import parsers -from hyperglass.models.config.devices import Device - -# Local -from ._construct import Construct - - -class Connection: - """Base transport driver class.""" - - def __init__(self, device: Device, query_data: Query) -> None: - """Initialize connection to device.""" - self.device = device - self.query_data = query_data - self.query_type = self.query_data.query_type - self.query_target = self.query_data.query_target - self._query = Construct(device=self.device, query_data=self.query_data) - self.query = self._query.queries() - - async def parsed_response( # noqa: C901 ("too complex") - self, output: Sequence[str] - ) -> Union[str, Sequence[Dict]]: - """Send output through common parsers.""" - - log.debug("Pre-parsed responses:\n{}", output) - parsed = () - response = None - - structured_nos = structured_parsers.keys() - structured_query_types = structured_parsers.get(self.device.nos, {}).keys() - - scrape_nos = scrape_parsers.keys() - scrape_query_types = scrape_parsers.get(self.device.nos, {}).keys() - - if not self.device.structured_output: - _parsed = () - for func in parsers: - for response in output: - _output = func(commands=self.query, output=response) - _parsed += (_output,) - if self.device.nos in scrape_nos and self.query_type in scrape_query_types: - func = scrape_parsers[self.device.nos][self.query_type] - for response in _parsed: - _output = func(response) - parsed += (_output,) - else: - parsed += _parsed - - response = "\n\n".join(parsed) - elif ( - self.device.structured_output - and self.device.nos in structured_nos - and self.query_type not in structured_query_types - ): - for func in parsers: - for response in output: - _output = func(commands=self.query, output=response) - parsed += (_output,) - response = "\n\n".join(parsed) - elif ( - self.device.structured_output - and self.device.nos in structured_nos - and self.query_type in structured_query_types - ): - func = structured_parsers[self.device.nos][self.query_type] - response = func(output) - - if response is None: - response = "\n\n".join(output) - - log.debug("Post-parsed responses:\n{}", response) - return response diff --git a/hyperglass/execution/drivers/_construct.py b/hyperglass/execution/drivers/_construct.py deleted file mode 100644 index ad3f41c..0000000 --- a/hyperglass/execution/drivers/_construct.py +++ /dev/null @@ -1,201 +0,0 @@ -"""Construct SSH command/API parameters from validated query data. - -Accepts filtered & validated input from execute.py, constructs SSH -command for Netmiko library or API call parameters for supported -hyperglass API modules. -""" - -# Standard Library -import re -import json as _json -from operator import attrgetter - -# Project -from hyperglass.log import log -from hyperglass.constants import TRANSPORT_REST, TARGET_FORMAT_SPACE -from hyperglass.configuration import commands - - -class Construct: - """Construct SSH commands/REST API parameters from validated query data.""" - - def __init__(self, device, query_data): - """Initialize command construction.""" - log.debug( - "Constructing {} query for '{}'", - query_data.query_type, - str(query_data.query_target), - ) - self.device = device - self.query_data = query_data - self.target = self.query_data.query_target - - # Set transport method based on NOS type - self.transport = "scrape" - if self.device.nos in TRANSPORT_REST: - self.transport = "rest" - - # Remove slashes from target for required platforms - if self.device.nos in TARGET_FORMAT_SPACE: - self.target = re.sub(r"\/", r" ", str(self.query_data.query_target)) - - # Set AFIs for based on query type - if self.query_data.query_type in ("bgp_route", "ping", "traceroute"): - # For IP queries, AFIs are enabled (not null/None) VRF -> AFI definitions - # where the IP version matches the IP version of the target. - self.afis = [ - v - for v in ( - self.query_data.query_vrf.ipv4, - self.query_data.query_vrf.ipv6, - ) - if v is not None and self.query_data.query_target.version == v.version - ] - elif self.query_data.query_type in ("bgp_aspath", "bgp_community"): - # For AS Path/Community queries, AFIs are just enabled VRF -> AFI - # definitions, no IP version checking is performed (since there is no IP). - self.afis = [ - v - for v in ( - self.query_data.query_vrf.ipv4, - self.query_data.query_vrf.ipv6, - ) - if v is not None - ] - - with Formatter(self.device.nos, self.query_data.query_type) as formatter: - self.target = formatter(self.query_data.query_target) - - def json(self, afi): - """Return JSON version of validated query for REST devices.""" - log.debug("Building JSON query for {q}", q=repr(self.query_data)) - return _json.dumps( - { - "query_type": self.query_data.query_type, - "vrf": self.query_data.query_vrf.name, - "afi": afi.protocol, - "source": str(afi.source_address), - "target": str(self.target), - } - ) - - def scrape(self, afi): - """Return formatted command for 'Scrape' endpoints (SSH).""" - if self.device.structured_output: - cmd_paths = ( - self.device.nos, - "structured", - afi.protocol, - self.query_data.query_type, - ) - else: - cmd_paths = (self.device.commands, afi.protocol, self.query_data.query_type) - - command = attrgetter(".".join(cmd_paths))(commands) - return command.format( - target=self.target, - source=str(afi.source_address), - vrf=self.query_data.query_vrf.name, - ) - - def queries(self): - """Return queries for each enabled AFI.""" - query = [] - - for afi in self.afis: - if self.transport == "rest": - query.append(self.json(afi=afi)) - else: - query.append(self.scrape(afi=afi)) - - log.debug("Constructed query: {}", query) - return query - - -class Formatter: - """Modify query target based on the device's NOS requirements and the query type.""" - - def __init__(self, nos: str, query_type: str) -> None: - """Initialize target formatting.""" - self.nos = nos - self.query_type = query_type - - def __enter__(self): - """Get the relevant formatter.""" - return self._get_formatter() - - def __exit__(self, exc_type, exc_value, exc_traceback): - """Handle context exit.""" - if exc_type is not None: - log.error(exc_traceback) - pass - - def _get_formatter(self): - if self.nos in ("juniper", "juniper_junos"): - if self.query_type == "bgp_aspath": - return self._juniper_bgp_aspath - if self.nos in ("bird", "bird_ssh"): - if self.query_type == "bgp_aspath": - return self._bird_bgp_aspath - elif self.query_type == "bgp_community": - return self._bird_bgp_community - return self._default - - def _default(self, target: str) -> str: - """Don't format targets by default.""" - return target - - def _juniper_bgp_aspath(self, target: str) -> str: - """Convert from Cisco AS_PATH format to Juniper format.""" - query = str(target) - asns = re.findall(r"\d+", query) - was_modified = False - - if bool(re.match(r"^\_", query)): - # Replace `_65000` with `.* 65000` - asns.insert(0, r".*") - was_modified = True - - if bool(re.match(r".*(\_)$", query)): - # Replace `65000_` with `65000 .*` - asns.append(r".*") - was_modified = True - - if was_modified: - modified = " ".join(asns) - log.debug("Modified target '{}' to '{}'", target, modified) - return modified - - return query - - def _bird_bgp_aspath(self, target: str) -> str: - """Convert from Cisco AS_PATH format to BIRD format.""" - - # Extract ASNs from query target string - asns = re.findall(r"\d+", target) - was_modified = False - - if bool(re.match(r"^\_", target)): - # Replace `_65000` with `.* 65000` - asns.insert(0, "*") - was_modified = True - - if bool(re.match(r".*(\_)$", target)): - # Replace `65000_` with `65000 .*` - asns.append("*") - was_modified = True - - asns.insert(0, "[=") - asns.append("=]") - - result = " ".join(asns) - - if was_modified: - log.debug("Modified target '{}' to '{}'", target, result) - - return result - - def _bird_bgp_community(self, target: str) -> str: - """Convert from standard community format to BIRD format.""" - parts = target.split(":") - return f'({",".join(parts)})' diff --git a/hyperglass/execution/drivers/agent.py b/hyperglass/execution/drivers/agent.py deleted file mode 100644 index 3800e9b..0000000 --- a/hyperglass/execution/drivers/agent.py +++ /dev/null @@ -1,139 +0,0 @@ -"""Execute validated & constructed query on device. - -Accepts input from front end application, validates the input and -returns errors if input is invalid. Passes validated parameters to -construct.py, which is used to build & run the Netmiko connections or -hyperglass-frr API calls, returns the output back to the front end. -""" - -# Standard Library -from ssl import CertificateError -from typing import Iterable - -# Third Party -import httpx - -# Project -from hyperglass.log import log -from hyperglass.util import parse_exception -from hyperglass.encode import jwt_decode, jwt_encode -from hyperglass.exceptions import RestError, ResponseEmpty -from hyperglass.configuration import params - -# Local -from ._common import Connection - - -class AgentConnection(Connection): - """Connect to target device via hyperglass-agent.""" - - async def collect(self) -> Iterable: # noqa: C901 - """Connect to a device running hyperglass-agent via HTTP.""" - log.debug("Query parameters: {}", self.query) - - client_params = { - "headers": {"Content-Type": "application/json"}, - "timeout": params.request_timeout, - } - if self.device.ssl is not None and self.device.ssl.enable: - with self.device.ssl.cert.open("r") as file: - cert = file.read() - if not cert: - raise RestError( - "SSL Certificate for device {d} has not been imported", - level="danger", - d=self.device.name, - ) - http_protocol = "https" - client_params.update({"verify": str(self.device.ssl.cert)}) - log.debug( - ( - f"Using {str(self.device.ssl.cert)} to validate connection " - f"to {self.device.name}" - ) - ) - else: - http_protocol = "http" - endpoint = "{protocol}://{address}:{port}/query/".format( - protocol=http_protocol, address=self.device._target, port=self.device.port - ) - - log.debug("URL endpoint: {}", endpoint) - - try: - async with httpx.AsyncClient(**client_params) as http_client: - responses = () - - for query in self.query: - encoded_query = await jwt_encode( - payload=query, - secret=self.device.credential.password.get_secret_value(), - duration=params.request_timeout, - ) - log.debug("Encoded JWT: {}", encoded_query) - - raw_response = await http_client.post( - endpoint, json={"encoded": encoded_query} - ) - log.debug("HTTP status code: {}", raw_response.status_code) - - raw = raw_response.text - log.debug("Raw Response:\n{}", raw) - - if raw_response.status_code == 200: - decoded = await jwt_decode( - payload=raw_response.json()["encoded"], - secret=self.device.credential.password.get_secret_value(), - ) - log.debug("Decoded Response:\n{}", decoded) - responses += (decoded,) - - elif raw_response.status_code == 204: - raise ResponseEmpty( - params.messages.no_output, device_name=self.device.name, - ) - - else: - log.error(raw_response.text) - - except httpx.exceptions.HTTPError as rest_error: - msg = parse_exception(rest_error) - log.error("Error connecting to device {}: {}", self.device.name, msg) - raise RestError( - params.messages.connection_error, - device_name=self.device.name, - error=msg, - ) - except OSError as ose: - log.critical(str(ose)) - raise RestError( - params.messages.connection_error, - device_name=self.device.name, - error="System error", - ) - except CertificateError as cert_error: - log.critical(str(cert_error)) - msg = parse_exception(cert_error) - raise RestError( - params.messages.connection_error, - device_name=self.device.name, - error=f"{msg}: {cert_error}", - ) - - if raw_response.status_code != 200: - log.error("Response code is {}", raw_response.status_code) - raise RestError( - params.messages.connection_error, - device_name=self.device.name, - error=params.messages.general, - ) - - if not responses: - log.error("No response from device {}", self.device.name) - raise RestError( - params.messages.connection_error, - device_name=self.device.name, - error=params.messages.no_response, - ) - - return responses diff --git a/hyperglass/execution/drivers/ssh.py b/hyperglass/execution/drivers/ssh.py deleted file mode 100644 index 0c73caf..0000000 --- a/hyperglass/execution/drivers/ssh.py +++ /dev/null @@ -1,62 +0,0 @@ -"""Common Classes or Utilities for SSH Drivers.""" - -# Standard Library -from typing import Callable - -# Project -from hyperglass.log import log -from hyperglass.exceptions import ScrapeError -from hyperglass.configuration import params -from hyperglass.compat._sshtunnel import BaseSSHTunnelForwarderError, open_tunnel - -# Local -from ._common import Connection - - -class SSHConnection(Connection): - """Base class for SSH drivers.""" - - def setup_proxy(self) -> Callable: - """Return a preconfigured sshtunnel.SSHTunnelForwarder instance.""" - - proxy = self.device.proxy - - def opener(): - """Set up an SSH tunnel according to a device's configuration.""" - tunnel_kwargs = { - "ssh_username": proxy.credential.username, - "remote_bind_address": (self.device._target, self.device.port), - "local_bind_address": ("localhost", 0), - "skip_tunnel_checkup": False, - "gateway_timeout": params.request_timeout - 2, - } - if proxy.credential._method == "password": - # Use password auth if no key is defined. - tunnel_kwargs[ - "ssh_password" - ] = proxy.credential.password.get_secret_value() - else: - # Otherwise, use key auth. - tunnel_kwargs["ssh_pkey"] = proxy.credential.key.as_posix() - if proxy.credential._method == "encrypted_key": - # If the key is encrypted, use the password field as the - # private key password. - tunnel_kwargs[ - "ssh_private_key_password" - ] = proxy.credential.password.get_secret_value() - try: - return open_tunnel(proxy._target, proxy.port, **tunnel_kwargs) - - except BaseSSHTunnelForwarderError as scrape_proxy_error: - log.error( - f"Error connecting to device {self.device.name} via " - f"proxy {proxy.name}" - ) - raise ScrapeError( - params.messages.connection_error, - device_name=self.device.name, - proxy=proxy.name, - error=str(scrape_proxy_error), - ) - - return opener diff --git a/hyperglass/execution/drivers/ssh_netmiko.py b/hyperglass/execution/drivers/ssh_netmiko.py deleted file mode 100644 index 5e055b4..0000000 --- a/hyperglass/execution/drivers/ssh_netmiko.py +++ /dev/null @@ -1,136 +0,0 @@ -"""Netmiko-Specific Classes & Utilities. - -https://github.com/ktbyers/netmiko -""" - -# Standard Library -import math -from typing import Iterable - -# Third Party -from netmiko import ( - ConnectHandler, - NetMikoTimeoutException, - NetMikoAuthenticationException, -) - -# Project -from hyperglass.log import log -from hyperglass.exceptions import AuthError, ScrapeError, DeviceTimeout -from hyperglass.configuration import params - -# Local -from .ssh import SSHConnection - -netmiko_nos_globals = { - # Netmiko doesn't currently handle Mikrotik echo verification well, - # see ktbyers/netmiko#1600 - "mikrotik_routeros": {"global_cmd_verify": False}, - "mikrotik_switchos": {"global_cmd_verify": False}, -} - -netmiko_nos_send_args = { - # Netmiko doesn't currently handle the Mikrotik prompt properly, see - # ktbyers/netmiko#1956 - "mikrotik_routeros": {"expect_string": r"\S+\s\>\s$"}, - "mikrotik_switchos": {"expect_string": r"\S+\s\>\s$"}, -} - - -class NetmikoConnection(SSHConnection): - """Handle a device connection via Netmiko.""" - - async def collect(self, host: str = None, port: int = None) -> Iterable: - """Connect directly to a device. - - Directly connects to the router via Netmiko library, returns the - command output. - """ - if host is not None: - log.debug( - "Connecting to {} via proxy {} [{}]", - self.device.name, - self.device.proxy.name, - f"{host}:{port}", - ) - else: - log.debug("Connecting directly to {}", self.device.name) - - global_args = netmiko_nos_globals.get(self.device.nos, {}) - - send_args = netmiko_nos_send_args.get(self.device.nos, {}) - - driver_kwargs = { - "host": host or self.device._target, - "port": port or self.device.port, - "device_type": self.device.nos, - "username": self.device.credential.username, - "global_delay_factor": params.netmiko_delay_factor, - "timeout": math.floor(params.request_timeout * 1.25), - "session_timeout": math.ceil(params.request_timeout - 1), - **global_args, - } - - if "_telnet" in self.device.nos: - # Telnet devices with a low delay factor (default) tend to - # throw login errors. - driver_kwargs["global_delay_factor"] = 2 - - if self.device.credential._method == "password": - # Use password auth if no key is defined. - driver_kwargs[ - "password" - ] = self.device.credential.password.get_secret_value() - else: - # Otherwise, use key auth. - driver_kwargs["use_keys"] = True - driver_kwargs["key_file"] = self.device.credential.key - if self.device.credential._method == "encrypted_key": - # If the key is encrypted, use the password field as the - # private key password. - driver_kwargs[ - "passphrase" - ] = self.device.credential.password.get_secret_value() - - try: - nm_connect_direct = ConnectHandler(**driver_kwargs) - - responses = () - - for query in self.query: - raw = nm_connect_direct.send_command(query, **send_args) - responses += (raw,) - log.debug(f'Raw response for command "{query}":\n{raw}') - - nm_connect_direct.disconnect() - - except NetMikoTimeoutException as scrape_error: - log.error(str(scrape_error)) - raise DeviceTimeout( - params.messages.connection_error, - device_name=self.device.name, - proxy=None, - error=params.messages.request_timeout, - ) - except NetMikoAuthenticationException as auth_error: - log.error( - "Error authenticating to device {loc}: {e}", - loc=self.device.name, - e=str(auth_error), - ) - - raise AuthError( - params.messages.connection_error, - device_name=self.device.name, - proxy=None, - error=params.messages.authentication_error, - ) - if not responses: - raise ScrapeError( - params.messages.connection_error, - device_name=self.device.name, - proxy=None, - error=params.messages.no_response, - ) - - return responses diff --git a/hyperglass/execution/drivers/ssh_scrapli.py b/hyperglass/execution/drivers/ssh_scrapli.py deleted file mode 100644 index 935dbeb..0000000 --- a/hyperglass/execution/drivers/ssh_scrapli.py +++ /dev/null @@ -1,160 +0,0 @@ -"""Scrapli-Specific Classes & Utilities. - -https://github.com/carlmontanari/scrapli -""" - -# Standard Library -import math -from typing import Sequence - -# Third Party -from scrapli.driver import AsyncGenericDriver -from scrapli.exceptions import ( - ScrapliTimeout, - ScrapliException, - ScrapliAuthenticationFailed, -) -from scrapli.driver.core import ( - AsyncEOSDriver, - AsyncNXOSDriver, - AsyncIOSXEDriver, - AsyncIOSXRDriver, - AsyncJunosDriver, -) - -# Project -from hyperglass.log import log -from hyperglass.exceptions import ( - AuthError, - ScrapeError, - DeviceTimeout, - UnsupportedDevice, -) -from hyperglass.configuration import params - -# Local -from .ssh import SSHConnection - -SCRAPLI_DRIVER_MAP = { - "arista_eos": AsyncEOSDriver, - "bird": AsyncGenericDriver, - "cisco_ios": AsyncIOSXEDriver, - "cisco_nxos": AsyncNXOSDriver, - "cisco_xr": AsyncIOSXRDriver, - "frr": AsyncGenericDriver, - "juniper": AsyncJunosDriver, - "tnsr": AsyncGenericDriver, -} - -driver_global_args = { - # Per-NOS driver keyword arguments - "tnsr": {"comms_prompt_pattern": r"\S+\s\S+[\#\>]"}, - "frr": {"comms_ansi": True}, - "bird": {"comms_ansi": True}, -} - - -def _map_driver(nos: str) -> AsyncGenericDriver: - driver = SCRAPLI_DRIVER_MAP.get(nos) - if driver is None: - raise UnsupportedDevice("{nos} is not supported by scrapli.", nos=nos) - return driver - - -class ScrapliConnection(SSHConnection): - """Handle a device connection via Scrapli.""" - - async def collect(self, host: str = None, port: int = None) -> Sequence: - """Connect directly to a device. - - Directly connects to the router via Netmiko library, returns the - command output. - """ - driver = _map_driver(self.device.nos) - - if host is not None: - log.debug( - "Connecting to {} via proxy {} [{}]", - self.device.name, - self.device.proxy.name, - f"{host}:{port}", - ) - else: - log.debug("Connecting directly to {}", self.device.name) - - global_args = driver_global_args.get(self.device.nos, {}) - - driver_kwargs = { - "host": host or self.device._target, - "port": port or self.device.port, - "auth_username": self.device.credential.username, - "timeout_ops": math.floor(params.request_timeout * 1.25), - "transport": "asyncssh", - "auth_strict_key": False, - "ssh_known_hosts_file": False, - **global_args, - } - - if self.device.credential._method == "password": - # Use password auth if no key is defined. - driver_kwargs[ - "auth_password" - ] = self.device.credential.password.get_secret_value() - else: - # Otherwise, use key auth. - driver_kwargs["auth_private_key"] = self.device.credential.key.as_posix() - if self.device.credential._method == "encrypted_key": - # If the key is encrypted, use the password field as the - # private key password. - driver_kwargs[ - "auth_private_key_passphrase" - ] = self.device.credential.password.get_secret_value() - - driver = driver(**driver_kwargs) - driver.logger = log.bind( - logger_name=f"scrapli.{driver.host}:{driver.port}-driver" - ) - try: - responses = () - async with driver as connection: - await connection.get_prompt() - for query in self.query: - raw = await connection.send_command(query) - responses += (raw.result,) - log.debug(f'Raw response for command "{query}":\n{raw.result}') - - except ScrapliTimeout as err: - log.error(err) - raise DeviceTimeout( - params.messages.connection_error, - device_name=self.device.name, - error=params.messages.request_timeout, - ) - except ScrapliAuthenticationFailed as err: - log.error( - "Error authenticating to device {loc}: {e}", - loc=self.device.name, - e=str(err), - ) - - raise AuthError( - params.messages.connection_error, - device_name=self.device.name, - error=params.messages.authentication_error, - ) - except ScrapliException as err: - log.error(err) - raise ScrapeError( - params.messages.connection_error, - device_name=self.device.name, - error=params.messages.no_response, - ) - - if not responses: - raise ScrapeError( - params.messages.connection_error, - device_name=self.device.name, - error=params.messages.no_response, - ) - - return responses diff --git a/hyperglass/execution/main.py b/hyperglass/execution/main.py deleted file mode 100644 index 618cf5d..0000000 --- a/hyperglass/execution/main.py +++ /dev/null @@ -1,96 +0,0 @@ -"""Execute validated & constructed query on device. - -Accepts input from front end application, validates the input and -returns errors if input is invalid. Passes validated parameters to -construct.py, which is used to build & run the Netmiko connections or -hyperglass-frr API calls, returns the output back to the front end. -""" - -# Standard Library -import signal -from typing import Any, Dict, Union, Callable, Sequence - -# Project -from hyperglass.log import log -from hyperglass.exceptions import DeviceTimeout, ResponseEmpty -from hyperglass.models.api import Query -from hyperglass.configuration import params - -# Local -from .drivers import Connection, AgentConnection, NetmikoConnection, ScrapliConnection - - -def map_driver(driver_name: str) -> Connection: - """Get the correct driver class based on the driver name.""" - - if driver_name == "scrapli": - return ScrapliConnection - - elif driver_name == "hyperglass_agent": - return AgentConnection - - return NetmikoConnection - - -def handle_timeout(**exc_args: Any) -> Callable: - """Return a function signal can use to raise a timeout exception.""" - - def handler(*args: Any, **kwargs: Any) -> None: - raise DeviceTimeout(**exc_args) - - return handler - - -async def execute(query: Query) -> Union[str, Sequence[Dict]]: - """Initiate query validation and execution.""" - - output = params.messages.general - - log.debug("Received query for {}", query.json()) - log.debug("Matched device config: {}", query.device) - - mapped_driver = map_driver(query.device.driver) - driver = mapped_driver(query.device, query) - - timeout_args = { - "unformatted_msg": params.messages.connection_error, - "device_name": query.device.name, - "error": params.messages.request_timeout, - } - - if query.device.proxy: - timeout_args["proxy"] = query.device.proxy.name - - signal.signal(signal.SIGALRM, handle_timeout(**timeout_args)) - signal.alarm(params.request_timeout - 1) - - if query.device.proxy: - proxy = driver.setup_proxy() - with proxy() as tunnel: - response = await driver.collect( - tunnel.local_bind_host, tunnel.local_bind_port - ) - else: - response = await driver.collect() - - output = await driver.parsed_response(response) - - if isinstance(output, str): - # If the output is a string (not structured) and is empty, - # produce an error. - if output == "" or output == "\n": - raise ResponseEmpty( - params.messages.no_output, device_name=query.device.name - ) - elif isinstance(output, Dict): - # If the output an empty dict, responses have data, produce an - # error. - if not output: - raise ResponseEmpty( - params.messages.no_output, device_name=query.device.name - ) - - log.debug("Output for query: {}:\n{}", query.json(), repr(output)) - signal.alarm(0) - - return output diff --git a/hyperglass/external/__init__.py b/hyperglass/external/__init__.py deleted file mode 100644 index 358b0d8..0000000 --- a/hyperglass/external/__init__.py +++ /dev/null @@ -1,5 +0,0 @@ -"""Functions & handlers for external data.""" - -# Local -from .ripestat import RIPEStat # noqa: F401 -from .webhooks import Webhook # noqa: F401 diff --git a/hyperglass/external/_base.py b/hyperglass/external/_base.py deleted file mode 100644 index b9d368e..0000000 --- a/hyperglass/external/_base.py +++ /dev/null @@ -1,330 +0,0 @@ -"""Session handler for RIPEStat Data API.""" - -# Standard Library -import re -import json as _json -import socket -from json import JSONDecodeError -from socket import gaierror - -# Third Party -import httpx -from httpx import StatusCode - -# Project -from hyperglass.log import log -from hyperglass.util import make_repr, parse_exception -from hyperglass.constants import __version__ -from hyperglass.exceptions import HyperglassError - - -def _prepare_dict(_dict): - return _json.loads(_json.dumps(_dict, default=str)) - - -class BaseExternal: - """Base session handler.""" - - def __init__( - self, - base_url, - config=None, - uri_prefix="", - uri_suffix="", - verify_ssl=True, - timeout=10, - parse=True, - ): - """Initialize connection instance.""" - self.__name__ = getattr(self, "name", "BaseExternal") - self.config = config - self.base_url = base_url.strip("/") - self.uri_prefix = uri_prefix.strip("/") - self.uri_suffix = uri_suffix.strip("/") - self.verify_ssl = verify_ssl - self.timeout = timeout - self.parse = parse - - session_args = { - "verify": self.verify_ssl, - "base_url": self.base_url, - "timeout": self.timeout, - } - self._session = httpx.Client(**session_args) - self._asession = httpx.AsyncClient(**session_args) - - @classmethod - def __init_subclass__(cls, name=None, **kwargs): - """Set correct subclass name.""" - super().__init_subclass__(**kwargs) - cls.name = name or cls.__name__ - - async def __aenter__(self): - """Test connection on entry.""" - available = await self._atest() - - if available: - log.debug("Initialized session with {}", self.base_url) - return self - else: - raise self._exception(f"Unable to create session to {self.name}") - - async def __aexit__(self, exc_type=None, exc_value=None, traceback=None): - """Close connection on exit.""" - log.debug("Closing session with {}", self.base_url) - - await self._asession.aclose() - return True - - def __enter__(self): - """Test connection on entry.""" - available = self._test() - - if available: - log.debug("Initialized session with {}", self.base_url) - return self - else: - raise self._exception(f"Unable to create session to {self.name}") - - def __exit__(self, exc_type=None, exc_value=None, traceback=None): - """Close connection on exit.""" - if exc_type is not None: - log.error(traceback) - self._session.close() - - def __repr__(self): - """Return user friendly representation of instance.""" - return make_repr(self) - - def _exception(self, message, exc=None, level="warning", **kwargs): - """Add stringified exception to message if passed.""" - if exc is not None: - message = f"{str(message)}: {str(exc)}" - - return HyperglassError(message, str(level), **kwargs) - - def _parse_response(self, response): - if self.parse: - parsed = {} - try: - parsed = response.json() - except JSONDecodeError: - try: - parsed = _json.loads(response) - except (JSONDecodeError, TypeError): - log.error("Error parsing JSON for response {}", repr(response)) - parsed = {"data": response.text} - else: - parsed = response - return parsed - - def _test(self): - """Open a low-level connection to the base URL to ensure its port is open.""" - log.debug("Testing connection to {}", self.base_url) - - try: - # Parse out just the hostname from a URL string. - # E.g. `https://www.example.com` becomes `www.example.com` - test_host = re.sub(r"http(s)?\:\/\/", "", self.base_url) - - # Create a generic socket object - test_socket = socket.socket() - - # Try opening a low-level socket to make sure it's even - # listening on the port prior to trying to use it. - test_socket.connect((test_host, 443)) - - # Properly shutdown & close the socket. - test_socket.shutdown(1) - test_socket.close() - - except gaierror as err: - # Raised if the target isn't listening on the port - raise self._exception( - f"{self.name} appears to be unreachable", err - ) from None - - return True - - async def _atest(self): - """Open a low-level connection to the base URL to ensure its port is open.""" - return self._test() - - def _build_request(self, **kwargs): - """Process requests parameters into structure usable by http library.""" - # Standard Library - from operator import itemgetter - - supported_methods = ("GET", "POST", "PUT", "DELETE", "HEAD", "PATCH") - - ( - method, - endpoint, - item, - headers, - params, - data, - timeout, - response_required, - ) = itemgetter(*kwargs.keys())(kwargs) - - if method.upper() not in supported_methods: - raise self._exception( - f'Method must be one of {", ".join(supported_methods)}. ' - f"Got: {str(method)}" - ) - - endpoint = "/".join( - i - for i in ( - "", - self.uri_prefix.strip("/"), - endpoint.strip("/"), - self.uri_suffix.strip("/"), - item, - ) - if i - ) - - request = { - "method": method, - "url": endpoint, - "headers": {"user-agent": f"hyperglass/{__version__}"}, - } - - if headers is not None: - request.update({"headers": headers}) - - if params is not None: - params = {str(k): str(v) for k, v in params.items() if v is not None} - request["params"] = params - - if data is not None: - if not isinstance(data, dict): - raise self._exception(f"Data must be a dict, got: {str(data)}") - request["json"] = _prepare_dict(data) - - if timeout is not None: - if not isinstance(timeout, int): - try: - timeout = int(timeout) - except TypeError: - raise self._exception( - f"Timeout must be an int, got: {str(timeout)}" - ) - request["timeout"] = timeout - - log.debug("Constructed request parameters {}", request) - return request - - async def _arequest( # noqa: C901 - self, - method, - endpoint, - item=None, - headers=None, - params=None, - data=None, - timeout=None, - response_required=False, - ): - """Run HTTP POST operation.""" - request = self._build_request( - method=method, - endpoint=endpoint, - item=item, - headers=None, - params=params, - data=data, - timeout=timeout, - response_required=response_required, - ) - - try: - response = await self._asession.request(**request) - - if response.status_code not in range(200, 300): - status = StatusCode(response.status_code) - error = self._parse_response(response) - raise self._exception( - f'{status.name.replace("_", " ")}: {error}', level="danger" - ) from None - - except httpx.HTTPError as http_err: - raise self._exception(parse_exception(http_err), level="danger") from None - - return self._parse_response(response) - - async def _aget(self, endpoint, **kwargs): - return await self._arequest(method="GET", endpoint=endpoint, **kwargs) - - async def _apost(self, endpoint, **kwargs): - return await self._arequest(method="POST", endpoint=endpoint, **kwargs) - - async def _aput(self, endpoint, **kwargs): - return await self._arequest(method="PUT", endpoint=endpoint, **kwargs) - - async def _adelete(self, endpoint, **kwargs): - return await self._arequest(method="DELETE", endpoint=endpoint, **kwargs) - - async def _apatch(self, endpoint, **kwargs): - return await self._arequest(method="PATCH", endpoint=endpoint, **kwargs) - - async def _ahead(self, endpoint, **kwargs): - return await self._arequest(method="HEAD", endpoint=endpoint, **kwargs) - - def _request( # noqa: C901 - self, - method, - endpoint, - item=None, - headers=None, - params=None, - data=None, - timeout=None, - response_required=False, - ): - """Run HTTP POST operation.""" - request = self._build_request( - method=method, - endpoint=endpoint, - item=item, - headers=None, - params=params, - data=data, - timeout=timeout, - response_required=response_required, - ) - - try: - response = self._session.request(**request) - - if response.status_code not in range(200, 300): - status = StatusCode(response.status_code) - error = self._parse_response(response) - raise self._exception( - f'{status.name.replace("_", " ")}: {error}', level="danger" - ) from None - - except httpx.HTTPError as http_err: - raise self._exception(parse_exception(http_err), level="danger") from None - - return self._parse_response(response) - - def _get(self, endpoint, **kwargs): - return self._request(method="GET", endpoint=endpoint, **kwargs) - - def _post(self, endpoint, **kwargs): - return self._request(method="POST", endpoint=endpoint, **kwargs) - - def _put(self, endpoint, **kwargs): - return self._request(method="PUT", endpoint=endpoint, **kwargs) - - def _delete(self, endpoint, **kwargs): - return self._request(method="DELETE", endpoint=endpoint, **kwargs) - - def _patch(self, endpoint, **kwargs): - return self._request(method="PATCH", endpoint=endpoint, **kwargs) - - def _head(self, endpoint, **kwargs): - return self._request(method="HEAD", endpoint=endpoint, **kwargs) diff --git a/hyperglass/external/bgptools.py b/hyperglass/external/bgptools.py deleted file mode 100644 index 87b9c38..0000000 --- a/hyperglass/external/bgptools.py +++ /dev/null @@ -1,204 +0,0 @@ -"""Query & parse data from bgp.tools. - -- See https://bgp.tools/credits for acknowledgements and licensing. -- See https://bgp.tools/kb/api for query documentation. -""" - -# Standard Library -import re -import socket -import asyncio -from typing import Dict, List - -# Project -from hyperglass.log import log -from hyperglass.cache import SyncCache, AsyncCache -from hyperglass.configuration import REDIS_CONFIG, params - -DEFAULT_KEYS = ("asn", "ip", "prefix", "country", "rir", "allocated", "org") - -CACHE_KEY = "hyperglass.external.bgptools" - - -def parse_whois(output: str, targets: List[str]) -> Dict[str, str]: - """Parse raw whois output from bgp.tools. - - Sample output: - AS | IP | BGP Prefix | CC | Registry | Allocated | AS Name - 13335 | 1.1.1.1 | 1.1.1.0/24 | US | ARIN | 2010-07-14 | Cloudflare, Inc. - """ - - def lines(raw): - """Generate clean string values for each column.""" - for r in (r for r in raw.split("\n") if r): - fields = ( - re.sub(r"(\n|\r)", "", field).strip(" ") for field in r.split("|") - ) - yield fields - - data = {} - - for line in lines(output): - - # Unpack each line's parsed values. - asn, ip, prefix, country, rir, allocated, org = line - - # Match the line to the item in the list of resources to query. - if ip in targets: - i = targets.index(ip) - data[targets[i]] = { - "asn": asn, - "ip": ip, - "prefix": prefix, - "country": country, - "rir": rir, - "allocated": allocated, - "org": org, - } - - log.debug("Parsed bgp.tools data: {}", data) - return data - - -async def run_whois(targets: List[str]) -> str: - """Open raw socket to bgp.tools and execute query.""" - - # Construct bulk query - query = "\n".join(("begin", *targets, "end\n")).encode() - - # Open the socket to bgp.tools - log.debug("Opening connection to bgp.tools") - reader, writer = await asyncio.open_connection("bgp.tools", port=43) - - # Send the query - writer.write(query) - if writer.can_write_eof(): - writer.write_eof() - await writer.drain() - - # Read the response - response = b"" - while True: - data = await reader.read(128) - if data: - response += data - else: - log.debug("Closing connection to bgp.tools") - writer.close() - break - - return response.decode() - - -def run_whois_sync(targets: List[str]) -> str: - """Open raw socket to bgp.tools and execute query.""" - - # Construct bulk query - query = "\n".join(("begin", *targets, "end\n")).encode() - - # Open the socket to bgp.tools - log.debug("Opening connection to bgp.tools") - sock = socket.socket() - sock.connect(("bgp.tools", 43)) - sock.send(query) - - # Read the response - response = b"" - while True: - data = sock.recv(128) - if data: - response += data - - else: - log.debug("Closing connection to bgp.tools") - sock.shutdown(1) - sock.close() - break - - return response.decode() - - -async def network_info(*targets: str) -> Dict[str, Dict[str, str]]: - """Get ASN, Containing Prefix, and other info about an internet resource.""" - - targets = [str(t) for t in targets] - cache = AsyncCache(db=params.cache.database, **REDIS_CONFIG) - - # Set default data structure. - data = {t: {k: "" for k in DEFAULT_KEYS} for t in targets} - - # Get all cached bgp.tools data. - cached = await cache.get_dict(CACHE_KEY) - - # Try to use cached data for each of the items in the list of - # resources. - for t in targets: - - if t in cached: - # Reassign the cached network info to the matching resource. - data[t] = cached[t] - log.debug("Using cached network info for {}", t) - - # Remove cached items from the resource list so they're not queried. - targets = [t for t in targets if t not in cached] - - try: - if targets: - whoisdata = await run_whois(targets) - - if whoisdata: - # If the response is not empty, parse it. - data.update(parse_whois(whoisdata, targets)) - - # Cache the response - for t in targets: - await cache.set_dict(CACHE_KEY, t, data[t]) - log.debug("Cached network info for {}", t) - - except Exception as err: - log.error(str(err)) - - return data - - -def network_info_sync(*targets: str) -> Dict[str, Dict[str, str]]: - """Get ASN, Containing Prefix, and other info about an internet resource.""" - - targets = [str(t) for t in targets] - cache = SyncCache(db=params.cache.database, **REDIS_CONFIG) - - # Set default data structure. - data = {t: {k: "" for k in DEFAULT_KEYS} for t in targets} - - # Get all cached bgp.tools data. - cached = cache.get_dict(CACHE_KEY) - - # Try to use cached data for each of the items in the list of - # resources. - for t in targets: - - if t in cached: - # Reassign the cached network info to the matching resource. - data[t] = cached[t] - log.debug("Using cached network info for {}", t) - - # Remove cached items from the resource list so they're not queried. - targets = [t for t in targets if t not in cached] - - try: - if targets: - whoisdata = run_whois_sync(targets) - - if whoisdata: - # If the response is not empty, parse it. - data.update(parse_whois(whoisdata, targets)) - - # Cache the response - for t in targets: - cache.set_dict(CACHE_KEY, t, data[t]) - log.debug("Cached network info for {}", t) - - except Exception as err: - log.error(str(err)) - - return data diff --git a/hyperglass/external/generic.py b/hyperglass/external/generic.py deleted file mode 100644 index 4fffa17..0000000 --- a/hyperglass/external/generic.py +++ /dev/null @@ -1,31 +0,0 @@ -"""Session handler for Generic HTTP API endpoint.""" - -# Project -from hyperglass.log import log -from hyperglass.external._base import BaseExternal -from hyperglass.models.webhook import Webhook - - -class GenericHook(BaseExternal, name="Generic"): - """Slack session handler.""" - - def __init__(self, config): - """Initialize external base class with http connection details.""" - - super().__init__( - base_url=f"{config.host.scheme}://{config.host.host}", config=config - ) - - async def send(self, query): - """Send an incoming webhook to http endpoint.""" - - payload = Webhook(**query) - - log.debug("Sending query data to {}:\n{}", self.config.host.host, payload) - - return await self._apost( - endpoint=self.config.host.path, - headers=self.config.headers, - params=self.config.params, - data=payload.export_dict(), - ) diff --git a/hyperglass/external/msteams.py b/hyperglass/external/msteams.py deleted file mode 100644 index 9afd102..0000000 --- a/hyperglass/external/msteams.py +++ /dev/null @@ -1,26 +0,0 @@ -"""Session handler for Microsoft Teams API.""" - -# Project -from hyperglass.log import log -from hyperglass.external._base import BaseExternal -from hyperglass.models.webhook import Webhook - - -class MSTeams(BaseExternal, name="MSTeams"): - """Microsoft Teams session handler.""" - - def __init__(self, config): - """Initialize external base class with Microsoft Teams connection details.""" - - super().__init__( - base_url="https://outlook.office.com", config=config, parse=False - ) - - async def send(self, query): - """Send an incoming webhook to Microsoft Teams.""" - - payload = Webhook(**query) - - log.debug("Sending query data to Microsoft Teams:\n{}", payload) - - return await self._apost(endpoint=self.config.host.path, data=payload.msteams()) diff --git a/hyperglass/external/ripestat.py b/hyperglass/external/ripestat.py deleted file mode 100644 index fe8e6ae..0000000 --- a/hyperglass/external/ripestat.py +++ /dev/null @@ -1,79 +0,0 @@ -"""Session handler for RIPEStat Data API.""" - -# Standard Library -from ipaddress import ip_address, ip_network - -# Project -from hyperglass.log import log -from hyperglass.external._base import BaseExternal - - -class RIPEStat(BaseExternal, name="RIPEStat"): - """RIPEStat session handler.""" - - def __init__(self): - """Initialize external base class with RIPEStat connection details.""" - - super().__init__( - base_url="https://stat.ripe.net", uri_prefix="/data", uri_suffix="data.json" - ) - - def network_info_sync(self, resource, serialize=False): - """Get network info via RIPE's Network Info API endpoint (synchronously). - - See: https://stat.ripe.net/docs/data_api#network-info - """ - try: - valid_ip = ip_address(resource) - - if not valid_ip.is_global: - log.debug("IP {ip} is not a global address", ip=str(valid_ip)) - return {"prefix": None, "asn": None} - - except ValueError: - log.debug("'{resource}' is not a valid IP address", resource=resource) - return {"prefix": None, "asn": None} - - raw = self._get(endpoint="network-info", params={"resource": valid_ip}) - - data = { - "asns": raw["data"]["asns"], - "prefix": ip_network(raw["data"]["prefix"]), - } - - if serialize: - data["prefix"] = str(data["prefix"]) - data["asns"] = data["asns"][0] - - log.debug("Collected network info from RIPEState: {i}", i=str(data)) - return data - - async def network_info(self, resource, serialize=False): - """Get network info via RIPE's Network Info API endpoint. - - See: https://stat.ripe.net/docs/data_api#network-info - """ - try: - valid_ip = ip_address(resource) - - if not valid_ip.is_global: - log.debug("IP {ip} is not a global address", ip=str(valid_ip)) - return {"prefix": None, "asn": None} - - except ValueError: - log.debug("'{resource}' is not a valid IP address", resource=resource) - return {"prefix": None, "asn": None} - - raw = await self._aget(endpoint="network-info", params={"resource": valid_ip}) - - data = { - "asns": raw["data"]["asns"], - "prefix": ip_network(raw["data"]["prefix"]), - } - - if serialize: - data["prefix"] = str(data["prefix"]) - data["asns"] = data["asns"][0] - - log.debug("Collected network info from RIPEState: {i}", i=str(data)) - return data diff --git a/hyperglass/external/rpki.py b/hyperglass/external/rpki.py deleted file mode 100644 index 78b1985..0000000 --- a/hyperglass/external/rpki.py +++ /dev/null @@ -1,51 +0,0 @@ -"""Validate RPKI state via Cloudflare GraphQL API.""" - -# Project -from hyperglass.log import log -from hyperglass.cache import SyncCache -from hyperglass.configuration import REDIS_CONFIG, params -from hyperglass.external._base import BaseExternal - -RPKI_STATE_MAP = {"Invalid": 0, "Valid": 1, "NotFound": 2, "DEFAULT": 3} -RPKI_NAME_MAP = {v: k for k, v in RPKI_STATE_MAP.items()} -CACHE_KEY = "hyperglass.external.rpki" - -cache = SyncCache(db=params.cache.database, **REDIS_CONFIG) - - -def rpki_state(prefix, asn): - """Get RPKI state and map to expected integer.""" - log.debug("Validating RPKI State for {p} via AS{a}", p=prefix, a=asn) - - state = 3 - ro = f"{prefix}@{asn}" - - cached = cache.get_dict(CACHE_KEY, ro) - - if cached is not None: - state = cached - else: - - ql = 'query GetValidation {{ validation(prefix: "{}", asn: {}) {{ state }} }}' - query = ql.format(prefix, asn) - - try: - with BaseExternal(base_url="https://rpki.cloudflare.com") as client: - response = client._post("/api/graphql", data={"query": query}) - validation_state = ( - response.get("data", {}).get("validation", {}).get("state", "DEFAULT") - ) - state = RPKI_STATE_MAP[validation_state] - cache.set_dict(CACHE_KEY, ro, state) - except Exception as err: - log.error(str(err)) - state = 3 - - msg = "RPKI Validation State for {} via AS{} is {}".format( - prefix, asn, RPKI_NAME_MAP[state] - ) - if cached is not None: - msg += " [CACHED]" - - log.debug(msg) - return state diff --git a/hyperglass/external/slack.py b/hyperglass/external/slack.py deleted file mode 100644 index cbc458c..0000000 --- a/hyperglass/external/slack.py +++ /dev/null @@ -1,24 +0,0 @@ -"""Session handler for Slack API.""" - -# Project -from hyperglass.log import log -from hyperglass.external._base import BaseExternal -from hyperglass.models.webhook import Webhook - - -class SlackHook(BaseExternal, name="Slack"): - """Slack session handler.""" - - def __init__(self, config): - """Initialize external base class with Slack connection details.""" - - super().__init__(base_url="https://hooks.slack.com", config=config, parse=False) - - async def send(self, query): - """Send an incoming webhook to Slack.""" - - payload = Webhook(**query) - - log.debug("Sending query data to Slack:\n{}", payload) - - return await self._apost(endpoint=self.config.host.path, data=payload.slack()) diff --git a/hyperglass/external/webhooks.py b/hyperglass/external/webhooks.py deleted file mode 100644 index 8348522..0000000 --- a/hyperglass/external/webhooks.py +++ /dev/null @@ -1,28 +0,0 @@ -"""Convenience functions for webhooks.""" - -# Project -from hyperglass.exceptions import HyperglassError -from hyperglass.external._base import BaseExternal -from hyperglass.external.slack import SlackHook -from hyperglass.external.generic import GenericHook -from hyperglass.external.msteams import MSTeams - -PROVIDER_MAP = { - "generic": GenericHook, - "msteams": MSTeams, - "slack": SlackHook, -} - - -class Webhook(BaseExternal): - """Get webhook for provider name.""" - - def __new__(cls, config): - """Return instance for correct provider handler.""" - try: - provider_class = PROVIDER_MAP[config.provider] - return provider_class(config) - except KeyError: - raise HyperglassError( - f"'{config.provider.title()}' is not yet supported as a webhook target." - ) diff --git a/hyperglass/images/hyperglass-dark.svg b/hyperglass/images/hyperglass-dark.svg deleted file mode 100644 index b2bb038..0000000 --- a/hyperglass/images/hyperglass-dark.svg +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/hyperglass/images/hyperglass-icon.svg b/hyperglass/images/hyperglass-icon.svg deleted file mode 100644 index ea9b648..0000000 --- a/hyperglass/images/hyperglass-icon.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/hyperglass/images/hyperglass-light.svg b/hyperglass/images/hyperglass-light.svg deleted file mode 100644 index b93080f..0000000 --- a/hyperglass/images/hyperglass-light.svg +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/hyperglass/images/hyperglass-opengraph.jpg b/hyperglass/images/hyperglass-opengraph.jpg deleted file mode 100644 index 3d621d9..0000000 Binary files a/hyperglass/images/hyperglass-opengraph.jpg and /dev/null differ diff --git a/hyperglass/log.py b/hyperglass/log.py deleted file mode 100644 index 8791a2e..0000000 --- a/hyperglass/log.py +++ /dev/null @@ -1,137 +0,0 @@ -"""Logging instance setup & configuration.""" - -# Standard Library -import os -import sys -import logging -from datetime import datetime - -# Third Party -from loguru import logger as _loguru_logger - -_FMT = ( - "[{level}] {time:YYYYMMDD} {time:HH:mm:ss} | {name}:" - "{line} | {function} → {message}" -) -_DATE_FMT = "%Y%m%d %H:%M:%S" -_FMT_BASIC = "{message}" -_LOG_LEVELS = [ - {"name": "TRACE", "color": ""}, - {"name": "DEBUG", "color": ""}, - {"name": "INFO", "color": ""}, - {"name": "SUCCESS", "color": ""}, - {"name": "WARNING", "color": ""}, - {"name": "ERROR", "color": ""}, - {"name": "CRITICAL", "color": ""}, -] - - -def setup_lib_logging() -> None: - """Override the logging handlers for dependency libraries.""" - for name in ( - "gunicorn", - "gunicorn.access", - "gunicorn.error", - "uvicorn", - "uvicorn.access", - "uvicorn.error", - "uvicorn.asgi", - "netmiko", - "scrapli", - "httpx", - ): - _loguru_logger.bind(logger_name=name) - - -def base_logger(level: str = "INFO"): - """Initialize hyperglass logging instance.""" - _loguru_logger.remove() - _loguru_logger.add(sys.stdout, format=_FMT, level=level, enqueue=True) - _loguru_logger.configure(levels=_LOG_LEVELS) - return _loguru_logger - - -log = base_logger() - -logging.addLevelName(25, "SUCCESS") - - -def _log_success(self, message, *a, **kw): - """Add custom builtin logging handler for the success level.""" - if self.isEnabledFor(25): - self._log(25, message, a, **kw) - - -logging.Logger.success = _log_success - - -def set_log_level(logger, debug): - """Set log level based on debug state.""" - if debug: - os.environ["HYPERGLASS_LOG_LEVEL"] = "DEBUG" - base_logger("DEBUG") - - if debug: - logger.debug("Debugging enabled") - return True - - -def enable_file_logging(logger, log_directory, log_format, log_max_size): - """Set up file-based logging from configuration parameters.""" - - if log_format == "json": - log_file_name = "hyperglass.log.json" - structured = True - else: - log_file_name = "hyperglass.log" - structured = False - - log_file = log_directory / log_file_name - - if log_format == "text": - now_str = "hyperglass logs for " + datetime.utcnow().strftime( - "%B %d, %Y beginning at %H:%M:%S UTC" - ) - now_str_y = len(now_str) + 6 - now_str_x = len(now_str) + 4 - log_break = ( - "#" * now_str_y, - "\n#" + " " * now_str_x + "#\n", - "# ", - now_str, - " #", - "\n#" + " " * now_str_x + "#\n", - "#" * now_str_y, - ) - - with log_file.open("a+") as lf: - lf.write(f'\n\n{"".join(log_break)}\n\n') - - logger.add( - log_file, - format=_FMT, - rotation=log_max_size, - serialize=structured, - enqueue=True, - ) - - logger.debug("Logging to {} enabled", str(log_file)) - - return True - - -def enable_syslog_logging(logger, syslog_host, syslog_port): - """Set up syslog logging from configuration parameters.""" - - # Standard Library - from logging.handlers import SysLogHandler - - logger.add( - SysLogHandler(address=(str(syslog_host), syslog_port)), - format=_FMT_BASIC, - enqueue=True, - ) - logger.debug( - "Logging to syslog target {}:{} enabled", str(syslog_host), str(syslog_port), - ) - return True diff --git a/hyperglass/main.py b/hyperglass/main.py deleted file mode 100644 index 4741481..0000000 --- a/hyperglass/main.py +++ /dev/null @@ -1,209 +0,0 @@ -"""Gunicorn Config File.""" - -# Standard Library -import sys -import math -import shutil -import logging -import platform - -# Third Party -from gunicorn.arbiter import Arbiter -from gunicorn.app.base import BaseApplication -from gunicorn.glogging import Logger - -# Local -from .log import log, setup_lib_logging -from .constants import MIN_NODE_VERSION, MIN_PYTHON_VERSION, __version__ -from .util.frontend import get_node_version - -# Ensure the Python version meets the minimum requirements. -pretty_version = ".".join(tuple(str(v) for v in MIN_PYTHON_VERSION)) -if sys.version_info < MIN_PYTHON_VERSION: - raise RuntimeError(f"Python {pretty_version}+ is required.") - -# Ensure the NodeJS version meets the minimum requirements. -node_major, _, __ = get_node_version() - -if node_major != MIN_NODE_VERSION: - raise RuntimeError(f"NodeJS {MIN_NODE_VERSION}+ is required.") - - -# Project -from hyperglass.compat._asyncio import aiorun - -# Local -from .util import cpu_count, clear_redis_cache, format_listen_address -from .cache import SyncCache -from .configuration import ( - URL_DEV, - URL_PROD, - CONFIG_PATH, - REDIS_CONFIG, - params, - frontend_params, -) -from .util.frontend import build_frontend - -if params.debug: - workers = 1 - loglevel = "DEBUG" -else: - workers = cpu_count(2) - loglevel = "WARNING" - - -class StubbedGunicornLogger(Logger): - """Custom logging to direct Gunicorn/Uvicorn logs to Loguru/Rich. - - See: https://pawamoy.github.io/posts/unify-logging-for-a-gunicorn-uvicorn-app/ - """ - - def setup(self, cfg): - """Override Gunicorn setup.""" - handler = logging.NullHandler() - self.error_logger = logging.getLogger("gunicorn.error") - self.error_logger.addHandler(handler) - self.access_logger = logging.getLogger("gunicorn.access") - self.access_logger.addHandler(handler) - self.error_logger.setLevel(loglevel) - self.access_logger.setLevel(loglevel) - - -def check_redis_instance() -> bool: - """Ensure Redis is running before starting server.""" - - cache = SyncCache(db=params.cache.database, **REDIS_CONFIG) - cache.test() - log.debug("Redis is running at: {}:{}", REDIS_CONFIG["host"], REDIS_CONFIG["port"]) - return True - - -async def build_ui() -> bool: - """Perform a UI build prior to starting the application.""" - await build_frontend( - dev_mode=params.developer_mode, - dev_url=URL_DEV, - prod_url=URL_PROD, - params=frontend_params, - app_path=CONFIG_PATH, - ) - return True - - -async def clear_cache(): - """Clear the Redis cache on shutdown.""" - try: - await clear_redis_cache(db=params.cache.database, config=REDIS_CONFIG) - except RuntimeError as e: - log.error(str(e)) - pass - - -def cache_config() -> bool: - """Add configuration to Redis cache as a pickled object.""" - # Standard Library - import pickle - - cache = SyncCache(db=params.cache.database, **REDIS_CONFIG) - cache.set("HYPERGLASS_CONFIG", pickle.dumps(params)) - - return True - - -def on_starting(server: Arbiter): - """Gunicorn pre-start tasks.""" - - setup_lib_logging() - - python_version = platform.python_version() - required = ".".join((str(v) for v in MIN_PYTHON_VERSION)) - log.info("Python {} detected ({} required)", python_version, required) - - async def runner(): - # Standard Library - from asyncio import gather - - await gather(build_ui(), cache_config()) - - check_redis_instance() - aiorun(build_ui()) - cache_config() - - log.success( - "Started hyperglass {v} on http://{h}:{p} with {w} workers", - v=__version__, - h=format_listen_address(params.listen_address), - p=str(params.listen_port), - w=server.app.cfg.settings["workers"].value, - ) - - -def on_exit(server: Arbiter): - """Gunicorn shutdown tasks.""" - - log.critical("Stopping hyperglass {}", __version__) - - async def runner(): - if not params.developer_mode: - await clear_cache() - - aiorun(runner()) - - -class HyperglassWSGI(BaseApplication): - """Custom gunicorn app.""" - - def __init__(self, app, options): - """Initialize custom WSGI.""" - self.application = app - self.options = options or {} - super().__init__() - - def load_config(self): - """Load gunicorn config.""" - config = { - key: value - for key, value in self.options.items() - if key in self.cfg.settings and value is not None - } - - for key, value in config.items(): - self.cfg.set(key.lower(), value) - - def load(self): - """Load gunicorn app.""" - return self.application - - -def start(**kwargs): - """Start hyperglass via gunicorn.""" - # Project - from hyperglass.api import app - - HyperglassWSGI( - app=app, - options={ - "worker_class": "uvicorn.workers.UvicornWorker", - "preload": True, - "keepalive": 10, - "command": shutil.which("gunicorn"), - "bind": ":".join( - (format_listen_address(params.listen_address), str(params.listen_port)) - ), - "workers": workers, - "loglevel": loglevel, - "timeout": math.ceil(params.request_timeout * 1.25), - "on_starting": on_starting, - "on_exit": on_exit, - "logger_class": StubbedGunicornLogger, - "accesslog": "-", - "errorlog": "-", - "logconfig_dict": {"formatters": {"generic": {"format": "%(message)s"}}}, - **kwargs, - }, - ).run() - - -if __name__ == "__main__": - start() diff --git a/hyperglass/models/__init__.py b/hyperglass/models/__init__.py deleted file mode 100644 index 98929cf..0000000 --- a/hyperglass/models/__init__.py +++ /dev/null @@ -1,4 +0,0 @@ -"""All Data Models used by hyperglass.""" - -# Local -from .main import HyperglassModel, HyperglassModelExtra diff --git a/hyperglass/models/api/__init__.py b/hyperglass/models/api/__init__.py deleted file mode 100644 index ffe11f6..0000000 --- a/hyperglass/models/api/__init__.py +++ /dev/null @@ -1,12 +0,0 @@ -"""Query & Response Validation Models.""" -# Local -from .query import Query -from .response import ( - QueryError, - InfoResponse, - QueryResponse, - RoutersResponse, - CommunityResponse, - SupportedQueryResponse, -) -from .cert_import import EncodedRequest diff --git a/hyperglass/models/api/cert_import.py b/hyperglass/models/api/cert_import.py deleted file mode 100644 index 7558411..0000000 --- a/hyperglass/models/api/cert_import.py +++ /dev/null @@ -1,16 +0,0 @@ -"""hyperglass-agent certificate import models.""" -# Standard Library -from typing import Union - -# Third Party -from pydantic import BaseModel, StrictStr - -# Local -from ..fields import StrictBytes - - -class EncodedRequest(BaseModel): - """Certificate request model.""" - - device: StrictStr - encoded: Union[StrictStr, StrictBytes] diff --git a/hyperglass/models/api/query.py b/hyperglass/models/api/query.py deleted file mode 100644 index 793efc5..0000000 --- a/hyperglass/models/api/query.py +++ /dev/null @@ -1,230 +0,0 @@ -"""Input query validation model.""" - -# Standard Library -import json -import hashlib -import secrets -from datetime import datetime - -# Third Party -from pydantic import BaseModel, StrictStr, constr, validator - -# Project -from hyperglass.exceptions import InputInvalid -from hyperglass.configuration import params, devices - -# Local -from .types import SupportedQuery -from .validators import ( - validate_ip, - validate_aspath, - validate_community_input, - validate_community_select, -) -from ..config.vrf import Vrf - - -def get_vrf_object(vrf_name: str) -> Vrf: - """Match VRF object from VRF name.""" - - for vrf_obj in devices.vrf_objects: - if vrf_name is not None: - if vrf_name == vrf_obj._id or vrf_name == vrf_obj.display_name: - return vrf_obj - - elif vrf_name == "__hyperglass_default" and vrf_obj.default: - return vrf_obj - elif vrf_name is None: - if vrf_obj.default: - return vrf_obj - - raise InputInvalid(params.messages.vrf_not_found, vrf_name=vrf_name) - - -class Query(BaseModel): - """Validation model for input query parameters.""" - - query_location: StrictStr - query_type: SupportedQuery - query_vrf: StrictStr - query_target: constr(strip_whitespace=True, min_length=1) - - class Config: - """Pydantic model configuration.""" - - extra = "allow" - fields = { - "query_location": { - "title": params.web.text.query_location, - "description": "Router/Location Name", - "example": "router01", - }, - "query_type": { - "title": params.web.text.query_type, - "description": "Type of Query to Execute", - "example": "bgp_route", - }, - "query_vrf": { - "title": params.web.text.query_vrf, - "description": "Routing Table/VRF", - "example": "default", - }, - "query_target": { - "title": params.web.text.query_target, - "description": "IP Address, Community, or AS Path", - "example": "1.1.1.0/24", - }, - } - schema_extra = { - "x-code-samples": [{"lang": "Python", "source": "print('stuff')"}] - } - - def __init__(self, **kwargs): - """Initialize the query with a UTC timestamp at initialization time.""" - super().__init__(**kwargs) - self.timestamp = datetime.utcnow().strftime("%Y-%m-%d %H:%M:%S") - - def __repr__(self): - """Represent only the query fields.""" - return ( - f"Query(query_location={str(self.query_location)}, " - f"query_type={str(self.query_type)}, query_vrf={str(self.query_vrf)}, " - f"query_target={str(self.query_target)})" - ) - - def digest(self): - """Create SHA256 hash digest of model representation.""" - return hashlib.sha256(repr(self).encode()).hexdigest() - - def random(self): - """Create a random string to prevent client or proxy caching.""" - return hashlib.sha256( - secrets.token_bytes(8) + repr(self).encode() + secrets.token_bytes(8) - ).hexdigest() - - @property - def summary(self): - """Create abbreviated representation of instance.""" - items = ( - f"query_location={self.query_location}", - f"query_type={self.query_type}", - f"query_vrf={self.query_vrf.name}", - f"query_target={str(self.query_target)}", - ) - return f'Query({", ".join(items)})' - - @property - def device(self): - """Get this query's device object by query_location.""" - return devices[self.query_location] - - @property - def query(self): - """Get this query's configuration object.""" - return params.queries[self.query_type] - - def export_dict(self, pretty=False): - """Create dictionary representation of instance.""" - - if pretty: - items = { - "query_location": self.device.name, - "query_type": self.query.display_name, - "query_vrf": self.query_vrf.display_name, - "query_target": str(self.query_target), - } - else: - items = { - "query_location": self.query_location, - "query_type": self.query_type, - "query_vrf": self.query_vrf._id, - "query_target": str(self.query_target), - } - return items - - def export_json(self): - """Create JSON representation of instance.""" - return json.dumps(self.export_dict(), default=str) - - @validator("query_type") - def validate_query_type(cls, value): - """Ensure query_type is enabled.""" - - query = params.queries[value] - - if not query.enable: - raise InputInvalid( - params.messages.feature_not_enabled, - level="warning", - feature=query.display_name, - ) - - return value - - @validator("query_location") - def validate_query_location(cls, value): - """Ensure query_location is defined.""" - - valid_id = value in devices._ids - valid_hostname = value in devices.hostnames - - if not any((valid_id, valid_hostname)): - raise InputInvalid( - params.messages.invalid_field, - level="warning", - input=value, - field=params.web.text.query_location, - ) - return value - - @validator("query_vrf") - def validate_query_vrf(cls, value, values): - """Ensure query_vrf is defined.""" - - vrf_object = get_vrf_object(value) - device = devices[values["query_location"]] - device_vrf = None - - for vrf in device.vrfs: - if vrf == vrf_object: - device_vrf = vrf - break - - if device_vrf is None: - raise InputInvalid( - params.messages.vrf_not_associated, - vrf_name=vrf_object.display_name, - device_name=device.name, - ) - return device_vrf - - @validator("query_target") - def validate_query_target(cls, value, values): - """Validate query target value based on query_type.""" - - query_type = values["query_type"] - value = value.strip() - - # Use relevant function based on query_type. - validator_map = { - "bgp_aspath": validate_aspath, - "bgp_community": validate_community_input, - "bgp_route": validate_ip, - "ping": validate_ip, - "traceroute": validate_ip, - } - validator_args_map = { - "bgp_aspath": (value,), - "bgp_community": (value,), - "bgp_route": (value, values["query_type"], values["query_vrf"]), - "ping": (value, values["query_type"], values["query_vrf"]), - "traceroute": (value, values["query_type"], values["query_vrf"]), - } - - if params.queries.bgp_community.mode == "select": - validator_map["bgp_community"] = validate_community_select - - validate_func = validator_map[query_type] - validate_args = validator_args_map[query_type] - - return validate_func(*validate_args) diff --git a/hyperglass/models/api/response.py b/hyperglass/models/api/response.py deleted file mode 100644 index 3b83a2c..0000000 --- a/hyperglass/models/api/response.py +++ /dev/null @@ -1,242 +0,0 @@ -"""Response model.""" - -# Standard Library -from typing import Dict, List, Union, Optional - -# Third Party -from pydantic import BaseModel, StrictInt, StrictStr, StrictBool, constr - -# Project -from hyperglass.configuration import params - -ErrorName = constr(regex=r"(success|warning|error|danger)") -ResponseLevel = constr(regex=r"success") -ResponseFormat = constr(regex=r"(application\/json|text\/plain)") - - -class QueryError(BaseModel): - """Query response model.""" - - output: StrictStr = params.messages.general - level: ErrorName = "danger" - id: Optional[StrictStr] - keywords: List[StrictStr] = [] - - class Config: - """Pydantic model configuration.""" - - title = "Query Error" - description = ( - "Response received when there is an error executing the requested query." - ) - fields = { - "output": { - "title": "Output", - "description": "Error Details", - "example": "192.0.2.1/32 is not allowed.", - }, - "level": { - "title": "Level", - "description": "Error Severity", - "example": "danger", - }, - "keywords": { - "title": "Keywords", - "description": "Relevant keyword values contained in the `output` field, which can be used for formatting.", - "example": ["192.0.2.1/32"], - }, - } - schema_extra = { - "examples": [ - { - "output": "192.0.2.1/32 is not allowed.", - "level": "danger", - "keywords": ["192.0.2.1/32"], - } - ] - } - - -class QueryResponse(BaseModel): - """Query response model.""" - - output: Union[Dict, StrictStr] - level: ResponseLevel = "success" - random: StrictStr - cached: StrictBool - runtime: StrictInt - keywords: List[StrictStr] = [] - timestamp: StrictStr - format: ResponseFormat = "text/plain" - - class Config: - """Pydantic model configuration.""" - - title = "Query Response" - description = "Looking glass response" - fields = { - "level": {"title": "Level", "description": "Severity"}, - "cached": { - "title": "Cached", - "description": "`true` if the response is from a previously cached query.", - }, - "random": { - "title": "Random", - "description": "Random string to prevent client or intermediate caching.", - "example": "504cbdb47eb8310ca237bf512c3e10b44b0a3d85868c4b64a20037dc1c3ef857", - }, - "runtime": { - "title": "Runtime", - "description": "Time it took to run the query in seconds.", - "example": 6, - }, - "timestamp": { - "title": "Timestamp", - "description": "UTC Time at which the backend application received the query.", - "example": "2020-04-18 14:45:37", - }, - "format": { - "title": "Format", - "description": "Response [MIME Type](http://www.iana.org/assignments/media-types/media-types.xhtml). Supported values: `text/plain` and `application/json`.", - "example": "text/plain", - }, - "keywords": { - "title": "Keywords", - "description": "Relevant keyword values contained in the `output` field, which can be used for formatting.", - "example": ["1.1.1.0/24", "best #1"], - }, - "output": { - "title": "Output", - "description": "Looking Glass Response", - "example": """ -BGP routing table entry for 1.1.1.0/24, version 224184946 -BGP Bestpath: deterministic-med -Paths: (12 available, best #1, table default) - Advertised to update-groups: - 1 40 - 13335, (aggregated by 13335 172.68.129.1), (received & used) - 192.0.2.1 (metric 51) from 192.0.2.1 (192.0.2.1) - Origin IGP, metric 0, localpref 250, valid, internal - Community: 65000:1 65000:2 - """, - }, - } - schema_extra = { - "examples": [ - { - "output": """ -BGP routing table entry for 1.1.1.0/24, version 224184946 -BGP Bestpath: deterministic-med -Paths: (12 available, best #1, table default) - Advertised to update-groups: - 1 40 - 13335, (aggregated by 13335 172.68.129.1), (received & used) - 192.0.2.1 (metric 51) from 192.0.2.1 (192.0.2.1) - Origin IGP, metric 0, localpref 250, valid, internal - Community: 65000:1 65000:2 - """, - "level": "success", - "keywords": ["1.1.1.0/24", "best #1"], - } - ] - } - - -class Vrf(BaseModel): - """Response model for /api/devices VRFs.""" - - name: StrictStr - display_name: StrictStr - - class Config: - """Pydantic model configuration.""" - - title = "VRF" - description = "VRF attributes" - schema_extra = { - "examples": [ - {"name": "default", "display_name": "Global Routing Table"}, - {"name": "customer_vrf_name", "display_name": "Customer Name"}, - ] - } - - -class Network(BaseModel): - """Response model for /api/devices networks.""" - - name: StrictStr - display_name: StrictStr - - class Config: - """Pydantic model configuration.""" - - title = "Network" - description = "Network/ASN attributes" - schema_extra = {"examples": [{"name": "primary", "display_name": "AS65000"}]} - - -class RoutersResponse(BaseModel): - """Response model for /api/devices list items.""" - - name: StrictStr - network: Network - vrfs: List[Vrf] - - class Config: - """Pydantic model configuration.""" - - title = "Device" - description = "Per-device attributes" - schema_extra = {"examples": [{"name": "router01-nyc01", "location": "nyc01"}]} - - -class CommunityResponse(BaseModel): - """Response model for /api/communities.""" - - community: StrictStr - display_name: StrictStr - description: StrictStr - - -class SupportedQueryResponse(BaseModel): - """Response model for /api/queries list items.""" - - name: StrictStr - display_name: StrictStr - enable: StrictBool - - class Config: - """Pydantic model configuration.""" - - title = "Query Type" - description = "If enabled is `true`, the `name` field may be used to specify the query type." - schema_extra = { - "examples": [ - {"name": "bgp_route", "display_name": "BGP Route", "enable": True} - ] - } - - -class InfoResponse(BaseModel): - """Response model for /api/info endpoint.""" - - name: StrictStr - organization: StrictStr - primary_asn: StrictInt - version: StrictStr - - class Config: - """Pydantic model configuration.""" - - title = "System Information" - description = "General information about this looking glass." - schema_extra = { - "examples": [ - { - "name": "hyperglass", - "organization": "Company Name", - "primary_asn": 65000, - "version": "hyperglass 1.0.0-beta.52", - } - ] - } diff --git a/hyperglass/models/api/rfc8522.py b/hyperglass/models/api/rfc8522.py deleted file mode 100644 index b546e85..0000000 --- a/hyperglass/models/api/rfc8522.py +++ /dev/null @@ -1,76 +0,0 @@ -"""Response model.""" - -# Standard Library -# flake8: noqa -import math -import secrets -from typing import List, Union, Optional -from datetime import datetime - -# Third Party -from pydantic import BaseModel, StrictInt, StrictStr, StrictFloat, constr, validator - -"""Patterns: -GET /.well-known/looking-glass/v1/ping/2001:DB8::35?protocol=2,1 -GET /.well-known/looking-glass/v1/traceroute/192.0.2.8?routerindex=5 -GET /.well-known/looking-glass/v1/show/route/2001:DB8::/48?protocol=2,1 -GET /.well-known/looking-glass/v1/show/bgp/192.0.2.0/24 -GET /.well-known/looking-glass/v1/show/bgp/summary?protocol=2&routerindex=3 -GET /.well-known/looking-glass/v1/show/bgp/neighbors/192.0.2.226 -GET /.well-known/looking-glass/v1/routers -GET /.well-known/looking-glass/v1/routers/1 -GET /.well-known/looking-glass/v1/cmd -""" - - -class _HyperglassQuery(BaseModel): - class Config: - validate_all = True - validate_assignment = True - - -class BaseQuery(_HyperglassQuery): - protocol: StrictStr = "1,1" - router: StrictStr - routerindex: StrictInt - random: StrictStr = secrets.token_urlsafe(16) - vrf: Optional[StrictStr] - runtime: StrictInt = 30 - query_format: constr(regex=r"(text\/plain|application\/json)") = "text/plain" - - @validator("runtime") - def validate_runtime(cls, value): - if isinstance(value, float) and math.modf(value)[0] == 0: - value = math.ceil(value) - return value - - class Config: - fields = {"query_format": "format"} - - -class BaseData(_HyperglassQuery): - router: StrictStr - performed_at: datetime - runtime: Union[StrictFloat, StrictInt] - output: List[StrictStr] - data_format: StrictStr - - @validator("runtime") - def validate_runtime(cls, value): - if isinstance(value, float) and math.modf(value)[0] == 0: - value = math.ceil(value) - return value - - class Config: - fields = {"data_format": "format"} - extra = "allow" - - -class QueryError(_HyperglassQuery): - status: constr(regex=r"error") - message: StrictStr - - -class QueryResponse(_HyperglassQuery): - status: constr(regex=r"success|fail") - data: BaseData diff --git a/hyperglass/models/api/types.py b/hyperglass/models/api/types.py deleted file mode 100644 index e815b1e..0000000 --- a/hyperglass/models/api/types.py +++ /dev/null @@ -1,26 +0,0 @@ -"""Custom validation types.""" - -# Project -from hyperglass.constants import SUPPORTED_QUERY_TYPES - - -class SupportedQuery(str): - """Query Type Validation Model.""" - - @classmethod - def __get_validators__(cls): - """Pydantic custom type method.""" - yield cls.validate - - @classmethod - def validate(cls, value): - """Ensure query type is supported by hyperglass.""" - if not isinstance(value, str): - raise TypeError("query_type must be a string") - if value not in SUPPORTED_QUERY_TYPES: - raise ValueError(f"'{value}' is not a supported query type") - return value - - def __repr__(self): - """Stringify custom field representation.""" - return f"SupportedQuery({super().__repr__()})" diff --git a/hyperglass/models/api/validators.py b/hyperglass/models/api/validators.py deleted file mode 100644 index 48b1756..0000000 --- a/hyperglass/models/api/validators.py +++ /dev/null @@ -1,234 +0,0 @@ -"""Input validation functions for submitted queries.""" - -# Standard Library -import re -from ipaddress import ip_network - -# Project -from hyperglass.log import log -from hyperglass.exceptions import InputInvalid, InputNotAllowed -from hyperglass.configuration import params -from hyperglass.external.bgptools import network_info_sync - - -def _member_of(target, network): - """Check if IP address belongs to network. - - Arguments: - target {object} -- Target IPv4/IPv6 address - network {object} -- ACL network - - Returns: - {bool} -- True if target is a member of network, False if not - """ - log.debug("Checking membership of {} for {}", target, network) - - membership = False - if ( - network.network_address <= target.network_address - and network.broadcast_address >= target.broadcast_address # NOQA: W503 - ): - log.debug("{} is a member of {}", target, network) - membership = True - return membership - - -def _prefix_range(target, ge, le): - """Verify if target prefix length is within ge/le threshold. - - Arguments: - target {IPv4Network|IPv6Network} -- Valid IPv4/IPv6 Network - ge {int} -- Greater than - le {int} -- Less than - - Returns: - {bool} -- True if target in range; False if not - """ - matched = False - if target.prefixlen <= le and target.prefixlen >= ge: - matched = True - return matched - - -def validate_ip(value, query_type, query_vrf): # noqa: C901 - """Ensure input IP address is both valid and not within restricted allocations. - - Arguments: - value {str} -- Unvalidated IP Address - query_type {str} -- Valid query type - query_vrf {object} -- Matched query vrf - Raises: - ValueError: Raised if input IP address is not an IP address. - ValueError: Raised if IP address is valid, but is within a restricted range. - Returns: - Union[IPv4Address, IPv6Address] -- Validated IP address object - """ - query_type_params = getattr(params.queries, query_type) - try: - - # Attempt to use IP object factory to create an IP address object - valid_ip = ip_network(value) - - except ValueError: - raise InputInvalid( - params.messages.invalid_input, - target=value, - query_type=query_type_params.display_name, - ) - - # Test the valid IP address to determine if it is: - # - Unspecified (See RFC5735, RFC2373) - # - Loopback (See RFC5735, RFC2373) - # - Otherwise IETF Reserved - # ...and returns an error if so. - if valid_ip.is_reserved or valid_ip.is_unspecified or valid_ip.is_loopback: - raise InputInvalid( - params.messages.invalid_input, - target=value, - query_type=query_type_params.display_name, - ) - - ip_version = valid_ip.version - - vrf_afi = getattr(query_vrf, f"ipv{ip_version}") - - if vrf_afi is None: - raise InputInvalid( - params.messages.feature_not_enabled, - feature=f"IPv{ip_version}", - device_name=f"VRF {query_vrf.display_name}", - ) - - for ace in [a for a in vrf_afi.access_list if a.network.version == ip_version]: - if _member_of(valid_ip, ace.network): - if query_type == "bgp_route" and _prefix_range(valid_ip, ace.ge, ace.le): - pass - - if ace.action == "permit": - log.debug( - "{t} is allowed by access-list {a}", t=str(valid_ip), a=repr(ace) - ) - break - elif ace.action == "deny": - raise InputNotAllowed( - params.messages.acl_denied, - target=str(valid_ip), - denied_network=str(ace.network), - ) - - # Handling logic for host queries, e.g. 192.0.2.1 vs. 192.0.2.0/24 - if valid_ip.num_addresses == 1: - - # For a host query with ping or traceroute query types, convert - # the query_target to an IP address instead of a network. - if query_type in ("ping", "traceroute"): - new_ip = valid_ip.network_address - - log.debug( - "Converted '{o}' to '{n}' for '{q}' query", - o=valid_ip, - n=new_ip, - q=query_type, - ) - - valid_ip = new_ip - - # Get the containing prefix for a host query if: - # - Query type is bgp_route - # - force_cidr option is enabled - # - Query target is not a private address/network - elif ( - query_type in ("bgp_route",) - and vrf_afi.force_cidr - and not valid_ip.is_private - ): - log.debug("Getting containing prefix for {q}", q=str(valid_ip)) - - ip_str = str(valid_ip.network_address) - network_info = network_info_sync(ip_str) - containing_prefix = network_info.get(ip_str, {}).get("prefix") - - if containing_prefix is None: - log.error( - "Unable to find containing prefix for {}. Got: {}", - str(valid_ip), - network_info, - ) - raise InputInvalid("{q} does not have a containing prefix", q=ip_str) - - try: - - valid_ip = ip_network(containing_prefix) - log.debug("Containing prefix: {p}", p=str(valid_ip)) - - except ValueError as err: - log.error( - "Unable to find containing prefix for {q}. Error: {e}", - q=str(valid_ip), - e=err, - ) - raise InputInvalid( - "{q} does does not have a containing prefix", q=valid_ip - ) - - # For a host query with bgp_route query type and force_cidr - # disabled, convert the host query to a single IP address. - elif query_type in ("bgp_route",) and not vrf_afi.force_cidr: - - valid_ip = valid_ip.network_address - - log.debug("Validation passed for {ip}", ip=value) - return valid_ip - - -def validate_community_input(value): - """Validate input communities against configured or default regex pattern.""" - - # RFC4360: Extended Communities (New Format) - if re.match(params.queries.bgp_community.pattern.extended_as, value): - pass - - # RFC4360: Extended Communities (32 Bit Format) - elif re.match(params.queries.bgp_community.pattern.decimal, value): - pass - - # RFC8092: Large Communities - elif re.match(params.queries.bgp_community.pattern.large, value): - pass - - else: - raise InputInvalid( - params.messages.invalid_input, - target=value, - query_type=params.queries.bgp_community.display_name, - ) - return value - - -def validate_community_select(value): - """Validate selected community against configured communities.""" - - communities = tuple(c.community for c in params.queries.bgp_community.communities) - if value not in communities: - raise InputInvalid( - params.messages.invalid_input, - target=value, - query_type=params.queries.bgp_community.display_name, - ) - return value - - -def validate_aspath(value): - """Validate input AS_PATH against configured or default regext pattern.""" - - mode = params.queries.bgp_aspath.pattern.mode - pattern = getattr(params.queries.bgp_aspath.pattern, mode) - - if not bool(re.match(pattern, value)): - raise InputInvalid( - params.messages.invalid_input, - target=value, - query_type=params.queries.bgp_aspath.display_name, - ) - - return value diff --git a/hyperglass/models/commands/__init__.py b/hyperglass/models/commands/__init__.py deleted file mode 100644 index 7a49b0b..0000000 --- a/hyperglass/models/commands/__init__.py +++ /dev/null @@ -1,76 +0,0 @@ -"""Validate command configuration variables.""" - -# Local -from .frr import FRRCommands -from .bird import BIRDCommands -from .tnsr import TNSRCommands -from .vyos import VyosCommands -from ..main import HyperglassModelExtra -from .common import CommandGroup -from .huawei import HuaweiCommands -from .juniper import JuniperCommands -from .cisco_xr import CiscoXRCommands -from .cisco_ios import CiscoIOSCommands -from .arista_eos import AristaEOSCommands -from .cisco_nxos import CiscoNXOSCommands -from .nokia_sros import NokiaSROSCommands -from .mikrotik_routeros import MikrotikRouterOS -from .mikrotik_switchos import MikrotikSwitchOS - -_NOS_MAP = { - "arista_eos": AristaEOSCommands, - "bird": BIRDCommands, - "cisco_ios": CiscoIOSCommands, - "cisco_nxos": CiscoNXOSCommands, - "cisco_xr": CiscoXRCommands, - "frr": FRRCommands, - "huawei": HuaweiCommands, - "juniper": JuniperCommands, - "mikrotik_routeros": MikrotikRouterOS, - "mikrotik_switchos": MikrotikSwitchOS, - "nokia_sros": NokiaSROSCommands, - "tnsr": TNSRCommands, - "vyos": VyosCommands, -} - - -class Commands(HyperglassModelExtra): - """Base class for command definitions.""" - - arista_eos: CommandGroup = AristaEOSCommands() - bird: CommandGroup = BIRDCommands() - cisco_ios: CommandGroup = CiscoIOSCommands() - cisco_nxos: CommandGroup = CiscoNXOSCommands() - cisco_xr: CommandGroup = CiscoXRCommands() - frr: CommandGroup = FRRCommands() - huawei: CommandGroup = HuaweiCommands() - juniper: CommandGroup = JuniperCommands() - mikrotik_routeros: CommandGroup = MikrotikRouterOS() - mikrotik_switchos: CommandGroup = MikrotikSwitchOS() - nokia_sros: CommandGroup = NokiaSROSCommands() - tnsr: CommandGroup = TNSRCommands() - vyos: CommandGroup = VyosCommands() - - @classmethod - def import_params(cls, **input_params): - """Import loaded YAML, initialize per-command definitions. - - Dynamically set attributes for the command class. - - Arguments: - input_params {dict} -- Unvalidated command definitions - - Returns: - {object} -- Validated commands object - """ - obj = Commands() - for nos, cmds in input_params.items(): - nos_cmd_set = _NOS_MAP.get(nos, CommandGroup) - nos_cmds = nos_cmd_set(**cmds) - setattr(obj, nos, nos_cmds) - return obj - - class Config: - """Override pydantic config.""" - - validate_all = False diff --git a/hyperglass/models/commands/_mikrotik_base.py b/hyperglass/models/commands/_mikrotik_base.py deleted file mode 100644 index 86ac480..0000000 --- a/hyperglass/models/commands/_mikrotik_base.py +++ /dev/null @@ -1,56 +0,0 @@ -"""Base Mikrotik Commands Model.""" - -# Third Party -from pydantic import StrictStr - -# Local -from .common import CommandSet, CommandGroup - - -class _IPv4(CommandSet): - """Default commands for ipv4 commands.""" - - bgp_community: StrictStr = "ip route print where bgp-communities={target}" - bgp_aspath: StrictStr = "ip route print where bgp-as-path={target}" - bgp_route: StrictStr = "ip route print where dst-address={target}" - ping: StrictStr = "ping src-address={source} count=5 {target}" - traceroute: StrictStr = "tool traceroute src-address={source} timeout=1 duration=5 count=1 {target}" - - -class _IPv6(CommandSet): - """Default commands for ipv6 commands.""" - - bgp_community: StrictStr = "ipv6 route print where bgp-communities={target}" - bgp_aspath: StrictStr = "ipv6 route print where bgp-as-path={target}" - bgp_route: StrictStr = "ipv6 route print where dst-address={target}" - ping: StrictStr = "ping src-address={source} count=5 {target}" - traceroute: StrictStr = "tool traceroute src-address={source} timeout=1 duration=5 count=1 {target}" - - -class _VPNIPv4(CommandSet): - """Default commands for dual afi commands.""" - - bgp_community: StrictStr = "ip route print where bgp-communities={target} routing-mark={vrf}" - bgp_aspath: StrictStr = "ip route print where bgp-as-path={target} routing-mark={vrf}" - bgp_route: StrictStr = "ip route print where dst-address={target} routing-mark={vrf}" - ping: StrictStr = "ping src-address={source} count=5 routing-table={vrf} {target}" - traceroute: StrictStr = "tool traceroute src-address={source} timeout=1 duration=5 count=1 routing-table={vrf} {target}" - - -class _VPNIPv6(CommandSet): - """Default commands for dual afi commands.""" - - bgp_community: StrictStr = "ipv6 route print where bgp-communities={target} routing-mark={vrf}" - bgp_aspath: StrictStr = "ipv6 route print where bgp-as-path={target} routing-mark={vrf}" - bgp_route: StrictStr = "ipv6 route print where dst-address={target} routing-mark={vrf}" - ping: StrictStr = "ping src-address={source} count=5 routing-table={vrf} {target}" - traceroute: StrictStr = "tool traceroute src-address={source} timeout=1 duration=5 count=1 routing-table={vrf} {target}" - - -class MikrotikCommands(CommandGroup): - """Validation model for default mikrotik commands.""" - - ipv4_default: _IPv4 = _IPv4() - ipv6_default: _IPv6 = _IPv6() - ipv4_vpn: _VPNIPv4 = _VPNIPv4() - ipv6_vpn: _VPNIPv6 = _VPNIPv6() diff --git a/hyperglass/models/commands/arista_eos.py b/hyperglass/models/commands/arista_eos.py deleted file mode 100644 index 29dbc3a..0000000 --- a/hyperglass/models/commands/arista_eos.py +++ /dev/null @@ -1,93 +0,0 @@ -"""Arista EOS Command Model.""" - -# Third Party -from pydantic import StrictStr - -# Local -from .common import CommandSet, CommandGroup - - -class _IPv4(CommandSet): - """Validation model for non-default dual afi commands.""" - - bgp_route: StrictStr = "show ip bgp {target}" - bgp_aspath: StrictStr = "show ip bgp regexp {target}" - bgp_community: StrictStr = "show ip bgp community {target}" - ping: StrictStr = "ping ip {target} source {source}" - traceroute: StrictStr = "traceroute ip {target} source {source}" - - -class _IPv6(CommandSet): - """Validation model for non-default ipv4 commands.""" - - bgp_route: StrictStr = "show ipv6 bgp {target}" - bgp_aspath: StrictStr = "show ipv6 bgp regexp {target}" - bgp_community: StrictStr = "show ipv6 bgp community {target}" - ping: StrictStr = "ping ipv6 {target} source {source}" - traceroute: StrictStr = "traceroute ipv6 {target} source {source}" - - -class _VPNIPv4(CommandSet): - """Validation model for non-default ipv6 commands.""" - - bgp_route: StrictStr = "show ip bgp {target} vrf {vrf}" - bgp_aspath: StrictStr = "show ip bgp regexp {target} vrf {vrf}" - bgp_community: StrictStr = "show ip bgp community {target} vrf {vrf}" - ping: StrictStr = "ping vrf {vrf} ip {target} source {source}" - traceroute: StrictStr = "traceroute vrf {vrf} ip {target} source {source}" - - -class _VPNIPv6(CommandSet): - """Validation model for non-default ipv6 commands.""" - - bgp_route: StrictStr = "show ipv6 bgp {target} vrf {vrf}" - bgp_aspath: StrictStr = "show ipv6 bgp regexp {target} vrf {vrf}" - bgp_community: StrictStr = "show ipv6 bgp community {target} vrf {vrf}" - ping: StrictStr = "ping vrf {vrf} ipv6 {target} source {source}" - traceroute: StrictStr = "traceroute vrf {vrf} ipv6 {target} source {source}" - - -_structured = CommandGroup( - ipv4_default=CommandSet( - bgp_route="show ip bgp {target} | json", - bgp_aspath="show ip bgp regexp {target} | json", - bgp_community="show ip bgp community {target} | json", - ping="ping ip {target} source {source}", - traceroute="traceroute ip {target} source {source}", - ), - ipv6_default=CommandSet( - bgp_route="show ipv6 bgp {target} | json", - bgp_aspath="show ipv6 bgp regexp {target} | json", - bgp_community="show ipv6 bgp community {target} | json", - ping="ping ipv6 {target} source {source}", - traceroute="traceroute ipv6 {target} source {source}", - ), - ipv4_vpn=CommandSet( - bgp_route="show ip bgp {target} vrf {vrf} | json", - bgp_aspath="show ip bgp regexp {target} vrf {vrf} | json", - bgp_community="show ip bgp community {target} vrf {vrf} | json", - ping="ping vrf {vrf} ip {target} source {source}", - traceroute="traceroute vrf {vrf} ip {target} source {source}", - ), - ipv6_vpn=CommandSet( - bgp_route="show ipv6 bgp {target} vrf {vrf} | json", - bgp_aspath="show ipv6 bgp regexp {target} vrf {vrf} | json", - bgp_community="show ipv6 bgp community {target} vrf {vrf} | json", - ping="ping vrf {vrf} ipv6 {target} source {source}", - traceroute="traceroute vrf {vrf} ipv6 {target} source {source}", - ), -) - - -class AristaEOSCommands(CommandGroup): - """Validation model for default arista_eos commands.""" - - ipv4_default: _IPv4 = _IPv4() - ipv6_default: _IPv6 = _IPv6() - ipv4_vpn: _VPNIPv4 = _VPNIPv4() - ipv6_vpn: _VPNIPv6 = _VPNIPv6() - - def __init__(self, **kwargs): - """Initialize command group, ensure structured fields are not overridden.""" - super().__init__(**kwargs) - self.structured = _structured diff --git a/hyperglass/models/commands/bird.py b/hyperglass/models/commands/bird.py deleted file mode 100644 index 9a86f0a..0000000 --- a/hyperglass/models/commands/bird.py +++ /dev/null @@ -1,56 +0,0 @@ -"""BIRD Routing Daemon Command Model.""" - -# Third Party -from pydantic import StrictStr - -# Local -from .common import CommandSet, CommandGroup - - -class _IPv4(CommandSet): - """Default commands for ipv4 commands.""" - - bgp_community: str = 'birdc "show route all where {target} ~ bgp_community"' - bgp_aspath: str = 'birdc "show route all where bgp_path ~ {target}"' - bgp_route: str = 'birdc "show route all where {target} ~ net"' - ping: str = "ping -4 -c 5 -I {source} {target}" - traceroute: str = "traceroute -4 -w 1 -q 1 -s {source} {target}" - - -class _IPv6(CommandSet): - """Default commands for ipv6 commands.""" - - bgp_community: str = 'birdc "show route all where {target} ~ bgp_community"' - bgp_aspath: str = 'birdc "show route all where bgp_path ~ {target}"' - bgp_route: str = 'birdc "show route all where {target} ~ net"' - ping: StrictStr = "ping -6 -c 5 -I {source} {target}" - traceroute: StrictStr = "traceroute -6 -w 1 -q 1 -s {source} {target}" - - -class _VPNIPv4(CommandSet): - """Default commands for dual afi commands.""" - - bgp_community: str = 'birdc "show route all table {vrf} where {target} ~ bgp_community"' - bgp_aspath: str = 'birdc "show route all table {vrf} where bgp_path ~ {target}"' - bgp_route: str = 'birdc "show route all table {vrf} where {target} ~ net"' - ping: StrictStr = "ping -4 -c 5 -I {source} {target}" - traceroute: StrictStr = "traceroute -4 -w 1 -q 1 -s {source} {target}" - - -class _VPNIPv6(CommandSet): - """Default commands for dual afi commands.""" - - bgp_community: str = 'birdc "show route all table {vrf} where {target} ~ bgp_community"' - bgp_aspath: str = 'birdc "show route all table {vrf} where bgp_path ~ {target}"' - bgp_route: str = 'birdc "show route all table {vrf} where {target} ~ net"' - ping: StrictStr = "ping -6 -c 5 -I {source} {target}" - traceroute: StrictStr = "traceroute -6 -w 1 -q 1 -s {source} {target}" - - -class BIRDCommands(CommandGroup): - """Validation model for default BIRD commands.""" - - ipv4_default: _IPv4 = _IPv4() - ipv6_default: _IPv6 = _IPv6() - ipv4_vpn: _VPNIPv4 = _VPNIPv4() - ipv6_vpn: _VPNIPv6 = _VPNIPv6() diff --git a/hyperglass/models/commands/cisco_ios.py b/hyperglass/models/commands/cisco_ios.py deleted file mode 100644 index affd3e5..0000000 --- a/hyperglass/models/commands/cisco_ios.py +++ /dev/null @@ -1,62 +0,0 @@ -"""Cisco IOS Command Model.""" - -# Third Party -from pydantic import StrictStr - -# Local -from .common import CommandSet, CommandGroup - - -class _IPv4(CommandSet): - """Default commands for ipv4 commands.""" - - bgp_community: StrictStr = "show bgp ipv4 unicast community {target}" - bgp_aspath: StrictStr = 'show bgp ipv4 unicast quote-regexp "{target}"' - bgp_route: StrictStr = "show bgp ipv4 unicast {target} | exclude pathid:|Epoch" - ping: StrictStr = "ping {target} repeat 5 source {source}" - traceroute: StrictStr = "traceroute {target} timeout 1 probe 2 source {source}" - - -class _IPv6(CommandSet): - """Default commands for ipv6 commands.""" - - bgp_community: StrictStr = "show bgp ipv6 unicast community {target}" - bgp_aspath: StrictStr = 'show bgp ipv6 unicast quote-regexp "{target}"' - bgp_route: StrictStr = "show bgp ipv6 unicast {target} | exclude pathid:|Epoch" - ping: StrictStr = "ping ipv6 {target} repeat 5 source {source}" - traceroute: StrictStr = ( - "traceroute ipv6 {target} timeout 1 probe 2 source {source}" - ) - - -class _VPNIPv4(CommandSet): - """Default commands for dual afi commands.""" - - bgp_community: StrictStr = "show bgp vpnv4 unicast vrf {vrf} community {target}" - bgp_aspath: StrictStr = 'show bgp vpnv4 unicast vrf {vrf} quote-regexp "{target}"' - bgp_route: StrictStr = "show bgp vpnv4 unicast vrf {vrf} {target}" - ping: StrictStr = "ping vrf {vrf} {target} repeat 5 source {source}" - traceroute: StrictStr = ( - "traceroute vrf {vrf} {target} timeout 1 probe 2 source {source}" - ) - - -class _VPNIPv6(CommandSet): - """Default commands for dual afi commands.""" - - bgp_community: StrictStr = "show bgp vpnv6 unicast vrf {vrf} community {target}" - bgp_aspath: StrictStr = 'show bgp vpnv6 unicast vrf {vrf} quote-regexp "{target}"' - bgp_route: StrictStr = "show bgp vpnv6 unicast vrf {vrf} {target}" - ping: StrictStr = "ping vrf {vrf} {target} repeat 5 source {source}" - traceroute: StrictStr = ( - "traceroute vrf {vrf} {target} timeout 1 probe 2 source {source}" - ) - - -class CiscoIOSCommands(CommandGroup): - """Validation model for default cisco_ios commands.""" - - ipv4_default: _IPv4 = _IPv4() - ipv6_default: _IPv6 = _IPv6() - ipv4_vpn: _VPNIPv4 = _VPNIPv4() - ipv6_vpn: _VPNIPv6 = _VPNIPv6() diff --git a/hyperglass/models/commands/cisco_nxos.py b/hyperglass/models/commands/cisco_nxos.py deleted file mode 100644 index 58e61fc..0000000 --- a/hyperglass/models/commands/cisco_nxos.py +++ /dev/null @@ -1,56 +0,0 @@ -"""Cisco NX-OS Command Model.""" - -# Third Party -from pydantic import StrictStr - -# Local -from .common import CommandSet, CommandGroup - - -class _IPv4(CommandSet): - """Validation model for non-default dual afi commands.""" - - bgp_route: StrictStr = "show bgp ipv4 unicast {target}" - bgp_aspath: StrictStr = 'show bgp ipv4 unicast regexp "{target}"' - bgp_community: StrictStr = "show bgp ipv4 unicast community {target}" - ping: StrictStr = "ping {target} source {source}" - traceroute: StrictStr = "traceroute {target} source {source}" - - -class _IPv6(CommandSet): - """Validation model for non-default ipv4 commands.""" - - bgp_route: StrictStr = "show bgp ipv6 unicast {target}" - bgp_aspath: StrictStr = 'show bgp ipv6 unicast regexp "{target}"' - bgp_community: StrictStr = "show bgp ipv6 unicast community {target}" - ping: StrictStr = "ping6 {target} source {source}" - traceroute: StrictStr = "traceroute6 {target} source {source}" - - -class _VPNIPv4(CommandSet): - """Validation model for non-default ipv6 commands.""" - - bgp_route: StrictStr = "show bgp ipv4 unicast {target} vrf {vrf}" - bgp_aspath: StrictStr = 'show bgp ipv4 unicast regexp "{target}" vrf {vrf}' - bgp_community: StrictStr = "show bgp ipv4 unicast community {target} vrf {vrf}" - ping: StrictStr = "ping {target} source {source} vrf {vrf}" - traceroute: StrictStr = "traceroute {target} source {source} vrf {vrf}" - - -class _VPNIPv6(CommandSet): - """Validation model for non-default ipv6 commands.""" - - bgp_route: StrictStr = "show bgp ipv6 unicast {target} vrf {vrf}" - bgp_aspath: StrictStr = 'show bgp ipv6 unicast regexp "{target}" vrf {vrf}' - bgp_community: StrictStr = "show bgp ipv6 unicast community {target} vrf {vrf}" - ping: StrictStr = "ping6 {target} source {source} vrf {vrf}" - traceroute: StrictStr = "traceroute6 {target} source {source} vrf {vrf}" - - -class CiscoNXOSCommands(CommandGroup): - """Validation model for default cisco_nxos commands.""" - - ipv4_default: _IPv4 = _IPv4() - ipv6_default: _IPv6 = _IPv6() - ipv4_vpn: _VPNIPv4 = _VPNIPv4() - ipv6_vpn: _VPNIPv6 = _VPNIPv6() diff --git a/hyperglass/models/commands/cisco_xr.py b/hyperglass/models/commands/cisco_xr.py deleted file mode 100644 index 01ed2a5..0000000 --- a/hyperglass/models/commands/cisco_xr.py +++ /dev/null @@ -1,56 +0,0 @@ -"""Cisco IOS XR Command Model.""" - -# Third Party -from pydantic import StrictStr - -# Local -from .common import CommandSet, CommandGroup - - -class _IPv4(CommandSet): - """Validation model for non-default dual afi commands.""" - - bgp_route: StrictStr = "show bgp ipv4 unicast {target}" - bgp_aspath: StrictStr = "show bgp ipv4 unicast regexp {target}" - bgp_community: StrictStr = "show bgp ipv4 unicast community {target}" - ping: StrictStr = "ping ipv4 {target} count 5 source {source}" - traceroute: StrictStr = "traceroute ipv4 {target} timeout 1 probe 2 source {source}" - - -class _IPv6(CommandSet): - """Validation model for non-default ipv4 commands.""" - - bgp_route: StrictStr = "show bgp ipv6 unicast {target}" - bgp_aspath: StrictStr = "show bgp ipv6 unicast regexp {target}" - bgp_community: StrictStr = "show bgp ipv6 unicast community {target}" - ping: StrictStr = "ping ipv6 {target} count 5 source {source}" - traceroute: StrictStr = "traceroute ipv6 {target} timeout 1 probe 2 source {source}" - - -class _VPNIPv4(CommandSet): - """Validation model for non-default ipv6 commands.""" - - bgp_route: StrictStr = "show bgp vpnv4 unicast vrf {vrf} {target}" - bgp_aspath: StrictStr = "show bgp vpnv4 unicast vrf {vrf} regexp {target}" - bgp_community: StrictStr = "show bgp vpnv4 unicast vrf {vrf} community {target}" - ping: StrictStr = "ping vrf {vrf} {target} count 5 source {source}" - traceroute: StrictStr = "traceroute vrf {vrf} {target} timeout 1 probe 2 source {source}" - - -class _VPNIPv6(CommandSet): - """Validation model for non-default ipv6 commands.""" - - bgp_route: StrictStr = "show bgp vpnv6 unicast vrf {vrf} {target}" - bgp_aspath: StrictStr = "show bgp vpnv6 unicast vrf {vrf} regexp {target}" - bgp_community: StrictStr = "show bgp vpnv6 unicast vrf {vrf} community {target}" - ping: StrictStr = "ping vrf {vrf} {target} count 5 source {source}" - traceroute: StrictStr = "traceroute vrf {vrf} {target} timeout 1 probe 2 source {source}" - - -class CiscoXRCommands(CommandGroup): - """Validation model for default cisco_xr commands.""" - - ipv4_default: _IPv4 = _IPv4() - ipv6_default: _IPv6 = _IPv6() - ipv4_vpn: _VPNIPv4 = _VPNIPv4() - ipv6_vpn: _VPNIPv6 = _VPNIPv6() diff --git a/hyperglass/models/commands/common.py b/hyperglass/models/commands/common.py deleted file mode 100644 index 347efd2..0000000 --- a/hyperglass/models/commands/common.py +++ /dev/null @@ -1,26 +0,0 @@ -"""Models common to entire commands module.""" - -# Third Party -from pydantic import StrictStr - -# Local -from ..main import HyperglassModel, HyperglassModelExtra - - -class CommandSet(HyperglassModel): - """Command set, defined per-AFI.""" - - bgp_route: StrictStr - bgp_aspath: StrictStr - bgp_community: StrictStr - ping: StrictStr - traceroute: StrictStr - - -class CommandGroup(HyperglassModelExtra): - """Validation model for all commands.""" - - ipv4_default: CommandSet - ipv6_default: CommandSet - ipv4_vpn: CommandSet - ipv6_vpn: CommandSet diff --git a/hyperglass/models/commands/frr.py b/hyperglass/models/commands/frr.py deleted file mode 100644 index 2dde708..0000000 --- a/hyperglass/models/commands/frr.py +++ /dev/null @@ -1,56 +0,0 @@ -"""FRRouting Command Model.""" - -# Third Party -from pydantic import StrictStr - -# Local -from .common import CommandSet, CommandGroup - - -class _IPv4(CommandSet): - """Default commands for ipv4 commands.""" - - bgp_community: StrictStr = 'vtysh -c "show bgp ipv4 unicast community {target}"' - bgp_aspath: StrictStr = 'vtysh -c "show bgp ipv4 unicast regexp {target}"' - bgp_route: StrictStr = 'vtysh -c "show bgp ipv4 unicast {target}"' - ping: StrictStr = "ping -4 -c 5 -I {source} {target}" - traceroute: StrictStr = "traceroute -4 -w 1 -q 1 -s {source} {target}" - - -class _IPv6(CommandSet): - """Default commands for ipv6 commands.""" - - bgp_community: StrictStr = 'vtysh -c "show bgp ipv6 unicast community {target}"' - bgp_aspath: StrictStr = 'vtysh -c "show bgp ipv6 unicast regexp {target}"' - bgp_route: StrictStr = 'vtysh -c "show bgp ipv6 unicast {target}"' - ping: StrictStr = "ping -6 -c 5 -I {source} {target}" - traceroute: StrictStr = "traceroute -6 -w 1 -q 1 -s {source} {target}" - - -class _VPNIPv4(CommandSet): - """Default commands for dual afi commands.""" - - bgp_community: StrictStr = 'vtysh -c "show bgp vrf {vrf} ipv4 unicast community {target}"' - bgp_aspath: StrictStr = 'vtysh -c "show bgp vrf {vrf} ipv4 unicast regexp {target}"' - bgp_route: StrictStr = 'vtysh -c "show bgp vrf {vrf} ipv4 unicast {target}"' - ping: StrictStr = "ping -4 -c 5 -I {source} {target}" - traceroute: StrictStr = "traceroute -4 -w 1 -q 1 -s {source} {target}" - - -class _VPNIPv6(CommandSet): - """Default commands for dual afi commands.""" - - bgp_community: StrictStr = 'vtysh -c "show bgp vrf {vrf} ipv6 unicast community {target}"' - bgp_aspath: StrictStr = 'vtysh -c "show bgp vrf {vrf} ipv6 unicast regexp {target}"' - bgp_route: StrictStr = 'vtysh -c "show bgp vrf {vrf} ipv6 unicast {target}"' - ping: StrictStr = "ping -6 -c 5 -I {source} {target}" - traceroute: StrictStr = "traceroute -6 -w 1 -q 1 -s {source} {target}" - - -class FRRCommands(CommandGroup): - """Validation model for default FRRouting commands.""" - - ipv4_default: _IPv4 = _IPv4() - ipv6_default: _IPv6 = _IPv6() - ipv4_vpn: _VPNIPv4 = _VPNIPv4() - ipv6_vpn: _VPNIPv6 = _VPNIPv6() diff --git a/hyperglass/models/commands/huawei.py b/hyperglass/models/commands/huawei.py deleted file mode 100644 index eea35d1..0000000 --- a/hyperglass/models/commands/huawei.py +++ /dev/null @@ -1,56 +0,0 @@ -"""Huawei Command Model.""" - -# Third Party -from pydantic import StrictStr - -# Local -from .common import CommandSet, CommandGroup - - -class _IPv4(CommandSet): - """Default commands for ipv4 commands.""" - - bgp_community: StrictStr = "display bgp routing-table regular-expression {target}" - bgp_aspath: StrictStr = "display bgp routing-table regular-expression {target}" - bgp_route: StrictStr = "display bgp routing-table {target}" - ping: StrictStr = "ping -c 5 -a {source} {target}" - traceroute: StrictStr = "tracert -q 2 -f 1 -a {source} {target}" - - -class _IPv6(CommandSet): - """Default commands for ipv6 commands.""" - - bgp_community: StrictStr = "display bgp ipv6 routing-table community {target}" - bgp_aspath: StrictStr = "display bgp ipv6 routing-table regular-expression {target}" - bgp_route: StrictStr = "display bgp ipv6 routing-table {target}" - ping: StrictStr = "ping ipv6 -c 5 -a {source} {target}" - traceroute: StrictStr = "tracert ipv6 -q 2 -f 1 -a {source} {target}" - - -class _VPNIPv4(CommandSet): - """Default commands for dual afi commands.""" - - bgp_community: StrictStr = "display bgp vpnv4 vpn-instance {vrf} routing-table regular-expression {target}" - bgp_aspath: StrictStr = "display bgp vpnv4 vpn-instance {vrf} routing-table regular-expression {target}" - bgp_route: StrictStr = "display bgp vpnv4 vpn-instance {vrf} routing-table {target}" - ping: StrictStr = "ping -vpn-instance {vrf} -c 5 -a {source} {target}" - traceroute: StrictStr = "tracert -q 2 -f 1 -vpn-instance {vrf} -a {source} {target}" - - -class _VPNIPv6(CommandSet): - """Default commands for dual afi commands.""" - - bgp_community: StrictStr = "display bgp vpnv6 vpn-instance {vrf} routing-table regular-expression {target}" - bgp_aspath: StrictStr = "display bgp vpnv6 vpn-instance {vrf} routing-table regular-expression {target}" - bgp_route: StrictStr = "display bgp vpnv6 vpn-instance {vrf} routing-table {target}" - ping: StrictStr = "ping vpnv6 vpn-instance {vrf} -c 5 -a {source} {target}" - traceroute: StrictStr = "tracert -q 2 -f 1 vpn-instance {vrf} -a {source} {target}" - - -class HuaweiCommands(CommandGroup): - """Validation model for default huawei commands.""" - - ipv4_default: _IPv4 = _IPv4() - ipv6_default: _IPv6 = _IPv6() - ipv4_vpn: _VPNIPv4 = _VPNIPv4() - ipv6_vpn: _VPNIPv6 = _VPNIPv6() diff --git a/hyperglass/models/commands/juniper.py b/hyperglass/models/commands/juniper.py deleted file mode 100644 index c0091cc..0000000 --- a/hyperglass/models/commands/juniper.py +++ /dev/null @@ -1,93 +0,0 @@ -"""Juniper Command Model.""" - -# Third Party -from pydantic import StrictStr - -# Local -from .common import CommandSet, CommandGroup - - -class _IPv4(CommandSet): - """Validation model for non-default dual afi commands.""" - - bgp_route: StrictStr = 'show route protocol bgp table inet.0 {target} best detail | except Label | except Label | except "Next hop type" | except Task | except Address | except "Session Id" | except State | except "Next-hop reference" | except destinations | except "Announcement bits"' - bgp_aspath: StrictStr = 'show route protocol bgp table inet.0 aspath-regex "{target}"' - bgp_community: StrictStr = "show route protocol bgp table inet.0 community {target}" - ping: StrictStr = "ping inet {target} count 5 source {source}" - traceroute: StrictStr = "traceroute inet {target} wait 1 source {source}" - - -class _IPv6(CommandSet): - """Validation model for non-default ipv4 commands.""" - - bgp_route: StrictStr = 'show route protocol bgp table inet6.0 {target} best detail | except Label | except Label | except "Next hop type" | except Task | except Address | except "Session Id" | except State | except "Next-hop reference" | except destinations | except "Announcement bits"' - bgp_aspath: StrictStr = 'show route protocol bgp table inet6.0 aspath-regex "{target}"' - bgp_community: StrictStr = "show route protocol bgp table inet6.0 community {target}" - ping: StrictStr = "ping inet6 {target} count 5 source {source}" - traceroute: StrictStr = "traceroute inet6 {target} wait 2 source {source}" - - -class _VPNIPv4(CommandSet): - """Validation model for non-default ipv6 commands.""" - - bgp_route: StrictStr = 'show route protocol bgp table {vrf}.inet.0 {target} best detail | except Label | except Label | except "Next hop type" | except Task | except Address | except "Session Id" | except State | except "Next-hop reference" | except destinations | except "Announcement bits"' - bgp_aspath: StrictStr = 'show route protocol bgp table {vrf}.inet.0 aspath-regex "{target}"' - bgp_community: StrictStr = "show route protocol bgp table {vrf}.inet.0 community {target}" - ping: StrictStr = "ping inet routing-instance {vrf} {target} count 5 source {source}" - traceroute: StrictStr = "traceroute inet routing-instance {vrf} {target} wait 1 source {source}" - - -class _VPNIPv6(CommandSet): - """Validation model for non-default ipv6 commands.""" - - bgp_route: StrictStr = 'show route protocol bgp table {vrf}.inet6.0 {target} best detail | except Label | except Label | except "Next hop type" | except Task | except Address | except "Session Id" | except State | except "Next-hop reference" | except destinations | except "Announcement bits"' - bgp_aspath: StrictStr = 'show route protocol bgp table {vrf}.inet6.0 aspath-regex "{target}"' - bgp_community: StrictStr = "show route protocol bgp table {vrf}.inet6.0 community {target}" - ping: StrictStr = "ping inet6 routing-instance {vrf} {target} count 5 source {source}" - traceroute: StrictStr = "traceroute inet6 routing-instance {vrf} {target} wait 2 source {source}" - - -_structured = CommandGroup( - ipv4_default=CommandSet( - bgp_route="show route protocol bgp table inet.0 {target} best detail | display xml", - bgp_aspath='show route protocol bgp table inet.0 aspath-regex "{target}" detail | display xml', - bgp_community="show route protocol bgp table inet.0 community {target} detail | display xml", - ping="ping inet {target} count 5 source {source}", - traceroute="traceroute inet {target} wait 1 source {source}", - ), - ipv6_default=CommandSet( - bgp_route="show route protocol bgp table inet6.0 {target} best detail | display xml", - bgp_aspath='show route protocol bgp table inet6.0 aspath-regex "{target}" detail | display xml', - bgp_community="show route protocol bgp table inet6.0 community {target} detail | display xml", - ping="ping inet6 {target} count 5 source {source}", - traceroute="traceroute inet6 {target} wait 2 source {source}", - ), - ipv4_vpn=CommandSet( - bgp_route="show route protocol bgp table {vrf}.inet.0 {target} best detail | display xml", - bgp_aspath='show route protocol bgp table {vrf}.inet.0 aspath-regex "{target}" detail | display xml', - bgp_community="show route protocol bgp table {vrf}.inet.0 community {target} detail | display xml", - ping="ping inet routing-instance {vrf} {target} count 5 source {source}", - traceroute="traceroute inet routing-instance {vrf} {target} wait 1 source {source}", - ), - ipv6_vpn=CommandSet( - bgp_route="show route protocol bgp table {vrf}.inet6.0 {target} best detail | display xml", - bgp_aspath='show route protocol bgp table {vrf}.inet6.0 aspath-regex "{target}" detail | display xml', - bgp_community="show route protocol bgp table {vrf}.inet6.0 community {target} detail | display xml", - ping="ping inet6 routing-instance {vrf} {target} count 5 source {source}", - traceroute="traceroute inet6 routing-instance {vrf} {target} wait 2 source {source}", - ), -) - - -class JuniperCommands(CommandGroup): - """Validation model for default juniper commands.""" - - ipv4_default: _IPv4 = _IPv4() - ipv6_default: _IPv6 = _IPv6() - ipv4_vpn: _VPNIPv4 = _VPNIPv4() - ipv6_vpn: _VPNIPv6 = _VPNIPv6() - - def __init__(self, **kwargs): - """Initialize command group, ensure structured fields are not overridden.""" - super().__init__(**kwargs) - self.structured = _structured diff --git a/hyperglass/models/commands/mikrotik_routeros.py b/hyperglass/models/commands/mikrotik_routeros.py deleted file mode 100644 index ab986f6..0000000 --- a/hyperglass/models/commands/mikrotik_routeros.py +++ /dev/null @@ -1,9 +0,0 @@ -"""Mikrotik RouterOS Commands Model.""" -# Local -from ._mikrotik_base import MikrotikCommands - - -class MikrotikRouterOS(MikrotikCommands): - """Alias for mikrotik_routeros.""" - - pass diff --git a/hyperglass/models/commands/mikrotik_switchos.py b/hyperglass/models/commands/mikrotik_switchos.py deleted file mode 100644 index 4e18c31..0000000 --- a/hyperglass/models/commands/mikrotik_switchos.py +++ /dev/null @@ -1,9 +0,0 @@ -"""Mikrotik SwitchOS Commands Model.""" -# Local -from ._mikrotik_base import MikrotikCommands - - -class MikrotikSwitchOS(MikrotikCommands): - """Alias for mikrotik_switchos.""" - - pass diff --git a/hyperglass/models/commands/nokia_sros.py b/hyperglass/models/commands/nokia_sros.py deleted file mode 100644 index bc8d5b6..0000000 --- a/hyperglass/models/commands/nokia_sros.py +++ /dev/null @@ -1,56 +0,0 @@ -"""Nokia SR-OS Command Model.""" - -# Third Party -from pydantic import StrictStr - -# Local -from .common import CommandSet, CommandGroup - - -class _IPv4(CommandSet): - """Default commands for ipv4 commands.""" - - bgp_community: StrictStr = "/show router bgp routes community {target}" - bgp_aspath: StrictStr = "/show router bgp routes aspath-regex {target}" - bgp_route: StrictStr = "/show router bgp routes {target} ipv4 hunt" - ping: StrictStr = "/ping {target} source-address {source}" - traceroute: StrictStr = "/traceroute {target} source-address {source} wait 2 seconds" - - -class _IPv6(CommandSet): - """Default commands for ipv6 commands.""" - - bgp_community: StrictStr = "/show router bgp routes community {target}" - bgp_aspath: StrictStr = "/show router bgp routes aspath-regex {target}" - bgp_route: StrictStr = "/show router bgp routes {target} ipv6 hunt" - ping: StrictStr = "/ping {target} source-address {source}" - traceroute: StrictStr = "/traceroute {target} source-address {source} wait 2 seconds" - - -class _VPNIPv4(CommandSet): - """Default commands for dual afi commands.""" - - bgp_community: StrictStr = "/show router bgp routes community {target}" - bgp_aspath: StrictStr = "/show router bgp routes aspath-regex {target}" - bgp_route: StrictStr = "/show router bgp routes {target} vpn-ipv4 hunt" - ping: StrictStr = "/ping {target} source-address {source}" - traceroute: StrictStr = "/traceroute {target} source-address {source} wait 2 seconds" - - -class _VPNIPv6(CommandSet): - """Default commands for dual afi commands.""" - - bgp_community: StrictStr = "/show router bgp routes community {target}" - bgp_aspath: StrictStr = "/show router bgp routes aspath-regex {target}" - bgp_route: StrictStr = "/show router bgp routes {target} vpn-ipv6 hunt" - ping: StrictStr = "/ping {target} source-address {source}" - traceroute: StrictStr = "/traceroute {target} source-address {source} wait 2 seconds" - - -class NokiaSROSCommands(CommandGroup): - """Validation model for default nokia_sros commands.""" - - ipv4_default: _IPv4 = _IPv4() - ipv6_default: _IPv6 = _IPv6() - ipv4_vpn: _VPNIPv4 = _VPNIPv4() - ipv6_vpn: _VPNIPv6 = _VPNIPv6() diff --git a/hyperglass/models/commands/tnsr.py b/hyperglass/models/commands/tnsr.py deleted file mode 100644 index 755a79d..0000000 --- a/hyperglass/models/commands/tnsr.py +++ /dev/null @@ -1,56 +0,0 @@ -"""Netgate TNSR Command Model.""" - -# Third Party -from pydantic import StrictStr - -# Local -from .common import CommandSet, CommandGroup - - -class _IPv4(CommandSet): - """Validation model for default VRF IPv4 commands.""" - - bgp_community: StrictStr = 'dataplane shell sudo vtysh -c "show bgp ipv4 unicast community {target}"' - bgp_aspath: StrictStr = 'dataplane shell sudo vtysh -c "show bgp ipv4 unicast regexp {target}"' - bgp_route: StrictStr = 'dataplane shell sudo vtysh -c "show bgp ipv4 unicast {target}"' - ping: StrictStr = "ping {target} ipv4 source {source} count 5 timeout 1" - traceroute: StrictStr = "traceroute {target} ipv4 source {source} timeout 1 waittime 1" - - -class _IPv6(CommandSet): - """Validation model for default VRF IPv6 commands.""" - - bgp_community: StrictStr = 'dataplane shell sudo vtysh -c "show bgp ipv6 unicast community {target}"' - bgp_aspath: StrictStr = 'dataplane shell sudo vtysh -c "show bgp ipv6 unicast regexp {target}"' - bgp_route: StrictStr = 'dataplane shell sudo vtysh -c "show bgp ipv6 unicast {target}"' - ping: StrictStr = "ping {target} ipv6 source {source} count 5 timeout 1" - traceroute: StrictStr = "traceroute {target} ipv6 source {source} timeout 1 waittime 1" - - -class _VPNIPv4(CommandSet): - """Validation model for non-default ipv6 commands.""" - - bgp_community: StrictStr = 'dataplane shell sudo vtysh -c "show bgp vrf {vrf} ipv4 unicast community {target}"' - bgp_aspath: StrictStr = 'dataplane shell sudo vtysh -c "show bgp vrf {vrf} ipv4 unicast regexp {target}"' - bgp_route: StrictStr = 'dataplane shell sudo vtysh -c "show bgp vrf {vrf} ipv4 unicast {target}"' - ping: StrictStr = "dataplane shell ping -4 -c 5 -W 1 -I {vrf} -S {source} {target}" - traceroute: StrictStr = "dataplane shell traceroute -4 -w 1 -q 1 -i {vrf} -s {source} {target}" - - -class _VPNIPv6(CommandSet): - """Validation model for non-default ipv6 commands.""" - - bgp_community: StrictStr = 'dataplane shell sudo vtysh -c "show bgp vrf {vrf} ipv6 unicast community {target}"' - bgp_aspath: StrictStr = 'dataplane shell sudo vtysh -c "show bgp vrf {vrf} ipv6 unicast regexp {target}"' - bgp_route: StrictStr = 'dataplane shell sudo vtysh -c "show bgp vrf {vrf} ipv6 unicast {target}"' - ping: StrictStr = "dataplane shell ping -6 -c 5 -W 1 -I {vrf} -S {source} {target}" - traceroute: StrictStr = "dataplane shell traceroute -6 -w 1 -q 1 -i {vrf} -s {source} {target}" - - -class TNSRCommands(CommandGroup): - """Validation model for default tnsr commands.""" - - ipv4_default: _IPv4 = _IPv4() - ipv6_default: _IPv6 = _IPv6() - ipv4_vpn: _VPNIPv4 = _VPNIPv4() - ipv6_vpn: _VPNIPv6 = _VPNIPv6() diff --git a/hyperglass/models/commands/vyos.py b/hyperglass/models/commands/vyos.py deleted file mode 100644 index fff5dd9..0000000 --- a/hyperglass/models/commands/vyos.py +++ /dev/null @@ -1,56 +0,0 @@ -"""VyOS Command Model.""" - -# Third Party -from pydantic import StrictStr - -# Local -from .common import CommandSet, CommandGroup - - -class _IPv4(CommandSet): - """Validation model for non-default dual afi commands.""" - - bgp_route: StrictStr = "show ip bgp {target}" - bgp_aspath: StrictStr = 'show ip bgp regexp "{target}"' - bgp_community: StrictStr = "show ip bgp community {target}" - ping: StrictStr = "ping {target} count 5 interface {source}" - traceroute: StrictStr = "mtr -4 -G 1 -c 1 -w -o SAL -a {source} {target}" - - -class _IPv6(CommandSet): - """Validation model for non-default ipv4 commands.""" - - bgp_route: StrictStr = "show ipv6 bgp {target}" - bgp_aspath: StrictStr = 'show ipv6 bgp regexp "{target}"' - bgp_community: StrictStr = "show ipv6 bgp community {target}" - ping: StrictStr = "ping {target} count 5 interface {source}" - traceroute: StrictStr = "mtr -6 -G 1 -c 1 -w -o SAL -a {source} {target}" - - -class _VPNIPv4(CommandSet): - """Validation model for non-default ipv6 commands.""" - - bgp_route: StrictStr = "show ip bgp {target}" - bgp_aspath: StrictStr = 'show ip bgp regexp "{target}"' - bgp_community: StrictStr = "show ip bgp community {target}" - ping: StrictStr = "ping {target} count 5 vrf {vrf} interface {source}" - traceroute: StrictStr = "ip vrf exec {vrf} mtr -4 -G 1 -c 1 -w -o SAL -a {source} {target}" - - -class _VPNIPv6(CommandSet): - """Validation model for non-default ipv6 commands.""" - - bgp_route: StrictStr = "show ipv6 bgp {target}" - bgp_aspath: StrictStr = 'show ipv6 bgp regexp "{target}"' - bgp_community: StrictStr = "show ipv6 bgp community {target}" - ping: StrictStr = "ping {target} count 5 interface {source}" - traceroute: StrictStr = "ip vrf exec {vrf} mtr -6 -G 1 -c 1 -w -o SAL -a {source} {target}" - - -class VyosCommands(CommandGroup): - """Validation model for default juniper commands.""" - - ipv4_default: _IPv4 = _IPv4() - ipv6_default: _IPv6 = _IPv6() - ipv4_vpn: _VPNIPv4 = _VPNIPv4() - ipv6_vpn: _VPNIPv6 = _VPNIPv6() diff --git a/hyperglass/models/config/__init__.py b/hyperglass/models/config/__init__.py deleted file mode 100644 index 1bff0e6..0000000 --- a/hyperglass/models/config/__init__.py +++ /dev/null @@ -1,5 +0,0 @@ -"""Define models for all config variables. - -Import config variables and overrides default class attributes. -Validate input for overridden parameters. -""" diff --git a/hyperglass/models/config/_utils.py b/hyperglass/models/config/_utils.py deleted file mode 100644 index ccd6505..0000000 --- a/hyperglass/models/config/_utils.py +++ /dev/null @@ -1,40 +0,0 @@ -"""Utility Functions for Pydantic Models.""" - -# Standard Library -import os -from pathlib import Path - -# Project -from hyperglass.log import log - - -def validate_image(value): - """Convert file path to URL path. - - Arguments: - value {FilePath} -- Path to logo file. - - Returns: - {str} -- Formatted logo path - """ - config_path = Path(os.environ["hyperglass_directory"]) - base_path = [v for v in value.split("/") if v != ""] - - if base_path[0] not in ("images", "custom"): - raise ValueError( - f"Logo files must be in the 'custom/' directory of your hyperglass directory. Got: {value}" - ) - - if base_path[0] == "custom": - file = config_path / "static" / "custom" / "/".join(base_path[1:]) - - else: - file = config_path / "static" / "images" / "/".join(base_path[1:]) - - log.error(file) - if not file.exists(): - raise ValueError(f"'{str(file)}' does not exist") - - base_index = file.parts.index(base_path[0]) - - return "/".join(file.parts[base_index:]) diff --git a/hyperglass/models/config/cache.py b/hyperglass/models/config/cache.py deleted file mode 100644 index ca4499c..0000000 --- a/hyperglass/models/config/cache.py +++ /dev/null @@ -1,37 +0,0 @@ -"""Validation model for Redis cache config.""" - -# Standard Library -from typing import Union, Optional - -# Third Party -from pydantic import SecretStr, StrictInt, StrictStr, StrictBool, IPvAnyAddress - -# Local -from ..main import HyperglassModel - - -class Cache(HyperglassModel): - """Validation model for params.cache.""" - - host: Union[IPvAnyAddress, StrictStr] = "localhost" - port: StrictInt = 6379 - database: StrictInt = 1 - password: Optional[SecretStr] - timeout: StrictInt = 120 - show_text: StrictBool = True - - class Config: - """Pydantic model configuration.""" - - title = "Cache" - description = "Redis server & cache timeout configuration." - fields = { - "host": {"description": "Redis server IP address or hostname."}, - "port": {"description": "Redis server TCP port."}, - "database": {"description": "Redis server database ID."}, - "password": {"description": "Redis authentication password."}, - "timeout": { - "description": "Time in seconds query output will be kept in the Redis cache." - }, - "show_test": {description: "Show the cache text in the hyperglass UI."}, - } diff --git a/hyperglass/models/config/credential.py b/hyperglass/models/config/credential.py deleted file mode 100644 index 364fc4e..0000000 --- a/hyperglass/models/config/credential.py +++ /dev/null @@ -1,42 +0,0 @@ -"""Validate credential configuration variables.""" - -# Standard Library -from typing import Optional - -# Third Party -from pydantic import FilePath, SecretStr, StrictStr, constr, root_validator - -# Local -from ..main import HyperglassModelExtra - -Methods = constr(regex=r"(password|unencrypted_key|encrypted_key)") - - -class Credential(HyperglassModelExtra): - """Model for per-credential config in devices.yaml.""" - - username: StrictStr - password: Optional[SecretStr] - key: Optional[FilePath] - - @root_validator - def validate_credential(cls, values): - """Ensure either a password or an SSH key is set.""" - if values["key"] is None and values["password"] is None: - raise ValueError( - "Either a password or an SSH key must be specified for user '{}'".format( - values["username"] - ) - ) - return values - - def __init__(self, **kwargs): - """Set private attribute _method based on validated model.""" - super().__init__(**kwargs) - self._method = None - if self.password is not None and self.key is not None: - self._method = "encrypted_key" - elif self.password is None: - self._method = "unencrypted_key" - elif self.key is None: - self._method = "password" diff --git a/hyperglass/models/config/devices.py b/hyperglass/models/config/devices.py deleted file mode 100644 index 51ff1d3..0000000 --- a/hyperglass/models/config/devices.py +++ /dev/null @@ -1,384 +0,0 @@ -"""Validate router configuration variables.""" - -# Standard Library -import os -import re -from typing import Any, Dict, List, Tuple, Union, Optional -from pathlib import Path -from ipaddress import IPv4Address, IPv6Address - -# Third Party -from pydantic import ( - StrictInt, - StrictStr, - StrictBool, - PrivateAttr, - validator, - root_validator, -) - -# Project -from hyperglass.log import log -from hyperglass.util import get_driver, validate_nos, resolve_hostname -from hyperglass.constants import SCRAPE_HELPERS, SUPPORTED_STRUCTURED_OUTPUT -from hyperglass.exceptions import ConfigError, UnsupportedDevice - -# Local -from .ssl import Ssl -from .vrf import Vrf, Info -from ..main import HyperglassModel, HyperglassModelExtra -from .proxy import Proxy -from ..fields import SupportedDriver -from .network import Network -from .credential import Credential - -_default_vrf = { - "name": "default", - "display_name": "Global", - "info": Info(), - "ipv4": { - "source_address": None, - "access_list": [ - {"network": "0.0.0.0/0", "action": "permit", "ge": 0, "le": 32} - ], - }, - "ipv6": { - "source_address": None, - "access_list": [{"network": "::/0", "action": "permit", "ge": 0, "le": 128}], - }, -} - - -def find_device_id(values: Dict) -> Tuple[str, Dict]: - """Generate device id & handle legacy display_name field.""" - - def generate_id(name: str) -> str: - scrubbed = re.sub(r"[^A-Za-z0-9\_\-\s]", "", name) - return "_".join(scrubbed.split()).lower() - - name = values.pop("name", None) - - if name is None: - raise ValueError("name is required.") - - legacy_display_name = values.pop("display_name", None) - - if legacy_display_name is not None: - log.warning( - "The 'display_name' field is deprecated. Use the 'name' field instead." - ) - device_id = generate_id(legacy_display_name) - display_name = legacy_display_name - else: - device_id = generate_id(name) - display_name = name - - return device_id, {"name": display_name, "display_name": None, **values} - - -class Device(HyperglassModel): - """Validation model for per-router config in devices.yaml.""" - - _id: StrictStr = PrivateAttr() - name: StrictStr - address: Union[IPv4Address, IPv6Address, StrictStr] - network: Network - credential: Credential - proxy: Optional[Proxy] - display_name: Optional[StrictStr] - port: StrictInt = 22 - ssl: Optional[Ssl] - nos: StrictStr - commands: Optional[StrictStr] - vrfs: List[Vrf] = [_default_vrf] - display_vrfs: List[StrictStr] = [] - vrf_names: List[StrictStr] = [] - structured_output: Optional[StrictBool] - driver: Optional[SupportedDriver] - - def __init__(self, **kwargs) -> None: - """Set the device ID.""" - _id, values = find_device_id(kwargs) - super().__init__(**values) - self._id = _id - - def __hash__(self) -> int: - """Make device object hashable so the object can be deduplicated with set().""" - return hash((self.name,)) - - def __eq__(self, other: Any) -> bool: - """Make device object comparable so the object can be deduplicated with set().""" - result = False - - if isinstance(other, HyperglassModel): - result = self.name == other.name - - return result - - @property - def _target(self): - return str(self.address) - - @validator("address") - def validate_address(cls, value, values): - """Ensure a hostname is resolvable.""" - if not isinstance(value, (IPv4Address, IPv6Address)): - if not any(resolve_hostname(value)): - raise ConfigError( - "Device '{d}' has an address of '{a}', which is not resolvable.", - d=values["name"], - a=value, - ) - return value - - @validator("structured_output", pre=True, always=True) - def validate_structured_output(cls, value: bool, values: Dict) -> bool: - """Validate structured output is supported on the device & set a default.""" - - if value is True and values["nos"] not in SUPPORTED_STRUCTURED_OUTPUT: - raise ConfigError( - "The 'structured_output' field is set to 'true' on device '{d}' with " - + "NOS '{n}', which does not support structured output", - d=values["name"], - n=values["nos"], - ) - - elif value is None and values["nos"] in SUPPORTED_STRUCTURED_OUTPUT: - value = True - else: - value = False - - return value - - @validator("ssl") - def validate_ssl(cls, value, values): - """Set default cert file location if undefined. - - Arguments: - value {object} -- SSL object - values {dict} -- Other already-validated fields - - Returns: - {object} -- SSL configuration - """ - if value is not None: - if value.enable and value.cert is None: - app_path = Path(os.environ["hyperglass_directory"]) - cert_file = app_path / "certs" / f'{values["name"]}.pem' - if not cert_file.exists(): - log.warning("No certificate found for device {d}", d=values["name"]) - cert_file.touch() - value.cert = cert_file - return value - - @root_validator(pre=True) - def validate_nos_commands(cls, values: "Device") -> "Device": - """Validate & rewrite NOS, set default commands.""" - - nos = values.get("nos", "") - if not nos: - # Ensure nos is defined. - raise ValueError( - f'Device {values["name"]} is missing a `nos` (Network Operating System).' - ) - - if nos in SCRAPE_HELPERS.keys(): - # Rewrite NOS to helper value if needed. - nos = SCRAPE_HELPERS[nos] - - # Verify NOS is supported by hyperglass. - supported, _ = validate_nos(nos) - if not supported: - raise UnsupportedDevice('"{nos}" is not supported.', nos=nos) - - values["nos"] = nos - - commands = values.get("commands") - - if commands is None: - # If no commands are defined, set commands to the NOS. - inferred = values["nos"] - - # If the _telnet prefix is added, remove it from the command - # profile so the commands are the same regardless of - # protocol. - if "_telnet" in inferred: - inferred = inferred.replace("_telnet", "") - - values["commands"] = inferred - - return values - - @validator("vrfs", pre=True) - def validate_vrfs(cls, value, values): - """Validate VRF definitions. - - - Ensures source IP addresses are set for the default VRF - (global routing table). - - Initializes the default VRF with the DefaultVRF() class so - that specific defaults can be set for the global routing - table. - - If the 'display_name' is not set for a non-default VRF, try - to make one that looks pretty based on the 'name'. - - Arguments: - value {list} -- List of VRFs - values {dict} -- Other already-validated fields - - Raises: - ConfigError: Raised if the VRF is missing a source address - - Returns: - {list} -- List of valid VRFs - """ - vrfs = [] - for vrf in value: - vrf_default = vrf.get("default", False) - - for afi in ("ipv4", "ipv6"): - vrf_afi = vrf.get(afi) - - # If AFI is actually defined (enabled), and if the - # source_address field is not set, raise an error - if vrf_afi is not None and vrf_afi.get("source_address") is None: - raise ConfigError( - ( - "VRF '{vrf}' in router '{router}' is missing a source " - "{afi} address." - ), - vrf=vrf.get("name"), - router=values.get("name"), - afi=afi.replace("ip", "IP"), - ) - - # If no display_name is set for a non-default VRF, try - # to make one by replacing non-alphanumeric characters - # with whitespaces and using str.title() to make each - # word look "pretty". - if not vrf_default and not isinstance(vrf.get("display_name"), str): - new_name = vrf["name"] - new_name = re.sub(r"[^a-zA-Z0-9]", " ", new_name) - new_name = re.split(" ", new_name) - vrf["display_name"] = " ".join([w.title() for w in new_name]) - - log.debug( - f'Field "display_name" for VRF "{vrf["name"]}" was not set. ' - f"Generated '{vrf['display_name']}'" - ) - - elif vrf_default and vrf.get("display_name") is None: - vrf["display_name"] = "Global" - - # Validate the non-default VRF against the standard - # Vrf() class. - vrf = Vrf(**vrf) - - vrfs.append(vrf) - return vrfs - - @validator("driver") - def validate_driver(cls, value: Optional[str], values: Dict) -> Dict: - """Set the correct driver and override if supported.""" - return get_driver(values["nos"], value) - - -class Devices(HyperglassModelExtra): - """Validation model for device configurations.""" - - _ids: List[StrictStr] = [] - hostnames: List[StrictStr] = [] - vrfs: List[StrictStr] = [] - display_vrfs: List[StrictStr] = [] - vrf_objects: List[Vrf] = [] - objects: List[Device] = [] - all_nos: List[StrictStr] = [] - default_vrf: Vrf = Vrf(name="default", display_name="Global") - - def __init__(self, input_params: List[Dict]) -> None: - """Import loaded YAML, initialize per-network definitions. - - Remove unsupported characters from device names, dynamically - set attributes for the devices class. Builds lists of common - attributes for easy access in other modules. - - Arguments: - input_params {dict} -- Unvalidated router definitions - - Returns: - {object} -- Validated routers object - """ - vrfs = set() - display_vrfs = set() - vrf_objects = set() - all_nos = set() - objects = set() - hostnames = set() - _ids = set() - - init_kwargs = {} - - for definition in input_params: - # Validate each router config against Router() model/schema - device = Device(**definition) - - # Add router-level attributes (assumed to be unique) to - # class lists, e.g. so all hostnames can be accessed as a - # list with `devices.hostnames`, same for all router - # classes, for when iteration over all routers is required. - hostnames.add(device.name) - _ids.add(device._id) - objects.add(device) - all_nos.add(device.commands) - - for vrf in device.vrfs: - - # For each configured router VRF, add its name and - # display_name to a class set (for automatic de-duping). - vrfs.add(vrf.name) - display_vrfs.add(vrf.display_name) - - # Also add the names to a router-level list so each - # router's VRFs and display VRFs can be easily accessed. - device.display_vrfs.append(vrf.display_name) - device.vrf_names.append(vrf.name) - - # Add a 'default_vrf' attribute to the devices class - # which contains the configured default VRF display name. - if vrf.name == "default" and not hasattr(self, "default_vrf"): - init_kwargs["default_vrf"] = Vrf( - name=vrf.name, display_name=vrf.display_name - ) - - # Add the native VRF objects to a set (for automatic - # de-duping), but exlcude device-specific fields. - vrf_objects.add( - vrf.copy( - deep=True, - exclude={ - "ipv4": {"source_address"}, - "ipv6": {"source_address"}, - }, - ) - ) - - # Convert the de-duplicated sets to a standard list, add lists - # as class attributes. Sort router list by router name attribute - init_kwargs["_ids"] = list(_ids) - init_kwargs["hostnames"] = list(hostnames) - init_kwargs["all_nos"] = list(all_nos) - init_kwargs["vrfs"] = list(vrfs) - init_kwargs["display_vrfs"] = list(vrfs) - init_kwargs["vrf_objects"] = list(vrf_objects) - init_kwargs["objects"] = sorted(objects, key=lambda x: x.name) - - super().__init__(**init_kwargs) - - def __getitem__(self, accessor: str) -> Device: - """Get a device by its name.""" - for device in self.objects: - if device._id == accessor: - return device - elif device.name == accessor: - return device - - raise AttributeError(f"No device named '{accessor}'") diff --git a/hyperglass/models/config/docs.py b/hyperglass/models/config/docs.py deleted file mode 100644 index abb2883..0000000 --- a/hyperglass/models/config/docs.py +++ /dev/null @@ -1,116 +0,0 @@ -"""Configuration for API docs feature.""" -# Third Party -from pydantic import Field, HttpUrl, StrictStr, StrictBool, constr - -# Local -from ..main import HyperglassModel -from ..fields import AnyUri - -DocsMode = constr(regex=r"(swagger|redoc)") - - -class EndpointConfig(HyperglassModel): - """Validation model for per API endpoint documentation.""" - - title: StrictStr = Field( - ..., - title="Endpoint Title", - description="Displayed as the header text above the API endpoint section.", - ) - description: StrictStr = Field( - ..., - title="Endpoint Description", - description="Displayed inside each API endpoint section.", - ) - summary: StrictStr = Field( - ..., - title="Endpoint Summary", - description="Displayed beside the API endpoint URI.", - ) - - -class Docs(HyperglassModel): - """Validation model for params.docs.""" - - enable: StrictBool = Field( - True, title="Enable", description="Enable or disable API documentation." - ) - mode: DocsMode = Field( - "redoc", - title="Docs Mode", - description="OpenAPI UI library to use for the hyperglass API docs. Currently, the options are [Swagger UI](/fixme) and [Redoc](/fixme).", - ) - base_url: HttpUrl = Field( - "https://lg.example.net", - title="Base URL", - description="Base URL used in request samples.", - ) - uri: AnyUri = Field( - "/api/docs", - title="URI", - description="HTTP URI/path where API documentation can be accessed.", - ) - openapi_uri: AnyUri = Field( - "/openapi.json", - title="OpenAPI URI", - description="Path to the automatically generated `openapi.json` file.", - ) - title: StrictStr = Field( - "{site_title} API Documentation", - title="Title", - description="API documentation title. `{site_title}` may be used to display the `site_title` parameter.", - ) - description: StrictStr = Field( - "", - title="Description", - description="API documentation description appearing below the title.", - ) - query: EndpointConfig = EndpointConfig( - title="Submit Query", - description="Request a query response per-location.", - summary="Query the Looking Glass", - ) - devices: EndpointConfig = EndpointConfig( - title="Devices", - description="List of all devices/locations with associated identifiers, display names, networks, & VRFs.", - summary="Devices List", - ) - queries: EndpointConfig = EndpointConfig( - title="Supported Queries", - description="List of supported query types.", - summary="Query Types", - ) - communities: EndpointConfig = EndpointConfig( - title="BGP Communities", - description="List of BGP communities.", - summary="BGP Communities List", - ) - info: EndpointConfig = EndpointConfig( - title="System Information", - description="General information about this looking glass.", - summary="System Information", - ) - - class Config: - """Pydantic model configuration.""" - - title = "API Docs" - description = "API documentation configuration parameters" - fields = { - "query": { - "title": "Query API Endpoint", - "description": "`/api/query/` API documentation options.", - }, - "devices": { - "title": "Devices API Endpoint", - "description": "`/api/devices` API documentation options.", - }, - "queries": { - "title": "Queries API Endpoint", - "description": "`/api/devices` API documentation options.", - }, - "communities": { - "title": "BGP Communities API Endpoint", - "description": "`/api/communities` API documentation options.", - }, - } diff --git a/hyperglass/models/config/logging.py b/hyperglass/models/config/logging.py deleted file mode 100644 index db718eb..0000000 --- a/hyperglass/models/config/logging.py +++ /dev/null @@ -1,109 +0,0 @@ -"""Validate logging configuration.""" - -# Standard Library -import base64 -from ast import literal_eval -from typing import Dict, Union, Optional -from pathlib import Path - -# Third Party -from pydantic import ( - ByteSize, - SecretStr, - StrictInt, - StrictStr, - AnyHttpUrl, - StrictBool, - StrictFloat, - DirectoryPath, - constr, - validator, -) - -# Project -from hyperglass.constants import __version__ - -# Local -from ..main import HyperglassModel, HyperglassModelExtra - -HttpAuthMode = constr(regex=r"(basic|api_key)") -HttpProvider = constr(regex=r"(msteams|slack|generic)") -LogFormat = constr(regex=r"(text|json)") - - -class Syslog(HyperglassModel): - """Validation model for syslog configuration.""" - - enable: StrictBool = True - host: StrictStr - port: StrictInt = 514 - - -class HttpAuth(HyperglassModel): - """HTTP hook authentication parameters.""" - - mode: HttpAuthMode = "basic" - username: Optional[StrictStr] - password: SecretStr - - def api_key(self, header_name="X-API-Key"): - """Represent authentication as an API key header.""" - return {header_name: self.password.get_secret_value()} - - def basic(self): - """Represent HTTP basic authentication.""" - return (self.username, self.password.get_secret_value()) - - -class Http(HyperglassModelExtra): - """HTTP logging parameters.""" - - enable: StrictBool = True - provider: HttpProvider = "generic" - host: AnyHttpUrl - authentication: Optional[HttpAuth] - headers: Dict[StrictStr, Union[StrictStr, StrictInt, StrictBool, None]] = {} - params: Dict[StrictStr, Union[StrictStr, StrictInt, StrictBool, None]] = {} - verify_ssl: StrictBool = True - timeout: Union[StrictFloat, StrictInt] = 5.0 - - @validator("headers", "params") - def stringify_headers_params(cls, value): - """Ensure headers and URL parameters are strings.""" - for k, v in value.items(): - if not isinstance(v, str): - value[k] = str(v) - return value - - def __init__(self, **kwargs): - """Initialize model, add obfuscated connection details as attribute.""" - super().__init__(**kwargs) - dumped = { - "headers": self.headers, - "params": self.params, - "verify": self.verify_ssl, - "timeout": self.timeout, - } - dumped["headers"].update({"user-agent": f"hyperglass/{__version__}"}) - - if self.authentication is not None: - if self.authentication.mode == "api_key": - dumped["headers"].update(self.authentication.api_key()) - else: - dumped["auth"] = self.authentication.basic() - - self._obscured_params = base64.encodestring(str(dumped).encode()) - - def decoded(self): - """Decode connection details.""" - return literal_eval(base64.decodestring(self._obscured_params).decode()) - - -class Logging(HyperglassModel): - """Validation model for logging configuration.""" - - directory: DirectoryPath = Path("/tmp") # noqa: S108 - format: LogFormat = "text" - max_size: ByteSize = "50MB" - syslog: Optional[Syslog] - http: Optional[Http] diff --git a/hyperglass/models/config/messages.py b/hyperglass/models/config/messages.py deleted file mode 100644 index 86ab546..0000000 --- a/hyperglass/models/config/messages.py +++ /dev/null @@ -1,93 +0,0 @@ -"""Validate error message configuration variables.""" - -# Third Party -from pydantic import Field, StrictStr - -# Local -from ..main import HyperglassModel - - -class Messages(HyperglassModel): - """Validation model for params.messages.""" - - no_input: StrictStr = Field( - "{field} must be specified.", - title="No Input", - description="Displayed when no a required field is not specified. `{field}` may be used to display the `display_name` of the field that was omitted.", - ) - acl_denied: StrictStr = Field( - "{target} is a member of {denied_network}, which is not allowed.", - title="ACL - Denied", - description="Displayed when a query target is explicitly denied by a matched VRF's ACL entry. `{target}` and `{denied_network}` may be used to display the denied query target and the ACL entry that caused it to be denied.", - ) - acl_not_allowed: StrictStr = Field( - "{target} is not allowed.", - title="ACL - Not Allowed", - description="Displayed when a query target is implicitly denied by a matched VRF's ACL. `{target}` may be used to display the denied query target.", - ) - feature_not_enabled: StrictStr = Field( - "{feature} is not enabled.", - title="Feature Not Enabled", - description="Displayed when a query type is submitted that is not supported or disabled. The hyperglass UI performs validation of supported query types prior to submitting any requests, so this is primarily relevant to the hyperglass API. `{feature}` may be used to display the disabled feature.", - ) - invalid_input: StrictStr = Field( - "{target} is not a valid {query_type} target.", - title="Invalid Input", - description="Displayed when a query target's value is invalid in relation to the corresponding query type. `{target}` and `{query_type}` maybe used to display the invalid target and corresponding query type.", - ) - invalid_field: StrictStr = Field( - "{input} is an invalid {field}.", - title="Invalid Field", - description="Displayed when a query field contains an invalid or unsupported value. `{input}` and `{field}` may be used to display the invalid input value and corresponding field name.", - ) - general: StrictStr = Field( - "Something went wrong.", - title="General Error", - description="Displayed when generalized errors occur. Seeing this error message may indicate a bug in hyperglass, as most other errors produced are highly contextual. If you see this in the wild, try enabling [debug mode](/fixme) and review the logs to pinpoint the source of the error.", - ) - request_timeout: StrictStr = Field( - "Request timed out.", - title="Request Timeout", - description="Displayed when the [request_timeout](/fixme) time expires.", - ) - connection_error: StrictStr = Field( - "Error connecting to {device_name}: {error}", - title="Displayed when hyperglass is unable to connect to a configured device. Usually, this indicates a configuration error. `{device_name}` and `{error}` may be used to display the device in question and the specific connection error.", - ) - authentication_error: StrictStr = Field( - "Authentication error occurred.", - title="Authentication Error", - description="Displayed when hyperglass is unable to authenticate to a configured device. Usually, this indicates a configuration error.", - ) - no_response: StrictStr = Field( - "No response.", - title="No Response", - description="Displayed when hyperglass can connect to a device, but no output able to be read. Seeing this error may indicate a bug in hyperglas or one of its dependencies. If you see this in the wild, try enabling [debug mode](/fixme) and review the logs to pinpoint the source of the error.", - ) - vrf_not_associated: StrictStr = Field( - "VRF {vrf_name} is not associated with {device_name}.", - title="VRF Not Associated", - description="Displayed when a query request's VRF field value contains a VRF that is not configured or associated with the corresponding location/device. The hyperglass UI automatically filters out VRFs that are not configured on a selected device, so this error is most likely to appear when using the hyperglass API. `{vrf_name}` and `{device_name}` may be used to display the VRF in question and corresponding device.", - ) - vrf_not_found: StrictStr = Field( - "VRF {vrf_name} is not defined.", - title="VRF Not Found", - description="Displayed when a query VRF is not configured on any devices. The hyperglass UI only shows configured VRFs, so this error is most likely to appear when using the hyperglass API. `{vrf_name}` may be used to display the VRF in question.", - ) - no_output: StrictStr = Field( - "The query completed, but no matching results were found.", - title="No Output", - description="Displayed when hyperglass can connect to a device and execute a query, but the response is empty.", - ) - parsing_error: StrictStr = Field( - "An error occurred while parsing the query output.", - title="Parsing Error", - description="Displayed when hyperglass can connect to a device and execute a query, but the response cannot be parsed.", - ) - - class Config: - """Pydantic model configuration.""" - - title = "Messages" - description = "Customize almost all user-facing UI & API messages." - schema_extra = {"level": 2} diff --git a/hyperglass/models/config/network.py b/hyperglass/models/config/network.py deleted file mode 100644 index 0248c46..0000000 --- a/hyperglass/models/config/network.py +++ /dev/null @@ -1,22 +0,0 @@ -"""Validate network configuration variables.""" - -# Third Party -from pydantic import Field, StrictStr - -# Local -from ..main import HyperglassModel - - -class Network(HyperglassModel): - """Validation Model for per-network/asn config in devices.yaml.""" - - name: StrictStr = Field( - ..., - title="Network Name", - description="Internal name of the device's primary network.", - ) - display_name: StrictStr = Field( - ..., - title="Network Display Name", - description="Display name of the device's primary network.", - ) diff --git a/hyperglass/models/config/opengraph.py b/hyperglass/models/config/opengraph.py deleted file mode 100644 index e80947f..0000000 --- a/hyperglass/models/config/opengraph.py +++ /dev/null @@ -1,40 +0,0 @@ -"""Validate OpenGraph Configuration Parameters.""" - -# Standard Library -import os -from pathlib import Path - -# Third Party -from pydantic import FilePath, validator - -# Local -from ..main import HyperglassModel - -CONFIG_PATH = Path(os.environ["hyperglass_directory"]) -DEFAULT_IMAGES = Path(__file__).parent.parent.parent / "images" - - -class OpenGraph(HyperglassModel): - """Validation model for params.opengraph.""" - - image: FilePath = DEFAULT_IMAGES / "hyperglass-opengraph.jpg" - - @validator("image") - def validate_opengraph(cls, value): - """Ensure the opengraph image is a supported format. - - Arguments: - value {FilePath} -- Path to opengraph image file. - - Returns: - {Path} -- Opengraph image file path object - """ - supported_extensions = (".jpg", ".jpeg", ".png") - if value is not None and value.suffix not in supported_extensions: - raise ValueError( - "OpenGraph image must be one of {e}".format( - e=", ".join(supported_extensions) - ) - ) - - return value diff --git a/hyperglass/models/config/params.py b/hyperglass/models/config/params.py deleted file mode 100644 index dc35064..0000000 --- a/hyperglass/models/config/params.py +++ /dev/null @@ -1,185 +0,0 @@ -"""Configuration validation entry point.""" - -# Standard Library -from typing import List, Union, Optional -from ipaddress import ip_address - -# Third Party -from pydantic import ( - Field, - StrictInt, - StrictStr, - StrictBool, - IPvAnyAddress, - constr, - validator, -) - -# Local -from .web import Web -from .docs import Docs -from ..main import HyperglassModel -from .cache import Cache -from ..fields import IntFloat -from .logging import Logging -from .queries import Queries -from .messages import Messages -from .structured import Structured - -Localhost = constr(regex=r"localhost") - - -class Params(HyperglassModel): - """Validation model for all configuration variables.""" - - # Top Level Params - debug: StrictBool = Field( - False, - title="Debug", - description="Enable debug mode. Warning: this will generate a *lot* of log output.", - ) - developer_mode: StrictBool = Field( - False, - title="Developer Mode", - description='Enable developer mode. If enabled, the hyperglass backend (Python) and frontend (React/Javascript) applications are "unlinked", so that React tools can be used for front end development. A `` convenience component is also displayed in the UI for easier UI development.', - ) - fake_output: StrictBool = Field( - False, - title="Fake Output", - description="If enabled, the hyperglass backend will return static fake output for development/testing purposes.", - ) - primary_asn: Union[StrictInt, StrictStr] = Field( - "65001", - title="Primary ASN", - description="Your network's primary ASN. This field is used to set some useful defaults such as the subtitle and PeeringDB URL.", - ) - org_name: StrictStr = Field( - "Beloved Hyperglass User", - title="Organization Name", - description="Your organization's name. This field is used in the UI & API documentation to set fields such as `` HTML tags for SEO and the terms & conditions footer component.", - ) - site_title: StrictStr = Field( - "hyperglass", - title="Site Title", - description="The name of your hyperglass site. This field is used in the UI & API documentation to set fields such as the `` HTML tag, and the terms & conditions footer component.", - ) - site_description: StrictStr = Field( - "{org_name} Network Looking Glass", - title="Site Description", - description='A short description of your hyperglass site. This field is used in th UI & API documentation to set the `<meta name="description"/>` tag. `{org_name}` may be used to insert the value of the `org_name` field.', - ) - site_keywords: List[StrictStr] = Field( - [ - "hyperglass", - "looking glass", - "lg", - "peer", - "peering", - "ip", - "ipv4", - "ipv6", - "transit", - "community", - "communities", - "bgp", - "routing", - "network", - "isp", - "internet service provider", - ], - title="Site Keywords", - description='Keywords pertaining to your hyperglass site. This field is used to generate `<meta name="keywords"/>` HTML tags, which helps tremendously with SEO.', - ) - request_timeout: StrictInt = Field( - 90, - title="Request Timeout", - description="Global timeout in seconds for all requests. The frontend application (UI) uses this field's exact value when submitting queries. The backend application uses this field's value, minus one second, for its own timeout handling. This is to ensure a contextual timeout error is presented to the end user in the event of a backend application timeout.", - ) - listen_address: Optional[Union[IPvAnyAddress, Localhost]] = Field( - None, - title="Listen Address", - description="Local IP Address or hostname the hyperglass application listens on to serve web traffic.", - ) - listen_port: StrictInt = Field( - 8001, - title="Listen Port", - description="Local TCP port the hyperglass application listens on to serve web traffic.", - ) - cors_origins: List[StrictStr] = Field( - [], - title="Cross-Origin Resource Sharing", - description="Allowed CORS hosts. By default, no CORS hosts are allowed.", - ) - netmiko_delay_factor: IntFloat = Field( - 0.1, - title="Netmiko Delay Factor", - description="Override the netmiko global delay factor.", - ) - google_analytics: Optional[StrictStr] - - # Sub Level Params - cache: Cache = Cache() - docs: Docs = Docs() - logging: Logging = Logging() - messages: Messages = Messages() - queries: Queries = Queries() - structured: Structured = Structured() - web: Web = Web() - - class Config: - """Pydantic model configuration.""" - - schema_extra = {"level": 1} - - @validator("listen_address", pre=True, always=True) - def validate_listen_address(cls, value, values): - """Set default listen_address based on debug mode. - - Arguments: - value {str|IPvAnyAddress|None} -- listen_address - values {dict} -- already-validated entries before listen_address - - Returns: - {str} -- Validated listen_address - """ - if value is None and not values["debug"]: - listen_address = ip_address("127.0.0.1") - elif value is None and values["debug"]: - listen_address = ip_address("0.0.0.0") # noqa: S104 - elif isinstance(value, str) and value != "localhost": - try: - listen_address = ip_address(value) - except ValueError: - raise ValueError(str(value)) - elif isinstance(value, str) and value == "localhost": - listen_address = ip_address("127.0.0.1") - else: - raise ValueError(str(value)) - return listen_address - - @validator("site_description") - def validate_site_description(cls, value, values): - """Format the site descripion with the org_name field. - - Arguments: - value {str} -- site_description - values {str} -- Values before site_description - - Returns: - {str} -- Formatted description - """ - return value.format(org_name=values["org_name"]) - - @validator("primary_asn") - def validate_primary_asn(cls, value): - """Stringify primary_asn if passed as an integer. - - Arguments: - value {str|int} -- Unvalidated Primary ASN - - Returns: - {str} -- Stringified Primary ASN. - """ - if not isinstance(value, str): - value = str(value) - return value diff --git a/hyperglass/models/config/proxy.py b/hyperglass/models/config/proxy.py deleted file mode 100644 index fbaec0c..0000000 --- a/hyperglass/models/config/proxy.py +++ /dev/null @@ -1,58 +0,0 @@ -"""Validate SSH proxy configuration variables.""" - -# Standard Library -from typing import Union -from ipaddress import IPv4Address, IPv6Address - -# Third Party -from pydantic import StrictInt, StrictStr, validator - -# Project -from hyperglass.util import resolve_hostname -from hyperglass.exceptions import ConfigError, UnsupportedDevice - -# Local -from ..main import HyperglassModel -from .credential import Credential - - -class Proxy(HyperglassModel): - """Validation model for per-proxy config in devices.yaml.""" - - name: StrictStr - address: Union[IPv4Address, IPv6Address, StrictStr] - port: StrictInt = 22 - credential: Credential - nos: StrictStr = "linux_ssh" - - @property - def _target(self): - return str(self.address) - - @validator("address") - def validate_address(cls, value, values): - """Ensure a hostname is resolvable.""" - if not isinstance(value, (IPv4Address, IPv6Address)): - if not any(resolve_hostname(value)): - raise ConfigError( - "Device '{d}' has an address of '{a}', which is not resolvable.", - d=values["name"], - a=value, - ) - return value - - @validator("nos") - def supported_nos(cls, value, values): - """Verify NOS is supported by hyperglass. - - Raises: - UnsupportedDevice: Raised if NOS is not supported. - - Returns: - {str} -- Valid NOS name - """ - if not value == "linux_ssh": - raise UnsupportedDevice( - f"Proxy '{values['name']}' uses NOS '{value}', which is currently unsupported." - ) - return value diff --git a/hyperglass/models/config/queries.py b/hyperglass/models/config/queries.py deleted file mode 100644 index dfe3b53..0000000 --- a/hyperglass/models/config/queries.py +++ /dev/null @@ -1,235 +0,0 @@ -"""Validate query configuration parameters.""" - -# Standard Library -from typing import List - -# Third Party -from pydantic import Field, StrictStr, StrictBool, constr - -# Project -from hyperglass.constants import SUPPORTED_QUERY_TYPES - -# Local -from ..main import HyperglassModel - -ASPathMode = constr(regex=r"asplain|asdot") -CommunityInput = constr(regex=r"(input|select)") - - -class BgpCommunityPattern(HyperglassModel): - """Validation model for bgp_community regex patterns.""" - - decimal: StrictStr = Field( - r"^[0-9]{1,10}$", - title="Decimal Community", - description="Regular expression pattern for validating decimal type BGP Community strings.", - ) - extended_as: StrictStr = Field( - r"^([0-9]{0,5})\:([0-9]{1,5})$", - title="Extended AS Community", - description="Regular expression pattern for validating extended AS type BGP Community strings, e.g. `65000:1`", - ) - large: StrictStr = Field( - r"^([0-9]{1,10})\:([0-9]{1,10})\:[0-9]{1,10}$", - title="Large Community", - description="Regular expression pattern for validating large community strings, e.g. `65000:65001:65002`", - ) - - class Config: - """Pydantic model configuration.""" - - title = "Pattern" - description = ( - "Regular expression patterns used to validate BGP Community queries." - ) - - -class BgpAsPathPattern(HyperglassModel): - """Validation model for bgp_aspath regex patterns.""" - - mode: ASPathMode = Field( - "asplain", - title="AS Path Mode", - description="Set ASN display mode. This field is dependent on how your network devices are configured.", - ) - asplain: StrictStr = Field( - r"^(\^|^\_)(\d+\_|\d+\$|\d+\(\_\.\+\_\))+$", - title="AS Plain", - description="Regular expression pattern for validating [AS Plain](/fixme) type BGP AS Path queries.", - ) - asdot: StrictStr = Field( - r"^(\^|^\_)((\d+\.\d+)\_|(\d+\.\d+)\$|(\d+\.\d+)\(\_\.\+\_\))+$", - title="AS Dot", - description="Regular expression pattern for validating [AS Dot](/fixme) type BGP AS Path queries.", - ) - - class Config: - """Pydantic model configuration.""" - - title = "Pattern" - description = ( - "Regular expression patterns used to validate BGP AS Path queries." - ) - - -class Community(HyperglassModel): - """Validation model for bgp_community communities.""" - - display_name: StrictStr - description: StrictStr - community: StrictStr - - -class BgpCommunity(HyperglassModel): - """Validation model for bgp_community configuration.""" - - enable: StrictBool = Field( - True, - title="Enable", - description="Enable or disable the BGP Community query type.", - ) - display_name: StrictStr = Field( - "BGP Community", - title="Display Name", - description="Text displayed for the BGP Community query type in the hyperglas UI.", - ) - pattern: BgpCommunityPattern = BgpCommunityPattern() - mode: CommunityInput = "input" - communities: List[Community] = [] - - -class BgpRoute(HyperglassModel): - """Validation model for bgp_route configuration.""" - - enable: StrictBool = Field( - True, title="Enable", description="Enable or disable the BGP Route query type." - ) - display_name: StrictStr = Field( - "BGP Route", - title="Display Name", - description="Text displayed for the BGP Route query type in the hyperglas UI.", - ) - - -class BgpAsPath(HyperglassModel): - """Validation model for bgp_aspath configuration.""" - - enable: StrictBool = Field( - True, - title="Enable", - description="Enable or disable the BGP AS Path query type.", - ) - display_name: StrictStr = Field( - "BGP AS Path", - title="Display Name", - description="Text displayed for the BGP AS Path query type in the hyperglas UI.", - ) - pattern: BgpAsPathPattern = BgpAsPathPattern() - - -class Ping(HyperglassModel): - """Validation model for ping configuration.""" - - enable: StrictBool = Field( - True, title="Enable", description="Enable or disable the Ping query type." - ) - display_name: StrictStr = Field( - "Ping", - title="Display Name", - description="Text displayed for the Ping query type in the hyperglas UI.", - ) - - -class Traceroute(HyperglassModel): - """Validation model for traceroute configuration.""" - - enable: StrictBool = Field( - True, title="Enable", description="Enable or disable the Traceroute query type." - ) - display_name: StrictStr = Field( - "Traceroute", - title="Display Name", - description="Text displayed for the Traceroute query type in the hyperglas UI.", - ) - - -class Queries(HyperglassModel): - """Validation model for all query types.""" - - @property - def map(self): - """Return a dict of all query display names, internal names, and enable state. - - Returns: - {dict} -- Dict of queries. - """ - _map = {} - for query in SUPPORTED_QUERY_TYPES: - query_obj = getattr(self, query) - _map[query] = { - "name": query, - **query_obj.export_dict( - include={"display_name", "enable", "mode", "communities"} - ), - } - return _map - - @property - def list(self): - """Return a list of all query display names, internal names, and enable state. - - Returns: - {list} -- Dict of queries. - """ - _list = [] - for query in SUPPORTED_QUERY_TYPES: - query_obj = getattr(self, query) - _list.append( - { - "name": query, - "display_name": query_obj.display_name, - "enable": query_obj.enable, - } - ) - return _list - - bgp_route: BgpRoute = BgpRoute() - bgp_community: BgpCommunity = BgpCommunity() - bgp_aspath: BgpAsPath = BgpAsPath() - ping: Ping = Ping() - traceroute: Traceroute = Traceroute() - - def __getitem__(self, query_type: str): - """Get a query's object by name.""" - if hasattr(self, query_type): - return getattr(self, query_type) - - raise AttributeError(f"Query '{query_type}' is invalid") - - class Config: - """Pydantic model configuration.""" - - title = "Queries" - description = "Enable, disable, or configure query types." - fields = { - "bgp_route": { - "title": "BGP Route", - "description": "Enable, disable, or configure the BGP Route query type.", - }, - "bgp_community": { - "title": "BGP Community", - "description": "Enable, disable, or configure the BGP Community query type.", - }, - "bgp_aspath": { - "title": "BGP AS Path", - "description": "Enable, disable, or configure the BGP AS Path query type.", - }, - "ping": { - "title": "Ping", - "description": "Enable, disable, or configure the Ping query type.", - }, - "traceroute": { - "title": "Traceroute", - "description": "Enable, disable, or configure the Traceroute query type.", - }, - } diff --git a/hyperglass/models/config/ssl.py b/hyperglass/models/config/ssl.py deleted file mode 100644 index e9dc32e..0000000 --- a/hyperglass/models/config/ssl.py +++ /dev/null @@ -1,33 +0,0 @@ -"""Validate SSL configuration variables.""" - -# Standard Library -from typing import Optional - -# Third Party -from pydantic import Field, FilePath, StrictBool - -# Local -from ..main import HyperglassModel - - -class Ssl(HyperglassModel): - """Validate SSL config parameters.""" - - enable: StrictBool = Field( - True, - title="Enable SSL", - description="If enabled, hyperglass will use HTTPS to connect to the configured device running [hyperglass-agent](/fixme). If enabled, a certificate file must be specified (hyperglass does not support connecting to a device over an unverified SSL session.)", - ) - cert: Optional[FilePath] - - class Config: - """Pydantic model configuration.""" - - title = "SSL" - description = "SSL configuration for devices running hyperglass-agent." - fields = { - "cert": { - "title": "Certificate", - "description": "Valid path to an SSL certificate. This certificate must be the public key used to serve the hyperglass-agent API on the device running hyperglass-agent.", - } - } diff --git a/hyperglass/models/config/structured.py b/hyperglass/models/config/structured.py deleted file mode 100644 index f3790d4..0000000 --- a/hyperglass/models/config/structured.py +++ /dev/null @@ -1,33 +0,0 @@ -"""Structured data configuration variables.""" - -# Standard Library -from typing import List - -# Third Party -from pydantic import StrictStr, constr - -# Local -from ..main import HyperglassModel - -StructuredCommunityMode = constr(regex=r"(permit|deny)") -StructuredRPKIMode = constr(regex=r"(router|external)") - - -class StructuredCommunities(HyperglassModel): - """Control structured data response for BGP communties.""" - - mode: StructuredCommunityMode = "deny" - items: List[StrictStr] = [] - - -class StructuredRpki(HyperglassModel): - """Control structured data response for RPKI state.""" - - mode: StructuredRPKIMode = "router" - - -class Structured(HyperglassModel): - """Control structured data responses.""" - - communities: StructuredCommunities = StructuredCommunities() - rpki: StructuredRpki = StructuredRpki() diff --git a/hyperglass/models/config/vrf.py b/hyperglass/models/config/vrf.py deleted file mode 100644 index a46666b..0000000 --- a/hyperglass/models/config/vrf.py +++ /dev/null @@ -1,299 +0,0 @@ -"""Validate VRF configuration variables.""" - -# Standard Library -import re -from typing import Dict, List, Union, Optional -from ipaddress import IPv4Address, IPv4Network, IPv6Address, IPv6Network - -# Third Party -from pydantic import ( - Field, - FilePath, - StrictStr, - StrictBool, - PrivateAttr, - conint, - constr, - validator, - root_validator, -) -from typing_extensions import Literal - -# Project -from hyperglass.log import log - -# Local -from ..main import HyperglassModel, HyperglassModelExtra - -ACLAction = constr(regex=r"permit|deny") -AddressFamily = Union[Literal[4], Literal[6]] - - -def find_vrf_id(values: Dict) -> str: - """Generate (private) VRF ID.""" - - def generate_id(name: str) -> str: - scrubbed = re.sub(r"[^A-Za-z0-9\_\-\s]", "", name) - return "_".join(scrubbed.split()).lower() - - display_name = values.get("display_name") - - if display_name is None: - raise ValueError("display_name is required.") - - return generate_id(display_name) - - -class AccessList4(HyperglassModel): - """Validation model for IPv4 access-lists.""" - - network: IPv4Network = Field( - "0.0.0.0/0", - title="Network", - description="IPv4 Network/Prefix that should be permitted or denied. ", - ) - action: ACLAction = Field( - "permit", - title="Action", - description="Permit or deny any networks contained within the prefix.", - ) - ge: conint(ge=0, le=32) = Field( - 0, - title="Greater Than or Equal To", - description="Similar to `ge` in a Cisco prefix-list, the `ge` field defines the **bottom** threshold for prefix size. For example, a value of `24` would result in a query for `192.0.2.0/23` being denied, but a query for `192.0.2.0/32` would be permitted. If this field is set to a value smaller than the `network` field's prefix length, this field's value will be overwritten to the prefix length of the prefix in the `network` field.", - ) - le: conint(ge=0, le=32) = Field( - 32, - title="Less Than or Equal To", - description="Similar to `le` in a Cisco prefix-list, the `le` field defines the **top** threshold for prefix size. For example, a value of `24` would result in a query for `192.0.2.0/23` being permitted, but a query for `192.0.2.0/32` would be denied.", - ) - - @validator("ge") - def validate_model(cls, value, values): - """Ensure ge is at least the size of the input prefix. - - Arguments: - value {int} -- Initial ge value - values {dict} -- Other post-validation fields - - Returns: - {int} -- Validated ge value - """ - net_len = values["network"].prefixlen - if net_len > value: - value = net_len - return value - - -class AccessList6(HyperglassModel): - """Validation model for IPv6 access-lists.""" - - network: IPv6Network = Field( - "::/0", - title="Network", - description="IPv6 Network/Prefix that should be permitted or denied. ", - ) - action: ACLAction = Field( - "permit", - title="Action", - description="Permit or deny any networks contained within the prefix.", - ) - ge: conint(ge=0, le=128) = Field( - 0, - title="Greater Than or Equal To", - description="Similar to `ge` in a Cisco prefix-list, the `ge` field defines the **bottom** threshold for prefix size. For example, a value of `64` would result in a query for `2001:db8::/48` being denied, but a query for `2001:db8::1/128` would be permitted. If this field is set to a value smaller than the `network` field's prefix length, this field's value will be overwritten to the prefix length of the prefix in the `network` field.", - ) - le: conint(ge=0, le=128) = Field( - 128, - title="Less Than or Equal To", - description="Similar to `le` in a Cisco prefix-list, the `le` field defines the **top** threshold for prefix size. For example, a value of `64` would result in a query for `2001:db8::/48` being permitted, but a query for `2001:db8::1/128` would be denied.", - ) - - @validator("ge") - def validate_model(cls, value, values): - """Ensure ge is at least the size of the input prefix. - - Arguments: - value {int} -- Initial ge value - values {dict} -- Other post-validation fields - - Returns: - {int} -- Validated ge value - """ - net_len = values["network"].prefixlen - if net_len > value: - value = net_len - return value - - -class InfoConfigParams(HyperglassModelExtra): - """Validation model for per-help params.""" - - title: Optional[StrictStr] - - class Config: - """Pydantic model configuration.""" - - title = "Help Parameters" - description = "Set dynamic or reusable values which may be used in the help/information content. Params my be access by using Python string formatting syntax, e.g. `{param_name}`. Any arbitrary values may be added." - - -class InfoConfig(HyperglassModel): - """Validation model for help configuration.""" - - enable: StrictBool = True - file: Optional[FilePath] - params: InfoConfigParams = InfoConfigParams() - - class Config: - """Pydantic model configuration.""" - - fields = { - "enable": { - "title": "Enable", - "description": "Enable or disable the display of help/information content for this query type.", - }, - "file": { - "title": "File Name", - "description": "Path to a valid text or Markdown file containing custom content.", - }, - } - - -class Info(HyperglassModel): - """Validation model for per-VRF, per-Command help.""" - - bgp_aspath: InfoConfig = InfoConfig() - bgp_community: InfoConfig = InfoConfig() - bgp_route: InfoConfig = InfoConfig() - ping: InfoConfig = InfoConfig() - traceroute: InfoConfig = InfoConfig() - - class Config: - """Pydantic model configuration.""" - - title = "VRF Information" - description = "Per-VRF help & information content." - fields = { - "bgp_aspath": { - "title": "BGP AS Path", - "description": "Show information about bgp_aspath queries when selected.", - }, - "bgp_community": { - "title": "BGP Community", - "description": "Show information about bgp_community queries when selected.", - }, - "bgp_route": { - "title": "BGP Route", - "description": "Show information about bgp_route queries when selected.", - }, - "ping": { - "title": "Ping", - "description": "Show information about ping queries when selected.", - }, - "traceroute": { - "title": "Traceroute", - "description": "Show information about traceroute queries when selected.", - }, - } - - -class DeviceVrf4(HyperglassModelExtra): - """Validation model for IPv4 AFI definitions.""" - - source_address: IPv4Address - access_list: List[AccessList4] = [AccessList4()] - force_cidr: StrictBool = True - - -class DeviceVrf6(HyperglassModelExtra): - """Validation model for IPv6 AFI definitions.""" - - source_address: IPv6Address - access_list: List[AccessList6] = [AccessList6()] - force_cidr: StrictBool = True - - -class Vrf(HyperglassModel): - """Validation model for per VRF/afi config in devices.yaml.""" - - _id: StrictStr = PrivateAttr() - name: StrictStr - display_name: StrictStr - info: Info = Info() - ipv4: Optional[DeviceVrf4] - ipv6: Optional[DeviceVrf6] - default: StrictBool = False - - def __init__(self, **kwargs) -> None: - """Set the VRF ID.""" - _id = find_vrf_id(kwargs) - super().__init__(**kwargs) - self._id = _id - - @root_validator - def set_dynamic(cls, values: Dict) -> Dict: - """Set dynamic attributes before VRF initialization.""" - - if values["name"] == "default": - log.warning( - """You have set the VRF name to 'default'. This is no longer the way to -designate a VRF as the default (or global routing table) VRF. Instead, -add 'default: true' to the VRF definition. -""" - ) - - if values.get("default", False) is True: - protocol4 = "ipv4_default" - protocol6 = "ipv6_default" - - else: - protocol4 = "ipv4_vpn" - protocol6 = "ipv6_vpn" - - if values.get("ipv4") is not None: - values["ipv4"].protocol = protocol4 - values["ipv4"].version = 4 - - if values.get("ipv6") is not None: - values["ipv6"].protocol = protocol6 - values["ipv6"].version = 6 - - if values.get("default", False) and values.get("display_name") is None: - values["display_name"] = "Global" - - return values - - def __getitem__(self, i: AddressFamily) -> Union[DeviceVrf4, DeviceVrf6]: - """Access the VRF's AFI by IP protocol number.""" - if i not in (4, 6): - raise AttributeError(f"Must be 4 or 6, got '{i}'") - - return getattr(self, f"ipv{i}") - - def __hash__(self) -> int: - """Make VRF object hashable so the object can be deduplicated with set().""" - return hash((self.name,)) - - def __eq__(self, other: object) -> bool: - """Make VRF object comparable so the object can be deduplicated with set().""" - result = False - if isinstance(other, HyperglassModel): - result = self.name == other.name - return result - - class Config: - """Pydantic model configuration.""" - - title = "VRF" - description = "Per-VRF configuration." - fields = { - "name": { - "title": "Name", - "description": "VRF name as configured on the router/device.", - }, - "display_name": { - "title": "Display Name", - "description": "Display name of VRF for use in the hyperglass UI. If none is specified, hyperglass will attempt to generate one.", - }, - } diff --git a/hyperglass/models/config/web.py b/hyperglass/models/config/web.py deleted file mode 100644 index 53d8627..0000000 --- a/hyperglass/models/config/web.py +++ /dev/null @@ -1,260 +0,0 @@ -"""Validate branding configuration variables.""" - -# Standard Library -from typing import Union, Optional, Sequence -from pathlib import Path - -# Third Party -from pydantic import ( - HttpUrl, - FilePath, - StrictInt, - StrictStr, - StrictBool, - constr, - validator, - root_validator, -) -from pydantic.color import Color - -# Project -from hyperglass.defaults import DEFAULT_HELP, DEFAULT_TERMS -from hyperglass.constants import DNS_OVER_HTTPS, FUNC_COLOR_MAP - -# Local -from ..main import HyperglassModel -from .opengraph import OpenGraph - -DEFAULT_IMAGES = Path(__file__).parent.parent.parent / "images" - -Percentage = constr(regex=r"^([1-9][0-9]?|100)\%$") -TitleMode = constr(regex=("logo_only|text_only|logo_title|logo_subtitle|all")) -ColorMode = constr(regex=r"light|dark") -DOHProvider = constr(regex="|".join(DNS_OVER_HTTPS.keys())) -Title = constr(max_length=32) -Side = constr(regex=r"left|right") - - -class Analytics(HyperglassModel): - """Validation model for Google Analytics.""" - - enable: StrictBool = False - id: Optional[StrictStr] - - @validator("id") - def validate_id(cls, value, values): - """Ensure ID is set if analytics is enabled. - - Arguments: - value {str|None} -- Google Analytics ID - values {[type]} -- Already-validated model parameters - - Raises: - ValueError: Raised if analytics is enabled but no ID is set. - - Returns: - {str|None} -- Google Analytics ID if enabled. - """ - if values["enable"] and value is None: - raise ValueError("Analytics is enabled, but no ID is set.") - return value - - -class Credit(HyperglassModel): - """Validation model for developer credit.""" - - enable: StrictBool = True - - -class Link(HyperglassModel): - """Validation model for generic link.""" - - title: StrictStr - url: HttpUrl - show_icon: StrictBool = True - side: Side = "left" - order: StrictInt = 0 - - -class Menu(HyperglassModel): - """Validation model for generic menu.""" - - title: StrictStr - content: StrictStr - side: Side = "left" - order: StrictInt = 0 - - @validator("content") - def validate_content(cls, value): - """Read content from file if a path is provided.""" - - if len(value) < 260: - path = Path(value) - if path.exists(): - with path.open("r") as f: - return f.read() - else: - return value - return value - - -class Greeting(HyperglassModel): - """Validation model for greeting modal.""" - - enable: StrictBool = False - file: Optional[FilePath] - title: StrictStr = "Welcome" - button: StrictStr = "Continue" - required: StrictBool = False - - @validator("file") - def validate_file(cls, value, values): - """Ensure file is specified if greeting is enabled.""" - if values["enable"] and value is None: - raise ValueError("Greeting is enabled, but no file is specified.") - return value - - -class Logo(HyperglassModel): - """Validation model for logo configuration.""" - - light: FilePath = DEFAULT_IMAGES / "hyperglass-light.svg" - dark: FilePath = DEFAULT_IMAGES / "hyperglass-dark.svg" - favicon: FilePath = DEFAULT_IMAGES / "hyperglass-icon.svg" - width: Optional[Union[StrictInt, Percentage]] = "100%" - height: Optional[Union[StrictInt, Percentage]] - - -class Text(HyperglassModel): - """Validation model for params.branding.text.""" - - title_mode: TitleMode = "logo_only" - title: Title = "hyperglass" - subtitle: Title = "Network Looking Glass" - query_location: StrictStr = "Location" - query_type: StrictStr = "Query Type" - query_target: StrictStr = "Target" - query_vrf: StrictStr = "Routing Table" - fqdn_tooltip: StrictStr = "Use {protocol}" # Formatted by Javascript - fqdn_message: StrictStr = "Your browser has resolved {fqdn} to" # Formatted by Javascript - fqdn_error: StrictStr = "Unable to resolve {fqdn}" # Formatted by Javascript - fqdn_error_button: StrictStr = "Try Again" - cache_prefix: StrictStr = "Results cached for " - cache_icon: StrictStr = "Cached from {time} UTC" # Formatted by Javascript - complete_time: StrictStr = "Completed in {seconds}" # Formatted by Javascript - rpki_invalid: StrictStr = "Invalid" - rpki_valid: StrictStr = "Valid" - rpki_unknown: StrictStr = "No ROAs Exist" - rpki_unverified: StrictStr = "Not Verified" - no_communities: StrictStr = "No Communities" - - @validator("title_mode") - def validate_title_mode(cls, value): - """Set legacy logo_title to logo_subtitle.""" - if value == "logo_title": - value = "logo_subtitle" - return value - - @validator("cache_prefix") - def validate_cache_prefix(cls, value): - """Ensure trailing whitespace.""" - return " ".join(value.split()) + " " - - -class ThemeColors(HyperglassModel): - """Validation model for theme colors.""" - - black: Color = "#000000" - white: Color = "#ffffff" - dark: Color = "#010101" - light: Color = "#f5f6f7" - gray: Color = "#c1c7cc" - red: Color = "#d84b4b" - orange: Color = "#ff6b35" - yellow: Color = "#edae49" - green: Color = "#35b246" - blue: Color = "#314cb6" - teal: Color = "#35b299" - cyan: Color = "#118ab2" - pink: Color = "#f2607d" - purple: Color = "#8d30b5" - primary: Optional[Color] - secondary: Optional[Color] - success: Optional[Color] - warning: Optional[Color] - error: Optional[Color] - danger: Optional[Color] - - @validator(*FUNC_COLOR_MAP.keys(), pre=True, always=True) - def validate_colors(cls, value, values, field): - """Set default functional color mapping. - - Arguments: - value {str|None} -- Functional color - values {str} -- Already-validated colors - Returns: - {str} -- Mapped color. - """ - if value is None: - default_color = FUNC_COLOR_MAP[field.name] - value = str(values[default_color]) - return value - - def dict(self, *args, **kwargs): - """Return dict for colors only.""" - return {k: v.as_hex() for k, v in self.__dict__.items()} - - -class ThemeFonts(HyperglassModel): - """Validation model for theme fonts.""" - - body: StrictStr = "Nunito" - mono: StrictStr = "Fira Code" - - -class Theme(HyperglassModel): - """Validation model for theme variables.""" - - colors: ThemeColors = ThemeColors() - default_color_mode: Optional[ColorMode] - fonts: ThemeFonts = ThemeFonts() - - -class DnsOverHttps(HyperglassModel): - """Validation model for DNS over HTTPS resolution.""" - - name: DOHProvider = "cloudflare" - url: StrictStr = "" - - @root_validator - def validate_dns(cls, values): - """Assign url field to model based on selected provider. - - Arguments: - values {dict} -- Dict of selected provider - - Returns: - {dict} -- Dict with url attribute - """ - provider = values["name"] - values["url"] = DNS_OVER_HTTPS[provider] - return values - - -class Web(HyperglassModel): - """Validation model for all web/browser-related configuration.""" - - credit: Credit = Credit() - dns_provider: DnsOverHttps = DnsOverHttps() - links: Sequence[Link] = [ - Link(title="PeeringDB", url="https://www.peeringdb.com/asn/{primary_asn}") - ] - menus: Sequence[Menu] = [ - Menu(title="Terms", content=DEFAULT_TERMS), - Menu(title="Help", content=DEFAULT_HELP), - ] - greeting: Greeting = Greeting() - logo: Logo = Logo() - opengraph: OpenGraph = OpenGraph() - text: Text = Text() - theme: Theme = Theme() diff --git a/hyperglass/models/fields.py b/hyperglass/models/fields.py deleted file mode 100644 index bd4d734..0000000 --- a/hyperglass/models/fields.py +++ /dev/null @@ -1,81 +0,0 @@ -"""Custom Pydantic Fields/Types.""" - -# Standard Library -import re -from typing import TypeVar - -# Third Party -from pydantic import StrictInt, StrictFloat, constr - -IntFloat = TypeVar("IntFloat", StrictInt, StrictFloat) - -SupportedDriver = constr(regex=r"(scrapli|netmiko|hyperglass_agent)") - - -class StrictBytes(bytes): - """Custom data type for a strict byte string. - - Used for validating the encoded JWT request payload. - """ - - @classmethod - def __get_validators__(cls): - """Yield Pydantic validator function. - - See: https://pydantic-docs.helpmanual.io/usage/types/#custom-data-types - - Yields: - {function} -- Validator - """ - yield cls.validate - - @classmethod - def validate(cls, value): - """Validate type. - - Arguments: - value {Any} -- Pre-validated input - - Raises: - TypeError: Raised if value is not bytes - - Returns: - {object} -- Instantiated class - """ - if not isinstance(value, bytes): - raise TypeError("bytes required") - return cls() - - def __repr__(self): - """Return representation of object. - - Returns: - {str} -- Representation - """ - return f"StrictBytes({super().__repr__()})" - - -class AnyUri(str): - """Custom field type for HTTP URI, e.g. /example.""" - - @classmethod - def __get_validators__(cls): - """Pydantic custim field method.""" - yield cls.validate - - @classmethod - def validate(cls, value): - """Ensure URI string contains a leading forward-slash.""" - uri_regex = re.compile(r"^(\/.*)$") - if not isinstance(value, str): - raise TypeError("AnyUri type must be a string") - match = uri_regex.fullmatch(value) - if not match: - raise ValueError( - "Invalid format. A URI must begin with a forward slash, e.g. '/example'" - ) - return cls(match.group()) - - def __repr__(self): - """Stringify custom field representation.""" - return f"AnyUri({super().__repr__()})" diff --git a/hyperglass/models/main.py b/hyperglass/models/main.py deleted file mode 100644 index 7e41a21..0000000 --- a/hyperglass/models/main.py +++ /dev/null @@ -1,99 +0,0 @@ -"""Data models used throughout hyperglass.""" - -# Standard Library -import re - -# Third Party -from pydantic import HttpUrl, BaseModel - -_WEBHOOK_TITLE = "hyperglass received a valid query with the following data" -_ICON_URL = "https://res.cloudinary.com/hyperglass/image/upload/v1593192484/icon.png" - - -def clean_name(_name: str) -> str: - """Remove unsupported characters from field names. - - Converts any "desirable" seperators to underscore, then removes all - characters that are unsupported in Python class variable names. - Also removes leading numbers underscores. - """ - _replaced = re.sub(r"[\-|\.|\@|\~|\:\/|\s]", "_", _name) - _scrubbed = "".join(re.findall(r"([a-zA-Z]\w+|\_+)", _replaced)) - return _scrubbed.lower() - - -class HyperglassModel(BaseModel): - """Base model for all hyperglass configuration models.""" - - class Config: - """Default Pydantic configuration. - - See https://pydantic-docs.helpmanual.io/usage/model_config - """ - - validate_all = True - extra = "forbid" - validate_assignment = True - alias_generator = clean_name - json_encoders = {HttpUrl: lambda v: str(v)} - - def export_json(self, *args, **kwargs): - """Return instance as JSON. - - Returns: - {str} -- Stringified JSON. - """ - - export_kwargs = { - "by_alias": True, - "exclude_unset": False, - **kwargs, - } - - return self.json(*args, **export_kwargs) - - def export_dict(self, *args, **kwargs): - """Return instance as dictionary. - - Returns: - {dict} -- Python dictionary. - """ - export_kwargs = { - "by_alias": True, - "exclude_unset": False, - **kwargs, - } - - return self.dict(*args, **export_kwargs) - - def export_yaml(self, *args, **kwargs): - """Return instance as YAML. - - Returns: - {str} -- Stringified YAML. - """ - # Standard Library - import json - - # Third Party - import yaml - - export_kwargs = { - "by_alias": kwargs.pop("by_alias", True), - "exclude_unset": kwargs.pop("by_alias", False), - } - - return yaml.safe_dump( - json.loads(self.export_json(**export_kwargs)), *args, **kwargs - ) - - -class HyperglassModelExtra(HyperglassModel): - """Model for hyperglass configuration models with dynamic fields.""" - - pass - - class Config: - """Default pydantic configuration.""" - - extra = "allow" diff --git a/hyperglass/models/parsing/__init__.py b/hyperglass/models/parsing/__init__.py deleted file mode 100644 index 9ce8b52..0000000 --- a/hyperglass/models/parsing/__init__.py +++ /dev/null @@ -1 +0,0 @@ -"""Data models for parsed responses.""" diff --git a/hyperglass/models/parsing/arista_eos.py b/hyperglass/models/parsing/arista_eos.py deleted file mode 100644 index 4643457..0000000 --- a/hyperglass/models/parsing/arista_eos.py +++ /dev/null @@ -1,165 +0,0 @@ -"""Data Models for Parsing Arista JSON Response.""" - -# Standard Library -from typing import Dict, List, Optional -from datetime import datetime - -# Project -from hyperglass.log import log - -# Local -from ..main import HyperglassModel -from .serialized import ParsedRoutes - -RPKI_STATE_MAP = { - "invalid": 0, - "valid": 1, - "notFound": 2, - "notValidated": 3, -} - -WINNING_WEIGHT = "high" - - -def _alias_generator(field: str) -> str: - caps = "".join(x for x in field.title() if x.isalnum()) - return caps[0].lower() + caps[1:] - - -class _AristaBase(HyperglassModel): - """Base Model for Arista validation.""" - - class Config: - extra = "ignore" - alias_generator = _alias_generator - - -class AristaAsPathEntry(_AristaBase): - """Validation model for Arista asPathEntry.""" - - as_path_type: str = "External" - as_path: Optional[str] = "" - - -class AristaPeerEntry(_AristaBase): - """Validation model for Arista peerEntry.""" - - peer_router_id: str - peer_addr: str - - -class AristaRouteType(_AristaBase): - """Validation model for Arista routeType.""" - - origin: str - suppressed: bool - valid: bool - active: bool - origin_validity: Optional[str] = "notVerified" - - -class AristaRouteDetail(_AristaBase): - """Validation for Arista routeDetail.""" - - origin: str - label_stack: List = [] - ext_community_list: List[str] = [] - ext_community_list_raw: List[str] = [] - community_list: List[str] = [] - large_community_list: List[str] = [] - - -class AristaRoutePath(_AristaBase): - """Validation model for Arista bgpRoutePaths.""" - - as_path_entry: AristaAsPathEntry - med: int - local_preference: int - weight: int - peer_entry: AristaPeerEntry - reason_not_bestpath: str - timestamp: int = int(datetime.utcnow().timestamp()) - next_hop: str - route_type: AristaRouteType - route_detail: Optional[AristaRouteDetail] - - -class AristaRouteEntry(_AristaBase): - """Validation model for Arista bgpRouteEntries.""" - - total_paths: int = 0 - bgp_advertised_peer_groups: Dict = {} - mask_length: int - bgp_route_paths: List[AristaRoutePath] = [] - - -class AristaRoute(_AristaBase): - """Validation model for Arista bgpRouteEntries data.""" - - router_id: str - vrf: str - bgp_route_entries: Dict[str, AristaRouteEntry] - # The raw value is really a string, but `int` will convert it. - asn: int - - @staticmethod - def _get_route_age(timestamp: int) -> int: - now = datetime.utcnow() - now_timestamp = int(now.timestamp()) - return now_timestamp - timestamp - - @staticmethod - def _get_as_path(as_path: str) -> List[str]: - if as_path == "": - return [] - return [int(p) for p in as_path.split() if p.isdecimal()] - - def serialize(self): - """Convert the Arista-formatted fields to standard parsed data model.""" - routes = [] - count = 0 - for prefix, entries in self.bgp_route_entries.items(): - - count += entries.total_paths - - for route in entries.bgp_route_paths: - - as_path = self._get_as_path(route.as_path_entry.as_path) - rpki_state = RPKI_STATE_MAP.get(route.route_type.origin_validity, 3) - - # BGP AS Path and BGP Community queries do not include the routeDetail - # block. Therefore, we must verify it exists before including its data. - communities = [] - if route.route_detail is not None: - communities = route.route_detail.community_list - - # iBGP paths contain an empty AS_PATH array. If the AS_PATH is empty, we - # set the source_as to the router's local-as. - source_as = self.asn - if len(as_path) != 0: - source_as = as_path[0] - - routes.append( - { - "prefix": prefix, - "active": route.route_type.active, - "age": self._get_route_age(route.timestamp), - "weight": route.weight, - "med": route.med, - "local_preference": route.local_preference, - "as_path": as_path, - "communities": communities, - "next_hop": route.next_hop, - "source_as": source_as, - "source_rid": route.peer_entry.peer_router_id, - "peer_rid": route.peer_entry.peer_router_id, - "rpki_state": rpki_state, - } - ) - - serialized = ParsedRoutes( - vrf=self.vrf, count=count, routes=routes, winning_weight=WINNING_WEIGHT, - ) - - log.debug("Serialized Arista response: {}", serialized) - return serialized diff --git a/hyperglass/models/parsing/arista_route.json b/hyperglass/models/parsing/arista_route.json deleted file mode 100644 index cde5965..0000000 --- a/hyperglass/models/parsing/arista_route.json +++ /dev/null @@ -1,65 +0,0 @@ -{ - "vrfs": { - "default": { - "routerId": "198.18.0.1", - "vrf": "default", - "bgpRouteEntries": { - "198.18.2.0/24": { - "totalPaths": 1, - "bgpAdvertisedPeerGroups": {}, - "maskLength": 24, - "bgpRoutePaths": [ - { - "asPathEntry": { - "asPathType": "External", - "asPath": "65002 65003" - }, - "med": 8675309, - "localPreference": 100, - "weight": 0, - "peerEntry": { - "peerRouterId": "198.18.0.2", - "peerAddr": "198.18.0.2" - }, - "reasonNotBestpath": "noReason", - "timestamp": 1612996830, - "nextHop": "198.18.0.2", - "routeType": { - "atomicAggregator": false, - "origin": "Igp", - "suppressed": false, - "queued": false, - "valid": true, - "ecmpContributor": false, - "luRoute": false, - "active": true, - "stale": false, - "ecmp": false, - "backup": false, - "ecmpHead": false, - "ucmp": false - }, - "routeDetail": { - "origin": "Igp", - "labelStack": [], - "isLeaked": false, - "tunnelRibEligible": false, - "extCommunityList": [], - "extCommunityListRaw": [], - "communityList": ["65002:1"], - "rxSafi": "Unicast", - "bgpContributors": [], - "recvdFromRRClient": false, - "igpMetric": 1, - "largeCommunityList": [], - "domainPath": [] - } - } - ], - "address": "198.18.2.0" - } - }, - "asn": "65001" - } - } -} diff --git a/hyperglass/models/parsing/frr.py b/hyperglass/models/parsing/frr.py deleted file mode 100644 index e9bdd21..0000000 --- a/hyperglass/models/parsing/frr.py +++ /dev/null @@ -1,118 +0,0 @@ -"""Data Models for Parsing FRRouting JSON Response.""" - -# Standard Library -from typing import List -from datetime import datetime - -# Third Party -from pydantic import StrictInt, StrictStr, StrictBool, constr, root_validator - -# Project -from hyperglass.log import log - -# Local -from ..main import HyperglassModel -from .serialized import ParsedRoutes - -FRRPeerType = constr(regex=r"(internal|external)") - - -def _alias_generator(field): - components = field.split("_") - return components[0] + "".join(x.title() for x in components[1:]) - - -class _FRRBase(HyperglassModel): - class Config: - alias_generator = _alias_generator - extra = "ignore" - - -class FRRNextHop(_FRRBase): - """FRR Next Hop Model.""" - - ip: StrictStr - afi: StrictStr - metric: StrictInt - accessible: StrictBool - used: StrictBool - - -class FRRPeer(_FRRBase): - """FRR Peer Model.""" - - peer_id: StrictStr - router_id: StrictStr - type: FRRPeerType - - -class FRRPath(_FRRBase): - """FRR Path Model.""" - - aspath: List[StrictInt] - aggregator_as: StrictInt - aggregator_id: StrictStr - med: StrictInt = 0 - localpref: StrictInt - weight: StrictInt - valid: StrictBool - last_update: StrictInt - bestpath: StrictBool - community: List[StrictStr] - nexthops: List[FRRNextHop] - peer: FRRPeer - - @root_validator(pre=True) - def validate_path(cls, values): - """Extract meaningful data from FRR response.""" - new = values.copy() - new["aspath"] = values["aspath"]["segments"][0]["list"] - new["community"] = values["community"]["list"] - new["lastUpdate"] = values["lastUpdate"]["epoch"] - bestpath = values.get("bestpath", {}) - new["bestpath"] = bestpath.get("overall", False) - return new - - -class FRRRoute(_FRRBase): - """FRR Route Model.""" - - prefix: StrictStr - paths: List[FRRPath] = [] - - def serialize(self): - """Convert the FRR-specific fields to standard parsed data model.""" - - # TODO: somehow, get the actual VRF - vrf = "default" - - routes = [] - for route in self.paths: - now = datetime.utcnow().timestamp() - then = datetime.utcfromtimestamp(route.last_update).timestamp() - age = int(now - then) - routes.append( - { - "prefix": self.prefix, - "active": route.bestpath, - "age": age, - "weight": route.weight, - "med": route.med, - "local_preference": route.localpref, - "as_path": route.aspath, - "communities": route.community, - "next_hop": route.nexthops[0].ip, - "source_as": route.aggregator_as, - "source_rid": route.aggregator_id, - "peer_rid": route.peer.peer_id, - # TODO: somehow, get the actual RPKI state - "rpki_state": 3, - } - ) - - serialized = ParsedRoutes( - vrf=vrf, count=len(routes), routes=routes, winning_weight="high", - ) - - log.info("Serialized FRR response: {}", serialized) - return serialized diff --git a/hyperglass/models/parsing/frr_bgp_community.json b/hyperglass/models/parsing/frr_bgp_community.json deleted file mode 100644 index a28d7ad..0000000 --- a/hyperglass/models/parsing/frr_bgp_community.json +++ /dev/null @@ -1,84 +0,0 @@ -{ - "vrfId": 0, - "vrfName": "default", - "tableVersion": 32856694, - "routerId": "199.34.92.3", - "defaultLocPrf": 100, - "localAS": 14525, - "routes": { - "38.29.214.0/24": [ - { - "valid": true, - "bestpath": true, - "pathFrom": "internal", - "prefix": "38.29.214.0", - "prefixLen": 24, - "network": "38.29.214.0/24", - "med": 0, - "metric": 0, - "localpref": 450, - "locPrf": 450, - "weight": 200, - "peerId": "199.34.92.1", - "aspath": "", - "path": "", - "origin": "IGP", - "nexthops": [{ "ip": "199.34.92.1", "afi": "ipv4", "used": true }] - } - ], - "199.34.92.0/23": [ - { - "valid": true, - "pathFrom": "internal", - "prefix": "199.34.92.0", - "prefixLen": 23, - "network": "199.34.92.0/23", - "med": 0, - "metric": 0, - "localpref": 450, - "locPrf": 450, - "weight": 200, - "peerId": "199.34.92.10", - "aspath": "", - "path": "", - "origin": "IGP", - "nexthops": [{ "ip": "199.34.92.10", "afi": "ipv4", "used": true }] - }, - { - "valid": true, - "pathFrom": "internal", - "prefix": "199.34.92.0", - "prefixLen": 23, - "network": "199.34.92.0/23", - "med": 0, - "metric": 0, - "localpref": 450, - "locPrf": 450, - "weight": 200, - "peerId": "199.34.92.9", - "aspath": "", - "path": "", - "origin": "IGP", - "nexthops": [{ "ip": "199.34.92.9", "afi": "ipv4", "used": true }] - }, - { - "valid": true, - "bestpath": true, - "pathFrom": "internal", - "prefix": "199.34.92.0", - "prefixLen": 23, - "network": "199.34.92.0/23", - "med": 0, - "metric": 0, - "localpref": 450, - "locPrf": 450, - "weight": 200, - "peerId": "199.34.92.1", - "aspath": "", - "path": "", - "origin": "IGP", - "nexthops": [{ "ip": "199.34.92.1", "afi": "ipv4", "used": true }] - } - ] - } -} diff --git a/hyperglass/models/parsing/frr_bgp_route.json b/hyperglass/models/parsing/frr_bgp_route.json deleted file mode 100644 index 90b936d..0000000 --- a/hyperglass/models/parsing/frr_bgp_route.json +++ /dev/null @@ -1,224 +0,0 @@ -{ - "prefix": "1.1.1.0/24", - "paths": [ - { - "aspath": { - "string": "174 13335", - "segments": [ - { - "type": "as-sequence", - "list": [174, 13335] - } - ], - "length": 2 - }, - "aggregatorAs": 13335, - "aggregatorId": "108.162.239.1", - "origin": "IGP", - "med": 25090, - "metric": 25090, - "localpref": 100, - "weight": 100, - "valid": true, - "community": { - "string": "174:21001 174:22003 14525:0 14525:40 14525:1021 14525:2840 14525:3003 14525:4004 14525:9001", - "list": [ - "174:21001", - "174:22003", - "14525:0", - "14525:40", - "14525:1021", - "14525:2840", - "14525:3003", - "14525:4004", - "14525:9001" - ] - }, - "lastUpdate": { - "epoch": 1588417118, - "string": "Sat May 2 10:58:38 2020\n" - }, - "nexthops": [ - { - "ip": "199.34.92.7", - "afi": "ipv4", - "metric": 1100, - "accessible": true, - "used": true - } - ], - "peer": { - "peerId": "199.34.92.7", - "routerId": "199.34.92.7", - "hostname": "er01.dtn01", - "type": "internal" - } - }, - { - "aspath": { - "string": "1299 13335", - "segments": [ - { - "type": "as-sequence", - "list": [1299, 13335] - } - ], - "length": 2 - }, - "aggregatorAs": 13335, - "aggregatorId": "162.158.140.1", - "origin": "IGP", - "med": 0, - "metric": 0, - "localpref": 150, - "weight": 200, - "valid": true, - "bestpath": { - "bestpathFromAs": 1299 - }, - "community": { - "string": "1299:35000 14525:0 14525:40 14525:1021 14525:2840 14525:3001 14525:4001 14525:9003", - "list": [ - "1299:35000", - "14525:0", - "14525:40", - "14525:1021", - "14525:2840", - "14525:3001", - "14525:4001", - "14525:9003" - ] - }, - "lastUpdate": { - "epoch": 1588584980, - "string": "Mon May 4 09:36:20 2020\n" - }, - "nexthops": [ - { - "ip": "199.34.92.9", - "afi": "ipv4", - "metric": 200, - "accessible": true, - "used": true - } - ], - "peer": { - "peerId": "199.34.92.9", - "routerId": "199.34.92.9", - "type": "internal" - } - }, - { - "aspath": { - "string": "6939 13335", - "segments": [ - { - "type": "as-sequence", - "list": [6939, 13335] - } - ], - "length": 2 - }, - "aggregatorAs": 13335, - "aggregatorId": "172.68.129.1", - "origin": "IGP", - "med": 0, - "metric": 0, - "localpref": 100, - "weight": 100, - "valid": true, - "bestpath": { - "bestpathFromAs": 6939 - }, - "community": { - "string": "6939:7107 6939:8840 6939:9001 14525:0 14525:40 14525:1021 14525:2840 14525:3002 14525:4003 14525:9002", - "list": [ - "6939:7107", - "6939:8840", - "6939:9001", - "14525:0", - "14525:40", - "14525:1021", - "14525:2840", - "14525:3002", - "14525:4003", - "14525:9002" - ] - }, - "lastUpdate": { - "epoch": 1586990260, - "string": "Wed Apr 15 22:37:40 2020\n" - }, - "nexthops": [ - { - "ip": "199.34.92.6", - "afi": "ipv4", - "metric": 151, - "accessible": true, - "used": true - } - ], - "peer": { - "peerId": "199.34.92.6", - "routerId": "199.34.92.6", - "type": "internal" - } - }, - { - "aspath": { - "string": "174 13335", - "segments": [ - { - "type": "as-sequence", - "list": [174, 13335] - } - ], - "length": 2 - }, - "aggregatorAs": 13335, - "aggregatorId": "162.158.140.1", - "origin": "IGP", - "med": 2020, - "metric": 2020, - "localpref": 150, - "weight": 200, - "valid": true, - "bestpath": { - "bestpathFromAs": 174, - "overall": true - }, - "community": { - "string": "174:21001 174:22013 14525:0 14525:20 14525:1021 14525:2840 14525:3001 14525:4001 14525:9001", - "list": [ - "174:21001", - "174:22013", - "14525:0", - "14525:20", - "14525:1021", - "14525:2840", - "14525:3001", - "14525:4001", - "14525:9001" - ] - }, - "lastUpdate": { - "epoch": 1588584997, - "string": "Mon May 4 09:36:37 2020\n" - }, - "nexthops": [ - { - "ip": "199.34.92.1", - "afi": "ipv4", - "metric": 101, - "accessible": true, - "used": true - } - ], - "peer": { - "peerId": "199.34.92.1", - "routerId": "199.34.92.1", - "type": "internal" - } - } - ] -} diff --git a/hyperglass/models/parsing/juniper.py b/hyperglass/models/parsing/juniper.py deleted file mode 100644 index 514ffc0..0000000 --- a/hyperglass/models/parsing/juniper.py +++ /dev/null @@ -1,201 +0,0 @@ -"""Data Models for Parsing Juniper XML Response.""" - -# Standard Library -from typing import Dict, List - -# Third Party -from pydantic import StrictInt, StrictStr, StrictBool, validator, root_validator - -# Project -from hyperglass.log import log - -# Local -from ..main import HyperglassModel -from .serialized import ParsedRoutes - -RPKI_STATE_MAP = { - "invalid": 0, - "valid": 1, - "unknown": 2, - "unverified": 3, -} - - -def _alias_generator(field): - return field.replace("_", "-") - - -class _JuniperBase(HyperglassModel): - class Config: - alias_generator = _alias_generator - extra = "ignore" - - -class JuniperRouteTableEntry(_JuniperBase): - """Parse Juniper rt-entry data.""" - - active_tag: StrictBool - preference: int - age: StrictInt - local_preference: int - metric: int = 0 - as_path: List[StrictInt] = [] - validation_state: StrictInt = 3 - next_hop: StrictStr - peer_rid: StrictStr - peer_as: int - source_as: int - source_rid: StrictStr - communities: List[StrictStr] = None - - @root_validator(pre=True) - def validate_optional_flags(cls, values): - """Flatten & rename keys prior to validation.""" - next_hops = [] - nh = None - - # Handle Juniper's 'Router' Next Hop Type - if "nh" in values: - nh = values.pop("nh") - - # Handle Juniper's 'Indirect' Next Hop Type - if "protocol-nh" in values: - nh = values.pop("protocol-nh") - - # Force the next hops to be a list - if isinstance(nh, Dict): - nh = [nh] - - if nh is not None: - next_hops.extend(nh) - - # Extract the 'to:' value from the next-hop - selected_next_hop = "" - for hop in next_hops: - if "selected-next-hop" in hop: - selected_next_hop = hop.get("to", "") - break - elif hop.get("to") is not None: - selected_next_hop = hop["to"] - break - - values["next-hop"] = selected_next_hop - - _path_attr = values.get("bgp-path-attributes", {}) - _path_attr_agg = _path_attr.get("attr-aggregator", {}).get("attr-value", {}) - values["as-path"] = _path_attr.get("attr-as-path-effective", {}).get( - "attr-value", "" - ) - values["source-as"] = _path_attr_agg.get("aggr-as-number", 0) - values["source-rid"] = _path_attr_agg.get("aggr-router-id", "") - values["peer-rid"] = values["peer-id"] - - return values - - @validator("validation_state", pre=True, always=True) - def validate_rpki_state(cls, value): - """Convert string RPKI state to standard integer mapping.""" - return RPKI_STATE_MAP.get(value, 3) - - @validator("active_tag", pre=True, always=True) - def validate_active_tag(cls, value): - """Convert active-tag from string/null to boolean.""" - if value == "*": - value = True - else: - value = False - return value - - @validator("age", pre=True, always=True) - def validate_age(cls, value): - """Get age as seconds.""" - if not isinstance(value, dict): - try: - value = int(value) - except ValueError: - raise ValueError(f"Age field is in an unexpected format. Got: {value}") - else: - value = value.get("@junos:seconds", 0) - return int(value) - - @validator("as_path", pre=True, always=True) - def validate_as_path(cls, value): - """Remove origin flags from AS_PATH.""" - disallowed = ("E", "I", "?") - return [int(a) for a in value.split() if a not in disallowed] - - @validator("communities", pre=True, always=True) - def validate_communities(cls, value): - """Flatten community list.""" - if value is not None: - flat = value.get("community", []) - else: - flat = [] - return flat - - -class JuniperRouteTable(_JuniperBase): - """Validation model for Juniper rt data.""" - - rt_destination: StrictStr - rt_prefix_length: int - rt_entry_count: int - rt_announced_count: int - rt_entry: List[JuniperRouteTableEntry] - - @validator("rt_entry_count", pre=True, always=True) - def validate_entry_count(cls, value): - """Flatten & convert entry-count to integer.""" - return int(value.get("#text")) - - -class JuniperRoute(_JuniperBase): - """Validation model for route-table data.""" - - table_name: StrictStr - destination_count: int - total_route_count: int - active_route_count: int - hidden_route_count: int - rt: List[JuniperRouteTable] - - def serialize(self): - """Convert the Juniper-specific fields to standard parsed data model.""" - vrf_parts = self.table_name.split(".") - if len(vrf_parts) == 2: - vrf = "default" - else: - vrf = vrf_parts[0] - - routes = [] - count = 0 - for table in self.rt: - count += table.rt_entry_count - prefix = "/".join( - str(i) for i in (table.rt_destination, table.rt_prefix_length) - ) - for route in table.rt_entry: - routes.append( - { - "prefix": prefix, - "active": route.active_tag, - "age": route.age, - "weight": route.preference, - "med": route.metric, - "local_preference": route.local_preference, - "as_path": route.as_path, - "communities": route.communities, - "next_hop": route.next_hop, - "source_as": route.source_as, - "source_rid": route.source_rid, - "peer_rid": route.peer_rid, - "rpki_state": route.validation_state, - } - ) - - serialized = ParsedRoutes( - vrf=vrf, count=count, routes=routes, winning_weight="low", - ) - - log.debug("Serialized Juniper response: {}", serialized) - return serialized diff --git a/hyperglass/models/parsing/juniper_route_aspath.xml b/hyperglass/models/parsing/juniper_route_aspath.xml deleted file mode 100644 index a7f2f20..0000000 --- a/hyperglass/models/parsing/juniper_route_aspath.xml +++ /dev/null @@ -1,31265 +0,0 @@ -<rpc-reply xmlns:junos="http://xml.juniper.net/junos/18.2R3/junos"> - <route-information xmlns="http://xml.juniper.net/junos/18.2R3/junos-routing"> - <!-- keepalive --> - <route-table> - <table-name> - inet.0 - </table-name> - <destination-count> - 851407 - </destination-count> - <total-route-count> - 3145804 - </total-route-count> - <active-route-count> - 851365 - </active-route-count> - <holddown-route-count> - 0 - </holddown-route-count> - <hidden-route-count> - 72 - </hidden-route-count> - <rt junos:style="detail"> - <rt-destination> - 78.31.120.0 - </rt-destination> - <rt-prefix-length> - 21 - </rt-prefix-length> - <rt-entry-count junos:format="4 entries"> - 4 - </rt-entry-count> - <rt-announced-count> - 1 - </rt-announced-count> - <rt-entry> - <active-tag> - * - </active-tag> - <current-active /> - <last-active /> - <protocol-name> - BGP - </protocol-name> - <preference> - 170 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x42439f4c - </nh-address> - <nh-reference-count> - 757869 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.92.10 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 0 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.10 - </to> - <via> - et-0/0/0.0 - </via> - <weight> - 0x1 - </weight> - <label-element> - 0x425dd00 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 13 - </label-element-refcount> - <label-element-childcount> - 9 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 0 - </session> - </nh> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.194 - </to> - <via> - et-0/0/1.3683 - </via> - <weight> - 0x1 - </weight> - <selected-next-hop /> - <label-element> - 0x425dd00 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 13 - </label-element-refcount> - <label-element-childcount> - 9 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 0 - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.92.10 - </to> - <indirect-nh> - 0xa00d600 1048582 INH Session ID: 0x2c0 - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Active Int Ext - </rt-entry-state> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="2523630"> - 4w1d 5:00:30 - </age> - <metric> - 0 - </metric> - <metric2> - 10 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 10 - </med-plus-igp> - <task-name> - BGP_14525.199.34.92.10 - </task-name> - <announce-bits> - 4 - </announce-bits> - <announce-tasks> - 0-KRT 8-Resolve tree 3 10-Aggregate 12-RT - </announce-tasks> - <as-path> - AS path: 3356 13293 29414 57476 I - AS path: Recorded - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 3356 13293 29414 57476 I - </attr-value> - <flags> - </flags> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 3356:2 - </community> - <community> - 3356:22 - </community> - <community> - 3356:100 - </community> - <community> - 3356:123 - </community> - <community> - 3356:501 - </community> - <community> - 3356:903 - </community> - <community> - 3356:2071 - </community> - <community> - 8501:1014 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3001 - </community> - <community> - 14525:4001 - </community> - <community> - 14525:9014 - </community> - <community> - 29414:1020 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.92.10 - </peer-id> - </rt-entry> - <rt-entry> - <active-tag> - </active-tag> - <protocol-name> - BGP - </protocol-name> - <preference> - 170 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Router - </nh-type> - <nh-index> - 1007 - </nh-index> - <nh-address> - 0x36d576ac - </nh-address> - <nh-reference-count> - 1336786 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 62.115.189.136 - </gateway> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 62.115.189.136 - </to> - <via> - xe-0/1/1.0 - </via> - <selected-next-hop /> - <session> - 4e3 - </session> - </nh> - <rt-entry-state> - Ext - </rt-entry-state> - <inactive-reason> - AS path - </inactive-reason> - <local-as> - 14525 - </local-as> - <peer-as> - 1299 - </peer-as> - <age junos:seconds="2523629"> - 4w1d 5:00:29 - </age> - <validation-state> - unknown - </validation-state> - <med-plus-igp> - 0 - </med-plus-igp> - <task-name> - BGP_1299.62.115.189.136 - </task-name> - <as-path> - AS path: 1299 3356 13293 29414 57476 I - AS path: Recorded - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 1299 3356 13293 29414 57476 I - </attr-value> - <flags> - </flags> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 1299:25000 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3001 - </community> - <community> - 14525:4001 - </community> - <community> - 14525:9003 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 2.255.254.43 - </peer-id> - </rt-entry> - <rt-entry> - <active-tag> - </active-tag> - <protocol-name> - BGP - </protocol-name> - <preference> - 200 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x122adabc - </nh-address> - <nh-reference-count> - 546682 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.94.1 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 1283 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.21 - </to> - <via> - et-0/0/2.3601 - </via> - <selected-next-hop /> - <label-element> - 0x8b6ab80 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 4 - </label-element-refcount> - <label-element-childcount> - 2 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 53c - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.94.1 - </to> - <indirect-nh> - 0xa011000 1048625 INH Session ID: 0x5dc - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Int Ext - </rt-entry-state> - <inactive-reason> - Route Preference - </inactive-reason> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="27339"> - 7:35:39 - </age> - <metric> - 0 - </metric> - <metric2> - 1000 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 1000 - </med-plus-igp> - <task-name> - BGP_14525.199.34.94.1 - </task-name> - <as-path> - AS path: 3356 13293 29414 57476 I - AS path: Recorded - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 3356 13293 29414 57476 I - </attr-value> - <flags> - </flags> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 3356:2 - </community> - <community> - 3356:22 - </community> - <community> - 3356:100 - </community> - <community> - 3356:123 - </community> - <community> - 3356:501 - </community> - <community> - 3356:903 - </community> - <community> - 3356:2071 - </community> - <community> - 8501:1014 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3003 - </community> - <community> - 14525:4003 - </community> - <community> - 14525:9014 - </community> - <community> - 29414:1020 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.94.1 - </peer-id> - </rt-entry> - <rt-entry> - <active-tag> - </active-tag> - <protocol-name> - BGP - </protocol-name> - <preference> - 200 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x1104e0dc - </nh-address> - <nh-reference-count> - 600498 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.94.2 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 1280 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.22 - </to> - <via> - et-0/0/2.3601 - </via> - <selected-next-hop /> - <label-element> - 0x4265080 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 4 - </label-element-refcount> - <label-element-childcount> - 2 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 532 - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.94.2 - </to> - <indirect-nh> - 0xa010800 1048619 INH Session ID: 0x5e1 - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Int Ext - </rt-entry-state> - <inactive-reason> - Route Preference - </inactive-reason> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="3535"> - 58:55 - </age> - <metric> - 0 - </metric> - <metric2> - 1000 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 1000 - </med-plus-igp> - <task-name> - BGP_14525.199.34.94.2 - </task-name> - <as-path> - AS path: 6939 196844 29414 57476 I - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 6939 196844 29414 57476 I - </attr-value> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 6939:7082 - </community> - <community> - 6939:8826 - </community> - <community> - 6939:9002 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3003 - </community> - <community> - 14525:4003 - </community> - <community> - 14525:9002 - </community> - <community> - large:8714:1000:2 - </community> - <community> - large:8714:1001:1 - </community> - <community> - large:8714:1001:2 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.94.2 - </peer-id> - </rt-entry> - </rt> - <rt junos:style="detail"> - <rt-destination> - 82.139.146.0 - </rt-destination> - <rt-prefix-length> - 23 - </rt-prefix-length> - <rt-entry-count junos:format="4 entries"> - 4 - </rt-entry-count> - <rt-announced-count> - 1 - </rt-announced-count> - <rt-entry> - <active-tag> - * - </active-tag> - <current-active /> - <last-active /> - <protocol-name> - BGP - </protocol-name> - <preference> - 170 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x42439f4c - </nh-address> - <nh-reference-count> - 757869 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.92.10 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 0 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.10 - </to> - <via> - et-0/0/0.0 - </via> - <weight> - 0x1 - </weight> - <label-element> - 0x425dd00 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 13 - </label-element-refcount> - <label-element-childcount> - 9 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 0 - </session> - </nh> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.194 - </to> - <via> - et-0/0/1.3683 - </via> - <weight> - 0x1 - </weight> - <selected-next-hop /> - <label-element> - 0x425dd00 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 13 - </label-element-refcount> - <label-element-childcount> - 9 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 0 - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.92.10 - </to> - <indirect-nh> - 0xa00d600 1048582 INH Session ID: 0x2c0 - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Active Int Ext - </rt-entry-state> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="2526186"> - 4w1d 5:43:06 - </age> - <metric> - 0 - </metric> - <metric2> - 10 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 10 - </med-plus-igp> - <task-name> - BGP_14525.199.34.92.10 - </task-name> - <announce-bits> - 4 - </announce-bits> - <announce-tasks> - 0-KRT 8-Resolve tree 3 10-Aggregate 12-RT - </announce-tasks> - <as-path> - AS path: 3356 13293 29414 I - AS path: Recorded - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 3356 13293 29414 I - </attr-value> - <flags> - </flags> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 3356:2 - </community> - <community> - 3356:22 - </community> - <community> - 3356:100 - </community> - <community> - 3356:123 - </community> - <community> - 3356:501 - </community> - <community> - 3356:903 - </community> - <community> - 3356:2071 - </community> - <community> - 8501:1013 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3001 - </community> - <community> - 14525:4001 - </community> - <community> - 14525:9014 - </community> - <community> - 15169:13100 - </community> - <community> - 29414:1000 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.92.10 - </peer-id> - </rt-entry> - <rt-entry> - <active-tag> - </active-tag> - <protocol-name> - BGP - </protocol-name> - <preference> - 170 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Router - </nh-type> - <nh-index> - 1007 - </nh-index> - <nh-address> - 0x36d576ac - </nh-address> - <nh-reference-count> - 1336784 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 62.115.189.136 - </gateway> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 62.115.189.136 - </to> - <via> - xe-0/1/1.0 - </via> - <selected-next-hop /> - <session> - 4e3 - </session> - </nh> - <rt-entry-state> - Ext - </rt-entry-state> - <inactive-reason> - AS path - </inactive-reason> - <local-as> - 14525 - </local-as> - <peer-as> - 1299 - </peer-as> - <age junos:seconds="2526272"> - 4w1d 5:44:32 - </age> - <validation-state> - unknown - </validation-state> - <med-plus-igp> - 0 - </med-plus-igp> - <task-name> - BGP_1299.62.115.189.136 - </task-name> - <as-path> - AS path: 1299 3356 13293 29414 I - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 1299 3356 13293 29414 I - </attr-value> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 1299:25000 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3001 - </community> - <community> - 14525:4001 - </community> - <community> - 14525:9003 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 2.255.254.43 - </peer-id> - </rt-entry> - <rt-entry> - <active-tag> - </active-tag> - <protocol-name> - BGP - </protocol-name> - <preference> - 200 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x122adabc - </nh-address> - <nh-reference-count> - 546682 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.94.1 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 1283 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.21 - </to> - <via> - et-0/0/2.3601 - </via> - <selected-next-hop /> - <label-element> - 0x8b6ab80 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 4 - </label-element-refcount> - <label-element-childcount> - 2 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 53c - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.94.1 - </to> - <indirect-nh> - 0xa011000 1048625 INH Session ID: 0x5dc - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Int Ext - </rt-entry-state> - <inactive-reason> - Route Preference - </inactive-reason> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="27339"> - 7:35:39 - </age> - <metric> - 0 - </metric> - <metric2> - 1000 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 1000 - </med-plus-igp> - <task-name> - BGP_14525.199.34.94.1 - </task-name> - <as-path> - AS path: 3356 13293 29414 I - AS path: Recorded - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 3356 13293 29414 I - </attr-value> - <flags> - </flags> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 3356:2 - </community> - <community> - 3356:22 - </community> - <community> - 3356:100 - </community> - <community> - 3356:123 - </community> - <community> - 3356:501 - </community> - <community> - 3356:903 - </community> - <community> - 3356:2071 - </community> - <community> - 8501:1013 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3003 - </community> - <community> - 14525:4003 - </community> - <community> - 14525:9014 - </community> - <community> - 15169:13100 - </community> - <community> - 29414:1000 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.94.1 - </peer-id> - </rt-entry> - <rt-entry> - <active-tag> - </active-tag> - <protocol-name> - BGP - </protocol-name> - <preference> - 200 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x1104e0dc - </nh-address> - <nh-reference-count> - 600499 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.94.2 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 1280 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.22 - </to> - <via> - et-0/0/2.3601 - </via> - <selected-next-hop /> - <label-element> - 0x4265080 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 4 - </label-element-refcount> - <label-element-childcount> - 2 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 532 - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.94.2 - </to> - <indirect-nh> - 0xa010800 1048619 INH Session ID: 0x5e1 - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Int Ext - </rt-entry-state> - <inactive-reason> - Route Preference - </inactive-reason> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="3535"> - 58:55 - </age> - <metric> - 0 - </metric> - <metric2> - 1000 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 1000 - </med-plus-igp> - <task-name> - BGP_14525.199.34.94.2 - </task-name> - <as-path> - AS path: 6939 196844 29414 I - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 6939 196844 29414 I - </attr-value> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 6939:7082 - </community> - <community> - 6939:8826 - </community> - <community> - 6939:9002 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3003 - </community> - <community> - 14525:4003 - </community> - <community> - 14525:9002 - </community> - <community> - large:8714:1000:2 - </community> - <community> - large:8714:1001:1 - </community> - <community> - large:8714:1001:2 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.94.2 - </peer-id> - </rt-entry> - </rt> - <rt junos:style="detail"> - <rt-destination> - 82.139.160.0 - </rt-destination> - <rt-prefix-length> - 21 - </rt-prefix-length> - <rt-entry-count junos:format="4 entries"> - 4 - </rt-entry-count> - <rt-announced-count> - 1 - </rt-announced-count> - <rt-entry> - <active-tag> - * - </active-tag> - <current-active /> - <last-active /> - <protocol-name> - BGP - </protocol-name> - <preference> - 170 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x42439f4c - </nh-address> - <nh-reference-count> - 757869 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.92.10 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 0 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.10 - </to> - <via> - et-0/0/0.0 - </via> - <weight> - 0x1 - </weight> - <label-element> - 0x425dd00 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 13 - </label-element-refcount> - <label-element-childcount> - 9 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 0 - </session> - </nh> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.194 - </to> - <via> - et-0/0/1.3683 - </via> - <weight> - 0x1 - </weight> - <selected-next-hop /> - <label-element> - 0x425dd00 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 13 - </label-element-refcount> - <label-element-childcount> - 9 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 0 - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.92.10 - </to> - <indirect-nh> - 0xa00d600 1048582 INH Session ID: 0x2c0 - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Active Int Ext - </rt-entry-state> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="2526216"> - 4w1d 5:43:36 - </age> - <metric> - 0 - </metric> - <metric2> - 10 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 10 - </med-plus-igp> - <task-name> - BGP_14525.199.34.92.10 - </task-name> - <announce-bits> - 4 - </announce-bits> - <announce-tasks> - 0-KRT 8-Resolve tree 3 10-Aggregate 12-RT - </announce-tasks> - <as-path> - AS path: 3356 13293 29414 I - AS path: Recorded - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 3356 13293 29414 I - </attr-value> - <flags> - </flags> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 3356:2 - </community> - <community> - 3356:22 - </community> - <community> - 3356:100 - </community> - <community> - 3356:123 - </community> - <community> - 3356:501 - </community> - <community> - 3356:903 - </community> - <community> - 3356:2071 - </community> - <community> - 8501:1013 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3001 - </community> - <community> - 14525:4001 - </community> - <community> - 14525:9014 - </community> - <community> - 15169:13100 - </community> - <community> - 29414:1000 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.92.10 - </peer-id> - </rt-entry> - <rt-entry> - <active-tag> - </active-tag> - <protocol-name> - BGP - </protocol-name> - <preference> - 170 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Router - </nh-type> - <nh-index> - 1007 - </nh-index> - <nh-address> - 0x36d576ac - </nh-address> - <nh-reference-count> - 1336784 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 62.115.189.136 - </gateway> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 62.115.189.136 - </to> - <via> - xe-0/1/1.0 - </via> - <selected-next-hop /> - <session> - 4e3 - </session> - </nh> - <rt-entry-state> - Ext - </rt-entry-state> - <inactive-reason> - AS path - </inactive-reason> - <local-as> - 14525 - </local-as> - <peer-as> - 1299 - </peer-as> - <age junos:seconds="2526272"> - 4w1d 5:44:32 - </age> - <validation-state> - unknown - </validation-state> - <med-plus-igp> - 0 - </med-plus-igp> - <task-name> - BGP_1299.62.115.189.136 - </task-name> - <as-path> - AS path: 1299 3356 13293 29414 I - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 1299 3356 13293 29414 I - </attr-value> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 1299:25000 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3001 - </community> - <community> - 14525:4001 - </community> - <community> - 14525:9003 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 2.255.254.43 - </peer-id> - </rt-entry> - <rt-entry> - <active-tag> - </active-tag> - <protocol-name> - BGP - </protocol-name> - <preference> - 200 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x122adabc - </nh-address> - <nh-reference-count> - 546682 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.94.1 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 1283 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.21 - </to> - <via> - et-0/0/2.3601 - </via> - <selected-next-hop /> - <label-element> - 0x8b6ab80 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 4 - </label-element-refcount> - <label-element-childcount> - 2 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 53c - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.94.1 - </to> - <indirect-nh> - 0xa011000 1048625 INH Session ID: 0x5dc - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Int Ext - </rt-entry-state> - <inactive-reason> - Route Preference - </inactive-reason> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="27339"> - 7:35:39 - </age> - <metric> - 0 - </metric> - <metric2> - 1000 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 1000 - </med-plus-igp> - <task-name> - BGP_14525.199.34.94.1 - </task-name> - <as-path> - AS path: 3356 13293 29414 I - AS path: Recorded - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 3356 13293 29414 I - </attr-value> - <flags> - </flags> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 3356:2 - </community> - <community> - 3356:22 - </community> - <community> - 3356:100 - </community> - <community> - 3356:123 - </community> - <community> - 3356:501 - </community> - <community> - 3356:903 - </community> - <community> - 3356:2071 - </community> - <community> - 8501:1013 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3003 - </community> - <community> - 14525:4003 - </community> - <community> - 14525:9014 - </community> - <community> - 15169:13100 - </community> - <community> - 29414:1000 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.94.1 - </peer-id> - </rt-entry> - <rt-entry> - <active-tag> - </active-tag> - <protocol-name> - BGP - </protocol-name> - <preference> - 200 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x1104e0dc - </nh-address> - <nh-reference-count> - 600499 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.94.2 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 1280 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.22 - </to> - <via> - et-0/0/2.3601 - </via> - <selected-next-hop /> - <label-element> - 0x4265080 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 4 - </label-element-refcount> - <label-element-childcount> - 2 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 532 - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.94.2 - </to> - <indirect-nh> - 0xa010800 1048619 INH Session ID: 0x5e1 - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Int Ext - </rt-entry-state> - <inactive-reason> - Route Preference - </inactive-reason> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="3535"> - 58:55 - </age> - <metric> - 0 - </metric> - <metric2> - 1000 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 1000 - </med-plus-igp> - <task-name> - BGP_14525.199.34.94.2 - </task-name> - <as-path> - AS path: 6939 196844 29414 I - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 6939 196844 29414 I - </attr-value> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 6939:7082 - </community> - <community> - 6939:8826 - </community> - <community> - 6939:9002 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3003 - </community> - <community> - 14525:4003 - </community> - <community> - 14525:9002 - </community> - <community> - large:8714:1000:2 - </community> - <community> - large:8714:1001:1 - </community> - <community> - large:8714:1001:2 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.94.2 - </peer-id> - </rt-entry> - </rt> - <rt junos:style="detail"> - <rt-destination> - 82.139.166.0 - </rt-destination> - <rt-prefix-length> - 24 - </rt-prefix-length> - <rt-entry-count junos:format="4 entries"> - 4 - </rt-entry-count> - <rt-announced-count> - 1 - </rt-announced-count> - <rt-entry> - <active-tag> - * - </active-tag> - <current-active /> - <last-active /> - <protocol-name> - BGP - </protocol-name> - <preference> - 170 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x42439f4c - </nh-address> - <nh-reference-count> - 757869 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.92.10 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 0 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.10 - </to> - <via> - et-0/0/0.0 - </via> - <weight> - 0x1 - </weight> - <label-element> - 0x425dd00 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 13 - </label-element-refcount> - <label-element-childcount> - 9 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 0 - </session> - </nh> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.194 - </to> - <via> - et-0/0/1.3683 - </via> - <weight> - 0x1 - </weight> - <selected-next-hop /> - <label-element> - 0x425dd00 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 13 - </label-element-refcount> - <label-element-childcount> - 9 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 0 - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.92.10 - </to> - <indirect-nh> - 0xa00d600 1048582 INH Session ID: 0x2c0 - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Active Int Ext - </rt-entry-state> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="2526246"> - 4w1d 5:44:06 - </age> - <metric> - 0 - </metric> - <metric2> - 10 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 10 - </med-plus-igp> - <task-name> - BGP_14525.199.34.92.10 - </task-name> - <announce-bits> - 4 - </announce-bits> - <announce-tasks> - 0-KRT 8-Resolve tree 3 10-Aggregate 12-RT - </announce-tasks> - <as-path> - AS path: 3356 13293 29414 I - AS path: Recorded - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 3356 13293 29414 I - </attr-value> - <flags> - </flags> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 3356:2 - </community> - <community> - 3356:22 - </community> - <community> - 3356:100 - </community> - <community> - 3356:123 - </community> - <community> - 3356:501 - </community> - <community> - 3356:903 - </community> - <community> - 3356:2071 - </community> - <community> - 8501:1013 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3001 - </community> - <community> - 14525:4001 - </community> - <community> - 14525:9014 - </community> - <community> - 15169:13100 - </community> - <community> - 29414:1000 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.92.10 - </peer-id> - </rt-entry> - <rt-entry> - <active-tag> - </active-tag> - <protocol-name> - BGP - </protocol-name> - <preference> - 170 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Router - </nh-type> - <nh-index> - 1007 - </nh-index> - <nh-address> - 0x36d576ac - </nh-address> - <nh-reference-count> - 1336784 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 62.115.189.136 - </gateway> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 62.115.189.136 - </to> - <via> - xe-0/1/1.0 - </via> - <selected-next-hop /> - <session> - 4e3 - </session> - </nh> - <rt-entry-state> - Ext - </rt-entry-state> - <inactive-reason> - AS path - </inactive-reason> - <local-as> - 14525 - </local-as> - <peer-as> - 1299 - </peer-as> - <age junos:seconds="2526245"> - 4w1d 5:44:05 - </age> - <validation-state> - unknown - </validation-state> - <med-plus-igp> - 0 - </med-plus-igp> - <task-name> - BGP_1299.62.115.189.136 - </task-name> - <as-path> - AS path: 1299 3356 13293 29414 I - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 1299 3356 13293 29414 I - </attr-value> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 1299:25000 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3001 - </community> - <community> - 14525:4001 - </community> - <community> - 14525:9003 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 2.255.254.43 - </peer-id> - </rt-entry> - <rt-entry> - <active-tag> - </active-tag> - <protocol-name> - BGP - </protocol-name> - <preference> - 200 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x122adabc - </nh-address> - <nh-reference-count> - 546682 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.94.1 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 1283 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.21 - </to> - <via> - et-0/0/2.3601 - </via> - <selected-next-hop /> - <label-element> - 0x8b6ab80 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 4 - </label-element-refcount> - <label-element-childcount> - 2 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 53c - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.94.1 - </to> - <indirect-nh> - 0xa011000 1048625 INH Session ID: 0x5dc - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Int Ext - </rt-entry-state> - <inactive-reason> - Route Preference - </inactive-reason> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="27339"> - 7:35:39 - </age> - <metric> - 0 - </metric> - <metric2> - 1000 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 1000 - </med-plus-igp> - <task-name> - BGP_14525.199.34.94.1 - </task-name> - <as-path> - AS path: 3356 13293 29414 I - AS path: Recorded - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 3356 13293 29414 I - </attr-value> - <flags> - </flags> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 3356:2 - </community> - <community> - 3356:22 - </community> - <community> - 3356:100 - </community> - <community> - 3356:123 - </community> - <community> - 3356:501 - </community> - <community> - 3356:903 - </community> - <community> - 3356:2071 - </community> - <community> - 8501:1013 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3003 - </community> - <community> - 14525:4003 - </community> - <community> - 14525:9014 - </community> - <community> - 15169:13100 - </community> - <community> - 29414:1000 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.94.1 - </peer-id> - </rt-entry> - <rt-entry> - <active-tag> - </active-tag> - <protocol-name> - BGP - </protocol-name> - <preference> - 200 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x1104e0dc - </nh-address> - <nh-reference-count> - 600499 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.94.2 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 1280 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.22 - </to> - <via> - et-0/0/2.3601 - </via> - <selected-next-hop /> - <label-element> - 0x4265080 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 4 - </label-element-refcount> - <label-element-childcount> - 2 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 532 - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.94.2 - </to> - <indirect-nh> - 0xa010800 1048619 INH Session ID: 0x5e1 - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Int Ext - </rt-entry-state> - <inactive-reason> - Route Preference - </inactive-reason> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="3535"> - 58:55 - </age> - <metric> - 0 - </metric> - <metric2> - 1000 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 1000 - </med-plus-igp> - <task-name> - BGP_14525.199.34.94.2 - </task-name> - <as-path> - AS path: 6939 196844 29414 I - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 6939 196844 29414 I - </attr-value> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 6939:7082 - </community> - <community> - 6939:8826 - </community> - <community> - 6939:9002 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3003 - </community> - <community> - 14525:4003 - </community> - <community> - 14525:9002 - </community> - <community> - large:8714:1000:2 - </community> - <community> - large:8714:1001:1 - </community> - <community> - large:8714:1001:2 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.94.2 - </peer-id> - </rt-entry> - </rt> - <rt junos:style="detail"> - <rt-destination> - 82.139.184.0 - </rt-destination> - <rt-prefix-length> - 21 - </rt-prefix-length> - <rt-entry-count junos:format="4 entries"> - 4 - </rt-entry-count> - <rt-announced-count> - 1 - </rt-announced-count> - <rt-entry> - <active-tag> - * - </active-tag> - <current-active /> - <last-active /> - <protocol-name> - BGP - </protocol-name> - <preference> - 170 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x42439f4c - </nh-address> - <nh-reference-count> - 757869 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.92.10 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 0 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.10 - </to> - <via> - et-0/0/0.0 - </via> - <weight> - 0x1 - </weight> - <selected-next-hop /> - <label-element> - 0x425dd00 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 13 - </label-element-refcount> - <label-element-childcount> - 9 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 0 - </session> - </nh> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.194 - </to> - <via> - et-0/0/1.3683 - </via> - <weight> - 0x1 - </weight> - <label-element> - 0x425dd00 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 13 - </label-element-refcount> - <label-element-childcount> - 9 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 0 - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.92.10 - </to> - <indirect-nh> - 0xa00d600 1048582 INH Session ID: 0x2c0 - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Active Int Ext - </rt-entry-state> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="2526216"> - 4w1d 5:43:36 - </age> - <metric> - 0 - </metric> - <metric2> - 10 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 10 - </med-plus-igp> - <task-name> - BGP_14525.199.34.92.10 - </task-name> - <announce-bits> - 4 - </announce-bits> - <announce-tasks> - 0-KRT 8-Resolve tree 3 10-Aggregate 12-RT - </announce-tasks> - <as-path> - AS path: 3356 13293 29414 I - AS path: Recorded - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 3356 13293 29414 I - </attr-value> - <flags> - </flags> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 3356:2 - </community> - <community> - 3356:22 - </community> - <community> - 3356:100 - </community> - <community> - 3356:123 - </community> - <community> - 3356:501 - </community> - <community> - 3356:903 - </community> - <community> - 3356:2071 - </community> - <community> - 8501:1013 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3001 - </community> - <community> - 14525:4001 - </community> - <community> - 14525:9014 - </community> - <community> - 15169:13100 - </community> - <community> - 29414:1000 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.92.10 - </peer-id> - </rt-entry> - <rt-entry> - <active-tag> - </active-tag> - <protocol-name> - BGP - </protocol-name> - <preference> - 170 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Router - </nh-type> - <nh-index> - 1007 - </nh-index> - <nh-address> - 0x36d576ac - </nh-address> - <nh-reference-count> - 1336784 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 62.115.189.136 - </gateway> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 62.115.189.136 - </to> - <via> - xe-0/1/1.0 - </via> - <selected-next-hop /> - <session> - 4e3 - </session> - </nh> - <rt-entry-state> - Ext - </rt-entry-state> - <inactive-reason> - AS path - </inactive-reason> - <local-as> - 14525 - </local-as> - <peer-as> - 1299 - </peer-as> - <age junos:seconds="2526272"> - 4w1d 5:44:32 - </age> - <validation-state> - unknown - </validation-state> - <med-plus-igp> - 0 - </med-plus-igp> - <task-name> - BGP_1299.62.115.189.136 - </task-name> - <as-path> - AS path: 1299 3356 13293 29414 I - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 1299 3356 13293 29414 I - </attr-value> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 1299:25000 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3001 - </community> - <community> - 14525:4001 - </community> - <community> - 14525:9003 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 2.255.254.43 - </peer-id> - </rt-entry> - <rt-entry> - <active-tag> - </active-tag> - <protocol-name> - BGP - </protocol-name> - <preference> - 200 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x122adabc - </nh-address> - <nh-reference-count> - 546682 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.94.1 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 1283 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.21 - </to> - <via> - et-0/0/2.3601 - </via> - <selected-next-hop /> - <label-element> - 0x8b6ab80 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 4 - </label-element-refcount> - <label-element-childcount> - 2 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 53c - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.94.1 - </to> - <indirect-nh> - 0xa011000 1048625 INH Session ID: 0x5dc - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Int Ext - </rt-entry-state> - <inactive-reason> - Route Preference - </inactive-reason> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="27339"> - 7:35:39 - </age> - <metric> - 0 - </metric> - <metric2> - 1000 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 1000 - </med-plus-igp> - <task-name> - BGP_14525.199.34.94.1 - </task-name> - <as-path> - AS path: 3356 13293 29414 I - AS path: Recorded - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 3356 13293 29414 I - </attr-value> - <flags> - </flags> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 3356:2 - </community> - <community> - 3356:22 - </community> - <community> - 3356:100 - </community> - <community> - 3356:123 - </community> - <community> - 3356:501 - </community> - <community> - 3356:903 - </community> - <community> - 3356:2071 - </community> - <community> - 8501:1013 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3003 - </community> - <community> - 14525:4003 - </community> - <community> - 14525:9014 - </community> - <community> - 15169:13100 - </community> - <community> - 29414:1000 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.94.1 - </peer-id> - </rt-entry> - <rt-entry> - <active-tag> - </active-tag> - <protocol-name> - BGP - </protocol-name> - <preference> - 200 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x1104e0dc - </nh-address> - <nh-reference-count> - 600499 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.94.2 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 1280 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.22 - </to> - <via> - et-0/0/2.3601 - </via> - <selected-next-hop /> - <label-element> - 0x4265080 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 4 - </label-element-refcount> - <label-element-childcount> - 2 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 532 - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.94.2 - </to> - <indirect-nh> - 0xa010800 1048619 INH Session ID: 0x5e1 - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Int Ext - </rt-entry-state> - <inactive-reason> - Route Preference - </inactive-reason> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="3535"> - 58:55 - </age> - <metric> - 0 - </metric> - <metric2> - 1000 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 1000 - </med-plus-igp> - <task-name> - BGP_14525.199.34.94.2 - </task-name> - <as-path> - AS path: 6939 196844 29414 I - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 6939 196844 29414 I - </attr-value> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 6939:7082 - </community> - <community> - 6939:8826 - </community> - <community> - 6939:9002 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3003 - </community> - <community> - 14525:4003 - </community> - <community> - 14525:9002 - </community> - <community> - large:8714:1000:2 - </community> - <community> - large:8714:1001:1 - </community> - <community> - large:8714:1001:2 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.94.2 - </peer-id> - </rt-entry> - </rt> - <rt junos:style="detail"> - <rt-destination> - 85.193.194.0 - </rt-destination> - <rt-prefix-length> - 23 - </rt-prefix-length> - <rt-entry-count junos:format="4 entries"> - 4 - </rt-entry-count> - <rt-announced-count> - 1 - </rt-announced-count> - <rt-entry> - <active-tag> - * - </active-tag> - <current-active /> - <last-active /> - <protocol-name> - BGP - </protocol-name> - <preference> - 170 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x42439f4c - </nh-address> - <nh-reference-count> - 757869 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.92.10 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 0 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.10 - </to> - <via> - et-0/0/0.0 - </via> - <weight> - 0x1 - </weight> - <selected-next-hop /> - <label-element> - 0x425dd00 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 13 - </label-element-refcount> - <label-element-childcount> - 9 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 0 - </session> - </nh> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.194 - </to> - <via> - et-0/0/1.3683 - </via> - <weight> - 0x1 - </weight> - <label-element> - 0x425dd00 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 13 - </label-element-refcount> - <label-element-childcount> - 9 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 0 - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.92.10 - </to> - <indirect-nh> - 0xa00d600 1048582 INH Session ID: 0x2c0 - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Active Int Ext - </rt-entry-state> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="2526246"> - 4w1d 5:44:06 - </age> - <metric> - 0 - </metric> - <metric2> - 10 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 10 - </med-plus-igp> - <task-name> - BGP_14525.199.34.92.10 - </task-name> - <announce-bits> - 4 - </announce-bits> - <announce-tasks> - 0-KRT 8-Resolve tree 3 10-Aggregate 12-RT - </announce-tasks> - <as-path> - AS path: 3356 13293 29414 34337 I - AS path: Recorded - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 3356 13293 29414 34337 I - </attr-value> - <flags> - </flags> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 3356:2 - </community> - <community> - 3356:22 - </community> - <community> - 3356:100 - </community> - <community> - 3356:123 - </community> - <community> - 3356:501 - </community> - <community> - 3356:903 - </community> - <community> - 3356:2071 - </community> - <community> - 8501:1014 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3001 - </community> - <community> - 14525:4001 - </community> - <community> - 14525:9014 - </community> - <community> - 29414:1020 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.92.10 - </peer-id> - </rt-entry> - <rt-entry> - <active-tag> - </active-tag> - <protocol-name> - BGP - </protocol-name> - <preference> - 200 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x122adabc - </nh-address> - <nh-reference-count> - 546682 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.94.1 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 1283 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.21 - </to> - <via> - et-0/0/2.3601 - </via> - <selected-next-hop /> - <label-element> - 0x8b6ab80 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 4 - </label-element-refcount> - <label-element-childcount> - 2 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 53c - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.94.1 - </to> - <indirect-nh> - 0xa011000 1048625 INH Session ID: 0x5dc - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Int Ext - </rt-entry-state> - <inactive-reason> - Route Preference - </inactive-reason> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="27367"> - 7:36:07 - </age> - <metric> - 0 - </metric> - <metric2> - 1000 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 1000 - </med-plus-igp> - <task-name> - BGP_14525.199.34.94.1 - </task-name> - <as-path> - AS path: 3356 13293 29414 34337 I - AS path: Recorded - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 3356 13293 29414 34337 I - </attr-value> - <flags> - </flags> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 3356:2 - </community> - <community> - 3356:22 - </community> - <community> - 3356:100 - </community> - <community> - 3356:123 - </community> - <community> - 3356:501 - </community> - <community> - 3356:903 - </community> - <community> - 3356:2071 - </community> - <community> - 8501:1014 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3003 - </community> - <community> - 14525:4003 - </community> - <community> - 14525:9014 - </community> - <community> - 29414:1020 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.94.1 - </peer-id> - </rt-entry> - <rt-entry> - <active-tag> - </active-tag> - <protocol-name> - BGP - </protocol-name> - <preference> - 200 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x1104e0dc - </nh-address> - <nh-reference-count> - 600499 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.94.2 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 1280 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.22 - </to> - <via> - et-0/0/2.3601 - </via> - <selected-next-hop /> - <label-element> - 0x4265080 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 4 - </label-element-refcount> - <label-element-childcount> - 2 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 532 - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.94.2 - </to> - <indirect-nh> - 0xa010800 1048619 INH Session ID: 0x5e1 - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Int Ext - </rt-entry-state> - <inactive-reason> - Route Preference - </inactive-reason> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="3790"> - 1:03:10 - </age> - <metric> - 0 - </metric> - <metric2> - 1000 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 1000 - </med-plus-igp> - <task-name> - BGP_14525.199.34.94.2 - </task-name> - <as-path> - AS path: 6939 196844 29414 34337 I - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 6939 196844 29414 34337 I - </attr-value> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 6939:7082 - </community> - <community> - 6939:8826 - </community> - <community> - 6939:9002 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3003 - </community> - <community> - 14525:4003 - </community> - <community> - 14525:9002 - </community> - <community> - large:8714:1000:2 - </community> - <community> - large:8714:1001:1 - </community> - <community> - large:8714:1001:2 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.94.2 - </peer-id> - </rt-entry> - </rt> - <rt junos:style="detail"> - <rt-destination> - 85.193.196.0 - </rt-destination> - <rt-prefix-length> - 23 - </rt-prefix-length> - <rt-entry-count junos:format="4 entries"> - 4 - </rt-entry-count> - <rt-announced-count> - 1 - </rt-announced-count> - <rt-entry> - <active-tag> - * - </active-tag> - <current-active /> - <last-active /> - <protocol-name> - BGP - </protocol-name> - <preference> - 170 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x42439f4c - </nh-address> - <nh-reference-count> - 757869 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.92.10 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 0 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.10 - </to> - <via> - et-0/0/0.0 - </via> - <weight> - 0x1 - </weight> - <selected-next-hop /> - <label-element> - 0x425dd00 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 13 - </label-element-refcount> - <label-element-childcount> - 9 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 0 - </session> - </nh> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.194 - </to> - <via> - et-0/0/1.3683 - </via> - <weight> - 0x1 - </weight> - <label-element> - 0x425dd00 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 13 - </label-element-refcount> - <label-element-childcount> - 9 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 0 - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.92.10 - </to> - <indirect-nh> - 0xa00d600 1048582 INH Session ID: 0x2c0 - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Active Int Ext - </rt-entry-state> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="2526246"> - 4w1d 5:44:06 - </age> - <metric> - 0 - </metric> - <metric2> - 10 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 10 - </med-plus-igp> - <task-name> - BGP_14525.199.34.92.10 - </task-name> - <announce-bits> - 4 - </announce-bits> - <announce-tasks> - 0-KRT 8-Resolve tree 3 10-Aggregate 12-RT - </announce-tasks> - <as-path> - AS path: 3356 13293 29414 34337 I - AS path: Recorded - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 3356 13293 29414 34337 I - </attr-value> - <flags> - </flags> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 3356:2 - </community> - <community> - 3356:22 - </community> - <community> - 3356:100 - </community> - <community> - 3356:123 - </community> - <community> - 3356:501 - </community> - <community> - 3356:903 - </community> - <community> - 3356:2071 - </community> - <community> - 8501:1014 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3001 - </community> - <community> - 14525:4001 - </community> - <community> - 14525:9014 - </community> - <community> - 29414:1020 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.92.10 - </peer-id> - </rt-entry> - <rt-entry> - <active-tag> - </active-tag> - <protocol-name> - BGP - </protocol-name> - <preference> - 200 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x122adabc - </nh-address> - <nh-reference-count> - 546682 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.94.1 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 1283 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.21 - </to> - <via> - et-0/0/2.3601 - </via> - <selected-next-hop /> - <label-element> - 0x8b6ab80 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 4 - </label-element-refcount> - <label-element-childcount> - 2 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 53c - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.94.1 - </to> - <indirect-nh> - 0xa011000 1048625 INH Session ID: 0x5dc - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Int Ext - </rt-entry-state> - <inactive-reason> - Route Preference - </inactive-reason> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="27367"> - 7:36:07 - </age> - <metric> - 0 - </metric> - <metric2> - 1000 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 1000 - </med-plus-igp> - <task-name> - BGP_14525.199.34.94.1 - </task-name> - <as-path> - AS path: 3356 13293 29414 34337 I - AS path: Recorded - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 3356 13293 29414 34337 I - </attr-value> - <flags> - </flags> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 3356:2 - </community> - <community> - 3356:22 - </community> - <community> - 3356:100 - </community> - <community> - 3356:123 - </community> - <community> - 3356:501 - </community> - <community> - 3356:903 - </community> - <community> - 3356:2071 - </community> - <community> - 8501:1014 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3003 - </community> - <community> - 14525:4003 - </community> - <community> - 14525:9014 - </community> - <community> - 29414:1020 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.94.1 - </peer-id> - </rt-entry> - <rt-entry> - <active-tag> - </active-tag> - <protocol-name> - BGP - </protocol-name> - <preference> - 200 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x1104e0dc - </nh-address> - <nh-reference-count> - 600499 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.94.2 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 1280 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.22 - </to> - <via> - et-0/0/2.3601 - </via> - <selected-next-hop /> - <label-element> - 0x4265080 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 4 - </label-element-refcount> - <label-element-childcount> - 2 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 532 - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.94.2 - </to> - <indirect-nh> - 0xa010800 1048619 INH Session ID: 0x5e1 - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Int Ext - </rt-entry-state> - <inactive-reason> - Route Preference - </inactive-reason> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="3790"> - 1:03:10 - </age> - <metric> - 0 - </metric> - <metric2> - 1000 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 1000 - </med-plus-igp> - <task-name> - BGP_14525.199.34.94.2 - </task-name> - <as-path> - AS path: 6939 196844 29414 34337 I - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 6939 196844 29414 34337 I - </attr-value> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 6939:7082 - </community> - <community> - 6939:8826 - </community> - <community> - 6939:9002 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3003 - </community> - <community> - 14525:4003 - </community> - <community> - 14525:9002 - </community> - <community> - large:8714:1000:2 - </community> - <community> - large:8714:1001:1 - </community> - <community> - large:8714:1001:2 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.94.2 - </peer-id> - </rt-entry> - </rt> - <rt junos:style="detail"> - <rt-destination> - 85.193.198.0 - </rt-destination> - <rt-prefix-length> - 23 - </rt-prefix-length> - <rt-entry-count junos:format="4 entries"> - 4 - </rt-entry-count> - <rt-announced-count> - 1 - </rt-announced-count> - <rt-entry> - <active-tag> - * - </active-tag> - <current-active /> - <last-active /> - <protocol-name> - BGP - </protocol-name> - <preference> - 170 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x42439f4c - </nh-address> - <nh-reference-count> - 757869 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.92.10 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 0 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.10 - </to> - <via> - et-0/0/0.0 - </via> - <weight> - 0x1 - </weight> - <selected-next-hop /> - <label-element> - 0x425dd00 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 13 - </label-element-refcount> - <label-element-childcount> - 9 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 0 - </session> - </nh> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.194 - </to> - <via> - et-0/0/1.3683 - </via> - <weight> - 0x1 - </weight> - <label-element> - 0x425dd00 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 13 - </label-element-refcount> - <label-element-childcount> - 9 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 0 - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.92.10 - </to> - <indirect-nh> - 0xa00d600 1048582 INH Session ID: 0x2c0 - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Active Int Ext - </rt-entry-state> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="2526246"> - 4w1d 5:44:06 - </age> - <metric> - 0 - </metric> - <metric2> - 10 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 10 - </med-plus-igp> - <task-name> - BGP_14525.199.34.92.10 - </task-name> - <announce-bits> - 4 - </announce-bits> - <announce-tasks> - 0-KRT 8-Resolve tree 3 10-Aggregate 12-RT - </announce-tasks> - <as-path> - AS path: 3356 13293 29414 34337 I - AS path: Recorded - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 3356 13293 29414 34337 I - </attr-value> - <flags> - </flags> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 3356:2 - </community> - <community> - 3356:22 - </community> - <community> - 3356:100 - </community> - <community> - 3356:123 - </community> - <community> - 3356:501 - </community> - <community> - 3356:903 - </community> - <community> - 3356:2071 - </community> - <community> - 8501:1014 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3001 - </community> - <community> - 14525:4001 - </community> - <community> - 14525:9014 - </community> - <community> - 29414:1020 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.92.10 - </peer-id> - </rt-entry> - <rt-entry> - <active-tag> - </active-tag> - <protocol-name> - BGP - </protocol-name> - <preference> - 200 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x122adabc - </nh-address> - <nh-reference-count> - 546682 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.94.1 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 1283 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.21 - </to> - <via> - et-0/0/2.3601 - </via> - <selected-next-hop /> - <label-element> - 0x8b6ab80 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 4 - </label-element-refcount> - <label-element-childcount> - 2 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 53c - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.94.1 - </to> - <indirect-nh> - 0xa011000 1048625 INH Session ID: 0x5dc - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Int Ext - </rt-entry-state> - <inactive-reason> - Route Preference - </inactive-reason> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="27367"> - 7:36:07 - </age> - <metric> - 0 - </metric> - <metric2> - 1000 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 1000 - </med-plus-igp> - <task-name> - BGP_14525.199.34.94.1 - </task-name> - <as-path> - AS path: 3356 13293 29414 34337 I - AS path: Recorded - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 3356 13293 29414 34337 I - </attr-value> - <flags> - </flags> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 3356:2 - </community> - <community> - 3356:22 - </community> - <community> - 3356:100 - </community> - <community> - 3356:123 - </community> - <community> - 3356:501 - </community> - <community> - 3356:903 - </community> - <community> - 3356:2071 - </community> - <community> - 8501:1014 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3003 - </community> - <community> - 14525:4003 - </community> - <community> - 14525:9014 - </community> - <community> - 29414:1020 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.94.1 - </peer-id> - </rt-entry> - <rt-entry> - <active-tag> - </active-tag> - <protocol-name> - BGP - </protocol-name> - <preference> - 200 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x1104e0dc - </nh-address> - <nh-reference-count> - 600499 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.94.2 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 1280 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.22 - </to> - <via> - et-0/0/2.3601 - </via> - <selected-next-hop /> - <label-element> - 0x4265080 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 4 - </label-element-refcount> - <label-element-childcount> - 2 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 532 - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.94.2 - </to> - <indirect-nh> - 0xa010800 1048619 INH Session ID: 0x5e1 - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Int Ext - </rt-entry-state> - <inactive-reason> - Route Preference - </inactive-reason> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="3790"> - 1:03:10 - </age> - <metric> - 0 - </metric> - <metric2> - 1000 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 1000 - </med-plus-igp> - <task-name> - BGP_14525.199.34.94.2 - </task-name> - <as-path> - AS path: 6939 196844 29414 34337 I - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 6939 196844 29414 34337 I - </attr-value> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 6939:7082 - </community> - <community> - 6939:8826 - </community> - <community> - 6939:9002 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3003 - </community> - <community> - 14525:4003 - </community> - <community> - 14525:9002 - </community> - <community> - large:8714:1000:2 - </community> - <community> - large:8714:1001:1 - </community> - <community> - large:8714:1001:2 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.94.2 - </peer-id> - </rt-entry> - </rt> - <rt junos:style="detail"> - <rt-destination> - 85.193.200.0 - </rt-destination> - <rt-prefix-length> - 23 - </rt-prefix-length> - <rt-entry-count junos:format="4 entries"> - 4 - </rt-entry-count> - <rt-announced-count> - 1 - </rt-announced-count> - <rt-entry> - <active-tag> - * - </active-tag> - <current-active /> - <last-active /> - <protocol-name> - BGP - </protocol-name> - <preference> - 170 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x42439f4c - </nh-address> - <nh-reference-count> - 757869 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.92.10 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 0 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.10 - </to> - <via> - et-0/0/0.0 - </via> - <weight> - 0x1 - </weight> - <label-element> - 0x425dd00 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 13 - </label-element-refcount> - <label-element-childcount> - 9 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 0 - </session> - </nh> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.194 - </to> - <via> - et-0/0/1.3683 - </via> - <weight> - 0x1 - </weight> - <selected-next-hop /> - <label-element> - 0x425dd00 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 13 - </label-element-refcount> - <label-element-childcount> - 9 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 0 - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.92.10 - </to> - <indirect-nh> - 0xa00d600 1048582 INH Session ID: 0x2c0 - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Active Int Ext - </rt-entry-state> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="2526246"> - 4w1d 5:44:06 - </age> - <metric> - 0 - </metric> - <metric2> - 10 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 10 - </med-plus-igp> - <task-name> - BGP_14525.199.34.92.10 - </task-name> - <announce-bits> - 4 - </announce-bits> - <announce-tasks> - 0-KRT 8-Resolve tree 3 10-Aggregate 12-RT - </announce-tasks> - <as-path> - AS path: 3356 13293 29414 34337 I - AS path: Recorded - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 3356 13293 29414 34337 I - </attr-value> - <flags> - </flags> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 3356:2 - </community> - <community> - 3356:22 - </community> - <community> - 3356:100 - </community> - <community> - 3356:123 - </community> - <community> - 3356:501 - </community> - <community> - 3356:903 - </community> - <community> - 3356:2071 - </community> - <community> - 8501:1014 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3001 - </community> - <community> - 14525:4001 - </community> - <community> - 14525:9014 - </community> - <community> - 29414:1020 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.92.10 - </peer-id> - </rt-entry> - <rt-entry> - <active-tag> - </active-tag> - <protocol-name> - BGP - </protocol-name> - <preference> - 200 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x122adabc - </nh-address> - <nh-reference-count> - 546682 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.94.1 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 1283 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.21 - </to> - <via> - et-0/0/2.3601 - </via> - <selected-next-hop /> - <label-element> - 0x8b6ab80 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 4 - </label-element-refcount> - <label-element-childcount> - 2 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 53c - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.94.1 - </to> - <indirect-nh> - 0xa011000 1048625 INH Session ID: 0x5dc - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Int Ext - </rt-entry-state> - <inactive-reason> - Route Preference - </inactive-reason> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="27367"> - 7:36:07 - </age> - <metric> - 0 - </metric> - <metric2> - 1000 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 1000 - </med-plus-igp> - <task-name> - BGP_14525.199.34.94.1 - </task-name> - <as-path> - AS path: 3356 13293 29414 34337 I - AS path: Recorded - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 3356 13293 29414 34337 I - </attr-value> - <flags> - </flags> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 3356:2 - </community> - <community> - 3356:22 - </community> - <community> - 3356:100 - </community> - <community> - 3356:123 - </community> - <community> - 3356:501 - </community> - <community> - 3356:903 - </community> - <community> - 3356:2071 - </community> - <community> - 8501:1014 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3003 - </community> - <community> - 14525:4003 - </community> - <community> - 14525:9014 - </community> - <community> - 29414:1020 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.94.1 - </peer-id> - </rt-entry> - <rt-entry> - <active-tag> - </active-tag> - <protocol-name> - BGP - </protocol-name> - <preference> - 200 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x1104e0dc - </nh-address> - <nh-reference-count> - 600499 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.94.2 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 1280 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.22 - </to> - <via> - et-0/0/2.3601 - </via> - <selected-next-hop /> - <label-element> - 0x4265080 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 4 - </label-element-refcount> - <label-element-childcount> - 2 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 532 - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.94.2 - </to> - <indirect-nh> - 0xa010800 1048619 INH Session ID: 0x5e1 - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Int Ext - </rt-entry-state> - <inactive-reason> - Route Preference - </inactive-reason> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="3790"> - 1:03:10 - </age> - <metric> - 0 - </metric> - <metric2> - 1000 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 1000 - </med-plus-igp> - <task-name> - BGP_14525.199.34.94.2 - </task-name> - <as-path> - AS path: 6939 196844 29414 34337 I - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 6939 196844 29414 34337 I - </attr-value> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 6939:7082 - </community> - <community> - 6939:8826 - </community> - <community> - 6939:9002 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3003 - </community> - <community> - 14525:4003 - </community> - <community> - 14525:9002 - </community> - <community> - large:8714:1000:2 - </community> - <community> - large:8714:1001:1 - </community> - <community> - large:8714:1001:2 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.94.2 - </peer-id> - </rt-entry> - </rt> - <rt junos:style="detail"> - <rt-destination> - 85.193.220.0 - </rt-destination> - <rt-prefix-length> - 23 - </rt-prefix-length> - <rt-entry-count junos:format="4 entries"> - 4 - </rt-entry-count> - <rt-announced-count> - 1 - </rt-announced-count> - <rt-entry> - <active-tag> - * - </active-tag> - <current-active /> - <last-active /> - <protocol-name> - BGP - </protocol-name> - <preference> - 170 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x42439f4c - </nh-address> - <nh-reference-count> - 757869 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.92.10 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 0 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.10 - </to> - <via> - et-0/0/0.0 - </via> - <weight> - 0x1 - </weight> - <label-element> - 0x425dd00 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 13 - </label-element-refcount> - <label-element-childcount> - 9 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 0 - </session> - </nh> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.194 - </to> - <via> - et-0/0/1.3683 - </via> - <weight> - 0x1 - </weight> - <selected-next-hop /> - <label-element> - 0x425dd00 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 13 - </label-element-refcount> - <label-element-childcount> - 9 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 0 - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.92.10 - </to> - <indirect-nh> - 0xa00d600 1048582 INH Session ID: 0x2c0 - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Active Int Ext - </rt-entry-state> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="2526246"> - 4w1d 5:44:06 - </age> - <metric> - 0 - </metric> - <metric2> - 10 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 10 - </med-plus-igp> - <task-name> - BGP_14525.199.34.92.10 - </task-name> - <announce-bits> - 4 - </announce-bits> - <announce-tasks> - 0-KRT 8-Resolve tree 3 10-Aggregate 12-RT - </announce-tasks> - <as-path> - AS path: 3356 13293 29414 34337 I - AS path: Recorded - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 3356 13293 29414 34337 I - </attr-value> - <flags> - </flags> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 3356:2 - </community> - <community> - 3356:22 - </community> - <community> - 3356:100 - </community> - <community> - 3356:123 - </community> - <community> - 3356:501 - </community> - <community> - 3356:903 - </community> - <community> - 3356:2071 - </community> - <community> - 8501:1014 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3001 - </community> - <community> - 14525:4001 - </community> - <community> - 14525:9014 - </community> - <community> - 29414:1020 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.92.10 - </peer-id> - </rt-entry> - <rt-entry> - <active-tag> - </active-tag> - <protocol-name> - BGP - </protocol-name> - <preference> - 200 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x122adabc - </nh-address> - <nh-reference-count> - 546682 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.94.1 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 1283 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.21 - </to> - <via> - et-0/0/2.3601 - </via> - <selected-next-hop /> - <label-element> - 0x8b6ab80 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 4 - </label-element-refcount> - <label-element-childcount> - 2 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 53c - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.94.1 - </to> - <indirect-nh> - 0xa011000 1048625 INH Session ID: 0x5dc - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Int Ext - </rt-entry-state> - <inactive-reason> - Route Preference - </inactive-reason> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="27367"> - 7:36:07 - </age> - <metric> - 0 - </metric> - <metric2> - 1000 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 1000 - </med-plus-igp> - <task-name> - BGP_14525.199.34.94.1 - </task-name> - <as-path> - AS path: 3356 13293 29414 34337 I - AS path: Recorded - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 3356 13293 29414 34337 I - </attr-value> - <flags> - </flags> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 3356:2 - </community> - <community> - 3356:22 - </community> - <community> - 3356:100 - </community> - <community> - 3356:123 - </community> - <community> - 3356:501 - </community> - <community> - 3356:903 - </community> - <community> - 3356:2071 - </community> - <community> - 8501:1014 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3003 - </community> - <community> - 14525:4003 - </community> - <community> - 14525:9014 - </community> - <community> - 29414:1020 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.94.1 - </peer-id> - </rt-entry> - <rt-entry> - <active-tag> - </active-tag> - <protocol-name> - BGP - </protocol-name> - <preference> - 200 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x1104e0dc - </nh-address> - <nh-reference-count> - 600499 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.94.2 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 1280 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.22 - </to> - <via> - et-0/0/2.3601 - </via> - <selected-next-hop /> - <label-element> - 0x4265080 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 4 - </label-element-refcount> - <label-element-childcount> - 2 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 532 - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.94.2 - </to> - <indirect-nh> - 0xa010800 1048619 INH Session ID: 0x5e1 - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Int Ext - </rt-entry-state> - <inactive-reason> - Route Preference - </inactive-reason> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="3790"> - 1:03:10 - </age> - <metric> - 0 - </metric> - <metric2> - 1000 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 1000 - </med-plus-igp> - <task-name> - BGP_14525.199.34.94.2 - </task-name> - <as-path> - AS path: 6939 196844 29414 34337 I - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 6939 196844 29414 34337 I - </attr-value> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 6939:7082 - </community> - <community> - 6939:8826 - </community> - <community> - 6939:9002 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3003 - </community> - <community> - 14525:4003 - </community> - <community> - 14525:9002 - </community> - <community> - large:8714:1000:2 - </community> - <community> - large:8714:1001:1 - </community> - <community> - large:8714:1001:2 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.94.2 - </peer-id> - </rt-entry> - </rt> - <rt junos:style="detail"> - <rt-destination> - 85.193.226.0 - </rt-destination> - <rt-prefix-length> - 23 - </rt-prefix-length> - <rt-entry-count junos:format="4 entries"> - 4 - </rt-entry-count> - <rt-announced-count> - 1 - </rt-announced-count> - <rt-entry> - <active-tag> - * - </active-tag> - <current-active /> - <last-active /> - <protocol-name> - BGP - </protocol-name> - <preference> - 170 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x42439f4c - </nh-address> - <nh-reference-count> - 757869 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.92.10 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 0 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.10 - </to> - <via> - et-0/0/0.0 - </via> - <weight> - 0x1 - </weight> - <selected-next-hop /> - <label-element> - 0x425dd00 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 13 - </label-element-refcount> - <label-element-childcount> - 9 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 0 - </session> - </nh> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.194 - </to> - <via> - et-0/0/1.3683 - </via> - <weight> - 0x1 - </weight> - <label-element> - 0x425dd00 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 13 - </label-element-refcount> - <label-element-childcount> - 9 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 0 - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.92.10 - </to> - <indirect-nh> - 0xa00d600 1048582 INH Session ID: 0x2c0 - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Active Int Ext - </rt-entry-state> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="2526246"> - 4w1d 5:44:06 - </age> - <metric> - 0 - </metric> - <metric2> - 10 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 10 - </med-plus-igp> - <task-name> - BGP_14525.199.34.92.10 - </task-name> - <announce-bits> - 4 - </announce-bits> - <announce-tasks> - 0-KRT 8-Resolve tree 3 10-Aggregate 12-RT - </announce-tasks> - <as-path> - AS path: 3356 13293 29414 34337 I - AS path: Recorded - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 3356 13293 29414 34337 I - </attr-value> - <flags> - </flags> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 3356:2 - </community> - <community> - 3356:22 - </community> - <community> - 3356:100 - </community> - <community> - 3356:123 - </community> - <community> - 3356:501 - </community> - <community> - 3356:903 - </community> - <community> - 3356:2071 - </community> - <community> - 8501:1014 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3001 - </community> - <community> - 14525:4001 - </community> - <community> - 14525:9014 - </community> - <community> - 29414:1020 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.92.10 - </peer-id> - </rt-entry> - <rt-entry> - <active-tag> - </active-tag> - <protocol-name> - BGP - </protocol-name> - <preference> - 200 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x122adabc - </nh-address> - <nh-reference-count> - 546682 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.94.1 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 1283 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.21 - </to> - <via> - et-0/0/2.3601 - </via> - <selected-next-hop /> - <label-element> - 0x8b6ab80 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 4 - </label-element-refcount> - <label-element-childcount> - 2 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 53c - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.94.1 - </to> - <indirect-nh> - 0xa011000 1048625 INH Session ID: 0x5dc - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Int Ext - </rt-entry-state> - <inactive-reason> - Route Preference - </inactive-reason> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="27367"> - 7:36:07 - </age> - <metric> - 0 - </metric> - <metric2> - 1000 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 1000 - </med-plus-igp> - <task-name> - BGP_14525.199.34.94.1 - </task-name> - <as-path> - AS path: 3356 13293 29414 34337 I - AS path: Recorded - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 3356 13293 29414 34337 I - </attr-value> - <flags> - </flags> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 3356:2 - </community> - <community> - 3356:22 - </community> - <community> - 3356:100 - </community> - <community> - 3356:123 - </community> - <community> - 3356:501 - </community> - <community> - 3356:903 - </community> - <community> - 3356:2071 - </community> - <community> - 8501:1014 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3003 - </community> - <community> - 14525:4003 - </community> - <community> - 14525:9014 - </community> - <community> - 29414:1020 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.94.1 - </peer-id> - </rt-entry> - <rt-entry> - <active-tag> - </active-tag> - <protocol-name> - BGP - </protocol-name> - <preference> - 200 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x1104e0dc - </nh-address> - <nh-reference-count> - 600499 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.94.2 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 1280 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.22 - </to> - <via> - et-0/0/2.3601 - </via> - <selected-next-hop /> - <label-element> - 0x4265080 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 4 - </label-element-refcount> - <label-element-childcount> - 2 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 532 - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.94.2 - </to> - <indirect-nh> - 0xa010800 1048619 INH Session ID: 0x5e1 - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Int Ext - </rt-entry-state> - <inactive-reason> - Route Preference - </inactive-reason> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="3790"> - 1:03:10 - </age> - <metric> - 0 - </metric> - <metric2> - 1000 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 1000 - </med-plus-igp> - <task-name> - BGP_14525.199.34.94.2 - </task-name> - <as-path> - AS path: 6939 196844 29414 34337 I - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 6939 196844 29414 34337 I - </attr-value> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 6939:7082 - </community> - <community> - 6939:8826 - </community> - <community> - 6939:9002 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3003 - </community> - <community> - 14525:4003 - </community> - <community> - 14525:9002 - </community> - <community> - large:8714:1000:2 - </community> - <community> - large:8714:1001:1 - </community> - <community> - large:8714:1001:2 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.94.2 - </peer-id> - </rt-entry> - </rt> - <rt junos:style="detail"> - <rt-destination> - 85.193.228.0 - </rt-destination> - <rt-prefix-length> - 23 - </rt-prefix-length> - <rt-entry-count junos:format="4 entries"> - 4 - </rt-entry-count> - <rt-announced-count> - 1 - </rt-announced-count> - <rt-entry> - <active-tag> - * - </active-tag> - <current-active /> - <last-active /> - <protocol-name> - BGP - </protocol-name> - <preference> - 170 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x42439f4c - </nh-address> - <nh-reference-count> - 757869 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.92.10 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 0 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.10 - </to> - <via> - et-0/0/0.0 - </via> - <weight> - 0x1 - </weight> - <selected-next-hop /> - <label-element> - 0x425dd00 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 13 - </label-element-refcount> - <label-element-childcount> - 9 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 0 - </session> - </nh> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.194 - </to> - <via> - et-0/0/1.3683 - </via> - <weight> - 0x1 - </weight> - <label-element> - 0x425dd00 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 13 - </label-element-refcount> - <label-element-childcount> - 9 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 0 - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.92.10 - </to> - <indirect-nh> - 0xa00d600 1048582 INH Session ID: 0x2c0 - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Active Int Ext - </rt-entry-state> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="2526246"> - 4w1d 5:44:06 - </age> - <metric> - 0 - </metric> - <metric2> - 10 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 10 - </med-plus-igp> - <task-name> - BGP_14525.199.34.92.10 - </task-name> - <announce-bits> - 4 - </announce-bits> - <announce-tasks> - 0-KRT 8-Resolve tree 3 10-Aggregate 12-RT - </announce-tasks> - <as-path> - AS path: 3356 13293 29414 34337 I - AS path: Recorded - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 3356 13293 29414 34337 I - </attr-value> - <flags> - </flags> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 3356:2 - </community> - <community> - 3356:22 - </community> - <community> - 3356:100 - </community> - <community> - 3356:123 - </community> - <community> - 3356:501 - </community> - <community> - 3356:903 - </community> - <community> - 3356:2071 - </community> - <community> - 8501:1014 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3001 - </community> - <community> - 14525:4001 - </community> - <community> - 14525:9014 - </community> - <community> - 29414:1020 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.92.10 - </peer-id> - </rt-entry> - <rt-entry> - <active-tag> - </active-tag> - <protocol-name> - BGP - </protocol-name> - <preference> - 200 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x122adabc - </nh-address> - <nh-reference-count> - 546682 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.94.1 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 1283 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.21 - </to> - <via> - et-0/0/2.3601 - </via> - <selected-next-hop /> - <label-element> - 0x8b6ab80 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 4 - </label-element-refcount> - <label-element-childcount> - 2 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 53c - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.94.1 - </to> - <indirect-nh> - 0xa011000 1048625 INH Session ID: 0x5dc - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Int Ext - </rt-entry-state> - <inactive-reason> - Route Preference - </inactive-reason> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="27367"> - 7:36:07 - </age> - <metric> - 0 - </metric> - <metric2> - 1000 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 1000 - </med-plus-igp> - <task-name> - BGP_14525.199.34.94.1 - </task-name> - <as-path> - AS path: 3356 13293 29414 34337 I - AS path: Recorded - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 3356 13293 29414 34337 I - </attr-value> - <flags> - </flags> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 3356:2 - </community> - <community> - 3356:22 - </community> - <community> - 3356:100 - </community> - <community> - 3356:123 - </community> - <community> - 3356:501 - </community> - <community> - 3356:903 - </community> - <community> - 3356:2071 - </community> - <community> - 8501:1014 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3003 - </community> - <community> - 14525:4003 - </community> - <community> - 14525:9014 - </community> - <community> - 29414:1020 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.94.1 - </peer-id> - </rt-entry> - <rt-entry> - <active-tag> - </active-tag> - <protocol-name> - BGP - </protocol-name> - <preference> - 200 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x1104e0dc - </nh-address> - <nh-reference-count> - 600499 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.94.2 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 1280 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.22 - </to> - <via> - et-0/0/2.3601 - </via> - <selected-next-hop /> - <label-element> - 0x4265080 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 4 - </label-element-refcount> - <label-element-childcount> - 2 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 532 - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.94.2 - </to> - <indirect-nh> - 0xa010800 1048619 INH Session ID: 0x5e1 - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Int Ext - </rt-entry-state> - <inactive-reason> - Route Preference - </inactive-reason> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="3790"> - 1:03:10 - </age> - <metric> - 0 - </metric> - <metric2> - 1000 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 1000 - </med-plus-igp> - <task-name> - BGP_14525.199.34.94.2 - </task-name> - <as-path> - AS path: 6939 196844 29414 34337 I - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 6939 196844 29414 34337 I - </attr-value> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 6939:7082 - </community> - <community> - 6939:8826 - </community> - <community> - 6939:9002 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3003 - </community> - <community> - 14525:4003 - </community> - <community> - 14525:9002 - </community> - <community> - large:8714:1000:2 - </community> - <community> - large:8714:1001:1 - </community> - <community> - large:8714:1001:2 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.94.2 - </peer-id> - </rt-entry> - </rt> - <rt junos:style="detail"> - <rt-destination> - 85.193.230.0 - </rt-destination> - <rt-prefix-length> - 23 - </rt-prefix-length> - <rt-entry-count junos:format="4 entries"> - 4 - </rt-entry-count> - <rt-announced-count> - 1 - </rt-announced-count> - <rt-entry> - <active-tag> - * - </active-tag> - <current-active /> - <last-active /> - <protocol-name> - BGP - </protocol-name> - <preference> - 170 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x42439f4c - </nh-address> - <nh-reference-count> - 757869 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.92.10 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 0 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.10 - </to> - <via> - et-0/0/0.0 - </via> - <weight> - 0x1 - </weight> - <selected-next-hop /> - <label-element> - 0x425dd00 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 13 - </label-element-refcount> - <label-element-childcount> - 9 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 0 - </session> - </nh> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.194 - </to> - <via> - et-0/0/1.3683 - </via> - <weight> - 0x1 - </weight> - <label-element> - 0x425dd00 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 13 - </label-element-refcount> - <label-element-childcount> - 9 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 0 - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.92.10 - </to> - <indirect-nh> - 0xa00d600 1048582 INH Session ID: 0x2c0 - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Active Int Ext - </rt-entry-state> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="2526246"> - 4w1d 5:44:06 - </age> - <metric> - 0 - </metric> - <metric2> - 10 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 10 - </med-plus-igp> - <task-name> - BGP_14525.199.34.92.10 - </task-name> - <announce-bits> - 4 - </announce-bits> - <announce-tasks> - 0-KRT 8-Resolve tree 3 10-Aggregate 12-RT - </announce-tasks> - <as-path> - AS path: 3356 13293 29414 34337 I - AS path: Recorded - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 3356 13293 29414 34337 I - </attr-value> - <flags> - </flags> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 3356:2 - </community> - <community> - 3356:22 - </community> - <community> - 3356:100 - </community> - <community> - 3356:123 - </community> - <community> - 3356:501 - </community> - <community> - 3356:903 - </community> - <community> - 3356:2071 - </community> - <community> - 8501:1014 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3001 - </community> - <community> - 14525:4001 - </community> - <community> - 14525:9014 - </community> - <community> - 29414:1020 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.92.10 - </peer-id> - </rt-entry> - <rt-entry> - <active-tag> - </active-tag> - <protocol-name> - BGP - </protocol-name> - <preference> - 200 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x122adabc - </nh-address> - <nh-reference-count> - 546682 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.94.1 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 1283 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.21 - </to> - <via> - et-0/0/2.3601 - </via> - <selected-next-hop /> - <label-element> - 0x8b6ab80 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 4 - </label-element-refcount> - <label-element-childcount> - 2 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 53c - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.94.1 - </to> - <indirect-nh> - 0xa011000 1048625 INH Session ID: 0x5dc - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Int Ext - </rt-entry-state> - <inactive-reason> - Route Preference - </inactive-reason> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="27367"> - 7:36:07 - </age> - <metric> - 0 - </metric> - <metric2> - 1000 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 1000 - </med-plus-igp> - <task-name> - BGP_14525.199.34.94.1 - </task-name> - <as-path> - AS path: 3356 13293 29414 34337 I - AS path: Recorded - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 3356 13293 29414 34337 I - </attr-value> - <flags> - </flags> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 3356:2 - </community> - <community> - 3356:22 - </community> - <community> - 3356:100 - </community> - <community> - 3356:123 - </community> - <community> - 3356:501 - </community> - <community> - 3356:903 - </community> - <community> - 3356:2071 - </community> - <community> - 8501:1014 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3003 - </community> - <community> - 14525:4003 - </community> - <community> - 14525:9014 - </community> - <community> - 29414:1020 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.94.1 - </peer-id> - </rt-entry> - <rt-entry> - <active-tag> - </active-tag> - <protocol-name> - BGP - </protocol-name> - <preference> - 200 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x1104e0dc - </nh-address> - <nh-reference-count> - 600499 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.94.2 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 1280 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.22 - </to> - <via> - et-0/0/2.3601 - </via> - <selected-next-hop /> - <label-element> - 0x4265080 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 4 - </label-element-refcount> - <label-element-childcount> - 2 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 532 - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.94.2 - </to> - <indirect-nh> - 0xa010800 1048619 INH Session ID: 0x5e1 - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Int Ext - </rt-entry-state> - <inactive-reason> - Route Preference - </inactive-reason> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="3790"> - 1:03:10 - </age> - <metric> - 0 - </metric> - <metric2> - 1000 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 1000 - </med-plus-igp> - <task-name> - BGP_14525.199.34.94.2 - </task-name> - <as-path> - AS path: 6939 196844 29414 34337 I - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 6939 196844 29414 34337 I - </attr-value> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 6939:7082 - </community> - <community> - 6939:8826 - </community> - <community> - 6939:9002 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3003 - </community> - <community> - 14525:4003 - </community> - <community> - 14525:9002 - </community> - <community> - large:8714:1000:2 - </community> - <community> - large:8714:1001:1 - </community> - <community> - large:8714:1001:2 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.94.2 - </peer-id> - </rt-entry> - </rt> - <rt junos:style="detail"> - <rt-destination> - 85.193.232.0 - </rt-destination> - <rt-prefix-length> - 21 - </rt-prefix-length> - <rt-entry-count junos:format="4 entries"> - 4 - </rt-entry-count> - <rt-announced-count> - 1 - </rt-announced-count> - <rt-entry> - <active-tag> - * - </active-tag> - <current-active /> - <last-active /> - <protocol-name> - BGP - </protocol-name> - <preference> - 170 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x42439f4c - </nh-address> - <nh-reference-count> - 757869 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.92.10 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 0 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.10 - </to> - <via> - et-0/0/0.0 - </via> - <weight> - 0x1 - </weight> - <label-element> - 0x425dd00 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 13 - </label-element-refcount> - <label-element-childcount> - 9 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 0 - </session> - </nh> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.194 - </to> - <via> - et-0/0/1.3683 - </via> - <weight> - 0x1 - </weight> - <selected-next-hop /> - <label-element> - 0x425dd00 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 13 - </label-element-refcount> - <label-element-childcount> - 9 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 0 - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.92.10 - </to> - <indirect-nh> - 0xa00d600 1048582 INH Session ID: 0x2c0 - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Active Int Ext - </rt-entry-state> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="2526246"> - 4w1d 5:44:06 - </age> - <metric> - 0 - </metric> - <metric2> - 10 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 10 - </med-plus-igp> - <task-name> - BGP_14525.199.34.92.10 - </task-name> - <announce-bits> - 4 - </announce-bits> - <announce-tasks> - 0-KRT 8-Resolve tree 3 10-Aggregate 12-RT - </announce-tasks> - <as-path> - AS path: 3356 13293 29414 34337 I - AS path: Recorded - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 3356 13293 29414 34337 I - </attr-value> - <flags> - </flags> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 3356:2 - </community> - <community> - 3356:22 - </community> - <community> - 3356:100 - </community> - <community> - 3356:123 - </community> - <community> - 3356:501 - </community> - <community> - 3356:903 - </community> - <community> - 3356:2071 - </community> - <community> - 8501:1014 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3001 - </community> - <community> - 14525:4001 - </community> - <community> - 14525:9014 - </community> - <community> - 29414:1020 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.92.10 - </peer-id> - </rt-entry> - <rt-entry> - <active-tag> - </active-tag> - <protocol-name> - BGP - </protocol-name> - <preference> - 200 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x122adabc - </nh-address> - <nh-reference-count> - 546682 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.94.1 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 1283 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.21 - </to> - <via> - et-0/0/2.3601 - </via> - <selected-next-hop /> - <label-element> - 0x8b6ab80 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 4 - </label-element-refcount> - <label-element-childcount> - 2 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 53c - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.94.1 - </to> - <indirect-nh> - 0xa011000 1048625 INH Session ID: 0x5dc - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Int Ext - </rt-entry-state> - <inactive-reason> - Route Preference - </inactive-reason> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="27367"> - 7:36:07 - </age> - <metric> - 0 - </metric> - <metric2> - 1000 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 1000 - </med-plus-igp> - <task-name> - BGP_14525.199.34.94.1 - </task-name> - <as-path> - AS path: 3356 13293 29414 34337 I - AS path: Recorded - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 3356 13293 29414 34337 I - </attr-value> - <flags> - </flags> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 3356:2 - </community> - <community> - 3356:22 - </community> - <community> - 3356:100 - </community> - <community> - 3356:123 - </community> - <community> - 3356:501 - </community> - <community> - 3356:903 - </community> - <community> - 3356:2071 - </community> - <community> - 8501:1014 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3003 - </community> - <community> - 14525:4003 - </community> - <community> - 14525:9014 - </community> - <community> - 29414:1020 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.94.1 - </peer-id> - </rt-entry> - <rt-entry> - <active-tag> - </active-tag> - <protocol-name> - BGP - </protocol-name> - <preference> - 200 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x1104e0dc - </nh-address> - <nh-reference-count> - 600499 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.94.2 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 1280 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.22 - </to> - <via> - et-0/0/2.3601 - </via> - <selected-next-hop /> - <label-element> - 0x4265080 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 4 - </label-element-refcount> - <label-element-childcount> - 2 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 532 - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.94.2 - </to> - <indirect-nh> - 0xa010800 1048619 INH Session ID: 0x5e1 - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Int Ext - </rt-entry-state> - <inactive-reason> - Route Preference - </inactive-reason> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="3790"> - 1:03:10 - </age> - <metric> - 0 - </metric> - <metric2> - 1000 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 1000 - </med-plus-igp> - <task-name> - BGP_14525.199.34.94.2 - </task-name> - <as-path> - AS path: 6939 196844 29414 34337 I - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 6939 196844 29414 34337 I - </attr-value> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 6939:7082 - </community> - <community> - 6939:8826 - </community> - <community> - 6939:9002 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3003 - </community> - <community> - 14525:4003 - </community> - <community> - 14525:9002 - </community> - <community> - large:8714:1000:2 - </community> - <community> - large:8714:1001:1 - </community> - <community> - large:8714:1001:2 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.94.2 - </peer-id> - </rt-entry> - </rt> - <rt junos:style="detail"> - <rt-destination> - 85.193.232.0 - </rt-destination> - <rt-prefix-length> - 23 - </rt-prefix-length> - <rt-entry-count junos:format="4 entries"> - 4 - </rt-entry-count> - <rt-announced-count> - 1 - </rt-announced-count> - <rt-entry> - <active-tag> - * - </active-tag> - <current-active /> - <last-active /> - <protocol-name> - BGP - </protocol-name> - <preference> - 170 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x42439f4c - </nh-address> - <nh-reference-count> - 757869 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.92.10 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 0 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.10 - </to> - <via> - et-0/0/0.0 - </via> - <weight> - 0x1 - </weight> - <label-element> - 0x425dd00 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 13 - </label-element-refcount> - <label-element-childcount> - 9 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 0 - </session> - </nh> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.194 - </to> - <via> - et-0/0/1.3683 - </via> - <weight> - 0x1 - </weight> - <selected-next-hop /> - <label-element> - 0x425dd00 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 13 - </label-element-refcount> - <label-element-childcount> - 9 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 0 - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.92.10 - </to> - <indirect-nh> - 0xa00d600 1048582 INH Session ID: 0x2c0 - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Active Int Ext - </rt-entry-state> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="2526246"> - 4w1d 5:44:06 - </age> - <metric> - 0 - </metric> - <metric2> - 10 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 10 - </med-plus-igp> - <task-name> - BGP_14525.199.34.92.10 - </task-name> - <announce-bits> - 4 - </announce-bits> - <announce-tasks> - 0-KRT 8-Resolve tree 3 10-Aggregate 12-RT - </announce-tasks> - <as-path> - AS path: 3356 13293 29414 34337 I - AS path: Recorded - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 3356 13293 29414 34337 I - </attr-value> - <flags> - </flags> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 3356:2 - </community> - <community> - 3356:22 - </community> - <community> - 3356:100 - </community> - <community> - 3356:123 - </community> - <community> - 3356:501 - </community> - <community> - 3356:903 - </community> - <community> - 3356:2071 - </community> - <community> - 8501:1014 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3001 - </community> - <community> - 14525:4001 - </community> - <community> - 14525:9014 - </community> - <community> - 29414:1020 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.92.10 - </peer-id> - </rt-entry> - <rt-entry> - <active-tag> - </active-tag> - <protocol-name> - BGP - </protocol-name> - <preference> - 200 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x122adabc - </nh-address> - <nh-reference-count> - 546682 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.94.1 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 1283 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.21 - </to> - <via> - et-0/0/2.3601 - </via> - <selected-next-hop /> - <label-element> - 0x8b6ab80 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 4 - </label-element-refcount> - <label-element-childcount> - 2 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 53c - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.94.1 - </to> - <indirect-nh> - 0xa011000 1048625 INH Session ID: 0x5dc - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Int Ext - </rt-entry-state> - <inactive-reason> - Route Preference - </inactive-reason> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="27367"> - 7:36:07 - </age> - <metric> - 0 - </metric> - <metric2> - 1000 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 1000 - </med-plus-igp> - <task-name> - BGP_14525.199.34.94.1 - </task-name> - <as-path> - AS path: 3356 13293 29414 34337 I - AS path: Recorded - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 3356 13293 29414 34337 I - </attr-value> - <flags> - </flags> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 3356:2 - </community> - <community> - 3356:22 - </community> - <community> - 3356:100 - </community> - <community> - 3356:123 - </community> - <community> - 3356:501 - </community> - <community> - 3356:903 - </community> - <community> - 3356:2071 - </community> - <community> - 8501:1014 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3003 - </community> - <community> - 14525:4003 - </community> - <community> - 14525:9014 - </community> - <community> - 29414:1020 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.94.1 - </peer-id> - </rt-entry> - <rt-entry> - <active-tag> - </active-tag> - <protocol-name> - BGP - </protocol-name> - <preference> - 200 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x1104e0dc - </nh-address> - <nh-reference-count> - 600499 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.94.2 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 1280 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.22 - </to> - <via> - et-0/0/2.3601 - </via> - <selected-next-hop /> - <label-element> - 0x4265080 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 4 - </label-element-refcount> - <label-element-childcount> - 2 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 532 - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.94.2 - </to> - <indirect-nh> - 0xa010800 1048619 INH Session ID: 0x5e1 - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Int Ext - </rt-entry-state> - <inactive-reason> - Route Preference - </inactive-reason> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="3790"> - 1:03:10 - </age> - <metric> - 0 - </metric> - <metric2> - 1000 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 1000 - </med-plus-igp> - <task-name> - BGP_14525.199.34.94.2 - </task-name> - <as-path> - AS path: 6939 196844 29414 34337 I - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 6939 196844 29414 34337 I - </attr-value> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 6939:7082 - </community> - <community> - 6939:8826 - </community> - <community> - 6939:9002 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3003 - </community> - <community> - 14525:4003 - </community> - <community> - 14525:9002 - </community> - <community> - large:8714:1000:2 - </community> - <community> - large:8714:1001:1 - </community> - <community> - large:8714:1001:2 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.94.2 - </peer-id> - </rt-entry> - </rt> - <rt junos:style="detail"> - <rt-destination> - 85.193.234.0 - </rt-destination> - <rt-prefix-length> - 23 - </rt-prefix-length> - <rt-entry-count junos:format="4 entries"> - 4 - </rt-entry-count> - <rt-announced-count> - 1 - </rt-announced-count> - <rt-entry> - <active-tag> - * - </active-tag> - <current-active /> - <last-active /> - <protocol-name> - BGP - </protocol-name> - <preference> - 170 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x42439f4c - </nh-address> - <nh-reference-count> - 757869 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.92.10 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 0 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.10 - </to> - <via> - et-0/0/0.0 - </via> - <weight> - 0x1 - </weight> - <label-element> - 0x425dd00 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 13 - </label-element-refcount> - <label-element-childcount> - 9 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 0 - </session> - </nh> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.194 - </to> - <via> - et-0/0/1.3683 - </via> - <weight> - 0x1 - </weight> - <selected-next-hop /> - <label-element> - 0x425dd00 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 13 - </label-element-refcount> - <label-element-childcount> - 9 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 0 - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.92.10 - </to> - <indirect-nh> - 0xa00d600 1048582 INH Session ID: 0x2c0 - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Active Int Ext - </rt-entry-state> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="2526246"> - 4w1d 5:44:06 - </age> - <metric> - 0 - </metric> - <metric2> - 10 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 10 - </med-plus-igp> - <task-name> - BGP_14525.199.34.92.10 - </task-name> - <announce-bits> - 4 - </announce-bits> - <announce-tasks> - 0-KRT 8-Resolve tree 3 10-Aggregate 12-RT - </announce-tasks> - <as-path> - AS path: 3356 13293 29414 34337 I - AS path: Recorded - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 3356 13293 29414 34337 I - </attr-value> - <flags> - </flags> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 3356:2 - </community> - <community> - 3356:22 - </community> - <community> - 3356:100 - </community> - <community> - 3356:123 - </community> - <community> - 3356:501 - </community> - <community> - 3356:903 - </community> - <community> - 3356:2071 - </community> - <community> - 8501:1014 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3001 - </community> - <community> - 14525:4001 - </community> - <community> - 14525:9014 - </community> - <community> - 29414:1020 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.92.10 - </peer-id> - </rt-entry> - <rt-entry> - <active-tag> - </active-tag> - <protocol-name> - BGP - </protocol-name> - <preference> - 200 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x122adabc - </nh-address> - <nh-reference-count> - 546682 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.94.1 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 1283 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.21 - </to> - <via> - et-0/0/2.3601 - </via> - <selected-next-hop /> - <label-element> - 0x8b6ab80 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 4 - </label-element-refcount> - <label-element-childcount> - 2 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 53c - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.94.1 - </to> - <indirect-nh> - 0xa011000 1048625 INH Session ID: 0x5dc - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Int Ext - </rt-entry-state> - <inactive-reason> - Route Preference - </inactive-reason> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="27367"> - 7:36:07 - </age> - <metric> - 0 - </metric> - <metric2> - 1000 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 1000 - </med-plus-igp> - <task-name> - BGP_14525.199.34.94.1 - </task-name> - <as-path> - AS path: 3356 13293 29414 34337 I - AS path: Recorded - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 3356 13293 29414 34337 I - </attr-value> - <flags> - </flags> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 3356:2 - </community> - <community> - 3356:22 - </community> - <community> - 3356:100 - </community> - <community> - 3356:123 - </community> - <community> - 3356:501 - </community> - <community> - 3356:903 - </community> - <community> - 3356:2071 - </community> - <community> - 8501:1014 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3003 - </community> - <community> - 14525:4003 - </community> - <community> - 14525:9014 - </community> - <community> - 29414:1020 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.94.1 - </peer-id> - </rt-entry> - <rt-entry> - <active-tag> - </active-tag> - <protocol-name> - BGP - </protocol-name> - <preference> - 200 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x1104e0dc - </nh-address> - <nh-reference-count> - 600499 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.94.2 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 1280 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.22 - </to> - <via> - et-0/0/2.3601 - </via> - <selected-next-hop /> - <label-element> - 0x4265080 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 4 - </label-element-refcount> - <label-element-childcount> - 2 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 532 - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.94.2 - </to> - <indirect-nh> - 0xa010800 1048619 INH Session ID: 0x5e1 - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Int Ext - </rt-entry-state> - <inactive-reason> - Route Preference - </inactive-reason> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="3790"> - 1:03:10 - </age> - <metric> - 0 - </metric> - <metric2> - 1000 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 1000 - </med-plus-igp> - <task-name> - BGP_14525.199.34.94.2 - </task-name> - <as-path> - AS path: 6939 196844 29414 34337 I - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 6939 196844 29414 34337 I - </attr-value> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 6939:7082 - </community> - <community> - 6939:8826 - </community> - <community> - 6939:9002 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3003 - </community> - <community> - 14525:4003 - </community> - <community> - 14525:9002 - </community> - <community> - large:8714:1000:2 - </community> - <community> - large:8714:1001:1 - </community> - <community> - large:8714:1001:2 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.94.2 - </peer-id> - </rt-entry> - </rt> - <rt junos:style="detail"> - <rt-destination> - 85.193.236.0 - </rt-destination> - <rt-prefix-length> - 23 - </rt-prefix-length> - <rt-entry-count junos:format="4 entries"> - 4 - </rt-entry-count> - <rt-announced-count> - 1 - </rt-announced-count> - <rt-entry> - <active-tag> - * - </active-tag> - <current-active /> - <last-active /> - <protocol-name> - BGP - </protocol-name> - <preference> - 170 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x42439f4c - </nh-address> - <nh-reference-count> - 757869 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.92.10 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 0 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.10 - </to> - <via> - et-0/0/0.0 - </via> - <weight> - 0x1 - </weight> - <label-element> - 0x425dd00 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 13 - </label-element-refcount> - <label-element-childcount> - 9 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 0 - </session> - </nh> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.194 - </to> - <via> - et-0/0/1.3683 - </via> - <weight> - 0x1 - </weight> - <selected-next-hop /> - <label-element> - 0x425dd00 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 13 - </label-element-refcount> - <label-element-childcount> - 9 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 0 - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.92.10 - </to> - <indirect-nh> - 0xa00d600 1048582 INH Session ID: 0x2c0 - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Active Int Ext - </rt-entry-state> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="2526246"> - 4w1d 5:44:06 - </age> - <metric> - 0 - </metric> - <metric2> - 10 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 10 - </med-plus-igp> - <task-name> - BGP_14525.199.34.92.10 - </task-name> - <announce-bits> - 4 - </announce-bits> - <announce-tasks> - 0-KRT 8-Resolve tree 3 10-Aggregate 12-RT - </announce-tasks> - <as-path> - AS path: 3356 13293 29414 34337 I - AS path: Recorded - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 3356 13293 29414 34337 I - </attr-value> - <flags> - </flags> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 3356:2 - </community> - <community> - 3356:22 - </community> - <community> - 3356:100 - </community> - <community> - 3356:123 - </community> - <community> - 3356:501 - </community> - <community> - 3356:903 - </community> - <community> - 3356:2071 - </community> - <community> - 8501:1014 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3001 - </community> - <community> - 14525:4001 - </community> - <community> - 14525:9014 - </community> - <community> - 29414:1020 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.92.10 - </peer-id> - </rt-entry> - <rt-entry> - <active-tag> - </active-tag> - <protocol-name> - BGP - </protocol-name> - <preference> - 200 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x122adabc - </nh-address> - <nh-reference-count> - 546682 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.94.1 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 1283 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.21 - </to> - <via> - et-0/0/2.3601 - </via> - <selected-next-hop /> - <label-element> - 0x8b6ab80 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 4 - </label-element-refcount> - <label-element-childcount> - 2 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 53c - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.94.1 - </to> - <indirect-nh> - 0xa011000 1048625 INH Session ID: 0x5dc - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Int Ext - </rt-entry-state> - <inactive-reason> - Route Preference - </inactive-reason> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="27367"> - 7:36:07 - </age> - <metric> - 0 - </metric> - <metric2> - 1000 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 1000 - </med-plus-igp> - <task-name> - BGP_14525.199.34.94.1 - </task-name> - <as-path> - AS path: 3356 13293 29414 34337 I - AS path: Recorded - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 3356 13293 29414 34337 I - </attr-value> - <flags> - </flags> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 3356:2 - </community> - <community> - 3356:22 - </community> - <community> - 3356:100 - </community> - <community> - 3356:123 - </community> - <community> - 3356:501 - </community> - <community> - 3356:903 - </community> - <community> - 3356:2071 - </community> - <community> - 8501:1014 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3003 - </community> - <community> - 14525:4003 - </community> - <community> - 14525:9014 - </community> - <community> - 29414:1020 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.94.1 - </peer-id> - </rt-entry> - <rt-entry> - <active-tag> - </active-tag> - <protocol-name> - BGP - </protocol-name> - <preference> - 200 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x1104e0dc - </nh-address> - <nh-reference-count> - 600499 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.94.2 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 1280 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.22 - </to> - <via> - et-0/0/2.3601 - </via> - <selected-next-hop /> - <label-element> - 0x4265080 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 4 - </label-element-refcount> - <label-element-childcount> - 2 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 532 - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.94.2 - </to> - <indirect-nh> - 0xa010800 1048619 INH Session ID: 0x5e1 - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Int Ext - </rt-entry-state> - <inactive-reason> - Route Preference - </inactive-reason> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="3790"> - 1:03:10 - </age> - <metric> - 0 - </metric> - <metric2> - 1000 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 1000 - </med-plus-igp> - <task-name> - BGP_14525.199.34.94.2 - </task-name> - <as-path> - AS path: 6939 196844 29414 34337 I - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 6939 196844 29414 34337 I - </attr-value> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 6939:7082 - </community> - <community> - 6939:8826 - </community> - <community> - 6939:9002 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3003 - </community> - <community> - 14525:4003 - </community> - <community> - 14525:9002 - </community> - <community> - large:8714:1000:2 - </community> - <community> - large:8714:1001:1 - </community> - <community> - large:8714:1001:2 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.94.2 - </peer-id> - </rt-entry> - </rt> - <rt junos:style="detail"> - <rt-destination> - 85.193.238.0 - </rt-destination> - <rt-prefix-length> - 23 - </rt-prefix-length> - <rt-entry-count junos:format="4 entries"> - 4 - </rt-entry-count> - <rt-announced-count> - 1 - </rt-announced-count> - <rt-entry> - <active-tag> - * - </active-tag> - <current-active /> - <last-active /> - <protocol-name> - BGP - </protocol-name> - <preference> - 170 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x42439f4c - </nh-address> - <nh-reference-count> - 757869 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.92.10 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 0 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.10 - </to> - <via> - et-0/0/0.0 - </via> - <weight> - 0x1 - </weight> - <label-element> - 0x425dd00 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 13 - </label-element-refcount> - <label-element-childcount> - 9 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 0 - </session> - </nh> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.194 - </to> - <via> - et-0/0/1.3683 - </via> - <weight> - 0x1 - </weight> - <selected-next-hop /> - <label-element> - 0x425dd00 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 13 - </label-element-refcount> - <label-element-childcount> - 9 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 0 - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.92.10 - </to> - <indirect-nh> - 0xa00d600 1048582 INH Session ID: 0x2c0 - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Active Int Ext - </rt-entry-state> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="2526246"> - 4w1d 5:44:06 - </age> - <metric> - 0 - </metric> - <metric2> - 10 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 10 - </med-plus-igp> - <task-name> - BGP_14525.199.34.92.10 - </task-name> - <announce-bits> - 4 - </announce-bits> - <announce-tasks> - 0-KRT 8-Resolve tree 3 10-Aggregate 12-RT - </announce-tasks> - <as-path> - AS path: 3356 13293 29414 34337 I - AS path: Recorded - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 3356 13293 29414 34337 I - </attr-value> - <flags> - </flags> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 3356:2 - </community> - <community> - 3356:22 - </community> - <community> - 3356:100 - </community> - <community> - 3356:123 - </community> - <community> - 3356:501 - </community> - <community> - 3356:903 - </community> - <community> - 3356:2071 - </community> - <community> - 8501:1014 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3001 - </community> - <community> - 14525:4001 - </community> - <community> - 14525:9014 - </community> - <community> - 29414:1020 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.92.10 - </peer-id> - </rt-entry> - <rt-entry> - <active-tag> - </active-tag> - <protocol-name> - BGP - </protocol-name> - <preference> - 200 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x122adabc - </nh-address> - <nh-reference-count> - 546682 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.94.1 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 1283 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.21 - </to> - <via> - et-0/0/2.3601 - </via> - <selected-next-hop /> - <label-element> - 0x8b6ab80 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 4 - </label-element-refcount> - <label-element-childcount> - 2 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 53c - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.94.1 - </to> - <indirect-nh> - 0xa011000 1048625 INH Session ID: 0x5dc - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Int Ext - </rt-entry-state> - <inactive-reason> - Route Preference - </inactive-reason> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="27367"> - 7:36:07 - </age> - <metric> - 0 - </metric> - <metric2> - 1000 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 1000 - </med-plus-igp> - <task-name> - BGP_14525.199.34.94.1 - </task-name> - <as-path> - AS path: 3356 13293 29414 34337 I - AS path: Recorded - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 3356 13293 29414 34337 I - </attr-value> - <flags> - </flags> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 3356:2 - </community> - <community> - 3356:22 - </community> - <community> - 3356:100 - </community> - <community> - 3356:123 - </community> - <community> - 3356:501 - </community> - <community> - 3356:903 - </community> - <community> - 3356:2071 - </community> - <community> - 8501:1014 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3003 - </community> - <community> - 14525:4003 - </community> - <community> - 14525:9014 - </community> - <community> - 29414:1020 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.94.1 - </peer-id> - </rt-entry> - <rt-entry> - <active-tag> - </active-tag> - <protocol-name> - BGP - </protocol-name> - <preference> - 200 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x1104e0dc - </nh-address> - <nh-reference-count> - 600499 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.94.2 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 1280 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.22 - </to> - <via> - et-0/0/2.3601 - </via> - <selected-next-hop /> - <label-element> - 0x4265080 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 4 - </label-element-refcount> - <label-element-childcount> - 2 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 532 - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.94.2 - </to> - <indirect-nh> - 0xa010800 1048619 INH Session ID: 0x5e1 - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Int Ext - </rt-entry-state> - <inactive-reason> - Route Preference - </inactive-reason> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="3790"> - 1:03:10 - </age> - <metric> - 0 - </metric> - <metric2> - 1000 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 1000 - </med-plus-igp> - <task-name> - BGP_14525.199.34.94.2 - </task-name> - <as-path> - AS path: 6939 196844 29414 34337 I - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 6939 196844 29414 34337 I - </attr-value> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 6939:7082 - </community> - <community> - 6939:8826 - </community> - <community> - 6939:9002 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3003 - </community> - <community> - 14525:4003 - </community> - <community> - 14525:9002 - </community> - <community> - large:8714:1000:2 - </community> - <community> - large:8714:1001:1 - </community> - <community> - large:8714:1001:2 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.94.2 - </peer-id> - </rt-entry> - </rt> - <rt junos:style="detail"> - <rt-destination> - 85.193.240.0 - </rt-destination> - <rt-prefix-length> - 20 - </rt-prefix-length> - <rt-entry-count junos:format="4 entries"> - 4 - </rt-entry-count> - <rt-announced-count> - 1 - </rt-announced-count> - <rt-entry> - <active-tag> - * - </active-tag> - <current-active /> - <last-active /> - <protocol-name> - BGP - </protocol-name> - <preference> - 170 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x42439f4c - </nh-address> - <nh-reference-count> - 757869 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.92.10 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 0 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.10 - </to> - <via> - et-0/0/0.0 - </via> - <weight> - 0x1 - </weight> - <selected-next-hop /> - <label-element> - 0x425dd00 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 13 - </label-element-refcount> - <label-element-childcount> - 9 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 0 - </session> - </nh> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.194 - </to> - <via> - et-0/0/1.3683 - </via> - <weight> - 0x1 - </weight> - <label-element> - 0x425dd00 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 13 - </label-element-refcount> - <label-element-childcount> - 9 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 0 - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.92.10 - </to> - <indirect-nh> - 0xa00d600 1048582 INH Session ID: 0x2c0 - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Active Int Ext - </rt-entry-state> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="2526246"> - 4w1d 5:44:06 - </age> - <metric> - 0 - </metric> - <metric2> - 10 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 10 - </med-plus-igp> - <task-name> - BGP_14525.199.34.92.10 - </task-name> - <announce-bits> - 4 - </announce-bits> - <announce-tasks> - 0-KRT 8-Resolve tree 3 10-Aggregate 12-RT - </announce-tasks> - <as-path> - AS path: 3356 13293 29414 34337 I - AS path: Recorded - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 3356 13293 29414 34337 I - </attr-value> - <flags> - </flags> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 3356:2 - </community> - <community> - 3356:22 - </community> - <community> - 3356:100 - </community> - <community> - 3356:123 - </community> - <community> - 3356:501 - </community> - <community> - 3356:903 - </community> - <community> - 3356:2071 - </community> - <community> - 8501:1014 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3001 - </community> - <community> - 14525:4001 - </community> - <community> - 14525:9014 - </community> - <community> - 29414:1020 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.92.10 - </peer-id> - </rt-entry> - <rt-entry> - <active-tag> - </active-tag> - <protocol-name> - BGP - </protocol-name> - <preference> - 200 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x122adabc - </nh-address> - <nh-reference-count> - 546682 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.94.1 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 1283 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.21 - </to> - <via> - et-0/0/2.3601 - </via> - <selected-next-hop /> - <label-element> - 0x8b6ab80 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 4 - </label-element-refcount> - <label-element-childcount> - 2 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 53c - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.94.1 - </to> - <indirect-nh> - 0xa011000 1048625 INH Session ID: 0x5dc - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Int Ext - </rt-entry-state> - <inactive-reason> - Route Preference - </inactive-reason> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="27367"> - 7:36:07 - </age> - <metric> - 0 - </metric> - <metric2> - 1000 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 1000 - </med-plus-igp> - <task-name> - BGP_14525.199.34.94.1 - </task-name> - <as-path> - AS path: 3356 13293 29414 34337 I - AS path: Recorded - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 3356 13293 29414 34337 I - </attr-value> - <flags> - </flags> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 3356:2 - </community> - <community> - 3356:22 - </community> - <community> - 3356:100 - </community> - <community> - 3356:123 - </community> - <community> - 3356:501 - </community> - <community> - 3356:903 - </community> - <community> - 3356:2071 - </community> - <community> - 8501:1014 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3003 - </community> - <community> - 14525:4003 - </community> - <community> - 14525:9014 - </community> - <community> - 29414:1020 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.94.1 - </peer-id> - </rt-entry> - <rt-entry> - <active-tag> - </active-tag> - <protocol-name> - BGP - </protocol-name> - <preference> - 200 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x1104e0dc - </nh-address> - <nh-reference-count> - 600499 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.94.2 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 1280 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.22 - </to> - <via> - et-0/0/2.3601 - </via> - <selected-next-hop /> - <label-element> - 0x4265080 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 4 - </label-element-refcount> - <label-element-childcount> - 2 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 532 - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.94.2 - </to> - <indirect-nh> - 0xa010800 1048619 INH Session ID: 0x5e1 - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Int Ext - </rt-entry-state> - <inactive-reason> - Route Preference - </inactive-reason> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="3790"> - 1:03:10 - </age> - <metric> - 0 - </metric> - <metric2> - 1000 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 1000 - </med-plus-igp> - <task-name> - BGP_14525.199.34.94.2 - </task-name> - <as-path> - AS path: 6939 196844 29414 34337 I - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 6939 196844 29414 34337 I - </attr-value> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 6939:7082 - </community> - <community> - 6939:8826 - </community> - <community> - 6939:9002 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3003 - </community> - <community> - 14525:4003 - </community> - <community> - 14525:9002 - </community> - <community> - large:8714:1000:2 - </community> - <community> - large:8714:1001:1 - </community> - <community> - large:8714:1001:2 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.94.2 - </peer-id> - </rt-entry> - </rt> - <rt junos:style="detail"> - <rt-destination> - 85.193.240.0 - </rt-destination> - <rt-prefix-length> - 23 - </rt-prefix-length> - <rt-entry-count junos:format="4 entries"> - 4 - </rt-entry-count> - <rt-announced-count> - 1 - </rt-announced-count> - <rt-entry> - <active-tag> - * - </active-tag> - <current-active /> - <last-active /> - <protocol-name> - BGP - </protocol-name> - <preference> - 170 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x42439f4c - </nh-address> - <nh-reference-count> - 757869 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.92.10 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 0 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.10 - </to> - <via> - et-0/0/0.0 - </via> - <weight> - 0x1 - </weight> - <selected-next-hop /> - <label-element> - 0x425dd00 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 13 - </label-element-refcount> - <label-element-childcount> - 9 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 0 - </session> - </nh> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.194 - </to> - <via> - et-0/0/1.3683 - </via> - <weight> - 0x1 - </weight> - <label-element> - 0x425dd00 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 13 - </label-element-refcount> - <label-element-childcount> - 9 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 0 - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.92.10 - </to> - <indirect-nh> - 0xa00d600 1048582 INH Session ID: 0x2c0 - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Active Int Ext - </rt-entry-state> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="2526246"> - 4w1d 5:44:06 - </age> - <metric> - 0 - </metric> - <metric2> - 10 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 10 - </med-plus-igp> - <task-name> - BGP_14525.199.34.92.10 - </task-name> - <announce-bits> - 4 - </announce-bits> - <announce-tasks> - 0-KRT 8-Resolve tree 3 10-Aggregate 12-RT - </announce-tasks> - <as-path> - AS path: 3356 13293 29414 34337 I - AS path: Recorded - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 3356 13293 29414 34337 I - </attr-value> - <flags> - </flags> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 3356:2 - </community> - <community> - 3356:22 - </community> - <community> - 3356:100 - </community> - <community> - 3356:123 - </community> - <community> - 3356:501 - </community> - <community> - 3356:903 - </community> - <community> - 3356:2071 - </community> - <community> - 8501:1014 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3001 - </community> - <community> - 14525:4001 - </community> - <community> - 14525:9014 - </community> - <community> - 29414:1020 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.92.10 - </peer-id> - </rt-entry> - <rt-entry> - <active-tag> - </active-tag> - <protocol-name> - BGP - </protocol-name> - <preference> - 200 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x122adabc - </nh-address> - <nh-reference-count> - 546682 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.94.1 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 1283 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.21 - </to> - <via> - et-0/0/2.3601 - </via> - <selected-next-hop /> - <label-element> - 0x8b6ab80 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 4 - </label-element-refcount> - <label-element-childcount> - 2 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 53c - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.94.1 - </to> - <indirect-nh> - 0xa011000 1048625 INH Session ID: 0x5dc - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Int Ext - </rt-entry-state> - <inactive-reason> - Route Preference - </inactive-reason> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="27367"> - 7:36:07 - </age> - <metric> - 0 - </metric> - <metric2> - 1000 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 1000 - </med-plus-igp> - <task-name> - BGP_14525.199.34.94.1 - </task-name> - <as-path> - AS path: 3356 13293 29414 34337 I - AS path: Recorded - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 3356 13293 29414 34337 I - </attr-value> - <flags> - </flags> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 3356:2 - </community> - <community> - 3356:22 - </community> - <community> - 3356:100 - </community> - <community> - 3356:123 - </community> - <community> - 3356:501 - </community> - <community> - 3356:903 - </community> - <community> - 3356:2071 - </community> - <community> - 8501:1014 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3003 - </community> - <community> - 14525:4003 - </community> - <community> - 14525:9014 - </community> - <community> - 29414:1020 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.94.1 - </peer-id> - </rt-entry> - <rt-entry> - <active-tag> - </active-tag> - <protocol-name> - BGP - </protocol-name> - <preference> - 200 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x1104e0dc - </nh-address> - <nh-reference-count> - 600499 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.94.2 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 1280 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.22 - </to> - <via> - et-0/0/2.3601 - </via> - <selected-next-hop /> - <label-element> - 0x4265080 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 4 - </label-element-refcount> - <label-element-childcount> - 2 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 532 - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.94.2 - </to> - <indirect-nh> - 0xa010800 1048619 INH Session ID: 0x5e1 - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Int Ext - </rt-entry-state> - <inactive-reason> - Route Preference - </inactive-reason> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="3790"> - 1:03:10 - </age> - <metric> - 0 - </metric> - <metric2> - 1000 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 1000 - </med-plus-igp> - <task-name> - BGP_14525.199.34.94.2 - </task-name> - <as-path> - AS path: 6939 196844 29414 34337 I - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 6939 196844 29414 34337 I - </attr-value> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 6939:7082 - </community> - <community> - 6939:8826 - </community> - <community> - 6939:9002 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3003 - </community> - <community> - 14525:4003 - </community> - <community> - 14525:9002 - </community> - <community> - large:8714:1000:2 - </community> - <community> - large:8714:1001:1 - </community> - <community> - large:8714:1001:2 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.94.2 - </peer-id> - </rt-entry> - </rt> - <rt junos:style="detail"> - <rt-destination> - 85.193.242.0 - </rt-destination> - <rt-prefix-length> - 23 - </rt-prefix-length> - <rt-entry-count junos:format="4 entries"> - 4 - </rt-entry-count> - <rt-announced-count> - 1 - </rt-announced-count> - <rt-entry> - <active-tag> - * - </active-tag> - <current-active /> - <last-active /> - <protocol-name> - BGP - </protocol-name> - <preference> - 170 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x42439f4c - </nh-address> - <nh-reference-count> - 757869 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.92.10 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 0 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.10 - </to> - <via> - et-0/0/0.0 - </via> - <weight> - 0x1 - </weight> - <selected-next-hop /> - <label-element> - 0x425dd00 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 13 - </label-element-refcount> - <label-element-childcount> - 9 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 0 - </session> - </nh> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.194 - </to> - <via> - et-0/0/1.3683 - </via> - <weight> - 0x1 - </weight> - <label-element> - 0x425dd00 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 13 - </label-element-refcount> - <label-element-childcount> - 9 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 0 - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.92.10 - </to> - <indirect-nh> - 0xa00d600 1048582 INH Session ID: 0x2c0 - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Active Int Ext - </rt-entry-state> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="2526246"> - 4w1d 5:44:06 - </age> - <metric> - 0 - </metric> - <metric2> - 10 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 10 - </med-plus-igp> - <task-name> - BGP_14525.199.34.92.10 - </task-name> - <announce-bits> - 4 - </announce-bits> - <announce-tasks> - 0-KRT 8-Resolve tree 3 10-Aggregate 12-RT - </announce-tasks> - <as-path> - AS path: 3356 13293 29414 34337 I - AS path: Recorded - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 3356 13293 29414 34337 I - </attr-value> - <flags> - </flags> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 3356:2 - </community> - <community> - 3356:22 - </community> - <community> - 3356:100 - </community> - <community> - 3356:123 - </community> - <community> - 3356:501 - </community> - <community> - 3356:903 - </community> - <community> - 3356:2071 - </community> - <community> - 8501:1014 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3001 - </community> - <community> - 14525:4001 - </community> - <community> - 14525:9014 - </community> - <community> - 29414:1020 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.92.10 - </peer-id> - </rt-entry> - <rt-entry> - <active-tag> - </active-tag> - <protocol-name> - BGP - </protocol-name> - <preference> - 200 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x122adabc - </nh-address> - <nh-reference-count> - 546682 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.94.1 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 1283 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.21 - </to> - <via> - et-0/0/2.3601 - </via> - <selected-next-hop /> - <label-element> - 0x8b6ab80 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 4 - </label-element-refcount> - <label-element-childcount> - 2 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 53c - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.94.1 - </to> - <indirect-nh> - 0xa011000 1048625 INH Session ID: 0x5dc - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Int Ext - </rt-entry-state> - <inactive-reason> - Route Preference - </inactive-reason> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="27367"> - 7:36:07 - </age> - <metric> - 0 - </metric> - <metric2> - 1000 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 1000 - </med-plus-igp> - <task-name> - BGP_14525.199.34.94.1 - </task-name> - <as-path> - AS path: 3356 13293 29414 34337 I - AS path: Recorded - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 3356 13293 29414 34337 I - </attr-value> - <flags> - </flags> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 3356:2 - </community> - <community> - 3356:22 - </community> - <community> - 3356:100 - </community> - <community> - 3356:123 - </community> - <community> - 3356:501 - </community> - <community> - 3356:903 - </community> - <community> - 3356:2071 - </community> - <community> - 8501:1014 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3003 - </community> - <community> - 14525:4003 - </community> - <community> - 14525:9014 - </community> - <community> - 29414:1020 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.94.1 - </peer-id> - </rt-entry> - <rt-entry> - <active-tag> - </active-tag> - <protocol-name> - BGP - </protocol-name> - <preference> - 200 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x1104e0dc - </nh-address> - <nh-reference-count> - 600499 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.94.2 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 1280 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.22 - </to> - <via> - et-0/0/2.3601 - </via> - <selected-next-hop /> - <label-element> - 0x4265080 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 4 - </label-element-refcount> - <label-element-childcount> - 2 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 532 - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.94.2 - </to> - <indirect-nh> - 0xa010800 1048619 INH Session ID: 0x5e1 - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Int Ext - </rt-entry-state> - <inactive-reason> - Route Preference - </inactive-reason> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="3790"> - 1:03:10 - </age> - <metric> - 0 - </metric> - <metric2> - 1000 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 1000 - </med-plus-igp> - <task-name> - BGP_14525.199.34.94.2 - </task-name> - <as-path> - AS path: 6939 196844 29414 34337 I - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 6939 196844 29414 34337 I - </attr-value> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 6939:7082 - </community> - <community> - 6939:8826 - </community> - <community> - 6939:9002 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3003 - </community> - <community> - 14525:4003 - </community> - <community> - 14525:9002 - </community> - <community> - large:8714:1000:2 - </community> - <community> - large:8714:1001:1 - </community> - <community> - large:8714:1001:2 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.94.2 - </peer-id> - </rt-entry> - </rt> - <rt junos:style="detail"> - <rt-destination> - 85.193.244.0 - </rt-destination> - <rt-prefix-length> - 23 - </rt-prefix-length> - <rt-entry-count junos:format="4 entries"> - 4 - </rt-entry-count> - <rt-announced-count> - 1 - </rt-announced-count> - <rt-entry> - <active-tag> - * - </active-tag> - <current-active /> - <last-active /> - <protocol-name> - BGP - </protocol-name> - <preference> - 170 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x42439f4c - </nh-address> - <nh-reference-count> - 757869 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.92.10 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 0 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.10 - </to> - <via> - et-0/0/0.0 - </via> - <weight> - 0x1 - </weight> - <selected-next-hop /> - <label-element> - 0x425dd00 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 13 - </label-element-refcount> - <label-element-childcount> - 9 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 0 - </session> - </nh> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.194 - </to> - <via> - et-0/0/1.3683 - </via> - <weight> - 0x1 - </weight> - <label-element> - 0x425dd00 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 13 - </label-element-refcount> - <label-element-childcount> - 9 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 0 - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.92.10 - </to> - <indirect-nh> - 0xa00d600 1048582 INH Session ID: 0x2c0 - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Active Int Ext - </rt-entry-state> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="2526246"> - 4w1d 5:44:06 - </age> - <metric> - 0 - </metric> - <metric2> - 10 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 10 - </med-plus-igp> - <task-name> - BGP_14525.199.34.92.10 - </task-name> - <announce-bits> - 4 - </announce-bits> - <announce-tasks> - 0-KRT 8-Resolve tree 3 10-Aggregate 12-RT - </announce-tasks> - <as-path> - AS path: 3356 13293 29414 34337 I - AS path: Recorded - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 3356 13293 29414 34337 I - </attr-value> - <flags> - </flags> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 3356:2 - </community> - <community> - 3356:22 - </community> - <community> - 3356:100 - </community> - <community> - 3356:123 - </community> - <community> - 3356:501 - </community> - <community> - 3356:903 - </community> - <community> - 3356:2071 - </community> - <community> - 8501:1014 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3001 - </community> - <community> - 14525:4001 - </community> - <community> - 14525:9014 - </community> - <community> - 29414:1020 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.92.10 - </peer-id> - </rt-entry> - <rt-entry> - <active-tag> - </active-tag> - <protocol-name> - BGP - </protocol-name> - <preference> - 200 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x122adabc - </nh-address> - <nh-reference-count> - 546682 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.94.1 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 1283 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.21 - </to> - <via> - et-0/0/2.3601 - </via> - <selected-next-hop /> - <label-element> - 0x8b6ab80 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 4 - </label-element-refcount> - <label-element-childcount> - 2 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 53c - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.94.1 - </to> - <indirect-nh> - 0xa011000 1048625 INH Session ID: 0x5dc - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Int Ext - </rt-entry-state> - <inactive-reason> - Route Preference - </inactive-reason> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="27367"> - 7:36:07 - </age> - <metric> - 0 - </metric> - <metric2> - 1000 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 1000 - </med-plus-igp> - <task-name> - BGP_14525.199.34.94.1 - </task-name> - <as-path> - AS path: 3356 13293 29414 34337 I - AS path: Recorded - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 3356 13293 29414 34337 I - </attr-value> - <flags> - </flags> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 3356:2 - </community> - <community> - 3356:22 - </community> - <community> - 3356:100 - </community> - <community> - 3356:123 - </community> - <community> - 3356:501 - </community> - <community> - 3356:903 - </community> - <community> - 3356:2071 - </community> - <community> - 8501:1014 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3003 - </community> - <community> - 14525:4003 - </community> - <community> - 14525:9014 - </community> - <community> - 29414:1020 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.94.1 - </peer-id> - </rt-entry> - <rt-entry> - <active-tag> - </active-tag> - <protocol-name> - BGP - </protocol-name> - <preference> - 200 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x1104e0dc - </nh-address> - <nh-reference-count> - 600499 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.94.2 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 1280 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.22 - </to> - <via> - et-0/0/2.3601 - </via> - <selected-next-hop /> - <label-element> - 0x4265080 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 4 - </label-element-refcount> - <label-element-childcount> - 2 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 532 - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.94.2 - </to> - <indirect-nh> - 0xa010800 1048619 INH Session ID: 0x5e1 - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Int Ext - </rt-entry-state> - <inactive-reason> - Route Preference - </inactive-reason> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="3790"> - 1:03:10 - </age> - <metric> - 0 - </metric> - <metric2> - 1000 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 1000 - </med-plus-igp> - <task-name> - BGP_14525.199.34.94.2 - </task-name> - <as-path> - AS path: 6939 196844 29414 34337 I - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 6939 196844 29414 34337 I - </attr-value> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 6939:7082 - </community> - <community> - 6939:8826 - </community> - <community> - 6939:9002 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3003 - </community> - <community> - 14525:4003 - </community> - <community> - 14525:9002 - </community> - <community> - large:8714:1000:2 - </community> - <community> - large:8714:1001:1 - </community> - <community> - large:8714:1001:2 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.94.2 - </peer-id> - </rt-entry> - </rt> - <rt junos:style="detail"> - <rt-destination> - 85.193.246.0 - </rt-destination> - <rt-prefix-length> - 23 - </rt-prefix-length> - <rt-entry-count junos:format="4 entries"> - 4 - </rt-entry-count> - <rt-announced-count> - 1 - </rt-announced-count> - <rt-entry> - <active-tag> - * - </active-tag> - <current-active /> - <last-active /> - <protocol-name> - BGP - </protocol-name> - <preference> - 170 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x42439f4c - </nh-address> - <nh-reference-count> - 757869 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.92.10 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 0 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.10 - </to> - <via> - et-0/0/0.0 - </via> - <weight> - 0x1 - </weight> - <selected-next-hop /> - <label-element> - 0x425dd00 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 13 - </label-element-refcount> - <label-element-childcount> - 9 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 0 - </session> - </nh> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.194 - </to> - <via> - et-0/0/1.3683 - </via> - <weight> - 0x1 - </weight> - <label-element> - 0x425dd00 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 13 - </label-element-refcount> - <label-element-childcount> - 9 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 0 - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.92.10 - </to> - <indirect-nh> - 0xa00d600 1048582 INH Session ID: 0x2c0 - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Active Int Ext - </rt-entry-state> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="2526246"> - 4w1d 5:44:06 - </age> - <metric> - 0 - </metric> - <metric2> - 10 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 10 - </med-plus-igp> - <task-name> - BGP_14525.199.34.92.10 - </task-name> - <announce-bits> - 4 - </announce-bits> - <announce-tasks> - 0-KRT 8-Resolve tree 3 10-Aggregate 12-RT - </announce-tasks> - <as-path> - AS path: 3356 13293 29414 34337 I - AS path: Recorded - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 3356 13293 29414 34337 I - </attr-value> - <flags> - </flags> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 3356:2 - </community> - <community> - 3356:22 - </community> - <community> - 3356:100 - </community> - <community> - 3356:123 - </community> - <community> - 3356:501 - </community> - <community> - 3356:903 - </community> - <community> - 3356:2071 - </community> - <community> - 8501:1014 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3001 - </community> - <community> - 14525:4001 - </community> - <community> - 14525:9014 - </community> - <community> - 29414:1020 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.92.10 - </peer-id> - </rt-entry> - <rt-entry> - <active-tag> - </active-tag> - <protocol-name> - BGP - </protocol-name> - <preference> - 200 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x122adabc - </nh-address> - <nh-reference-count> - 546682 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.94.1 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 1283 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.21 - </to> - <via> - et-0/0/2.3601 - </via> - <selected-next-hop /> - <label-element> - 0x8b6ab80 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 4 - </label-element-refcount> - <label-element-childcount> - 2 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 53c - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.94.1 - </to> - <indirect-nh> - 0xa011000 1048625 INH Session ID: 0x5dc - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Int Ext - </rt-entry-state> - <inactive-reason> - Route Preference - </inactive-reason> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="27367"> - 7:36:07 - </age> - <metric> - 0 - </metric> - <metric2> - 1000 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 1000 - </med-plus-igp> - <task-name> - BGP_14525.199.34.94.1 - </task-name> - <as-path> - AS path: 3356 13293 29414 34337 I - AS path: Recorded - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 3356 13293 29414 34337 I - </attr-value> - <flags> - </flags> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 3356:2 - </community> - <community> - 3356:22 - </community> - <community> - 3356:100 - </community> - <community> - 3356:123 - </community> - <community> - 3356:501 - </community> - <community> - 3356:903 - </community> - <community> - 3356:2071 - </community> - <community> - 8501:1014 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3003 - </community> - <community> - 14525:4003 - </community> - <community> - 14525:9014 - </community> - <community> - 29414:1020 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.94.1 - </peer-id> - </rt-entry> - <rt-entry> - <active-tag> - </active-tag> - <protocol-name> - BGP - </protocol-name> - <preference> - 200 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x1104e0dc - </nh-address> - <nh-reference-count> - 600499 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.94.2 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 1280 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.22 - </to> - <via> - et-0/0/2.3601 - </via> - <selected-next-hop /> - <label-element> - 0x4265080 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 4 - </label-element-refcount> - <label-element-childcount> - 2 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 532 - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.94.2 - </to> - <indirect-nh> - 0xa010800 1048619 INH Session ID: 0x5e1 - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Int Ext - </rt-entry-state> - <inactive-reason> - Route Preference - </inactive-reason> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="3790"> - 1:03:10 - </age> - <metric> - 0 - </metric> - <metric2> - 1000 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 1000 - </med-plus-igp> - <task-name> - BGP_14525.199.34.94.2 - </task-name> - <as-path> - AS path: 6939 196844 29414 34337 I - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 6939 196844 29414 34337 I - </attr-value> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 6939:7082 - </community> - <community> - 6939:8826 - </community> - <community> - 6939:9002 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3003 - </community> - <community> - 14525:4003 - </community> - <community> - 14525:9002 - </community> - <community> - large:8714:1000:2 - </community> - <community> - large:8714:1001:1 - </community> - <community> - large:8714:1001:2 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.94.2 - </peer-id> - </rt-entry> - </rt> - <rt junos:style="detail"> - <rt-destination> - 85.193.248.0 - </rt-destination> - <rt-prefix-length> - 23 - </rt-prefix-length> - <rt-entry-count junos:format="4 entries"> - 4 - </rt-entry-count> - <rt-announced-count> - 1 - </rt-announced-count> - <rt-entry> - <active-tag> - * - </active-tag> - <current-active /> - <last-active /> - <protocol-name> - BGP - </protocol-name> - <preference> - 170 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x42439f4c - </nh-address> - <nh-reference-count> - 757869 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.92.10 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 0 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.10 - </to> - <via> - et-0/0/0.0 - </via> - <weight> - 0x1 - </weight> - <label-element> - 0x425dd00 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 13 - </label-element-refcount> - <label-element-childcount> - 9 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 0 - </session> - </nh> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.194 - </to> - <via> - et-0/0/1.3683 - </via> - <weight> - 0x1 - </weight> - <selected-next-hop /> - <label-element> - 0x425dd00 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 13 - </label-element-refcount> - <label-element-childcount> - 9 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 0 - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.92.10 - </to> - <indirect-nh> - 0xa00d600 1048582 INH Session ID: 0x2c0 - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Active Int Ext - </rt-entry-state> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="2526246"> - 4w1d 5:44:06 - </age> - <metric> - 0 - </metric> - <metric2> - 10 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 10 - </med-plus-igp> - <task-name> - BGP_14525.199.34.92.10 - </task-name> - <announce-bits> - 4 - </announce-bits> - <announce-tasks> - 0-KRT 8-Resolve tree 3 10-Aggregate 12-RT - </announce-tasks> - <as-path> - AS path: 3356 13293 29414 34337 I - AS path: Recorded - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 3356 13293 29414 34337 I - </attr-value> - <flags> - </flags> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 3356:2 - </community> - <community> - 3356:22 - </community> - <community> - 3356:100 - </community> - <community> - 3356:123 - </community> - <community> - 3356:501 - </community> - <community> - 3356:903 - </community> - <community> - 3356:2071 - </community> - <community> - 8501:1014 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3001 - </community> - <community> - 14525:4001 - </community> - <community> - 14525:9014 - </community> - <community> - 29414:1020 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.92.10 - </peer-id> - </rt-entry> - <rt-entry> - <active-tag> - </active-tag> - <protocol-name> - BGP - </protocol-name> - <preference> - 200 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x122adabc - </nh-address> - <nh-reference-count> - 546682 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.94.1 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 1283 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.21 - </to> - <via> - et-0/0/2.3601 - </via> - <selected-next-hop /> - <label-element> - 0x8b6ab80 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 4 - </label-element-refcount> - <label-element-childcount> - 2 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 53c - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.94.1 - </to> - <indirect-nh> - 0xa011000 1048625 INH Session ID: 0x5dc - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Int Ext - </rt-entry-state> - <inactive-reason> - Route Preference - </inactive-reason> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="27367"> - 7:36:07 - </age> - <metric> - 0 - </metric> - <metric2> - 1000 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 1000 - </med-plus-igp> - <task-name> - BGP_14525.199.34.94.1 - </task-name> - <as-path> - AS path: 3356 13293 29414 34337 I - AS path: Recorded - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 3356 13293 29414 34337 I - </attr-value> - <flags> - </flags> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 3356:2 - </community> - <community> - 3356:22 - </community> - <community> - 3356:100 - </community> - <community> - 3356:123 - </community> - <community> - 3356:501 - </community> - <community> - 3356:903 - </community> - <community> - 3356:2071 - </community> - <community> - 8501:1014 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3003 - </community> - <community> - 14525:4003 - </community> - <community> - 14525:9014 - </community> - <community> - 29414:1020 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.94.1 - </peer-id> - </rt-entry> - <rt-entry> - <active-tag> - </active-tag> - <protocol-name> - BGP - </protocol-name> - <preference> - 200 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x1104e0dc - </nh-address> - <nh-reference-count> - 600499 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.94.2 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 1280 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.22 - </to> - <via> - et-0/0/2.3601 - </via> - <selected-next-hop /> - <label-element> - 0x4265080 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 4 - </label-element-refcount> - <label-element-childcount> - 2 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 532 - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.94.2 - </to> - <indirect-nh> - 0xa010800 1048619 INH Session ID: 0x5e1 - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Int Ext - </rt-entry-state> - <inactive-reason> - Route Preference - </inactive-reason> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="3790"> - 1:03:10 - </age> - <metric> - 0 - </metric> - <metric2> - 1000 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 1000 - </med-plus-igp> - <task-name> - BGP_14525.199.34.94.2 - </task-name> - <as-path> - AS path: 6939 196844 29414 34337 I - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 6939 196844 29414 34337 I - </attr-value> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 6939:7082 - </community> - <community> - 6939:8826 - </community> - <community> - 6939:9002 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3003 - </community> - <community> - 14525:4003 - </community> - <community> - 14525:9002 - </community> - <community> - large:8714:1000:2 - </community> - <community> - large:8714:1001:1 - </community> - <community> - large:8714:1001:2 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.94.2 - </peer-id> - </rt-entry> - </rt> - <rt junos:style="detail"> - <rt-destination> - 85.193.250.0 - </rt-destination> - <rt-prefix-length> - 23 - </rt-prefix-length> - <rt-entry-count junos:format="4 entries"> - 4 - </rt-entry-count> - <rt-announced-count> - 1 - </rt-announced-count> - <rt-entry> - <active-tag> - * - </active-tag> - <current-active /> - <last-active /> - <protocol-name> - BGP - </protocol-name> - <preference> - 170 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x42439f4c - </nh-address> - <nh-reference-count> - 757869 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.92.10 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 0 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.10 - </to> - <via> - et-0/0/0.0 - </via> - <weight> - 0x1 - </weight> - <label-element> - 0x425dd00 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 13 - </label-element-refcount> - <label-element-childcount> - 9 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 0 - </session> - </nh> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.194 - </to> - <via> - et-0/0/1.3683 - </via> - <weight> - 0x1 - </weight> - <selected-next-hop /> - <label-element> - 0x425dd00 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 13 - </label-element-refcount> - <label-element-childcount> - 9 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 0 - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.92.10 - </to> - <indirect-nh> - 0xa00d600 1048582 INH Session ID: 0x2c0 - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Active Int Ext - </rt-entry-state> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="2526246"> - 4w1d 5:44:06 - </age> - <metric> - 0 - </metric> - <metric2> - 10 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 10 - </med-plus-igp> - <task-name> - BGP_14525.199.34.92.10 - </task-name> - <announce-bits> - 4 - </announce-bits> - <announce-tasks> - 0-KRT 8-Resolve tree 3 10-Aggregate 12-RT - </announce-tasks> - <as-path> - AS path: 3356 13293 29414 34337 I - AS path: Recorded - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 3356 13293 29414 34337 I - </attr-value> - <flags> - </flags> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 3356:2 - </community> - <community> - 3356:22 - </community> - <community> - 3356:100 - </community> - <community> - 3356:123 - </community> - <community> - 3356:501 - </community> - <community> - 3356:903 - </community> - <community> - 3356:2071 - </community> - <community> - 8501:1014 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3001 - </community> - <community> - 14525:4001 - </community> - <community> - 14525:9014 - </community> - <community> - 29414:1020 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.92.10 - </peer-id> - </rt-entry> - <rt-entry> - <active-tag> - </active-tag> - <protocol-name> - BGP - </protocol-name> - <preference> - 200 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x122adabc - </nh-address> - <nh-reference-count> - 546682 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.94.1 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 1283 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.21 - </to> - <via> - et-0/0/2.3601 - </via> - <selected-next-hop /> - <label-element> - 0x8b6ab80 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 4 - </label-element-refcount> - <label-element-childcount> - 2 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 53c - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.94.1 - </to> - <indirect-nh> - 0xa011000 1048625 INH Session ID: 0x5dc - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Int Ext - </rt-entry-state> - <inactive-reason> - Route Preference - </inactive-reason> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="27367"> - 7:36:07 - </age> - <metric> - 0 - </metric> - <metric2> - 1000 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 1000 - </med-plus-igp> - <task-name> - BGP_14525.199.34.94.1 - </task-name> - <as-path> - AS path: 3356 13293 29414 34337 I - AS path: Recorded - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 3356 13293 29414 34337 I - </attr-value> - <flags> - </flags> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 3356:2 - </community> - <community> - 3356:22 - </community> - <community> - 3356:100 - </community> - <community> - 3356:123 - </community> - <community> - 3356:501 - </community> - <community> - 3356:903 - </community> - <community> - 3356:2071 - </community> - <community> - 8501:1014 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3003 - </community> - <community> - 14525:4003 - </community> - <community> - 14525:9014 - </community> - <community> - 29414:1020 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.94.1 - </peer-id> - </rt-entry> - <rt-entry> - <active-tag> - </active-tag> - <protocol-name> - BGP - </protocol-name> - <preference> - 200 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x1104e0dc - </nh-address> - <nh-reference-count> - 600499 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.94.2 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 1280 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.22 - </to> - <via> - et-0/0/2.3601 - </via> - <selected-next-hop /> - <label-element> - 0x4265080 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 4 - </label-element-refcount> - <label-element-childcount> - 2 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 532 - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.94.2 - </to> - <indirect-nh> - 0xa010800 1048619 INH Session ID: 0x5e1 - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Int Ext - </rt-entry-state> - <inactive-reason> - Route Preference - </inactive-reason> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="3790"> - 1:03:10 - </age> - <metric> - 0 - </metric> - <metric2> - 1000 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 1000 - </med-plus-igp> - <task-name> - BGP_14525.199.34.94.2 - </task-name> - <as-path> - AS path: 6939 196844 29414 34337 I - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 6939 196844 29414 34337 I - </attr-value> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 6939:7082 - </community> - <community> - 6939:8826 - </community> - <community> - 6939:9002 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3003 - </community> - <community> - 14525:4003 - </community> - <community> - 14525:9002 - </community> - <community> - large:8714:1000:2 - </community> - <community> - large:8714:1001:1 - </community> - <community> - large:8714:1001:2 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.94.2 - </peer-id> - </rt-entry> - </rt> - <rt junos:style="detail"> - <rt-destination> - 85.193.252.0 - </rt-destination> - <rt-prefix-length> - 23 - </rt-prefix-length> - <rt-entry-count junos:format="4 entries"> - 4 - </rt-entry-count> - <rt-announced-count> - 1 - </rt-announced-count> - <rt-entry> - <active-tag> - * - </active-tag> - <current-active /> - <last-active /> - <protocol-name> - BGP - </protocol-name> - <preference> - 170 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x42439f4c - </nh-address> - <nh-reference-count> - 757869 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.92.10 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 0 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.10 - </to> - <via> - et-0/0/0.0 - </via> - <weight> - 0x1 - </weight> - <label-element> - 0x425dd00 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 13 - </label-element-refcount> - <label-element-childcount> - 9 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 0 - </session> - </nh> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.194 - </to> - <via> - et-0/0/1.3683 - </via> - <weight> - 0x1 - </weight> - <selected-next-hop /> - <label-element> - 0x425dd00 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 13 - </label-element-refcount> - <label-element-childcount> - 9 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 0 - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.92.10 - </to> - <indirect-nh> - 0xa00d600 1048582 INH Session ID: 0x2c0 - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Active Int Ext - </rt-entry-state> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="2526246"> - 4w1d 5:44:06 - </age> - <metric> - 0 - </metric> - <metric2> - 10 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 10 - </med-plus-igp> - <task-name> - BGP_14525.199.34.92.10 - </task-name> - <announce-bits> - 4 - </announce-bits> - <announce-tasks> - 0-KRT 8-Resolve tree 3 10-Aggregate 12-RT - </announce-tasks> - <as-path> - AS path: 3356 13293 29414 34337 I - AS path: Recorded - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 3356 13293 29414 34337 I - </attr-value> - <flags> - </flags> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 3356:2 - </community> - <community> - 3356:22 - </community> - <community> - 3356:100 - </community> - <community> - 3356:123 - </community> - <community> - 3356:501 - </community> - <community> - 3356:903 - </community> - <community> - 3356:2071 - </community> - <community> - 8501:1014 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3001 - </community> - <community> - 14525:4001 - </community> - <community> - 14525:9014 - </community> - <community> - 29414:1020 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.92.10 - </peer-id> - </rt-entry> - <rt-entry> - <active-tag> - </active-tag> - <protocol-name> - BGP - </protocol-name> - <preference> - 200 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x122adabc - </nh-address> - <nh-reference-count> - 546682 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.94.1 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 1283 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.21 - </to> - <via> - et-0/0/2.3601 - </via> - <selected-next-hop /> - <label-element> - 0x8b6ab80 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 4 - </label-element-refcount> - <label-element-childcount> - 2 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 53c - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.94.1 - </to> - <indirect-nh> - 0xa011000 1048625 INH Session ID: 0x5dc - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Int Ext - </rt-entry-state> - <inactive-reason> - Route Preference - </inactive-reason> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="27367"> - 7:36:07 - </age> - <metric> - 0 - </metric> - <metric2> - 1000 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 1000 - </med-plus-igp> - <task-name> - BGP_14525.199.34.94.1 - </task-name> - <as-path> - AS path: 3356 13293 29414 34337 I - AS path: Recorded - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 3356 13293 29414 34337 I - </attr-value> - <flags> - </flags> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 3356:2 - </community> - <community> - 3356:22 - </community> - <community> - 3356:100 - </community> - <community> - 3356:123 - </community> - <community> - 3356:501 - </community> - <community> - 3356:903 - </community> - <community> - 3356:2071 - </community> - <community> - 8501:1014 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3003 - </community> - <community> - 14525:4003 - </community> - <community> - 14525:9014 - </community> - <community> - 29414:1020 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.94.1 - </peer-id> - </rt-entry> - <rt-entry> - <active-tag> - </active-tag> - <protocol-name> - BGP - </protocol-name> - <preference> - 200 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x1104e0dc - </nh-address> - <nh-reference-count> - 600499 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.94.2 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 1280 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.22 - </to> - <via> - et-0/0/2.3601 - </via> - <selected-next-hop /> - <label-element> - 0x4265080 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 4 - </label-element-refcount> - <label-element-childcount> - 2 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 532 - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.94.2 - </to> - <indirect-nh> - 0xa010800 1048619 INH Session ID: 0x5e1 - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Int Ext - </rt-entry-state> - <inactive-reason> - Route Preference - </inactive-reason> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="3790"> - 1:03:10 - </age> - <metric> - 0 - </metric> - <metric2> - 1000 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 1000 - </med-plus-igp> - <task-name> - BGP_14525.199.34.94.2 - </task-name> - <as-path> - AS path: 6939 196844 29414 34337 I - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 6939 196844 29414 34337 I - </attr-value> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 6939:7082 - </community> - <community> - 6939:8826 - </community> - <community> - 6939:9002 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3003 - </community> - <community> - 14525:4003 - </community> - <community> - 14525:9002 - </community> - <community> - large:8714:1000:2 - </community> - <community> - large:8714:1001:1 - </community> - <community> - large:8714:1001:2 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.94.2 - </peer-id> - </rt-entry> - </rt> - <rt junos:style="detail"> - <rt-destination> - 89.31.65.0 - </rt-destination> - <rt-prefix-length> - 24 - </rt-prefix-length> - <rt-entry-count junos:format="4 entries"> - 4 - </rt-entry-count> - <rt-announced-count> - 1 - </rt-announced-count> - <rt-entry> - <active-tag> - * - </active-tag> - <current-active /> - <last-active /> - <protocol-name> - BGP - </protocol-name> - <preference> - 170 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x42439f4c - </nh-address> - <nh-reference-count> - 757869 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.92.10 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 0 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.10 - </to> - <via> - et-0/0/0.0 - </via> - <weight> - 0x1 - </weight> - <selected-next-hop /> - <label-element> - 0x425dd00 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 13 - </label-element-refcount> - <label-element-childcount> - 9 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 0 - </session> - </nh> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.194 - </to> - <via> - et-0/0/1.3683 - </via> - <weight> - 0x1 - </weight> - <label-element> - 0x425dd00 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 13 - </label-element-refcount> - <label-element-childcount> - 9 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 0 - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.92.10 - </to> - <indirect-nh> - 0xa00d600 1048582 INH Session ID: 0x2c0 - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Active Int Ext - </rt-entry-state> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="1131114"> - 1w6d 2:11:54 - </age> - <metric> - 0 - </metric> - <metric2> - 10 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 10 - </med-plus-igp> - <task-name> - BGP_14525.199.34.92.10 - </task-name> - <announce-bits> - 4 - </announce-bits> - <announce-tasks> - 0-KRT 8-Resolve tree 3 10-Aggregate 12-RT - </announce-tasks> - <as-path> - AS path: 3356 13293 29414 204987 I - AS path: Recorded - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 3356 13293 29414 204987 I - </attr-value> - <flags> - </flags> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 3356:2 - </community> - <community> - 3356:22 - </community> - <community> - 3356:100 - </community> - <community> - 3356:123 - </community> - <community> - 3356:501 - </community> - <community> - 3356:903 - </community> - <community> - 3356:2071 - </community> - <community> - 8501:1014 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3001 - </community> - <community> - 14525:4001 - </community> - <community> - 14525:9014 - </community> - <community> - 29414:1020 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.92.10 - </peer-id> - </rt-entry> - <rt-entry> - <active-tag> - </active-tag> - <protocol-name> - BGP - </protocol-name> - <preference> - 200 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x122adabc - </nh-address> - <nh-reference-count> - 546682 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.94.1 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 1283 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.21 - </to> - <via> - et-0/0/2.3601 - </via> - <selected-next-hop /> - <label-element> - 0x8b6ab80 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 4 - </label-element-refcount> - <label-element-childcount> - 2 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 53c - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.94.1 - </to> - <indirect-nh> - 0xa011000 1048625 INH Session ID: 0x5dc - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Int Ext - </rt-entry-state> - <inactive-reason> - Route Preference - </inactive-reason> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="27418"> - 7:36:58 - </age> - <metric> - 0 - </metric> - <metric2> - 1000 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 1000 - </med-plus-igp> - <task-name> - BGP_14525.199.34.94.1 - </task-name> - <as-path> - AS path: 3356 13293 29414 204987 I - AS path: Recorded - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 3356 13293 29414 204987 I - </attr-value> - <flags> - </flags> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 3356:2 - </community> - <community> - 3356:22 - </community> - <community> - 3356:100 - </community> - <community> - 3356:123 - </community> - <community> - 3356:501 - </community> - <community> - 3356:903 - </community> - <community> - 3356:2071 - </community> - <community> - 8501:1014 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3003 - </community> - <community> - 14525:4003 - </community> - <community> - 14525:9014 - </community> - <community> - 29414:1020 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.94.1 - </peer-id> - </rt-entry> - <rt-entry> - <active-tag> - </active-tag> - <protocol-name> - BGP - </protocol-name> - <preference> - 200 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x1104e0dc - </nh-address> - <nh-reference-count> - 600499 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.94.2 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 1280 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.22 - </to> - <via> - et-0/0/2.3601 - </via> - <selected-next-hop /> - <label-element> - 0x4265080 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 4 - </label-element-refcount> - <label-element-childcount> - 2 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 532 - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.94.2 - </to> - <indirect-nh> - 0xa010800 1048619 INH Session ID: 0x5e1 - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Int Ext - </rt-entry-state> - <inactive-reason> - Route Preference - </inactive-reason> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="3535"> - 58:55 - </age> - <metric> - 0 - </metric> - <metric2> - 1000 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 1000 - </med-plus-igp> - <task-name> - BGP_14525.199.34.94.2 - </task-name> - <as-path> - AS path: 6939 196844 29414 204987 I - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 6939 196844 29414 204987 I - </attr-value> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 6939:7082 - </community> - <community> - 6939:8826 - </community> - <community> - 6939:9002 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3003 - </community> - <community> - 14525:4003 - </community> - <community> - 14525:9002 - </community> - <community> - large:8714:1000:2 - </community> - <community> - large:8714:1001:1 - </community> - <community> - large:8714:1001:2 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.94.2 - </peer-id> - </rt-entry> - </rt> - <rt junos:style="detail"> - <rt-destination> - 89.31.66.0 - </rt-destination> - <rt-prefix-length> - 24 - </rt-prefix-length> - <rt-entry-count junos:format="4 entries"> - 4 - </rt-entry-count> - <rt-announced-count> - 1 - </rt-announced-count> - <rt-entry> - <active-tag> - * - </active-tag> - <current-active /> - <last-active /> - <protocol-name> - BGP - </protocol-name> - <preference> - 170 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x42439f4c - </nh-address> - <nh-reference-count> - 757869 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.92.10 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 0 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.10 - </to> - <via> - et-0/0/0.0 - </via> - <weight> - 0x1 - </weight> - <selected-next-hop /> - <label-element> - 0x425dd00 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 13 - </label-element-refcount> - <label-element-childcount> - 9 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 0 - </session> - </nh> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.194 - </to> - <via> - et-0/0/1.3683 - </via> - <weight> - 0x1 - </weight> - <label-element> - 0x425dd00 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 13 - </label-element-refcount> - <label-element-childcount> - 9 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 0 - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.92.10 - </to> - <indirect-nh> - 0xa00d600 1048582 INH Session ID: 0x2c0 - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Active Int Ext - </rt-entry-state> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="1131048"> - 1w6d 2:10:48 - </age> - <metric> - 0 - </metric> - <metric2> - 10 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 10 - </med-plus-igp> - <task-name> - BGP_14525.199.34.92.10 - </task-name> - <announce-bits> - 4 - </announce-bits> - <announce-tasks> - 0-KRT 8-Resolve tree 3 10-Aggregate 12-RT - </announce-tasks> - <as-path> - AS path: 3356 13293 29414 208404 I - AS path: Recorded - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 3356 13293 29414 208404 I - </attr-value> - <flags> - </flags> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 3356:2 - </community> - <community> - 3356:22 - </community> - <community> - 3356:100 - </community> - <community> - 3356:123 - </community> - <community> - 3356:501 - </community> - <community> - 3356:903 - </community> - <community> - 3356:2071 - </community> - <community> - 8501:1014 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3001 - </community> - <community> - 14525:4001 - </community> - <community> - 14525:9014 - </community> - <community> - 29414:1020 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.92.10 - </peer-id> - </rt-entry> - <rt-entry> - <active-tag> - </active-tag> - <protocol-name> - BGP - </protocol-name> - <preference> - 170 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Router - </nh-type> - <nh-index> - 1007 - </nh-index> - <nh-address> - 0x36d576ac - </nh-address> - <nh-reference-count> - 1336784 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 62.115.189.136 - </gateway> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 62.115.189.136 - </to> - <via> - xe-0/1/1.0 - </via> - <selected-next-hop /> - <session> - 4e3 - </session> - </nh> - <rt-entry-state> - Ext - </rt-entry-state> - <inactive-reason> - AS path - </inactive-reason> - <local-as> - 14525 - </local-as> - <peer-as> - 1299 - </peer-as> - <age junos:seconds="1131049"> - 1w6d 2:10:49 - </age> - <validation-state> - unknown - </validation-state> - <med-plus-igp> - 0 - </med-plus-igp> - <task-name> - BGP_1299.62.115.189.136 - </task-name> - <as-path> - AS path: 1299 3356 13293 29414 208404 I - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 1299 3356 13293 29414 208404 I - </attr-value> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 1299:25000 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3001 - </community> - <community> - 14525:4001 - </community> - <community> - 14525:9003 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 2.255.254.43 - </peer-id> - </rt-entry> - <rt-entry> - <active-tag> - </active-tag> - <protocol-name> - BGP - </protocol-name> - <preference> - 200 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x122adabc - </nh-address> - <nh-reference-count> - 546682 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.94.1 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 1283 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.21 - </to> - <via> - et-0/0/2.3601 - </via> - <selected-next-hop /> - <label-element> - 0x8b6ab80 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 4 - </label-element-refcount> - <label-element-childcount> - 2 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 53c - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.94.1 - </to> - <indirect-nh> - 0xa011000 1048625 INH Session ID: 0x5dc - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Int Ext - </rt-entry-state> - <inactive-reason> - Route Preference - </inactive-reason> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="27326"> - 7:35:26 - </age> - <metric> - 0 - </metric> - <metric2> - 1000 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 1000 - </med-plus-igp> - <task-name> - BGP_14525.199.34.94.1 - </task-name> - <as-path> - AS path: 3356 13293 29414 208404 I - AS path: Recorded - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 3356 13293 29414 208404 I - </attr-value> - <flags> - </flags> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 3356:2 - </community> - <community> - 3356:22 - </community> - <community> - 3356:100 - </community> - <community> - 3356:123 - </community> - <community> - 3356:501 - </community> - <community> - 3356:903 - </community> - <community> - 3356:2071 - </community> - <community> - 8501:1014 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3003 - </community> - <community> - 14525:4003 - </community> - <community> - 14525:9014 - </community> - <community> - 29414:1020 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.94.1 - </peer-id> - </rt-entry> - <rt-entry> - <active-tag> - </active-tag> - <protocol-name> - BGP - </protocol-name> - <preference> - 200 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x1104e0dc - </nh-address> - <nh-reference-count> - 600499 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.94.2 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 1280 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.22 - </to> - <via> - et-0/0/2.3601 - </via> - <selected-next-hop /> - <label-element> - 0x4265080 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 4 - </label-element-refcount> - <label-element-childcount> - 2 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 532 - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.94.2 - </to> - <indirect-nh> - 0xa010800 1048619 INH Session ID: 0x5e1 - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Int Ext - </rt-entry-state> - <inactive-reason> - Route Preference - </inactive-reason> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="3535"> - 58:55 - </age> - <metric> - 0 - </metric> - <metric2> - 1000 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 1000 - </med-plus-igp> - <task-name> - BGP_14525.199.34.94.2 - </task-name> - <as-path> - AS path: 6939 196844 29414 208404 I - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 6939 196844 29414 208404 I - </attr-value> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 6939:7082 - </community> - <community> - 6939:8826 - </community> - <community> - 6939:9002 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3003 - </community> - <community> - 14525:4003 - </community> - <community> - 14525:9002 - </community> - <community> - large:8714:1000:2 - </community> - <community> - large:8714:1001:1 - </community> - <community> - large:8714:1001:2 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.94.2 - </peer-id> - </rt-entry> - </rt> - <rt junos:style="detail"> - <rt-destination> - 89.161.0.0 - </rt-destination> - <rt-prefix-length> - 22 - </rt-prefix-length> - <rt-entry-count junos:format="3 entries"> - 3 - </rt-entry-count> - <rt-announced-count> - 1 - </rt-announced-count> - <rt-entry> - <active-tag> - * - </active-tag> - <current-active /> - <last-active /> - <protocol-name> - BGP - </protocol-name> - <preference> - 170 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x42439f4c - </nh-address> - <nh-reference-count> - 757869 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.92.10 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 0 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.10 - </to> - <via> - et-0/0/0.0 - </via> - <weight> - 0x1 - </weight> - <label-element> - 0x425dd00 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 13 - </label-element-refcount> - <label-element-childcount> - 9 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 0 - </session> - </nh> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.194 - </to> - <via> - et-0/0/1.3683 - </via> - <weight> - 0x1 - </weight> - <selected-next-hop /> - <label-element> - 0x425dd00 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 13 - </label-element-refcount> - <label-element-childcount> - 9 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 0 - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.92.10 - </to> - <indirect-nh> - 0xa00d600 1048582 INH Session ID: 0x2c0 - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Active Int Ext - </rt-entry-state> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="2526196"> - 4w1d 5:43:16 - </age> - <metric> - 0 - </metric> - <metric2> - 10 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 10 - </med-plus-igp> - <task-name> - BGP_14525.199.34.92.10 - </task-name> - <announce-bits> - 4 - </announce-bits> - <announce-tasks> - 0-KRT 8-Resolve tree 3 10-Aggregate 12-RT - </announce-tasks> - <as-path> - AS path: 3356 13293 29414 39375 39375 I - AS path: Recorded - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 3356 13293 29414 39375 39375 I - </attr-value> - <flags> - </flags> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 3356:2 - </community> - <community> - 3356:22 - </community> - <community> - 3356:100 - </community> - <community> - 3356:123 - </community> - <community> - 3356:501 - </community> - <community> - 3356:903 - </community> - <community> - 3356:2071 - </community> - <community> - 8501:1014 - </community> - <community> - 8545:50 - </community> - <community> - 13344:13300 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3001 - </community> - <community> - 14525:4001 - </community> - <community> - 14525:9014 - </community> - <community> - 15169:13300 - </community> - <community> - 29414:1020 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.92.10 - </peer-id> - </rt-entry> - </rt> - <rt junos:style="detail"> - <rt-destination> - 89.161.4.0 - </rt-destination> - <rt-prefix-length> - 22 - </rt-prefix-length> - <rt-entry-count junos:format="3 entries"> - 3 - </rt-entry-count> - <rt-announced-count> - 1 - </rt-announced-count> - <rt-entry> - <active-tag> - * - </active-tag> - <current-active /> - <last-active /> - <protocol-name> - BGP - </protocol-name> - <preference> - 170 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x42439f4c - </nh-address> - <nh-reference-count> - 757869 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.92.10 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 0 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.10 - </to> - <via> - et-0/0/0.0 - </via> - <weight> - 0x1 - </weight> - <label-element> - 0x425dd00 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 13 - </label-element-refcount> - <label-element-childcount> - 9 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 0 - </session> - </nh> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.194 - </to> - <via> - et-0/0/1.3683 - </via> - <weight> - 0x1 - </weight> - <selected-next-hop /> - <label-element> - 0x425dd00 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 13 - </label-element-refcount> - <label-element-childcount> - 9 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 0 - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.92.10 - </to> - <indirect-nh> - 0xa00d600 1048582 INH Session ID: 0x2c0 - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Active Int Ext - </rt-entry-state> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="2526196"> - 4w1d 5:43:16 - </age> - <metric> - 0 - </metric> - <metric2> - 10 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 10 - </med-plus-igp> - <task-name> - BGP_14525.199.34.92.10 - </task-name> - <announce-bits> - 4 - </announce-bits> - <announce-tasks> - 0-KRT 8-Resolve tree 3 10-Aggregate 12-RT - </announce-tasks> - <as-path> - AS path: 3356 13293 29414 39375 39375 I - AS path: Recorded - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 3356 13293 29414 39375 39375 I - </attr-value> - <flags> - </flags> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 3356:2 - </community> - <community> - 3356:22 - </community> - <community> - 3356:100 - </community> - <community> - 3356:123 - </community> - <community> - 3356:501 - </community> - <community> - 3356:903 - </community> - <community> - 3356:2071 - </community> - <community> - 8501:1014 - </community> - <community> - 8545:50 - </community> - <community> - 13344:13300 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3001 - </community> - <community> - 14525:4001 - </community> - <community> - 14525:9014 - </community> - <community> - 15169:13300 - </community> - <community> - 29414:1020 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.92.10 - </peer-id> - </rt-entry> - </rt> - <rt junos:style="detail"> - <rt-destination> - 89.161.8.0 - </rt-destination> - <rt-prefix-length> - 22 - </rt-prefix-length> - <rt-entry-count junos:format="3 entries"> - 3 - </rt-entry-count> - <rt-announced-count> - 1 - </rt-announced-count> - <rt-entry> - <active-tag> - * - </active-tag> - <current-active /> - <last-active /> - <protocol-name> - BGP - </protocol-name> - <preference> - 170 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x42439f4c - </nh-address> - <nh-reference-count> - 757869 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.92.10 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 0 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.10 - </to> - <via> - et-0/0/0.0 - </via> - <weight> - 0x1 - </weight> - <selected-next-hop /> - <label-element> - 0x425dd00 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 13 - </label-element-refcount> - <label-element-childcount> - 9 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 0 - </session> - </nh> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.194 - </to> - <via> - et-0/0/1.3683 - </via> - <weight> - 0x1 - </weight> - <label-element> - 0x425dd00 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 13 - </label-element-refcount> - <label-element-childcount> - 9 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 0 - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.92.10 - </to> - <indirect-nh> - 0xa00d600 1048582 INH Session ID: 0x2c0 - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Active Int Ext - </rt-entry-state> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="2526196"> - 4w1d 5:43:16 - </age> - <metric> - 0 - </metric> - <metric2> - 10 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 10 - </med-plus-igp> - <task-name> - BGP_14525.199.34.92.10 - </task-name> - <announce-bits> - 4 - </announce-bits> - <announce-tasks> - 0-KRT 8-Resolve tree 3 10-Aggregate 12-RT - </announce-tasks> - <as-path> - AS path: 3356 13293 29414 39375 39375 I - AS path: Recorded - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 3356 13293 29414 39375 39375 I - </attr-value> - <flags> - </flags> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 3356:2 - </community> - <community> - 3356:22 - </community> - <community> - 3356:100 - </community> - <community> - 3356:123 - </community> - <community> - 3356:501 - </community> - <community> - 3356:903 - </community> - <community> - 3356:2071 - </community> - <community> - 8501:1014 - </community> - <community> - 8545:50 - </community> - <community> - 13344:13300 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3001 - </community> - <community> - 14525:4001 - </community> - <community> - 14525:9014 - </community> - <community> - 15169:13300 - </community> - <community> - 29414:1020 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.92.10 - </peer-id> - </rt-entry> - </rt> - <rt junos:style="detail"> - <rt-destination> - 89.161.12.0 - </rt-destination> - <rt-prefix-length> - 22 - </rt-prefix-length> - <rt-entry-count junos:format="3 entries"> - 3 - </rt-entry-count> - <rt-announced-count> - 1 - </rt-announced-count> - <rt-entry> - <active-tag> - * - </active-tag> - <current-active /> - <last-active /> - <protocol-name> - BGP - </protocol-name> - <preference> - 170 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x42439f4c - </nh-address> - <nh-reference-count> - 757869 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.92.10 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 0 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.10 - </to> - <via> - et-0/0/0.0 - </via> - <weight> - 0x1 - </weight> - <selected-next-hop /> - <label-element> - 0x425dd00 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 13 - </label-element-refcount> - <label-element-childcount> - 9 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 0 - </session> - </nh> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.194 - </to> - <via> - et-0/0/1.3683 - </via> - <weight> - 0x1 - </weight> - <label-element> - 0x425dd00 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 13 - </label-element-refcount> - <label-element-childcount> - 9 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 0 - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.92.10 - </to> - <indirect-nh> - 0xa00d600 1048582 INH Session ID: 0x2c0 - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Active Int Ext - </rt-entry-state> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="2526196"> - 4w1d 5:43:16 - </age> - <metric> - 0 - </metric> - <metric2> - 10 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 10 - </med-plus-igp> - <task-name> - BGP_14525.199.34.92.10 - </task-name> - <announce-bits> - 4 - </announce-bits> - <announce-tasks> - 0-KRT 8-Resolve tree 3 10-Aggregate 12-RT - </announce-tasks> - <as-path> - AS path: 3356 13293 29414 39375 39375 I - AS path: Recorded - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 3356 13293 29414 39375 39375 I - </attr-value> - <flags> - </flags> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 3356:2 - </community> - <community> - 3356:22 - </community> - <community> - 3356:100 - </community> - <community> - 3356:123 - </community> - <community> - 3356:501 - </community> - <community> - 3356:903 - </community> - <community> - 3356:2071 - </community> - <community> - 8501:1014 - </community> - <community> - 8545:50 - </community> - <community> - 13344:13300 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3001 - </community> - <community> - 14525:4001 - </community> - <community> - 14525:9014 - </community> - <community> - 15169:13300 - </community> - <community> - 29414:1020 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.92.10 - </peer-id> - </rt-entry> - </rt> - <rt junos:style="detail"> - <rt-destination> - 89.161.16.0 - </rt-destination> - <rt-prefix-length> - 22 - </rt-prefix-length> - <rt-entry-count junos:format="3 entries"> - 3 - </rt-entry-count> - <rt-announced-count> - 1 - </rt-announced-count> - <rt-entry> - <active-tag> - * - </active-tag> - <current-active /> - <last-active /> - <protocol-name> - BGP - </protocol-name> - <preference> - 170 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x42439f4c - </nh-address> - <nh-reference-count> - 757869 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.92.10 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 0 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.10 - </to> - <via> - et-0/0/0.0 - </via> - <weight> - 0x1 - </weight> - <label-element> - 0x425dd00 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 13 - </label-element-refcount> - <label-element-childcount> - 9 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 0 - </session> - </nh> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.194 - </to> - <via> - et-0/0/1.3683 - </via> - <weight> - 0x1 - </weight> - <selected-next-hop /> - <label-element> - 0x425dd00 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 13 - </label-element-refcount> - <label-element-childcount> - 9 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 0 - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.92.10 - </to> - <indirect-nh> - 0xa00d600 1048582 INH Session ID: 0x2c0 - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Active Int Ext - </rt-entry-state> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="2526196"> - 4w1d 5:43:16 - </age> - <metric> - 0 - </metric> - <metric2> - 10 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 10 - </med-plus-igp> - <task-name> - BGP_14525.199.34.92.10 - </task-name> - <announce-bits> - 4 - </announce-bits> - <announce-tasks> - 0-KRT 8-Resolve tree 3 10-Aggregate 12-RT - </announce-tasks> - <as-path> - AS path: 3356 13293 29414 39375 39375 I - AS path: Recorded - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 3356 13293 29414 39375 39375 I - </attr-value> - <flags> - </flags> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 3356:2 - </community> - <community> - 3356:22 - </community> - <community> - 3356:100 - </community> - <community> - 3356:123 - </community> - <community> - 3356:501 - </community> - <community> - 3356:903 - </community> - <community> - 3356:2071 - </community> - <community> - 8501:1014 - </community> - <community> - 8545:50 - </community> - <community> - 13344:13300 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3001 - </community> - <community> - 14525:4001 - </community> - <community> - 14525:9014 - </community> - <community> - 15169:13300 - </community> - <community> - 29414:1020 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.92.10 - </peer-id> - </rt-entry> - </rt> - <rt junos:style="detail"> - <rt-destination> - 89.161.20.0 - </rt-destination> - <rt-prefix-length> - 22 - </rt-prefix-length> - <rt-entry-count junos:format="3 entries"> - 3 - </rt-entry-count> - <rt-announced-count> - 1 - </rt-announced-count> - <rt-entry> - <active-tag> - * - </active-tag> - <current-active /> - <last-active /> - <protocol-name> - BGP - </protocol-name> - <preference> - 170 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x42439f4c - </nh-address> - <nh-reference-count> - 757869 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.92.10 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 0 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.10 - </to> - <via> - et-0/0/0.0 - </via> - <weight> - 0x1 - </weight> - <label-element> - 0x425dd00 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 13 - </label-element-refcount> - <label-element-childcount> - 9 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 0 - </session> - </nh> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.194 - </to> - <via> - et-0/0/1.3683 - </via> - <weight> - 0x1 - </weight> - <selected-next-hop /> - <label-element> - 0x425dd00 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 13 - </label-element-refcount> - <label-element-childcount> - 9 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 0 - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.92.10 - </to> - <indirect-nh> - 0xa00d600 1048582 INH Session ID: 0x2c0 - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Active Int Ext - </rt-entry-state> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="2526196"> - 4w1d 5:43:16 - </age> - <metric> - 0 - </metric> - <metric2> - 10 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 10 - </med-plus-igp> - <task-name> - BGP_14525.199.34.92.10 - </task-name> - <announce-bits> - 4 - </announce-bits> - <announce-tasks> - 0-KRT 8-Resolve tree 3 10-Aggregate 12-RT - </announce-tasks> - <as-path> - AS path: 3356 13293 29414 39375 39375 I - AS path: Recorded - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 3356 13293 29414 39375 39375 I - </attr-value> - <flags> - </flags> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 3356:2 - </community> - <community> - 3356:22 - </community> - <community> - 3356:100 - </community> - <community> - 3356:123 - </community> - <community> - 3356:501 - </community> - <community> - 3356:903 - </community> - <community> - 3356:2071 - </community> - <community> - 8501:1014 - </community> - <community> - 8545:50 - </community> - <community> - 13344:13300 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3001 - </community> - <community> - 14525:4001 - </community> - <community> - 14525:9014 - </community> - <community> - 15169:13300 - </community> - <community> - 29414:1020 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.92.10 - </peer-id> - </rt-entry> - </rt> - <rt junos:style="detail"> - <rt-destination> - 89.161.27.0 - </rt-destination> - <rt-prefix-length> - 24 - </rt-prefix-length> - <rt-entry-count junos:format="3 entries"> - 3 - </rt-entry-count> - <rt-announced-count> - 1 - </rt-announced-count> - <rt-entry> - <active-tag> - * - </active-tag> - <current-active /> - <last-active /> - <protocol-name> - BGP - </protocol-name> - <preference> - 170 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x42439f4c - </nh-address> - <nh-reference-count> - 757869 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.92.10 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 0 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.10 - </to> - <via> - et-0/0/0.0 - </via> - <weight> - 0x1 - </weight> - <selected-next-hop /> - <label-element> - 0x425dd00 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 13 - </label-element-refcount> - <label-element-childcount> - 9 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 0 - </session> - </nh> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.194 - </to> - <via> - et-0/0/1.3683 - </via> - <weight> - 0x1 - </weight> - <label-element> - 0x425dd00 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 13 - </label-element-refcount> - <label-element-childcount> - 9 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 0 - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.92.10 - </to> - <indirect-nh> - 0xa00d600 1048582 INH Session ID: 0x2c0 - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Active Int Ext - </rt-entry-state> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="2526196"> - 4w1d 5:43:16 - </age> - <metric> - 0 - </metric> - <metric2> - 10 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 10 - </med-plus-igp> - <task-name> - BGP_14525.199.34.92.10 - </task-name> - <announce-bits> - 4 - </announce-bits> - <announce-tasks> - 0-KRT 8-Resolve tree 3 10-Aggregate 12-RT - </announce-tasks> - <as-path> - AS path: 3356 13293 29414 39375 39375 I - AS path: Recorded - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 3356 13293 29414 39375 39375 I - </attr-value> - <flags> - </flags> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 3356:2 - </community> - <community> - 3356:22 - </community> - <community> - 3356:100 - </community> - <community> - 3356:123 - </community> - <community> - 3356:501 - </community> - <community> - 3356:903 - </community> - <community> - 3356:2071 - </community> - <community> - 8501:1014 - </community> - <community> - 8545:50 - </community> - <community> - 13344:13300 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3001 - </community> - <community> - 14525:4001 - </community> - <community> - 14525:9014 - </community> - <community> - 15169:13300 - </community> - <community> - 29414:1020 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.92.10 - </peer-id> - </rt-entry> - </rt> - <rt junos:style="detail"> - <rt-destination> - 89.161.48.0 - </rt-destination> - <rt-prefix-length> - 22 - </rt-prefix-length> - <rt-entry-count junos:format="3 entries"> - 3 - </rt-entry-count> - <rt-announced-count> - 1 - </rt-announced-count> - <rt-entry> - <active-tag> - * - </active-tag> - <current-active /> - <last-active /> - <protocol-name> - BGP - </protocol-name> - <preference> - 170 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x42439f4c - </nh-address> - <nh-reference-count> - 757869 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.92.10 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 0 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.10 - </to> - <via> - et-0/0/0.0 - </via> - <weight> - 0x1 - </weight> - <label-element> - 0x425dd00 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 13 - </label-element-refcount> - <label-element-childcount> - 9 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 0 - </session> - </nh> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.194 - </to> - <via> - et-0/0/1.3683 - </via> - <weight> - 0x1 - </weight> - <selected-next-hop /> - <label-element> - 0x425dd00 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 13 - </label-element-refcount> - <label-element-childcount> - 9 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 0 - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.92.10 - </to> - <indirect-nh> - 0xa00d600 1048582 INH Session ID: 0x2c0 - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Active Int Ext - </rt-entry-state> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="2526196"> - 4w1d 5:43:16 - </age> - <metric> - 0 - </metric> - <metric2> - 10 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 10 - </med-plus-igp> - <task-name> - BGP_14525.199.34.92.10 - </task-name> - <announce-bits> - 4 - </announce-bits> - <announce-tasks> - 0-KRT 8-Resolve tree 3 10-Aggregate 12-RT - </announce-tasks> - <as-path> - AS path: 3356 13293 29414 39375 39375 I - AS path: Recorded - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 3356 13293 29414 39375 39375 I - </attr-value> - <flags> - </flags> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 3356:2 - </community> - <community> - 3356:22 - </community> - <community> - 3356:100 - </community> - <community> - 3356:123 - </community> - <community> - 3356:501 - </community> - <community> - 3356:903 - </community> - <community> - 3356:2071 - </community> - <community> - 8501:1014 - </community> - <community> - 8545:50 - </community> - <community> - 13344:13300 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3001 - </community> - <community> - 14525:4001 - </community> - <community> - 14525:9014 - </community> - <community> - 15169:13300 - </community> - <community> - 29414:1020 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.92.10 - </peer-id> - </rt-entry> - </rt> - <rt junos:style="detail"> - <rt-destination> - 89.161.52.0 - </rt-destination> - <rt-prefix-length> - 22 - </rt-prefix-length> - <rt-entry-count junos:format="3 entries"> - 3 - </rt-entry-count> - <rt-announced-count> - 1 - </rt-announced-count> - <rt-entry> - <active-tag> - * - </active-tag> - <current-active /> - <last-active /> - <protocol-name> - BGP - </protocol-name> - <preference> - 170 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x42439f4c - </nh-address> - <nh-reference-count> - 757869 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.92.10 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 0 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.10 - </to> - <via> - et-0/0/0.0 - </via> - <weight> - 0x1 - </weight> - <label-element> - 0x425dd00 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 13 - </label-element-refcount> - <label-element-childcount> - 9 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 0 - </session> - </nh> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.194 - </to> - <via> - et-0/0/1.3683 - </via> - <weight> - 0x1 - </weight> - <selected-next-hop /> - <label-element> - 0x425dd00 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 13 - </label-element-refcount> - <label-element-childcount> - 9 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 0 - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.92.10 - </to> - <indirect-nh> - 0xa00d600 1048582 INH Session ID: 0x2c0 - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Active Int Ext - </rt-entry-state> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="2526196"> - 4w1d 5:43:16 - </age> - <metric> - 0 - </metric> - <metric2> - 10 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 10 - </med-plus-igp> - <task-name> - BGP_14525.199.34.92.10 - </task-name> - <announce-bits> - 4 - </announce-bits> - <announce-tasks> - 0-KRT 8-Resolve tree 3 10-Aggregate 12-RT - </announce-tasks> - <as-path> - AS path: 3356 13293 29414 39375 39375 I - AS path: Recorded - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 3356 13293 29414 39375 39375 I - </attr-value> - <flags> - </flags> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 3356:2 - </community> - <community> - 3356:22 - </community> - <community> - 3356:100 - </community> - <community> - 3356:123 - </community> - <community> - 3356:501 - </community> - <community> - 3356:903 - </community> - <community> - 3356:2071 - </community> - <community> - 8501:1014 - </community> - <community> - 8545:50 - </community> - <community> - 13344:13300 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3001 - </community> - <community> - 14525:4001 - </community> - <community> - 14525:9014 - </community> - <community> - 15169:13300 - </community> - <community> - 29414:1020 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.92.10 - </peer-id> - </rt-entry> - </rt> - <rt junos:style="detail"> - <rt-destination> - 89.161.60.0 - </rt-destination> - <rt-prefix-length> - 23 - </rt-prefix-length> - <rt-entry-count junos:format="3 entries"> - 3 - </rt-entry-count> - <rt-announced-count> - 1 - </rt-announced-count> - <rt-entry> - <active-tag> - * - </active-tag> - <current-active /> - <last-active /> - <protocol-name> - BGP - </protocol-name> - <preference> - 170 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x42439f4c - </nh-address> - <nh-reference-count> - 757869 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.92.10 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 0 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.10 - </to> - <via> - et-0/0/0.0 - </via> - <weight> - 0x1 - </weight> - <selected-next-hop /> - <label-element> - 0x425dd00 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 13 - </label-element-refcount> - <label-element-childcount> - 9 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 0 - </session> - </nh> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.194 - </to> - <via> - et-0/0/1.3683 - </via> - <weight> - 0x1 - </weight> - <label-element> - 0x425dd00 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 13 - </label-element-refcount> - <label-element-childcount> - 9 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 0 - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.92.10 - </to> - <indirect-nh> - 0xa00d600 1048582 INH Session ID: 0x2c0 - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Active Int Ext - </rt-entry-state> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="2526196"> - 4w1d 5:43:16 - </age> - <metric> - 0 - </metric> - <metric2> - 10 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 10 - </med-plus-igp> - <task-name> - BGP_14525.199.34.92.10 - </task-name> - <announce-bits> - 4 - </announce-bits> - <announce-tasks> - 0-KRT 8-Resolve tree 3 10-Aggregate 12-RT - </announce-tasks> - <as-path> - AS path: 3356 13293 29414 39375 39375 I - AS path: Recorded - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 3356 13293 29414 39375 39375 I - </attr-value> - <flags> - </flags> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 3356:2 - </community> - <community> - 3356:22 - </community> - <community> - 3356:100 - </community> - <community> - 3356:123 - </community> - <community> - 3356:501 - </community> - <community> - 3356:903 - </community> - <community> - 3356:2071 - </community> - <community> - 8501:1014 - </community> - <community> - 8545:50 - </community> - <community> - 13344:13300 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3001 - </community> - <community> - 14525:4001 - </community> - <community> - 14525:9014 - </community> - <community> - 15169:13300 - </community> - <community> - 29414:1020 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.92.10 - </peer-id> - </rt-entry> - </rt> - <rt junos:style="detail"> - <rt-destination> - 89.161.62.0 - </rt-destination> - <rt-prefix-length> - 24 - </rt-prefix-length> - <rt-entry-count junos:format="3 entries"> - 3 - </rt-entry-count> - <rt-announced-count> - 1 - </rt-announced-count> - <rt-entry> - <active-tag> - * - </active-tag> - <current-active /> - <last-active /> - <protocol-name> - BGP - </protocol-name> - <preference> - 170 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x42439f4c - </nh-address> - <nh-reference-count> - 757869 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.92.10 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 0 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.10 - </to> - <via> - et-0/0/0.0 - </via> - <weight> - 0x1 - </weight> - <selected-next-hop /> - <label-element> - 0x425dd00 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 13 - </label-element-refcount> - <label-element-childcount> - 9 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 0 - </session> - </nh> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.194 - </to> - <via> - et-0/0/1.3683 - </via> - <weight> - 0x1 - </weight> - <label-element> - 0x425dd00 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 13 - </label-element-refcount> - <label-element-childcount> - 9 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 0 - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.92.10 - </to> - <indirect-nh> - 0xa00d600 1048582 INH Session ID: 0x2c0 - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Active Int Ext - </rt-entry-state> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="2526196"> - 4w1d 5:43:16 - </age> - <metric> - 0 - </metric> - <metric2> - 10 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 10 - </med-plus-igp> - <task-name> - BGP_14525.199.34.92.10 - </task-name> - <announce-bits> - 4 - </announce-bits> - <announce-tasks> - 0-KRT 8-Resolve tree 3 10-Aggregate 12-RT - </announce-tasks> - <as-path> - AS path: 3356 13293 29414 39375 39375 I - AS path: Recorded - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 3356 13293 29414 39375 39375 I - </attr-value> - <flags> - </flags> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 3356:2 - </community> - <community> - 3356:22 - </community> - <community> - 3356:100 - </community> - <community> - 3356:123 - </community> - <community> - 3356:501 - </community> - <community> - 3356:903 - </community> - <community> - 3356:2071 - </community> - <community> - 8501:1014 - </community> - <community> - 8545:50 - </community> - <community> - 13344:13300 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3001 - </community> - <community> - 14525:4001 - </community> - <community> - 14525:9014 - </community> - <community> - 15169:13300 - </community> - <community> - 29414:1020 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.92.10 - </peer-id> - </rt-entry> - </rt> - <rt junos:style="detail"> - <rt-destination> - 89.161.63.0 - </rt-destination> - <rt-prefix-length> - 24 - </rt-prefix-length> - <rt-entry-count junos:format="3 entries"> - 3 - </rt-entry-count> - <rt-announced-count> - 1 - </rt-announced-count> - <rt-entry> - <active-tag> - * - </active-tag> - <current-active /> - <last-active /> - <protocol-name> - BGP - </protocol-name> - <preference> - 170 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x42439f4c - </nh-address> - <nh-reference-count> - 757869 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.92.10 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 0 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.10 - </to> - <via> - et-0/0/0.0 - </via> - <weight> - 0x1 - </weight> - <selected-next-hop /> - <label-element> - 0x425dd00 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 13 - </label-element-refcount> - <label-element-childcount> - 9 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 0 - </session> - </nh> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.194 - </to> - <via> - et-0/0/1.3683 - </via> - <weight> - 0x1 - </weight> - <label-element> - 0x425dd00 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 13 - </label-element-refcount> - <label-element-childcount> - 9 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 0 - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.92.10 - </to> - <indirect-nh> - 0xa00d600 1048582 INH Session ID: 0x2c0 - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Active Int Ext - </rt-entry-state> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="2526196"> - 4w1d 5:43:16 - </age> - <metric> - 0 - </metric> - <metric2> - 10 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 10 - </med-plus-igp> - <task-name> - BGP_14525.199.34.92.10 - </task-name> - <announce-bits> - 4 - </announce-bits> - <announce-tasks> - 0-KRT 8-Resolve tree 3 10-Aggregate 12-RT - </announce-tasks> - <as-path> - AS path: 3356 13293 29414 39375 39375 I - AS path: Recorded - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 3356 13293 29414 39375 39375 I - </attr-value> - <flags> - </flags> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 3356:2 - </community> - <community> - 3356:22 - </community> - <community> - 3356:100 - </community> - <community> - 3356:123 - </community> - <community> - 3356:501 - </community> - <community> - 3356:903 - </community> - <community> - 3356:2071 - </community> - <community> - 8501:1014 - </community> - <community> - 8545:50 - </community> - <community> - 13344:13300 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3001 - </community> - <community> - 14525:4001 - </community> - <community> - 14525:9014 - </community> - <community> - 15169:13300 - </community> - <community> - 29414:1020 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.92.10 - </peer-id> - </rt-entry> - </rt> - <rt junos:style="detail"> - <rt-destination> - 89.161.64.0 - </rt-destination> - <rt-prefix-length> - 20 - </rt-prefix-length> - <rt-entry-count junos:format="4 entries"> - 4 - </rt-entry-count> - <rt-announced-count> - 1 - </rt-announced-count> - <rt-entry> - <active-tag> - * - </active-tag> - <current-active /> - <last-active /> - <protocol-name> - BGP - </protocol-name> - <preference> - 170 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x42439f4c - </nh-address> - <nh-reference-count> - 757869 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.92.10 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 0 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.10 - </to> - <via> - et-0/0/0.0 - </via> - <weight> - 0x1 - </weight> - <label-element> - 0x425dd00 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 13 - </label-element-refcount> - <label-element-childcount> - 9 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 0 - </session> - </nh> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.194 - </to> - <via> - et-0/0/1.3683 - </via> - <weight> - 0x1 - </weight> - <selected-next-hop /> - <label-element> - 0x425dd00 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 13 - </label-element-refcount> - <label-element-childcount> - 9 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 0 - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.92.10 - </to> - <indirect-nh> - 0xa00d600 1048582 INH Session ID: 0x2c0 - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Active Int Ext - </rt-entry-state> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="2526218"> - 4w1d 5:43:38 - </age> - <metric> - 0 - </metric> - <metric2> - 10 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 10 - </med-plus-igp> - <task-name> - BGP_14525.199.34.92.10 - </task-name> - <announce-bits> - 4 - </announce-bits> - <announce-tasks> - 0-KRT 8-Resolve tree 3 10-Aggregate 12-RT - </announce-tasks> - <as-path> - AS path: 3356 13293 29414 39375 39375 I - AS path: Recorded - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 3356 13293 29414 39375 39375 I - </attr-value> - <flags> - </flags> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 3356:2 - </community> - <community> - 3356:22 - </community> - <community> - 3356:100 - </community> - <community> - 3356:123 - </community> - <community> - 3356:501 - </community> - <community> - 3356:903 - </community> - <community> - 3356:2071 - </community> - <community> - 8501:1014 - </community> - <community> - 8545:50 - </community> - <community> - 13344:13300 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3001 - </community> - <community> - 14525:4001 - </community> - <community> - 14525:9014 - </community> - <community> - 15169:13300 - </community> - <community> - 29414:1020 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.92.10 - </peer-id> - </rt-entry> - <rt-entry> - <active-tag> - </active-tag> - <protocol-name> - BGP - </protocol-name> - <preference> - 170 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Router - </nh-type> - <nh-index> - 1007 - </nh-index> - <nh-address> - 0x36d576ac - </nh-address> - <nh-reference-count> - 1336784 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 62.115.189.136 - </gateway> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 62.115.189.136 - </to> - <via> - xe-0/1/1.0 - </via> - <selected-next-hop /> - <session> - 4e3 - </session> - </nh> - <rt-entry-state> - Ext - </rt-entry-state> - <inactive-reason> - AS path - </inactive-reason> - <local-as> - 14525 - </local-as> - <peer-as> - 1299 - </peer-as> - <age junos:seconds="2526272"> - 4w1d 5:44:32 - </age> - <validation-state> - unknown - </validation-state> - <med-plus-igp> - 0 - </med-plus-igp> - <task-name> - BGP_1299.62.115.189.136 - </task-name> - <as-path> - AS path: 1299 3356 13293 29414 39375 39375 I - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 1299 3356 13293 29414 39375 39375 I - </attr-value> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 1299:25000 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3001 - </community> - <community> - 14525:4001 - </community> - <community> - 14525:9003 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 2.255.254.43 - </peer-id> - </rt-entry> - <rt-entry> - <active-tag> - </active-tag> - <protocol-name> - BGP - </protocol-name> - <preference> - 200 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x122adabc - </nh-address> - <nh-reference-count> - 546682 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.94.1 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 1283 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.21 - </to> - <via> - et-0/0/2.3601 - </via> - <selected-next-hop /> - <label-element> - 0x8b6ab80 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 4 - </label-element-refcount> - <label-element-childcount> - 2 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 53c - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.94.1 - </to> - <indirect-nh> - 0xa011000 1048625 INH Session ID: 0x5dc - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Int Ext - </rt-entry-state> - <inactive-reason> - Route Preference - </inactive-reason> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="27352"> - 7:35:52 - </age> - <metric> - 0 - </metric> - <metric2> - 1000 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 1000 - </med-plus-igp> - <task-name> - BGP_14525.199.34.94.1 - </task-name> - <as-path> - AS path: 3356 13293 29414 39375 39375 I - AS path: Recorded - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 3356 13293 29414 39375 39375 I - </attr-value> - <flags> - </flags> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 3356:2 - </community> - <community> - 3356:22 - </community> - <community> - 3356:100 - </community> - <community> - 3356:123 - </community> - <community> - 3356:501 - </community> - <community> - 3356:903 - </community> - <community> - 3356:2071 - </community> - <community> - 8501:1014 - </community> - <community> - 8545:50 - </community> - <community> - 13344:13300 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3003 - </community> - <community> - 14525:4003 - </community> - <community> - 14525:9014 - </community> - <community> - 15169:13300 - </community> - <community> - 29414:1020 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.94.1 - </peer-id> - </rt-entry> - <rt-entry> - <active-tag> - </active-tag> - <protocol-name> - BGP - </protocol-name> - <preference> - 200 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x1104e0dc - </nh-address> - <nh-reference-count> - 600499 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.94.2 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 1280 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.22 - </to> - <via> - et-0/0/2.3601 - </via> - <selected-next-hop /> - <label-element> - 0x4265080 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 4 - </label-element-refcount> - <label-element-childcount> - 2 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 532 - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.94.2 - </to> - <indirect-nh> - 0xa010800 1048619 INH Session ID: 0x5e1 - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Int Ext - </rt-entry-state> - <inactive-reason> - Route Preference - </inactive-reason> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="3504"> - 58:24 - </age> - <metric> - 0 - </metric> - <metric2> - 1000 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 1000 - </med-plus-igp> - <task-name> - BGP_14525.199.34.94.2 - </task-name> - <as-path> - AS path: 6939 196844 29414 39375 39375 I - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 6939 196844 29414 39375 39375 I - </attr-value> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 6939:7218 - </community> - <community> - 6939:8276 - </community> - <community> - 6939:9002 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3003 - </community> - <community> - 14525:4003 - </community> - <community> - 14525:9002 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.94.2 - </peer-id> - </rt-entry> - </rt> - <rt junos:style="detail"> - <rt-destination> - 89.161.68.0 - </rt-destination> - <rt-prefix-length> - 24 - </rt-prefix-length> - <rt-entry-count junos:format="3 entries"> - 3 - </rt-entry-count> - <rt-announced-count> - 1 - </rt-announced-count> - <rt-entry> - <active-tag> - * - </active-tag> - <current-active /> - <last-active /> - <protocol-name> - BGP - </protocol-name> - <preference> - 170 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x42439f4c - </nh-address> - <nh-reference-count> - 757869 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.92.10 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 0 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.10 - </to> - <via> - et-0/0/0.0 - </via> - <weight> - 0x1 - </weight> - <label-element> - 0x425dd00 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 13 - </label-element-refcount> - <label-element-childcount> - 9 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 0 - </session> - </nh> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.194 - </to> - <via> - et-0/0/1.3683 - </via> - <weight> - 0x1 - </weight> - <selected-next-hop /> - <label-element> - 0x425dd00 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 13 - </label-element-refcount> - <label-element-childcount> - 9 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 0 - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.92.10 - </to> - <indirect-nh> - 0xa00d600 1048582 INH Session ID: 0x2c0 - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Active Int Ext - </rt-entry-state> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="2526196"> - 4w1d 5:43:16 - </age> - <metric> - 0 - </metric> - <metric2> - 10 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 10 - </med-plus-igp> - <task-name> - BGP_14525.199.34.92.10 - </task-name> - <announce-bits> - 4 - </announce-bits> - <announce-tasks> - 0-KRT 8-Resolve tree 3 10-Aggregate 12-RT - </announce-tasks> - <as-path> - AS path: 3356 13293 29414 39375 39375 I - AS path: Recorded - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 3356 13293 29414 39375 39375 I - </attr-value> - <flags> - </flags> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 3356:2 - </community> - <community> - 3356:22 - </community> - <community> - 3356:100 - </community> - <community> - 3356:123 - </community> - <community> - 3356:501 - </community> - <community> - 3356:903 - </community> - <community> - 3356:2071 - </community> - <community> - 8501:1014 - </community> - <community> - 8545:50 - </community> - <community> - 13344:13300 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3001 - </community> - <community> - 14525:4001 - </community> - <community> - 14525:9014 - </community> - <community> - 15169:13300 - </community> - <community> - 29414:1020 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.92.10 - </peer-id> - </rt-entry> - </rt> - <rt junos:style="detail"> - <rt-destination> - 89.161.69.0 - </rt-destination> - <rt-prefix-length> - 24 - </rt-prefix-length> - <rt-entry-count junos:format="3 entries"> - 3 - </rt-entry-count> - <rt-announced-count> - 1 - </rt-announced-count> - <rt-entry> - <active-tag> - * - </active-tag> - <current-active /> - <last-active /> - <protocol-name> - BGP - </protocol-name> - <preference> - 170 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x42439f4c - </nh-address> - <nh-reference-count> - 757869 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.92.10 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 0 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.10 - </to> - <via> - et-0/0/0.0 - </via> - <weight> - 0x1 - </weight> - <label-element> - 0x425dd00 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 13 - </label-element-refcount> - <label-element-childcount> - 9 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 0 - </session> - </nh> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.194 - </to> - <via> - et-0/0/1.3683 - </via> - <weight> - 0x1 - </weight> - <selected-next-hop /> - <label-element> - 0x425dd00 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 13 - </label-element-refcount> - <label-element-childcount> - 9 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 0 - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.92.10 - </to> - <indirect-nh> - 0xa00d600 1048582 INH Session ID: 0x2c0 - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Active Int Ext - </rt-entry-state> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="2526196"> - 4w1d 5:43:16 - </age> - <metric> - 0 - </metric> - <metric2> - 10 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 10 - </med-plus-igp> - <task-name> - BGP_14525.199.34.92.10 - </task-name> - <announce-bits> - 4 - </announce-bits> - <announce-tasks> - 0-KRT 8-Resolve tree 3 10-Aggregate 12-RT - </announce-tasks> - <as-path> - AS path: 3356 13293 29414 39375 39375 I - AS path: Recorded - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 3356 13293 29414 39375 39375 I - </attr-value> - <flags> - </flags> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 3356:2 - </community> - <community> - 3356:22 - </community> - <community> - 3356:100 - </community> - <community> - 3356:123 - </community> - <community> - 3356:501 - </community> - <community> - 3356:903 - </community> - <community> - 3356:2071 - </community> - <community> - 8501:1014 - </community> - <community> - 8545:50 - </community> - <community> - 13344:13300 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3001 - </community> - <community> - 14525:4001 - </community> - <community> - 14525:9014 - </community> - <community> - 15169:13300 - </community> - <community> - 29414:1020 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.92.10 - </peer-id> - </rt-entry> - </rt> - <rt junos:style="detail"> - <rt-destination> - 89.161.74.0 - </rt-destination> - <rt-prefix-length> - 23 - </rt-prefix-length> - <rt-entry-count junos:format="3 entries"> - 3 - </rt-entry-count> - <rt-announced-count> - 1 - </rt-announced-count> - <rt-entry> - <active-tag> - * - </active-tag> - <current-active /> - <last-active /> - <protocol-name> - BGP - </protocol-name> - <preference> - 170 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x42439f4c - </nh-address> - <nh-reference-count> - 757869 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.92.10 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 0 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.10 - </to> - <via> - et-0/0/0.0 - </via> - <weight> - 0x1 - </weight> - <selected-next-hop /> - <label-element> - 0x425dd00 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 13 - </label-element-refcount> - <label-element-childcount> - 9 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 0 - </session> - </nh> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.194 - </to> - <via> - et-0/0/1.3683 - </via> - <weight> - 0x1 - </weight> - <label-element> - 0x425dd00 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 13 - </label-element-refcount> - <label-element-childcount> - 9 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 0 - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.92.10 - </to> - <indirect-nh> - 0xa00d600 1048582 INH Session ID: 0x2c0 - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Active Int Ext - </rt-entry-state> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="2526196"> - 4w1d 5:43:16 - </age> - <metric> - 0 - </metric> - <metric2> - 10 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 10 - </med-plus-igp> - <task-name> - BGP_14525.199.34.92.10 - </task-name> - <announce-bits> - 4 - </announce-bits> - <announce-tasks> - 0-KRT 8-Resolve tree 3 10-Aggregate 12-RT - </announce-tasks> - <as-path> - AS path: 3356 13293 29414 39375 39375 I - AS path: Recorded - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 3356 13293 29414 39375 39375 I - </attr-value> - <flags> - </flags> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 3356:2 - </community> - <community> - 3356:22 - </community> - <community> - 3356:100 - </community> - <community> - 3356:123 - </community> - <community> - 3356:501 - </community> - <community> - 3356:903 - </community> - <community> - 3356:2071 - </community> - <community> - 8501:1014 - </community> - <community> - 8545:50 - </community> - <community> - 13344:13300 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3001 - </community> - <community> - 14525:4001 - </community> - <community> - 14525:9014 - </community> - <community> - 15169:13300 - </community> - <community> - 29414:1020 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.92.10 - </peer-id> - </rt-entry> - </rt> - <rt junos:style="detail"> - <rt-destination> - 89.161.96.0 - </rt-destination> - <rt-prefix-length> - 24 - </rt-prefix-length> - <rt-entry-count junos:format="3 entries"> - 3 - </rt-entry-count> - <rt-announced-count> - 1 - </rt-announced-count> - <rt-entry> - <active-tag> - * - </active-tag> - <current-active /> - <last-active /> - <protocol-name> - BGP - </protocol-name> - <preference> - 170 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x42439f4c - </nh-address> - <nh-reference-count> - 757869 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.92.10 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 0 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.10 - </to> - <via> - et-0/0/0.0 - </via> - <weight> - 0x1 - </weight> - <label-element> - 0x425dd00 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 13 - </label-element-refcount> - <label-element-childcount> - 9 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 0 - </session> - </nh> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.194 - </to> - <via> - et-0/0/1.3683 - </via> - <weight> - 0x1 - </weight> - <selected-next-hop /> - <label-element> - 0x425dd00 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 13 - </label-element-refcount> - <label-element-childcount> - 9 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 0 - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.92.10 - </to> - <indirect-nh> - 0xa00d600 1048582 INH Session ID: 0x2c0 - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Active Int Ext - </rt-entry-state> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="2526196"> - 4w1d 5:43:16 - </age> - <metric> - 0 - </metric> - <metric2> - 10 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 10 - </med-plus-igp> - <task-name> - BGP_14525.199.34.92.10 - </task-name> - <announce-bits> - 4 - </announce-bits> - <announce-tasks> - 0-KRT 8-Resolve tree 3 10-Aggregate 12-RT - </announce-tasks> - <as-path> - AS path: 3356 13293 29414 39375 39375 I - AS path: Recorded - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 3356 13293 29414 39375 39375 I - </attr-value> - <flags> - </flags> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 3356:2 - </community> - <community> - 3356:22 - </community> - <community> - 3356:100 - </community> - <community> - 3356:123 - </community> - <community> - 3356:501 - </community> - <community> - 3356:903 - </community> - <community> - 3356:2071 - </community> - <community> - 8501:1014 - </community> - <community> - 8545:50 - </community> - <community> - 13344:13300 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3001 - </community> - <community> - 14525:4001 - </community> - <community> - 14525:9014 - </community> - <community> - 15169:13300 - </community> - <community> - 29414:1020 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.92.10 - </peer-id> - </rt-entry> - </rt> - <rt junos:style="detail"> - <rt-destination> - 89.161.99.0 - </rt-destination> - <rt-prefix-length> - 24 - </rt-prefix-length> - <rt-entry-count junos:format="3 entries"> - 3 - </rt-entry-count> - <rt-announced-count> - 1 - </rt-announced-count> - <rt-entry> - <active-tag> - * - </active-tag> - <current-active /> - <last-active /> - <protocol-name> - BGP - </protocol-name> - <preference> - 170 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x42439f4c - </nh-address> - <nh-reference-count> - 757869 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.92.10 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 0 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.10 - </to> - <via> - et-0/0/0.0 - </via> - <weight> - 0x1 - </weight> - <label-element> - 0x425dd00 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 13 - </label-element-refcount> - <label-element-childcount> - 9 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 0 - </session> - </nh> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.194 - </to> - <via> - et-0/0/1.3683 - </via> - <weight> - 0x1 - </weight> - <selected-next-hop /> - <label-element> - 0x425dd00 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 13 - </label-element-refcount> - <label-element-childcount> - 9 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 0 - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.92.10 - </to> - <indirect-nh> - 0xa00d600 1048582 INH Session ID: 0x2c0 - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Active Int Ext - </rt-entry-state> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="2526169"> - 4w1d 5:42:49 - </age> - <metric> - 0 - </metric> - <metric2> - 10 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 10 - </med-plus-igp> - <task-name> - BGP_14525.199.34.92.10 - </task-name> - <announce-bits> - 4 - </announce-bits> - <announce-tasks> - 0-KRT 8-Resolve tree 3 10-Aggregate 12-RT - </announce-tasks> - <as-path> - AS path: 3356 13293 29414 39375 39375 I - AS path: Recorded - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 3356 13293 29414 39375 39375 I - </attr-value> - <flags> - </flags> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 3356:2 - </community> - <community> - 3356:22 - </community> - <community> - 3356:100 - </community> - <community> - 3356:123 - </community> - <community> - 3356:501 - </community> - <community> - 3356:903 - </community> - <community> - 3356:2071 - </community> - <community> - 8501:1014 - </community> - <community> - 8545:50 - </community> - <community> - 13344:13300 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3001 - </community> - <community> - 14525:4001 - </community> - <community> - 14525:9014 - </community> - <community> - 15169:13300 - </community> - <community> - 29414:1020 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.92.10 - </peer-id> - </rt-entry> - </rt> - <rt junos:style="detail"> - <rt-destination> - 91.199.12.0 - </rt-destination> - <rt-prefix-length> - 24 - </rt-prefix-length> - <rt-entry-count junos:format="4 entries"> - 4 - </rt-entry-count> - <rt-announced-count> - 1 - </rt-announced-count> - <rt-entry> - <active-tag> - * - </active-tag> - <current-active /> - <last-active /> - <protocol-name> - BGP - </protocol-name> - <preference> - 170 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x42439f4c - </nh-address> - <nh-reference-count> - 757869 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.92.10 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 0 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.10 - </to> - <via> - et-0/0/0.0 - </via> - <weight> - 0x1 - </weight> - <selected-next-hop /> - <label-element> - 0x425dd00 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 13 - </label-element-refcount> - <label-element-childcount> - 9 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 0 - </session> - </nh> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.194 - </to> - <via> - et-0/0/1.3683 - </via> - <weight> - 0x1 - </weight> - <label-element> - 0x425dd00 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 13 - </label-element-refcount> - <label-element-childcount> - 9 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 0 - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.92.10 - </to> - <indirect-nh> - 0xa00d600 1048582 INH Session ID: 0x2c0 - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Active Int Ext - </rt-entry-state> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="2523634"> - 4w1d 5:00:34 - </age> - <metric> - 0 - </metric> - <metric2> - 10 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 10 - </med-plus-igp> - <task-name> - BGP_14525.199.34.92.10 - </task-name> - <announce-bits> - 4 - </announce-bits> - <announce-tasks> - 0-KRT 8-Resolve tree 3 10-Aggregate 12-RT - </announce-tasks> - <as-path> - AS path: 3356 13293 29414 198984 198984 198984 I - AS path: Recorded - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 3356 13293 29414 198984 198984 198984 I - </attr-value> - <flags> - </flags> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 3356:2 - </community> - <community> - 3356:22 - </community> - <community> - 3356:100 - </community> - <community> - 3356:123 - </community> - <community> - 3356:501 - </community> - <community> - 3356:903 - </community> - <community> - 3356:2071 - </community> - <community> - 8501:1014 - </community> - <community> - 8545:50 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3001 - </community> - <community> - 14525:4001 - </community> - <community> - 14525:9014 - </community> - <community> - 29414:1020 - </community> - <extended-community> - target:196844L:5522 - </extended-community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.92.10 - </peer-id> - </rt-entry> - <rt-entry> - <active-tag> - </active-tag> - <protocol-name> - BGP - </protocol-name> - <preference> - 170 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Router - </nh-type> - <nh-index> - 1007 - </nh-index> - <nh-address> - 0x36d576ac - </nh-address> - <nh-reference-count> - 1336784 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 62.115.189.136 - </gateway> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 62.115.189.136 - </to> - <via> - xe-0/1/1.0 - </via> - <selected-next-hop /> - <session> - 4e3 - </session> - </nh> - <rt-entry-state> - Ext - </rt-entry-state> - <inactive-reason> - AS path - </inactive-reason> - <local-as> - 14525 - </local-as> - <peer-as> - 1299 - </peer-as> - <age junos:seconds="2523633"> - 4w1d 5:00:33 - </age> - <validation-state> - unknown - </validation-state> - <med-plus-igp> - 0 - </med-plus-igp> - <task-name> - BGP_1299.62.115.189.136 - </task-name> - <as-path> - AS path: 1299 3356 13293 29414 198984 198984 198984 I - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 1299 3356 13293 29414 198984 198984 198984 I - </attr-value> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 1299:25000 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3001 - </community> - <community> - 14525:4001 - </community> - <community> - 14525:9003 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 2.255.254.43 - </peer-id> - </rt-entry> - <rt-entry> - <active-tag> - </active-tag> - <protocol-name> - BGP - </protocol-name> - <preference> - 200 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x122adabc - </nh-address> - <nh-reference-count> - 546682 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.94.1 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 1283 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.21 - </to> - <via> - et-0/0/2.3601 - </via> - <selected-next-hop /> - <label-element> - 0x8b6ab80 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 4 - </label-element-refcount> - <label-element-childcount> - 2 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 53c - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.94.1 - </to> - <indirect-nh> - 0xa011000 1048625 INH Session ID: 0x5dc - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Int Ext - </rt-entry-state> - <inactive-reason> - Route Preference - </inactive-reason> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="27359"> - 7:35:59 - </age> - <metric> - 0 - </metric> - <metric2> - 1000 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 1000 - </med-plus-igp> - <task-name> - BGP_14525.199.34.94.1 - </task-name> - <as-path> - AS path: 3356 13293 29414 198984 198984 198984 I - AS path: Recorded - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 3356 13293 29414 198984 198984 198984 I - </attr-value> - <flags> - </flags> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 3356:2 - </community> - <community> - 3356:22 - </community> - <community> - 3356:100 - </community> - <community> - 3356:123 - </community> - <community> - 3356:501 - </community> - <community> - 3356:903 - </community> - <community> - 3356:2071 - </community> - <community> - 8501:1014 - </community> - <community> - 8545:50 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3003 - </community> - <community> - 14525:4003 - </community> - <community> - 14525:9014 - </community> - <community> - 29414:1020 - </community> - <extended-community> - target:196844L:5522 - </extended-community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.94.1 - </peer-id> - </rt-entry> - <rt-entry> - <active-tag> - </active-tag> - <protocol-name> - BGP - </protocol-name> - <preference> - 200 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x1104e0dc - </nh-address> - <nh-reference-count> - 600499 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.94.2 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 1280 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.22 - </to> - <via> - et-0/0/2.3601 - </via> - <selected-next-hop /> - <label-element> - 0x4265080 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 4 - </label-element-refcount> - <label-element-childcount> - 2 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 532 - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.94.2 - </to> - <indirect-nh> - 0xa010800 1048619 INH Session ID: 0x5e1 - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Int Ext - </rt-entry-state> - <inactive-reason> - Route Preference - </inactive-reason> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="3511"> - 58:31 - </age> - <metric> - 0 - </metric> - <metric2> - 1000 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 1000 - </med-plus-igp> - <task-name> - BGP_14525.199.34.94.2 - </task-name> - <as-path> - AS path: 6939 196844 29414 198984 198984 198984 I - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 6939 196844 29414 198984 198984 198984 I - </attr-value> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 6939:7082 - </community> - <community> - 6939:8826 - </community> - <community> - 6939:9002 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3003 - </community> - <community> - 14525:4003 - </community> - <community> - 14525:9002 - </community> - <community> - large:8714:1000:2 - </community> - <community> - large:8714:1001:1 - </community> - <community> - large:8714:1001:2 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.94.2 - </peer-id> - </rt-entry> - </rt> - <rt junos:style="detail"> - <rt-destination> - 91.201.16.0 - </rt-destination> - <rt-prefix-length> - 22 - </rt-prefix-length> - <rt-entry-count junos:format="4 entries"> - 4 - </rt-entry-count> - <rt-announced-count> - 1 - </rt-announced-count> - <rt-entry> - <active-tag> - * - </active-tag> - <current-active /> - <last-active /> - <protocol-name> - BGP - </protocol-name> - <preference> - 170 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x42439f4c - </nh-address> - <nh-reference-count> - 757869 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.92.10 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 0 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.10 - </to> - <via> - et-0/0/0.0 - </via> - <weight> - 0x1 - </weight> - <selected-next-hop /> - <label-element> - 0x425dd00 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 13 - </label-element-refcount> - <label-element-childcount> - 9 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 0 - </session> - </nh> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.194 - </to> - <via> - et-0/0/1.3683 - </via> - <weight> - 0x1 - </weight> - <label-element> - 0x425dd00 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 13 - </label-element-refcount> - <label-element-childcount> - 9 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 0 - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.92.10 - </to> - <indirect-nh> - 0xa00d600 1048582 INH Session ID: 0x2c0 - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Active Int Ext - </rt-entry-state> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="2526246"> - 4w1d 5:44:06 - </age> - <metric> - 0 - </metric> - <metric2> - 10 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 10 - </med-plus-igp> - <task-name> - BGP_14525.199.34.92.10 - </task-name> - <announce-bits> - 4 - </announce-bits> - <announce-tasks> - 0-KRT 8-Resolve tree 3 10-Aggregate 12-RT - </announce-tasks> - <as-path> - AS path: 3356 13293 29414 57476 I - AS path: Recorded - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 3356 13293 29414 57476 I - </attr-value> - <flags> - </flags> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 3356:2 - </community> - <community> - 3356:22 - </community> - <community> - 3356:100 - </community> - <community> - 3356:123 - </community> - <community> - 3356:501 - </community> - <community> - 3356:903 - </community> - <community> - 3356:2071 - </community> - <community> - 8501:1014 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3001 - </community> - <community> - 14525:4001 - </community> - <community> - 14525:9014 - </community> - <community> - 29414:1020 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.92.10 - </peer-id> - </rt-entry> - <rt-entry> - <active-tag> - </active-tag> - <protocol-name> - BGP - </protocol-name> - <preference> - 170 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Router - </nh-type> - <nh-index> - 1007 - </nh-index> - <nh-address> - 0x36d576ac - </nh-address> - <nh-reference-count> - 1336784 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 62.115.189.136 - </gateway> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 62.115.189.136 - </to> - <via> - xe-0/1/1.0 - </via> - <selected-next-hop /> - <session> - 4e3 - </session> - </nh> - <rt-entry-state> - Ext - </rt-entry-state> - <inactive-reason> - AS path - </inactive-reason> - <local-as> - 14525 - </local-as> - <peer-as> - 1299 - </peer-as> - <age junos:seconds="2526245"> - 4w1d 5:44:05 - </age> - <validation-state> - unknown - </validation-state> - <med-plus-igp> - 0 - </med-plus-igp> - <task-name> - BGP_1299.62.115.189.136 - </task-name> - <as-path> - AS path: 1299 3356 13293 29414 57476 I - AS path: Recorded - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 1299 3356 13293 29414 57476 I - </attr-value> - <flags> - </flags> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 1299:25000 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3001 - </community> - <community> - 14525:4001 - </community> - <community> - 14525:9003 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 2.255.254.43 - </peer-id> - </rt-entry> - <rt-entry> - <active-tag> - </active-tag> - <protocol-name> - BGP - </protocol-name> - <preference> - 200 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x122adabc - </nh-address> - <nh-reference-count> - 546682 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.94.1 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 1283 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.21 - </to> - <via> - et-0/0/2.3601 - </via> - <selected-next-hop /> - <label-element> - 0x8b6ab80 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 4 - </label-element-refcount> - <label-element-childcount> - 2 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 53c - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.94.1 - </to> - <indirect-nh> - 0xa011000 1048625 INH Session ID: 0x5dc - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Int Ext - </rt-entry-state> - <inactive-reason> - Route Preference - </inactive-reason> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="27339"> - 7:35:39 - </age> - <metric> - 0 - </metric> - <metric2> - 1000 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 1000 - </med-plus-igp> - <task-name> - BGP_14525.199.34.94.1 - </task-name> - <as-path> - AS path: 3356 13293 29414 57476 I - AS path: Recorded - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 3356 13293 29414 57476 I - </attr-value> - <flags> - </flags> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 3356:2 - </community> - <community> - 3356:22 - </community> - <community> - 3356:100 - </community> - <community> - 3356:123 - </community> - <community> - 3356:501 - </community> - <community> - 3356:903 - </community> - <community> - 3356:2071 - </community> - <community> - 8501:1014 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3003 - </community> - <community> - 14525:4003 - </community> - <community> - 14525:9014 - </community> - <community> - 29414:1020 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.94.1 - </peer-id> - </rt-entry> - <rt-entry> - <active-tag> - </active-tag> - <protocol-name> - BGP - </protocol-name> - <preference> - 200 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x1104e0dc - </nh-address> - <nh-reference-count> - 600499 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.94.2 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 1280 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.22 - </to> - <via> - et-0/0/2.3601 - </via> - <selected-next-hop /> - <label-element> - 0x4265080 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 4 - </label-element-refcount> - <label-element-childcount> - 2 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 532 - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.94.2 - </to> - <indirect-nh> - 0xa010800 1048619 INH Session ID: 0x5e1 - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Int Ext - </rt-entry-state> - <inactive-reason> - Route Preference - </inactive-reason> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="3535"> - 58:55 - </age> - <metric> - 0 - </metric> - <metric2> - 1000 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 1000 - </med-plus-igp> - <task-name> - BGP_14525.199.34.94.2 - </task-name> - <as-path> - AS path: 6939 196844 29414 57476 I - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 6939 196844 29414 57476 I - </attr-value> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 6939:7082 - </community> - <community> - 6939:8826 - </community> - <community> - 6939:9002 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3003 - </community> - <community> - 14525:4003 - </community> - <community> - 14525:9002 - </community> - <community> - large:8714:1000:2 - </community> - <community> - large:8714:1001:1 - </community> - <community> - large:8714:1001:2 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.94.2 - </peer-id> - </rt-entry> - </rt> - <rt junos:style="detail"> - <rt-destination> - 130.180.192.0 - </rt-destination> - <rt-prefix-length> - 21 - </rt-prefix-length> - <rt-entry-count junos:format="4 entries"> - 4 - </rt-entry-count> - <rt-announced-count> - 1 - </rt-announced-count> - <rt-entry> - <active-tag> - * - </active-tag> - <current-active /> - <last-active /> - <protocol-name> - BGP - </protocol-name> - <preference> - 170 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x42439f4c - </nh-address> - <nh-reference-count> - 757869 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.92.10 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 0 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.10 - </to> - <via> - et-0/0/0.0 - </via> - <weight> - 0x1 - </weight> - <selected-next-hop /> - <label-element> - 0x425dd00 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 13 - </label-element-refcount> - <label-element-childcount> - 9 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 0 - </session> - </nh> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.194 - </to> - <via> - et-0/0/1.3683 - </via> - <weight> - 0x1 - </weight> - <label-element> - 0x425dd00 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 13 - </label-element-refcount> - <label-element-childcount> - 9 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 0 - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.92.10 - </to> - <indirect-nh> - 0xa00d600 1048582 INH Session ID: 0x2c0 - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Active Int Ext - </rt-entry-state> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="2526216"> - 4w1d 5:43:36 - </age> - <metric> - 0 - </metric> - <metric2> - 10 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 10 - </med-plus-igp> - <task-name> - BGP_14525.199.34.92.10 - </task-name> - <announce-bits> - 4 - </announce-bits> - <announce-tasks> - 0-KRT 8-Resolve tree 3 10-Aggregate 12-RT - </announce-tasks> - <as-path> - AS path: 3356 13293 29414 I - AS path: Recorded - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 3356 13293 29414 I - </attr-value> - <flags> - </flags> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 3356:2 - </community> - <community> - 3356:22 - </community> - <community> - 3356:100 - </community> - <community> - 3356:123 - </community> - <community> - 3356:501 - </community> - <community> - 3356:903 - </community> - <community> - 3356:2071 - </community> - <community> - 8501:1013 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3001 - </community> - <community> - 14525:4001 - </community> - <community> - 14525:9014 - </community> - <community> - 15169:13100 - </community> - <community> - 29414:1000 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.92.10 - </peer-id> - </rt-entry> - <rt-entry> - <active-tag> - </active-tag> - <protocol-name> - BGP - </protocol-name> - <preference> - 170 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Router - </nh-type> - <nh-index> - 1007 - </nh-index> - <nh-address> - 0x36d576ac - </nh-address> - <nh-reference-count> - 1336784 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 62.115.189.136 - </gateway> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 62.115.189.136 - </to> - <via> - xe-0/1/1.0 - </via> - <selected-next-hop /> - <session> - 4e3 - </session> - </nh> - <rt-entry-state> - Ext - </rt-entry-state> - <inactive-reason> - AS path - </inactive-reason> - <local-as> - 14525 - </local-as> - <peer-as> - 1299 - </peer-as> - <age junos:seconds="2526272"> - 4w1d 5:44:32 - </age> - <validation-state> - unknown - </validation-state> - <med-plus-igp> - 0 - </med-plus-igp> - <task-name> - BGP_1299.62.115.189.136 - </task-name> - <as-path> - AS path: 1299 3356 13293 29414 I - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 1299 3356 13293 29414 I - </attr-value> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 1299:25000 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3001 - </community> - <community> - 14525:4001 - </community> - <community> - 14525:9003 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 2.255.254.43 - </peer-id> - </rt-entry> - <rt-entry> - <active-tag> - </active-tag> - <protocol-name> - BGP - </protocol-name> - <preference> - 200 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x122adabc - </nh-address> - <nh-reference-count> - 546682 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.94.1 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 1283 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.21 - </to> - <via> - et-0/0/2.3601 - </via> - <selected-next-hop /> - <label-element> - 0x8b6ab80 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 4 - </label-element-refcount> - <label-element-childcount> - 2 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 53c - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.94.1 - </to> - <indirect-nh> - 0xa011000 1048625 INH Session ID: 0x5dc - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Int Ext - </rt-entry-state> - <inactive-reason> - Route Preference - </inactive-reason> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="27339"> - 7:35:39 - </age> - <metric> - 0 - </metric> - <metric2> - 1000 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 1000 - </med-plus-igp> - <task-name> - BGP_14525.199.34.94.1 - </task-name> - <as-path> - AS path: 3356 13293 29414 I - AS path: Recorded - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 3356 13293 29414 I - </attr-value> - <flags> - </flags> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 3356:2 - </community> - <community> - 3356:22 - </community> - <community> - 3356:100 - </community> - <community> - 3356:123 - </community> - <community> - 3356:501 - </community> - <community> - 3356:903 - </community> - <community> - 3356:2071 - </community> - <community> - 8501:1013 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3003 - </community> - <community> - 14525:4003 - </community> - <community> - 14525:9014 - </community> - <community> - 15169:13100 - </community> - <community> - 29414:1000 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.94.1 - </peer-id> - </rt-entry> - <rt-entry> - <active-tag> - </active-tag> - <protocol-name> - BGP - </protocol-name> - <preference> - 200 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x1104e0dc - </nh-address> - <nh-reference-count> - 600499 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.94.2 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 1280 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.22 - </to> - <via> - et-0/0/2.3601 - </via> - <selected-next-hop /> - <label-element> - 0x4265080 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 4 - </label-element-refcount> - <label-element-childcount> - 2 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 532 - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.94.2 - </to> - <indirect-nh> - 0xa010800 1048619 INH Session ID: 0x5e1 - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Int Ext - </rt-entry-state> - <inactive-reason> - Route Preference - </inactive-reason> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="3535"> - 58:55 - </age> - <metric> - 0 - </metric> - <metric2> - 1000 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 1000 - </med-plus-igp> - <task-name> - BGP_14525.199.34.94.2 - </task-name> - <as-path> - AS path: 6939 196844 29414 I - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 6939 196844 29414 I - </attr-value> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 6939:7082 - </community> - <community> - 6939:8826 - </community> - <community> - 6939:9002 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3003 - </community> - <community> - 14525:4003 - </community> - <community> - 14525:9002 - </community> - <community> - large:8714:1000:2 - </community> - <community> - large:8714:1001:1 - </community> - <community> - large:8714:1001:2 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.94.2 - </peer-id> - </rt-entry> - </rt> - <rt junos:style="detail"> - <rt-destination> - 130.180.199.0 - </rt-destination> - <rt-prefix-length> - 24 - </rt-prefix-length> - <rt-entry-count junos:format="4 entries"> - 4 - </rt-entry-count> - <rt-announced-count> - 1 - </rt-announced-count> - <rt-entry> - <active-tag> - * - </active-tag> - <current-active /> - <last-active /> - <protocol-name> - BGP - </protocol-name> - <preference> - 170 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x42439f4c - </nh-address> - <nh-reference-count> - 757869 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.92.10 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 0 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.10 - </to> - <via> - et-0/0/0.0 - </via> - <weight> - 0x1 - </weight> - <selected-next-hop /> - <label-element> - 0x425dd00 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 13 - </label-element-refcount> - <label-element-childcount> - 9 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 0 - </session> - </nh> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.194 - </to> - <via> - et-0/0/1.3683 - </via> - <weight> - 0x1 - </weight> - <label-element> - 0x425dd00 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 13 - </label-element-refcount> - <label-element-childcount> - 9 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 0 - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.92.10 - </to> - <indirect-nh> - 0xa00d600 1048582 INH Session ID: 0x2c0 - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Active Int Ext - </rt-entry-state> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="2526246"> - 4w1d 5:44:06 - </age> - <metric> - 0 - </metric> - <metric2> - 10 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 10 - </med-plus-igp> - <task-name> - BGP_14525.199.34.92.10 - </task-name> - <announce-bits> - 4 - </announce-bits> - <announce-tasks> - 0-KRT 8-Resolve tree 3 10-Aggregate 12-RT - </announce-tasks> - <as-path> - AS path: 3356 13293 29414 209522 I - Aggregator: 209522 82.139.191.13 - AS path: Recorded - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 3356 13293 29414 209522 I - </attr-value> - <flags> - </flags> - </attr-as-path-effective> - <attr-aggregator> - <attr-length> - 11 - </attr-length> - <attr-value> - <aggr-as-number> - 209522 - </aggr-as-number> - <aggr-router-id> - 82.139.191.13 - </aggr-router-id> - </attr-value> - </attr-aggregator> - </bgp-path-attributes> - <communities> - <community> - 3356:2 - </community> - <community> - 3356:22 - </community> - <community> - 3356:100 - </community> - <community> - 3356:123 - </community> - <community> - 3356:501 - </community> - <community> - 3356:903 - </community> - <community> - 3356:2071 - </community> - <community> - 8501:1014 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3001 - </community> - <community> - 14525:4001 - </community> - <community> - 14525:9014 - </community> - <community> - 29414:1020 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.92.10 - </peer-id> - </rt-entry> - <rt-entry> - <active-tag> - </active-tag> - <protocol-name> - BGP - </protocol-name> - <preference> - 170 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Router - </nh-type> - <nh-index> - 1007 - </nh-index> - <nh-address> - 0x36d576ac - </nh-address> - <nh-reference-count> - 1336784 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 62.115.189.136 - </gateway> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 62.115.189.136 - </to> - <via> - xe-0/1/1.0 - </via> - <selected-next-hop /> - <session> - 4e3 - </session> - </nh> - <rt-entry-state> - Ext - </rt-entry-state> - <inactive-reason> - AS path - </inactive-reason> - <local-as> - 14525 - </local-as> - <peer-as> - 1299 - </peer-as> - <age junos:seconds="2526245"> - 4w1d 5:44:05 - </age> - <validation-state> - unknown - </validation-state> - <med-plus-igp> - 0 - </med-plus-igp> - <task-name> - BGP_1299.62.115.189.136 - </task-name> - <as-path> - AS path: 1299 3356 13293 29414 209522 I - Aggregator: 209522 82.139.191.13 - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 1299 3356 13293 29414 209522 I - </attr-value> - </attr-as-path-effective> - <attr-aggregator> - <attr-length> - 11 - </attr-length> - <attr-value> - <aggr-as-number> - 209522 - </aggr-as-number> - <aggr-router-id> - 82.139.191.13 - </aggr-router-id> - </attr-value> - </attr-aggregator> - </bgp-path-attributes> - <communities> - <community> - 1299:25000 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3001 - </community> - <community> - 14525:4001 - </community> - <community> - 14525:9003 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 2.255.254.43 - </peer-id> - </rt-entry> - <rt-entry> - <active-tag> - </active-tag> - <protocol-name> - BGP - </protocol-name> - <preference> - 200 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x122adabc - </nh-address> - <nh-reference-count> - 546682 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.94.1 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 1283 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.21 - </to> - <via> - et-0/0/2.3601 - </via> - <selected-next-hop /> - <label-element> - 0x8b6ab80 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 4 - </label-element-refcount> - <label-element-childcount> - 2 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 53c - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.94.1 - </to> - <indirect-nh> - 0xa011000 1048625 INH Session ID: 0x5dc - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Int Ext - </rt-entry-state> - <inactive-reason> - Route Preference - </inactive-reason> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="27339"> - 7:35:39 - </age> - <metric> - 0 - </metric> - <metric2> - 1000 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 1000 - </med-plus-igp> - <task-name> - BGP_14525.199.34.94.1 - </task-name> - <as-path> - AS path: 3356 13293 29414 209522 I - Aggregator: 209522 82.139.191.13 - AS path: Recorded - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 3356 13293 29414 209522 I - </attr-value> - <flags> - </flags> - </attr-as-path-effective> - <attr-aggregator> - <attr-length> - 11 - </attr-length> - <attr-value> - <aggr-as-number> - 209522 - </aggr-as-number> - <aggr-router-id> - 82.139.191.13 - </aggr-router-id> - </attr-value> - </attr-aggregator> - </bgp-path-attributes> - <communities> - <community> - 3356:2 - </community> - <community> - 3356:22 - </community> - <community> - 3356:100 - </community> - <community> - 3356:123 - </community> - <community> - 3356:501 - </community> - <community> - 3356:903 - </community> - <community> - 3356:2071 - </community> - <community> - 8501:1014 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3003 - </community> - <community> - 14525:4003 - </community> - <community> - 14525:9014 - </community> - <community> - 29414:1020 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.94.1 - </peer-id> - </rt-entry> - <rt-entry> - <active-tag> - </active-tag> - <protocol-name> - BGP - </protocol-name> - <preference> - 200 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x1104e0dc - </nh-address> - <nh-reference-count> - 600499 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.94.2 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 1280 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.22 - </to> - <via> - et-0/0/2.3601 - </via> - <selected-next-hop /> - <label-element> - 0x4265080 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 4 - </label-element-refcount> - <label-element-childcount> - 2 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 532 - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.94.2 - </to> - <indirect-nh> - 0xa010800 1048619 INH Session ID: 0x5e1 - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Int Ext - </rt-entry-state> - <inactive-reason> - Route Preference - </inactive-reason> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="3535"> - 58:55 - </age> - <metric> - 0 - </metric> - <metric2> - 1000 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 1000 - </med-plus-igp> - <task-name> - BGP_14525.199.34.94.2 - </task-name> - <as-path> - AS path: 6939 196844 29414 209522 I - Aggregator: 209522 82.139.191.13 - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 6939 196844 29414 209522 I - </attr-value> - </attr-as-path-effective> - <attr-aggregator> - <attr-length> - 11 - </attr-length> - <attr-value> - <aggr-as-number> - 209522 - </aggr-as-number> - <aggr-router-id> - 82.139.191.13 - </aggr-router-id> - </attr-value> - </attr-aggregator> - </bgp-path-attributes> - <communities> - <community> - 6939:7082 - </community> - <community> - 6939:8826 - </community> - <community> - 6939:9002 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3003 - </community> - <community> - 14525:4003 - </community> - <community> - 14525:9002 - </community> - <community> - large:8714:1000:2 - </community> - <community> - large:8714:1001:1 - </community> - <community> - large:8714:1001:2 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.94.2 - </peer-id> - </rt-entry> - </rt> - <rt junos:style="detail"> - <rt-destination> - 152.89.52.0 - </rt-destination> - <rt-prefix-length> - 22 - </rt-prefix-length> - <rt-entry-count junos:format="4 entries"> - 4 - </rt-entry-count> - <rt-announced-count> - 1 - </rt-announced-count> - <rt-entry> - <active-tag> - * - </active-tag> - <current-active /> - <last-active /> - <protocol-name> - BGP - </protocol-name> - <preference> - 170 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x42439f4c - </nh-address> - <nh-reference-count> - 757869 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.92.10 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 0 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.10 - </to> - <via> - et-0/0/0.0 - </via> - <weight> - 0x1 - </weight> - <selected-next-hop /> - <label-element> - 0x425dd00 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 13 - </label-element-refcount> - <label-element-childcount> - 9 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 0 - </session> - </nh> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.194 - </to> - <via> - et-0/0/1.3683 - </via> - <weight> - 0x1 - </weight> - <label-element> - 0x425dd00 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 13 - </label-element-refcount> - <label-element-childcount> - 9 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 0 - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.92.10 - </to> - <indirect-nh> - 0xa00d600 1048582 INH Session ID: 0x2c0 - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Active Int Ext - </rt-entry-state> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="2526246"> - 4w1d 5:44:06 - </age> - <metric> - 0 - </metric> - <metric2> - 10 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 10 - </med-plus-igp> - <task-name> - BGP_14525.199.34.92.10 - </task-name> - <announce-bits> - 4 - </announce-bits> - <announce-tasks> - 0-KRT 8-Resolve tree 3 10-Aggregate 12-RT - </announce-tasks> - <as-path> - AS path: 3356 13293 29414 209522 I - AS path: Recorded - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 3356 13293 29414 209522 I - </attr-value> - <flags> - </flags> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 3356:2 - </community> - <community> - 3356:22 - </community> - <community> - 3356:100 - </community> - <community> - 3356:123 - </community> - <community> - 3356:501 - </community> - <community> - 3356:901 - </community> - <community> - 3356:2071 - </community> - <community> - 8501:1014 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:600 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3001 - </community> - <community> - 14525:4001 - </community> - <community> - 14525:9014 - </community> - <community> - 29414:1020 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.92.10 - </peer-id> - </rt-entry> - <rt-entry> - <active-tag> - </active-tag> - <protocol-name> - BGP - </protocol-name> - <preference> - 170 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Router - </nh-type> - <nh-index> - 1007 - </nh-index> - <nh-address> - 0x36d576ac - </nh-address> - <nh-reference-count> - 1336784 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 62.115.189.136 - </gateway> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 62.115.189.136 - </to> - <via> - xe-0/1/1.0 - </via> - <selected-next-hop /> - <session> - 4e3 - </session> - </nh> - <rt-entry-state> - Ext - </rt-entry-state> - <inactive-reason> - AS path - </inactive-reason> - <local-as> - 14525 - </local-as> - <peer-as> - 1299 - </peer-as> - <age junos:seconds="2526245"> - 4w1d 5:44:05 - </age> - <validation-state> - valid - </validation-state> - <med-plus-igp> - 0 - </med-plus-igp> - <task-name> - BGP_1299.62.115.189.136 - </task-name> - <as-path> - AS path: 1299 3356 13293 29414 209522 I - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 1299 3356 13293 29414 209522 I - </attr-value> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 1299:25000 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:600 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3001 - </community> - <community> - 14525:4001 - </community> - <community> - 14525:9003 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 2.255.254.43 - </peer-id> - </rt-entry> - <rt-entry> - <active-tag> - </active-tag> - <protocol-name> - BGP - </protocol-name> - <preference> - 200 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x122adabc - </nh-address> - <nh-reference-count> - 546682 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.94.1 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 1283 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.21 - </to> - <via> - et-0/0/2.3601 - </via> - <selected-next-hop /> - <label-element> - 0x8b6ab80 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 4 - </label-element-refcount> - <label-element-childcount> - 2 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 53c - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.94.1 - </to> - <indirect-nh> - 0xa011000 1048625 INH Session ID: 0x5dc - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Int Ext - </rt-entry-state> - <inactive-reason> - Route Preference - </inactive-reason> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="27339"> - 7:35:39 - </age> - <metric> - 0 - </metric> - <metric2> - 1000 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 1000 - </med-plus-igp> - <task-name> - BGP_14525.199.34.94.1 - </task-name> - <as-path> - AS path: 3356 13293 29414 209522 I - AS path: Recorded - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 3356 13293 29414 209522 I - </attr-value> - <flags> - </flags> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 3356:2 - </community> - <community> - 3356:22 - </community> - <community> - 3356:100 - </community> - <community> - 3356:123 - </community> - <community> - 3356:501 - </community> - <community> - 3356:901 - </community> - <community> - 3356:2071 - </community> - <community> - 8501:1014 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:600 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3003 - </community> - <community> - 14525:4003 - </community> - <community> - 14525:9014 - </community> - <community> - 29414:1020 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.94.1 - </peer-id> - </rt-entry> - <rt-entry> - <active-tag> - </active-tag> - <protocol-name> - BGP - </protocol-name> - <preference> - 200 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x1104e0dc - </nh-address> - <nh-reference-count> - 600499 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.94.2 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 1280 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.22 - </to> - <via> - et-0/0/2.3601 - </via> - <selected-next-hop /> - <label-element> - 0x4265080 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 4 - </label-element-refcount> - <label-element-childcount> - 2 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 532 - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.94.2 - </to> - <indirect-nh> - 0xa010800 1048619 INH Session ID: 0x5e1 - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Int Ext - </rt-entry-state> - <inactive-reason> - Route Preference - </inactive-reason> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="3528"> - 58:48 - </age> - <metric> - 0 - </metric> - <metric2> - 1000 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 1000 - </med-plus-igp> - <task-name> - BGP_14525.199.34.94.2 - </task-name> - <as-path> - AS path: 6939 196844 29414 209522 I - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 6939 196844 29414 209522 I - </attr-value> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 6939:7082 - </community> - <community> - 6939:8826 - </community> - <community> - 6939:9002 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:600 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3003 - </community> - <community> - 14525:4003 - </community> - <community> - 14525:9002 - </community> - <community> - large:8714:1000:1 - </community> - <community> - large:8714:1001:2 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.94.2 - </peer-id> - </rt-entry> - </rt> - <rt junos:style="detail"> - <rt-destination> - 176.101.160.0 - </rt-destination> - <rt-prefix-length> - 21 - </rt-prefix-length> - <rt-entry-count junos:format="4 entries"> - 4 - </rt-entry-count> - <rt-announced-count> - 1 - </rt-announced-count> - <rt-entry> - <active-tag> - * - </active-tag> - <current-active /> - <last-active /> - <protocol-name> - BGP - </protocol-name> - <preference> - 170 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x42439f4c - </nh-address> - <nh-reference-count> - 757869 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.92.10 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 0 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.10 - </to> - <via> - et-0/0/0.0 - </via> - <weight> - 0x1 - </weight> - <selected-next-hop /> - <label-element> - 0x425dd00 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 13 - </label-element-refcount> - <label-element-childcount> - 9 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 0 - </session> - </nh> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.194 - </to> - <via> - et-0/0/1.3683 - </via> - <weight> - 0x1 - </weight> - <label-element> - 0x425dd00 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 13 - </label-element-refcount> - <label-element-childcount> - 9 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 0 - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.92.10 - </to> - <indirect-nh> - 0xa00d600 1048582 INH Session ID: 0x2c0 - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Active Int Ext - </rt-entry-state> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="2526246"> - 4w1d 5:44:06 - </age> - <metric> - 0 - </metric> - <metric2> - 10 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 10 - </med-plus-igp> - <task-name> - BGP_14525.199.34.92.10 - </task-name> - <announce-bits> - 4 - </announce-bits> - <announce-tasks> - 0-KRT 8-Resolve tree 3 10-Aggregate 12-RT - </announce-tasks> - <as-path> - AS path: 3356 13293 29414 57476 57476 I - AS path: Recorded - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 3356 13293 29414 57476 57476 I - </attr-value> - <flags> - </flags> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 3356:2 - </community> - <community> - 3356:22 - </community> - <community> - 3356:100 - </community> - <community> - 3356:123 - </community> - <community> - 3356:501 - </community> - <community> - 3356:903 - </community> - <community> - 3356:2071 - </community> - <community> - 8501:1014 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3001 - </community> - <community> - 14525:4001 - </community> - <community> - 14525:9014 - </community> - <community> - 29414:1020 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.92.10 - </peer-id> - </rt-entry> - <rt-entry> - <active-tag> - </active-tag> - <protocol-name> - BGP - </protocol-name> - <preference> - 170 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Router - </nh-type> - <nh-index> - 1007 - </nh-index> - <nh-address> - 0x36d576ac - </nh-address> - <nh-reference-count> - 1336784 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 62.115.189.136 - </gateway> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 62.115.189.136 - </to> - <via> - xe-0/1/1.0 - </via> - <selected-next-hop /> - <session> - 4e3 - </session> - </nh> - <rt-entry-state> - Ext - </rt-entry-state> - <inactive-reason> - AS path - </inactive-reason> - <local-as> - 14525 - </local-as> - <peer-as> - 1299 - </peer-as> - <age junos:seconds="2526245"> - 4w1d 5:44:05 - </age> - <validation-state> - unknown - </validation-state> - <med-plus-igp> - 0 - </med-plus-igp> - <task-name> - BGP_1299.62.115.189.136 - </task-name> - <as-path> - AS path: 1299 3356 13293 29414 57476 57476 I - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 1299 3356 13293 29414 57476 57476 I - </attr-value> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 1299:25000 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3001 - </community> - <community> - 14525:4001 - </community> - <community> - 14525:9003 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 2.255.254.43 - </peer-id> - </rt-entry> - <rt-entry> - <active-tag> - </active-tag> - <protocol-name> - BGP - </protocol-name> - <preference> - 200 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x122adabc - </nh-address> - <nh-reference-count> - 546682 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.94.1 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 1283 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.21 - </to> - <via> - et-0/0/2.3601 - </via> - <selected-next-hop /> - <label-element> - 0x8b6ab80 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 4 - </label-element-refcount> - <label-element-childcount> - 2 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 53c - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.94.1 - </to> - <indirect-nh> - 0xa011000 1048625 INH Session ID: 0x5dc - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Int Ext - </rt-entry-state> - <inactive-reason> - Route Preference - </inactive-reason> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="27339"> - 7:35:39 - </age> - <metric> - 0 - </metric> - <metric2> - 1000 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 1000 - </med-plus-igp> - <task-name> - BGP_14525.199.34.94.1 - </task-name> - <as-path> - AS path: 3356 13293 29414 57476 57476 I - AS path: Recorded - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 3356 13293 29414 57476 57476 I - </attr-value> - <flags> - </flags> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 3356:2 - </community> - <community> - 3356:22 - </community> - <community> - 3356:100 - </community> - <community> - 3356:123 - </community> - <community> - 3356:501 - </community> - <community> - 3356:903 - </community> - <community> - 3356:2071 - </community> - <community> - 8501:1014 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3003 - </community> - <community> - 14525:4003 - </community> - <community> - 14525:9014 - </community> - <community> - 29414:1020 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.94.1 - </peer-id> - </rt-entry> - <rt-entry> - <active-tag> - </active-tag> - <protocol-name> - BGP - </protocol-name> - <preference> - 200 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x1104e0dc - </nh-address> - <nh-reference-count> - 600499 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.94.2 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 1280 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.22 - </to> - <via> - et-0/0/2.3601 - </via> - <selected-next-hop /> - <label-element> - 0x4265080 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 4 - </label-element-refcount> - <label-element-childcount> - 2 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 532 - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.94.2 - </to> - <indirect-nh> - 0xa010800 1048619 INH Session ID: 0x5e1 - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Int Ext - </rt-entry-state> - <inactive-reason> - Route Preference - </inactive-reason> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="3535"> - 58:55 - </age> - <metric> - 0 - </metric> - <metric2> - 1000 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 1000 - </med-plus-igp> - <task-name> - BGP_14525.199.34.94.2 - </task-name> - <as-path> - AS path: 6939 196844 29414 57476 57476 I - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 6939 196844 29414 57476 57476 I - </attr-value> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 6939:7082 - </community> - <community> - 6939:8826 - </community> - <community> - 6939:9002 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3003 - </community> - <community> - 14525:4003 - </community> - <community> - 14525:9002 - </community> - <community> - large:8714:1000:2 - </community> - <community> - large:8714:1001:1 - </community> - <community> - large:8714:1001:2 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.94.2 - </peer-id> - </rt-entry> - </rt> - <rt junos:style="detail"> - <rt-destination> - 176.124.240.0 - </rt-destination> - <rt-prefix-length> - 24 - </rt-prefix-length> - <rt-entry-count junos:format="4 entries"> - 4 - </rt-entry-count> - <rt-announced-count> - 1 - </rt-announced-count> - <rt-entry> - <active-tag> - * - </active-tag> - <current-active /> - <last-active /> - <protocol-name> - BGP - </protocol-name> - <preference> - 170 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x42439f4c - </nh-address> - <nh-reference-count> - 757869 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.92.10 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 0 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.10 - </to> - <via> - et-0/0/0.0 - </via> - <weight> - 0x1 - </weight> - <label-element> - 0x425dd00 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 13 - </label-element-refcount> - <label-element-childcount> - 9 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 0 - </session> - </nh> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.194 - </to> - <via> - et-0/0/1.3683 - </via> - <weight> - 0x1 - </weight> - <selected-next-hop /> - <label-element> - 0x425dd00 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 13 - </label-element-refcount> - <label-element-childcount> - 9 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 0 - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.92.10 - </to> - <indirect-nh> - 0xa00d600 1048582 INH Session ID: 0x2c0 - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Active Int Ext - </rt-entry-state> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="1401715"> - 2w2d 5:21:55 - </age> - <metric> - 0 - </metric> - <metric2> - 10 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 10 - </med-plus-igp> - <task-name> - BGP_14525.199.34.92.10 - </task-name> - <announce-bits> - 4 - </announce-bits> - <announce-tasks> - 0-KRT 8-Resolve tree 3 10-Aggregate 12-RT - </announce-tasks> - <as-path> - AS path: 3356 13293 29414 205363 I - AS path: Recorded - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 3356 13293 29414 205363 I - </attr-value> - <flags> - </flags> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 3356:2 - </community> - <community> - 3356:22 - </community> - <community> - 3356:100 - </community> - <community> - 3356:123 - </community> - <community> - 3356:501 - </community> - <community> - 3356:903 - </community> - <community> - 3356:2071 - </community> - <community> - 8501:1014 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3001 - </community> - <community> - 14525:4001 - </community> - <community> - 14525:9014 - </community> - <community> - 29414:1020 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.92.10 - </peer-id> - </rt-entry> - <rt-entry> - <active-tag> - </active-tag> - <protocol-name> - BGP - </protocol-name> - <preference> - 170 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Router - </nh-type> - <nh-index> - 1007 - </nh-index> - <nh-address> - 0x36d576ac - </nh-address> - <nh-reference-count> - 1336784 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 62.115.189.136 - </gateway> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 62.115.189.136 - </to> - <via> - xe-0/1/1.0 - </via> - <selected-next-hop /> - <session> - 4e3 - </session> - </nh> - <rt-entry-state> - Ext - </rt-entry-state> - <inactive-reason> - AS path - </inactive-reason> - <local-as> - 14525 - </local-as> - <peer-as> - 1299 - </peer-as> - <age junos:seconds="1401715"> - 2w2d 5:21:55 - </age> - <validation-state> - unknown - </validation-state> - <med-plus-igp> - 0 - </med-plus-igp> - <task-name> - BGP_1299.62.115.189.136 - </task-name> - <as-path> - AS path: 1299 3356 13293 29414 205363 I - AS path: Recorded - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 1299 3356 13293 29414 205363 I - </attr-value> - <flags> - </flags> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 1299:25000 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3001 - </community> - <community> - 14525:4001 - </community> - <community> - 14525:9003 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 2.255.254.43 - </peer-id> - </rt-entry> - <rt-entry> - <active-tag> - </active-tag> - <protocol-name> - BGP - </protocol-name> - <preference> - 200 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x122adabc - </nh-address> - <nh-reference-count> - 546682 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.94.1 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 1283 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.21 - </to> - <via> - et-0/0/2.3601 - </via> - <selected-next-hop /> - <label-element> - 0x8b6ab80 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 4 - </label-element-refcount> - <label-element-childcount> - 2 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 53c - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.94.1 - </to> - <indirect-nh> - 0xa011000 1048625 INH Session ID: 0x5dc - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Int Ext - </rt-entry-state> - <inactive-reason> - Route Preference - </inactive-reason> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="27337"> - 7:35:37 - </age> - <metric> - 0 - </metric> - <metric2> - 1000 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 1000 - </med-plus-igp> - <task-name> - BGP_14525.199.34.94.1 - </task-name> - <as-path> - AS path: 3356 13293 29414 205363 I - AS path: Recorded - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 3356 13293 29414 205363 I - </attr-value> - <flags> - </flags> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 3356:2 - </community> - <community> - 3356:22 - </community> - <community> - 3356:100 - </community> - <community> - 3356:123 - </community> - <community> - 3356:501 - </community> - <community> - 3356:903 - </community> - <community> - 3356:2071 - </community> - <community> - 8501:1014 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3003 - </community> - <community> - 14525:4003 - </community> - <community> - 14525:9014 - </community> - <community> - 29414:1020 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.94.1 - </peer-id> - </rt-entry> - <rt-entry> - <active-tag> - </active-tag> - <protocol-name> - BGP - </protocol-name> - <preference> - 200 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x1104e0dc - </nh-address> - <nh-reference-count> - 600499 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.94.2 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 1280 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.22 - </to> - <via> - et-0/0/2.3601 - </via> - <selected-next-hop /> - <label-element> - 0x4265080 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 4 - </label-element-refcount> - <label-element-childcount> - 2 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 532 - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.94.2 - </to> - <indirect-nh> - 0xa010800 1048619 INH Session ID: 0x5e1 - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Int Ext - </rt-entry-state> - <inactive-reason> - Route Preference - </inactive-reason> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="3804"> - 1:03:24 - </age> - <metric> - 0 - </metric> - <metric2> - 1000 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 1000 - </med-plus-igp> - <task-name> - BGP_14525.199.34.94.2 - </task-name> - <as-path> - AS path: 6939 196844 29414 205363 I - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 6939 196844 29414 205363 I - </attr-value> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 6939:7082 - </community> - <community> - 6939:8826 - </community> - <community> - 6939:9002 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3003 - </community> - <community> - 14525:4003 - </community> - <community> - 14525:9002 - </community> - <community> - large:8714:1000:2 - </community> - <community> - large:8714:1001:1 - </community> - <community> - large:8714:1001:2 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.94.2 - </peer-id> - </rt-entry> - </rt> - <rt junos:style="detail"> - <rt-destination> - 176.124.241.0 - </rt-destination> - <rt-prefix-length> - 24 - </rt-prefix-length> - <rt-entry-count junos:format="4 entries"> - 4 - </rt-entry-count> - <rt-announced-count> - 1 - </rt-announced-count> - <rt-entry> - <active-tag> - * - </active-tag> - <current-active /> - <last-active /> - <protocol-name> - BGP - </protocol-name> - <preference> - 170 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x42439f4c - </nh-address> - <nh-reference-count> - 757869 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.92.10 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 0 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.10 - </to> - <via> - et-0/0/0.0 - </via> - <weight> - 0x1 - </weight> - <label-element> - 0x425dd00 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 13 - </label-element-refcount> - <label-element-childcount> - 9 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 0 - </session> - </nh> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.194 - </to> - <via> - et-0/0/1.3683 - </via> - <weight> - 0x1 - </weight> - <selected-next-hop /> - <label-element> - 0x425dd00 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 13 - </label-element-refcount> - <label-element-childcount> - 9 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 0 - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.92.10 - </to> - <indirect-nh> - 0xa00d600 1048582 INH Session ID: 0x2c0 - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Active Int Ext - </rt-entry-state> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="2523633"> - 4w1d 5:00:33 - </age> - <metric> - 0 - </metric> - <metric2> - 10 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 10 - </med-plus-igp> - <task-name> - BGP_14525.199.34.92.10 - </task-name> - <announce-bits> - 4 - </announce-bits> - <announce-tasks> - 0-KRT 8-Resolve tree 3 10-Aggregate 12-RT - </announce-tasks> - <as-path> - AS path: 3356 13293 29414 205363 I - AS path: Recorded - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 3356 13293 29414 205363 I - </attr-value> - <flags> - </flags> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 3356:2 - </community> - <community> - 3356:22 - </community> - <community> - 3356:100 - </community> - <community> - 3356:123 - </community> - <community> - 3356:501 - </community> - <community> - 3356:903 - </community> - <community> - 3356:2071 - </community> - <community> - 8501:1014 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3001 - </community> - <community> - 14525:4001 - </community> - <community> - 14525:9014 - </community> - <community> - 29414:1020 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.92.10 - </peer-id> - </rt-entry> - <rt-entry> - <active-tag> - </active-tag> - <protocol-name> - BGP - </protocol-name> - <preference> - 170 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Router - </nh-type> - <nh-index> - 1007 - </nh-index> - <nh-address> - 0x36d576ac - </nh-address> - <nh-reference-count> - 1336784 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 62.115.189.136 - </gateway> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 62.115.189.136 - </to> - <via> - xe-0/1/1.0 - </via> - <selected-next-hop /> - <session> - 4e3 - </session> - </nh> - <rt-entry-state> - Ext - </rt-entry-state> - <inactive-reason> - AS path - </inactive-reason> - <local-as> - 14525 - </local-as> - <peer-as> - 1299 - </peer-as> - <age junos:seconds="2523633"> - 4w1d 5:00:33 - </age> - <validation-state> - unknown - </validation-state> - <med-plus-igp> - 0 - </med-plus-igp> - <task-name> - BGP_1299.62.115.189.136 - </task-name> - <as-path> - AS path: 1299 3356 13293 29414 205363 I - AS path: Recorded - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 1299 3356 13293 29414 205363 I - </attr-value> - <flags> - </flags> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 1299:25000 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3001 - </community> - <community> - 14525:4001 - </community> - <community> - 14525:9003 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 2.255.254.43 - </peer-id> - </rt-entry> - <rt-entry> - <active-tag> - </active-tag> - <protocol-name> - BGP - </protocol-name> - <preference> - 200 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x122adabc - </nh-address> - <nh-reference-count> - 546682 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.94.1 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 1283 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.21 - </to> - <via> - et-0/0/2.3601 - </via> - <selected-next-hop /> - <label-element> - 0x8b6ab80 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 4 - </label-element-refcount> - <label-element-childcount> - 2 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 53c - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.94.1 - </to> - <indirect-nh> - 0xa011000 1048625 INH Session ID: 0x5dc - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Int Ext - </rt-entry-state> - <inactive-reason> - Route Preference - </inactive-reason> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="27337"> - 7:35:37 - </age> - <metric> - 0 - </metric> - <metric2> - 1000 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 1000 - </med-plus-igp> - <task-name> - BGP_14525.199.34.94.1 - </task-name> - <as-path> - AS path: 3356 13293 29414 205363 I - AS path: Recorded - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 3356 13293 29414 205363 I - </attr-value> - <flags> - </flags> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 3356:2 - </community> - <community> - 3356:22 - </community> - <community> - 3356:100 - </community> - <community> - 3356:123 - </community> - <community> - 3356:501 - </community> - <community> - 3356:903 - </community> - <community> - 3356:2071 - </community> - <community> - 8501:1014 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3003 - </community> - <community> - 14525:4003 - </community> - <community> - 14525:9014 - </community> - <community> - 29414:1020 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.94.1 - </peer-id> - </rt-entry> - <rt-entry> - <active-tag> - </active-tag> - <protocol-name> - BGP - </protocol-name> - <preference> - 200 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x1104e0dc - </nh-address> - <nh-reference-count> - 600499 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.94.2 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 1280 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.22 - </to> - <via> - et-0/0/2.3601 - </via> - <selected-next-hop /> - <label-element> - 0x4265080 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 4 - </label-element-refcount> - <label-element-childcount> - 2 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 532 - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.94.2 - </to> - <indirect-nh> - 0xa010800 1048619 INH Session ID: 0x5e1 - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Int Ext - </rt-entry-state> - <inactive-reason> - Route Preference - </inactive-reason> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="3804"> - 1:03:24 - </age> - <metric> - 0 - </metric> - <metric2> - 1000 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 1000 - </med-plus-igp> - <task-name> - BGP_14525.199.34.94.2 - </task-name> - <as-path> - AS path: 6939 196844 29414 205363 I - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 6939 196844 29414 205363 I - </attr-value> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 6939:7082 - </community> - <community> - 6939:8826 - </community> - <community> - 6939:9002 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3003 - </community> - <community> - 14525:4003 - </community> - <community> - 14525:9002 - </community> - <community> - large:8714:1000:2 - </community> - <community> - large:8714:1001:1 - </community> - <community> - large:8714:1001:2 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.94.2 - </peer-id> - </rt-entry> - </rt> - <rt junos:style="detail"> - <rt-destination> - 178.21.136.0 - </rt-destination> - <rt-prefix-length> - 21 - </rt-prefix-length> - <rt-entry-count junos:format="4 entries"> - 4 - </rt-entry-count> - <rt-announced-count> - 1 - </rt-announced-count> - <rt-entry> - <active-tag> - * - </active-tag> - <current-active /> - <last-active /> - <protocol-name> - BGP - </protocol-name> - <preference> - 170 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x42439f4c - </nh-address> - <nh-reference-count> - 757869 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.92.10 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 0 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.10 - </to> - <via> - et-0/0/0.0 - </via> - <weight> - 0x1 - </weight> - <label-element> - 0x425dd00 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 13 - </label-element-refcount> - <label-element-childcount> - 9 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 0 - </session> - </nh> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.194 - </to> - <via> - et-0/0/1.3683 - </via> - <weight> - 0x1 - </weight> - <selected-next-hop /> - <label-element> - 0x425dd00 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 13 - </label-element-refcount> - <label-element-childcount> - 9 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 0 - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.92.10 - </to> - <indirect-nh> - 0xa00d600 1048582 INH Session ID: 0x2c0 - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Active Int Ext - </rt-entry-state> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="215662"> - 2d 11:54:22 - </age> - <metric> - 0 - </metric> - <metric2> - 10 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 10 - </med-plus-igp> - <task-name> - BGP_14525.199.34.92.10 - </task-name> - <announce-bits> - 4 - </announce-bits> - <announce-tasks> - 0-KRT 8-Resolve tree 3 10-Aggregate 12-RT - </announce-tasks> - <as-path> - AS path: 3356 13293 29414 197480 I - AS path: Recorded - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 3356 13293 29414 197480 I - </attr-value> - <flags> - </flags> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 3356:2 - </community> - <community> - 3356:22 - </community> - <community> - 3356:100 - </community> - <community> - 3356:123 - </community> - <community> - 3356:501 - </community> - <community> - 3356:901 - </community> - <community> - 3356:2071 - </community> - <community> - 8501:1014 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:600 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3001 - </community> - <community> - 14525:4001 - </community> - <community> - 14525:9014 - </community> - <community> - 29414:1020 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.92.10 - </peer-id> - </rt-entry> - <rt-entry> - <active-tag> - </active-tag> - <protocol-name> - BGP - </protocol-name> - <preference> - 200 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x122adabc - </nh-address> - <nh-reference-count> - 546682 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.94.1 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 1283 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.21 - </to> - <via> - et-0/0/2.3601 - </via> - <selected-next-hop /> - <label-element> - 0x8b6ab80 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 4 - </label-element-refcount> - <label-element-childcount> - 2 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 53c - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.94.1 - </to> - <indirect-nh> - 0xa011000 1048625 INH Session ID: 0x5dc - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Int Ext - </rt-entry-state> - <inactive-reason> - Route Preference - </inactive-reason> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="27354"> - 7:35:54 - </age> - <metric> - 0 - </metric> - <metric2> - 1000 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 1000 - </med-plus-igp> - <task-name> - BGP_14525.199.34.94.1 - </task-name> - <as-path> - AS path: 3356 13293 29414 197480 I - AS path: Recorded - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 3356 13293 29414 197480 I - </attr-value> - <flags> - </flags> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 3356:2 - </community> - <community> - 3356:22 - </community> - <community> - 3356:100 - </community> - <community> - 3356:123 - </community> - <community> - 3356:501 - </community> - <community> - 3356:901 - </community> - <community> - 3356:2071 - </community> - <community> - 8501:1014 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:600 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3003 - </community> - <community> - 14525:4003 - </community> - <community> - 14525:9014 - </community> - <community> - 29414:1020 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.94.1 - </peer-id> - </rt-entry> - <rt-entry> - <active-tag> - </active-tag> - <protocol-name> - BGP - </protocol-name> - <preference> - 200 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x1104e0dc - </nh-address> - <nh-reference-count> - 600499 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.94.2 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 1280 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.22 - </to> - <via> - et-0/0/2.3601 - </via> - <selected-next-hop /> - <label-element> - 0x4265080 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 4 - </label-element-refcount> - <label-element-childcount> - 2 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 532 - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.94.2 - </to> - <indirect-nh> - 0xa010800 1048619 INH Session ID: 0x5e1 - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Int Ext - </rt-entry-state> - <inactive-reason> - Route Preference - </inactive-reason> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="3587"> - 59:47 - </age> - <metric> - 0 - </metric> - <metric2> - 1000 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 1000 - </med-plus-igp> - <task-name> - BGP_14525.199.34.94.2 - </task-name> - <as-path> - AS path: 6939 196844 29414 197480 I - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 6939 196844 29414 197480 I - </attr-value> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 6939:7082 - </community> - <community> - 6939:8826 - </community> - <community> - 6939:9002 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:600 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3003 - </community> - <community> - 14525:4003 - </community> - <community> - 14525:9002 - </community> - <community> - large:8714:1000:1 - </community> - <community> - large:8714:1001:2 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.94.2 - </peer-id> - </rt-entry> - </rt> - <rt junos:style="detail"> - <rt-destination> - 185.3.224.0 - </rt-destination> - <rt-prefix-length> - 22 - </rt-prefix-length> - <rt-entry-count junos:format="4 entries"> - 4 - </rt-entry-count> - <rt-announced-count> - 1 - </rt-announced-count> - <rt-entry> - <active-tag> - * - </active-tag> - <current-active /> - <last-active /> - <protocol-name> - BGP - </protocol-name> - <preference> - 170 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x42439f4c - </nh-address> - <nh-reference-count> - 757869 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.92.10 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 0 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.10 - </to> - <via> - et-0/0/0.0 - </via> - <weight> - 0x1 - </weight> - <label-element> - 0x425dd00 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 13 - </label-element-refcount> - <label-element-childcount> - 9 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 0 - </session> - </nh> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.194 - </to> - <via> - et-0/0/1.3683 - </via> - <weight> - 0x1 - </weight> - <selected-next-hop /> - <label-element> - 0x425dd00 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 13 - </label-element-refcount> - <label-element-childcount> - 9 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 0 - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.92.10 - </to> - <indirect-nh> - 0xa00d600 1048582 INH Session ID: 0x2c0 - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Active Int Ext - </rt-entry-state> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="215662"> - 2d 11:54:22 - </age> - <metric> - 0 - </metric> - <metric2> - 10 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 10 - </med-plus-igp> - <task-name> - BGP_14525.199.34.92.10 - </task-name> - <announce-bits> - 4 - </announce-bits> - <announce-tasks> - 0-KRT 8-Resolve tree 3 10-Aggregate 12-RT - </announce-tasks> - <as-path> - AS path: 3356 13293 29414 197480 I - AS path: Recorded - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 3356 13293 29414 197480 I - </attr-value> - <flags> - </flags> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 3356:2 - </community> - <community> - 3356:22 - </community> - <community> - 3356:100 - </community> - <community> - 3356:123 - </community> - <community> - 3356:501 - </community> - <community> - 3356:901 - </community> - <community> - 3356:2071 - </community> - <community> - 8501:1014 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:600 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3001 - </community> - <community> - 14525:4001 - </community> - <community> - 14525:9014 - </community> - <community> - 29414:1020 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.92.10 - </peer-id> - </rt-entry> - <rt-entry> - <active-tag> - </active-tag> - <protocol-name> - BGP - </protocol-name> - <preference> - 200 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x122adabc - </nh-address> - <nh-reference-count> - 546682 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.94.1 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 1283 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.21 - </to> - <via> - et-0/0/2.3601 - </via> - <selected-next-hop /> - <label-element> - 0x8b6ab80 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 4 - </label-element-refcount> - <label-element-childcount> - 2 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 53c - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.94.1 - </to> - <indirect-nh> - 0xa011000 1048625 INH Session ID: 0x5dc - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Int Ext - </rt-entry-state> - <inactive-reason> - Route Preference - </inactive-reason> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="27354"> - 7:35:54 - </age> - <metric> - 0 - </metric> - <metric2> - 1000 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 1000 - </med-plus-igp> - <task-name> - BGP_14525.199.34.94.1 - </task-name> - <as-path> - AS path: 3356 13293 29414 197480 I - AS path: Recorded - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 3356 13293 29414 197480 I - </attr-value> - <flags> - </flags> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 3356:2 - </community> - <community> - 3356:22 - </community> - <community> - 3356:100 - </community> - <community> - 3356:123 - </community> - <community> - 3356:501 - </community> - <community> - 3356:901 - </community> - <community> - 3356:2071 - </community> - <community> - 8501:1014 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:600 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3003 - </community> - <community> - 14525:4003 - </community> - <community> - 14525:9014 - </community> - <community> - 29414:1020 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.94.1 - </peer-id> - </rt-entry> - <rt-entry> - <active-tag> - </active-tag> - <protocol-name> - BGP - </protocol-name> - <preference> - 200 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x1104e0dc - </nh-address> - <nh-reference-count> - 600499 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.94.2 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 1280 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.22 - </to> - <via> - et-0/0/2.3601 - </via> - <selected-next-hop /> - <label-element> - 0x4265080 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 4 - </label-element-refcount> - <label-element-childcount> - 2 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 532 - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.94.2 - </to> - <indirect-nh> - 0xa010800 1048619 INH Session ID: 0x5e1 - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Int Ext - </rt-entry-state> - <inactive-reason> - Route Preference - </inactive-reason> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="3587"> - 59:47 - </age> - <metric> - 0 - </metric> - <metric2> - 1000 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 1000 - </med-plus-igp> - <task-name> - BGP_14525.199.34.94.2 - </task-name> - <as-path> - AS path: 6939 196844 29414 197480 I - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 6939 196844 29414 197480 I - </attr-value> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 6939:7082 - </community> - <community> - 6939:8826 - </community> - <community> - 6939:9002 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:600 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3003 - </community> - <community> - 14525:4003 - </community> - <community> - 14525:9002 - </community> - <community> - large:8714:1000:1 - </community> - <community> - large:8714:1001:2 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.94.2 - </peer-id> - </rt-entry> - </rt> - <rt junos:style="detail"> - <rt-destination> - 185.61.4.0 - </rt-destination> - <rt-prefix-length> - 23 - </rt-prefix-length> - <rt-entry-count junos:format="4 entries"> - 4 - </rt-entry-count> - <rt-announced-count> - 1 - </rt-announced-count> - <rt-entry> - <active-tag> - * - </active-tag> - <current-active /> - <last-active /> - <protocol-name> - BGP - </protocol-name> - <preference> - 170 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x42439f4c - </nh-address> - <nh-reference-count> - 757869 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.92.10 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 0 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.10 - </to> - <via> - et-0/0/0.0 - </via> - <weight> - 0x1 - </weight> - <selected-next-hop /> - <label-element> - 0x425dd00 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 13 - </label-element-refcount> - <label-element-childcount> - 9 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 0 - </session> - </nh> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.194 - </to> - <via> - et-0/0/1.3683 - </via> - <weight> - 0x1 - </weight> - <label-element> - 0x425dd00 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 13 - </label-element-refcount> - <label-element-childcount> - 9 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 0 - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.92.10 - </to> - <indirect-nh> - 0xa00d600 1048582 INH Session ID: 0x2c0 - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Active Int Ext - </rt-entry-state> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="2526216"> - 4w1d 5:43:36 - </age> - <metric> - 0 - </metric> - <metric2> - 10 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 10 - </med-plus-igp> - <task-name> - BGP_14525.199.34.92.10 - </task-name> - <announce-bits> - 4 - </announce-bits> - <announce-tasks> - 0-KRT 8-Resolve tree 3 10-Aggregate 12-RT - </announce-tasks> - <as-path> - AS path: 3356 13293 29414 I - AS path: Recorded - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 3356 13293 29414 I - </attr-value> - <flags> - </flags> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 3356:2 - </community> - <community> - 3356:22 - </community> - <community> - 3356:100 - </community> - <community> - 3356:123 - </community> - <community> - 3356:501 - </community> - <community> - 3356:903 - </community> - <community> - 3356:2071 - </community> - <community> - 8501:1013 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3001 - </community> - <community> - 14525:4001 - </community> - <community> - 14525:9014 - </community> - <community> - 15169:13100 - </community> - <community> - 29414:1000 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.92.10 - </peer-id> - </rt-entry> - <rt-entry> - <active-tag> - </active-tag> - <protocol-name> - BGP - </protocol-name> - <preference> - 170 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Router - </nh-type> - <nh-index> - 1007 - </nh-index> - <nh-address> - 0x36d576ac - </nh-address> - <nh-reference-count> - 1336784 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 62.115.189.136 - </gateway> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 62.115.189.136 - </to> - <via> - xe-0/1/1.0 - </via> - <selected-next-hop /> - <session> - 4e3 - </session> - </nh> - <rt-entry-state> - Ext - </rt-entry-state> - <inactive-reason> - AS path - </inactive-reason> - <local-as> - 14525 - </local-as> - <peer-as> - 1299 - </peer-as> - <age junos:seconds="2526272"> - 4w1d 5:44:32 - </age> - <validation-state> - unknown - </validation-state> - <med-plus-igp> - 0 - </med-plus-igp> - <task-name> - BGP_1299.62.115.189.136 - </task-name> - <as-path> - AS path: 1299 3356 13293 29414 I - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 1299 3356 13293 29414 I - </attr-value> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 1299:25000 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3001 - </community> - <community> - 14525:4001 - </community> - <community> - 14525:9003 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 2.255.254.43 - </peer-id> - </rt-entry> - <rt-entry> - <active-tag> - </active-tag> - <protocol-name> - BGP - </protocol-name> - <preference> - 200 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x122adabc - </nh-address> - <nh-reference-count> - 546682 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.94.1 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 1283 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.21 - </to> - <via> - et-0/0/2.3601 - </via> - <selected-next-hop /> - <label-element> - 0x8b6ab80 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 4 - </label-element-refcount> - <label-element-childcount> - 2 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 53c - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.94.1 - </to> - <indirect-nh> - 0xa011000 1048625 INH Session ID: 0x5dc - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Int Ext - </rt-entry-state> - <inactive-reason> - Route Preference - </inactive-reason> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="27339"> - 7:35:39 - </age> - <metric> - 0 - </metric> - <metric2> - 1000 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 1000 - </med-plus-igp> - <task-name> - BGP_14525.199.34.94.1 - </task-name> - <as-path> - AS path: 3356 13293 29414 I - AS path: Recorded - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 3356 13293 29414 I - </attr-value> - <flags> - </flags> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 3356:2 - </community> - <community> - 3356:22 - </community> - <community> - 3356:100 - </community> - <community> - 3356:123 - </community> - <community> - 3356:501 - </community> - <community> - 3356:903 - </community> - <community> - 3356:2071 - </community> - <community> - 8501:1013 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3003 - </community> - <community> - 14525:4003 - </community> - <community> - 14525:9014 - </community> - <community> - 15169:13100 - </community> - <community> - 29414:1000 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.94.1 - </peer-id> - </rt-entry> - <rt-entry> - <active-tag> - </active-tag> - <protocol-name> - BGP - </protocol-name> - <preference> - 200 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x1104e0dc - </nh-address> - <nh-reference-count> - 600499 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.94.2 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 1280 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.22 - </to> - <via> - et-0/0/2.3601 - </via> - <selected-next-hop /> - <label-element> - 0x4265080 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 4 - </label-element-refcount> - <label-element-childcount> - 2 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 532 - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.94.2 - </to> - <indirect-nh> - 0xa010800 1048619 INH Session ID: 0x5e1 - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Int Ext - </rt-entry-state> - <inactive-reason> - Route Preference - </inactive-reason> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="3535"> - 58:55 - </age> - <metric> - 0 - </metric> - <metric2> - 1000 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 1000 - </med-plus-igp> - <task-name> - BGP_14525.199.34.94.2 - </task-name> - <as-path> - AS path: 6939 196844 29414 I - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 6939 196844 29414 I - </attr-value> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 6939:7082 - </community> - <community> - 6939:8826 - </community> - <community> - 6939:9002 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3003 - </community> - <community> - 14525:4003 - </community> - <community> - 14525:9002 - </community> - <community> - large:8714:1000:2 - </community> - <community> - large:8714:1001:1 - </community> - <community> - large:8714:1001:2 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.94.2 - </peer-id> - </rt-entry> - </rt> - <rt junos:style="detail"> - <rt-destination> - 185.61.6.0 - </rt-destination> - <rt-prefix-length> - 24 - </rt-prefix-length> - <rt-entry-count junos:format="4 entries"> - 4 - </rt-entry-count> - <rt-announced-count> - 1 - </rt-announced-count> - <rt-entry> - <active-tag> - * - </active-tag> - <current-active /> - <last-active /> - <protocol-name> - BGP - </protocol-name> - <preference> - 170 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x42439f4c - </nh-address> - <nh-reference-count> - 757869 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.92.10 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 0 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.10 - </to> - <via> - et-0/0/0.0 - </via> - <weight> - 0x1 - </weight> - <selected-next-hop /> - <label-element> - 0x425dd00 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 13 - </label-element-refcount> - <label-element-childcount> - 9 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 0 - </session> - </nh> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.194 - </to> - <via> - et-0/0/1.3683 - </via> - <weight> - 0x1 - </weight> - <label-element> - 0x425dd00 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 13 - </label-element-refcount> - <label-element-childcount> - 9 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 0 - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.92.10 - </to> - <indirect-nh> - 0xa00d600 1048582 INH Session ID: 0x2c0 - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Active Int Ext - </rt-entry-state> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="2523687"> - 4w1d 5:01:27 - </age> - <metric> - 0 - </metric> - <metric2> - 10 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 10 - </med-plus-igp> - <task-name> - BGP_14525.199.34.92.10 - </task-name> - <announce-bits> - 4 - </announce-bits> - <announce-tasks> - 0-KRT 8-Resolve tree 3 10-Aggregate 12-RT - </announce-tasks> - <as-path> - AS path: 3356 13293 29414 201209 I - AS path: Recorded - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 3356 13293 29414 201209 I - </attr-value> - <flags> - </flags> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 3356:2 - </community> - <community> - 3356:22 - </community> - <community> - 3356:100 - </community> - <community> - 3356:123 - </community> - <community> - 3356:501 - </community> - <community> - 3356:903 - </community> - <community> - 3356:2071 - </community> - <community> - 8501:1014 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3001 - </community> - <community> - 14525:4001 - </community> - <community> - 14525:9014 - </community> - <community> - 29414:1020 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.92.10 - </peer-id> - </rt-entry> - <rt-entry> - <active-tag> - </active-tag> - <protocol-name> - BGP - </protocol-name> - <preference> - 170 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Router - </nh-type> - <nh-index> - 1007 - </nh-index> - <nh-address> - 0x36d576ac - </nh-address> - <nh-reference-count> - 1336784 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 62.115.189.136 - </gateway> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 62.115.189.136 - </to> - <via> - xe-0/1/1.0 - </via> - <selected-next-hop /> - <session> - 4e3 - </session> - </nh> - <rt-entry-state> - Ext - </rt-entry-state> - <inactive-reason> - AS path - </inactive-reason> - <local-as> - 14525 - </local-as> - <peer-as> - 1299 - </peer-as> - <age junos:seconds="2523687"> - 4w1d 5:01:27 - </age> - <validation-state> - unknown - </validation-state> - <med-plus-igp> - 0 - </med-plus-igp> - <task-name> - BGP_1299.62.115.189.136 - </task-name> - <as-path> - AS path: 1299 3356 13293 29414 201209 I - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 1299 3356 13293 29414 201209 I - </attr-value> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 1299:25000 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3001 - </community> - <community> - 14525:4001 - </community> - <community> - 14525:9003 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 2.255.254.43 - </peer-id> - </rt-entry> - <rt-entry> - <active-tag> - </active-tag> - <protocol-name> - BGP - </protocol-name> - <preference> - 200 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x122adabc - </nh-address> - <nh-reference-count> - 546682 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.94.1 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 1283 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.21 - </to> - <via> - et-0/0/2.3601 - </via> - <selected-next-hop /> - <label-element> - 0x8b6ab80 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 4 - </label-element-refcount> - <label-element-childcount> - 2 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 53c - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.94.1 - </to> - <indirect-nh> - 0xa011000 1048625 INH Session ID: 0x5dc - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Int Ext - </rt-entry-state> - <inactive-reason> - Route Preference - </inactive-reason> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="27354"> - 7:35:54 - </age> - <metric> - 0 - </metric> - <metric2> - 1000 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 1000 - </med-plus-igp> - <task-name> - BGP_14525.199.34.94.1 - </task-name> - <as-path> - AS path: 3356 13293 29414 201209 I - AS path: Recorded - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 3356 13293 29414 201209 I - </attr-value> - <flags> - </flags> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 3356:2 - </community> - <community> - 3356:22 - </community> - <community> - 3356:100 - </community> - <community> - 3356:123 - </community> - <community> - 3356:501 - </community> - <community> - 3356:903 - </community> - <community> - 3356:2071 - </community> - <community> - 8501:1014 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3003 - </community> - <community> - 14525:4003 - </community> - <community> - 14525:9014 - </community> - <community> - 29414:1020 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.94.1 - </peer-id> - </rt-entry> - <rt-entry> - <active-tag> - </active-tag> - <protocol-name> - BGP - </protocol-name> - <preference> - 200 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x1104e0dc - </nh-address> - <nh-reference-count> - 600499 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.94.2 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 1280 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.22 - </to> - <via> - et-0/0/2.3601 - </via> - <selected-next-hop /> - <label-element> - 0x4265080 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 4 - </label-element-refcount> - <label-element-childcount> - 2 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 532 - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.94.2 - </to> - <indirect-nh> - 0xa010800 1048619 INH Session ID: 0x5e1 - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Int Ext - </rt-entry-state> - <inactive-reason> - Route Preference - </inactive-reason> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="3539"> - 58:59 - </age> - <metric> - 0 - </metric> - <metric2> - 1000 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 1000 - </med-plus-igp> - <task-name> - BGP_14525.199.34.94.2 - </task-name> - <as-path> - AS path: 6939 196844 29414 201209 I - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 6939 196844 29414 201209 I - </attr-value> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 6939:7082 - </community> - <community> - 6939:8826 - </community> - <community> - 6939:9002 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3003 - </community> - <community> - 14525:4003 - </community> - <community> - 14525:9002 - </community> - <community> - large:8714:1000:2 - </community> - <community> - large:8714:1001:1 - </community> - <community> - large:8714:1001:2 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.94.2 - </peer-id> - </rt-entry> - </rt> - <rt junos:style="detail"> - <rt-destination> - 195.138.200.0 - </rt-destination> - <rt-prefix-length> - 24 - </rt-prefix-length> - <rt-entry-count junos:format="4 entries"> - 4 - </rt-entry-count> - <rt-announced-count> - 1 - </rt-announced-count> - <rt-entry> - <active-tag> - * - </active-tag> - <current-active /> - <last-active /> - <protocol-name> - BGP - </protocol-name> - <preference> - 170 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x42439f4c - </nh-address> - <nh-reference-count> - 757869 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.92.10 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 0 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.10 - </to> - <via> - et-0/0/0.0 - </via> - <weight> - 0x1 - </weight> - <selected-next-hop /> - <label-element> - 0x425dd00 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 13 - </label-element-refcount> - <label-element-childcount> - 9 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 0 - </session> - </nh> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.194 - </to> - <via> - et-0/0/1.3683 - </via> - <weight> - 0x1 - </weight> - <label-element> - 0x425dd00 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 13 - </label-element-refcount> - <label-element-childcount> - 9 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 0 - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.92.10 - </to> - <indirect-nh> - 0xa00d600 1048582 INH Session ID: 0x2c0 - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Active Int Ext - </rt-entry-state> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="2523686"> - 4w1d 5:01:26 - </age> - <metric> - 0 - </metric> - <metric2> - 10 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 10 - </med-plus-igp> - <task-name> - BGP_14525.199.34.92.10 - </task-name> - <announce-bits> - 4 - </announce-bits> - <announce-tasks> - 0-KRT 8-Resolve tree 3 10-Aggregate 12-RT - </announce-tasks> - <as-path> - AS path: 3356 13293 29414 41580 I - AS path: Recorded - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 3356 13293 29414 41580 I - </attr-value> - <flags> - </flags> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 3356:2 - </community> - <community> - 3356:22 - </community> - <community> - 3356:100 - </community> - <community> - 3356:123 - </community> - <community> - 3356:501 - </community> - <community> - 3356:903 - </community> - <community> - 3356:2071 - </community> - <community> - 8501:1014 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3001 - </community> - <community> - 14525:4001 - </community> - <community> - 14525:9014 - </community> - <community> - 29414:1020 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.92.10 - </peer-id> - </rt-entry> - <rt-entry> - <active-tag> - </active-tag> - <protocol-name> - BGP - </protocol-name> - <preference> - 200 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x122adabc - </nh-address> - <nh-reference-count> - 546682 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.94.1 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 1283 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.21 - </to> - <via> - et-0/0/2.3601 - </via> - <selected-next-hop /> - <label-element> - 0x8b6ab80 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 4 - </label-element-refcount> - <label-element-childcount> - 2 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 53c - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.94.1 - </to> - <indirect-nh> - 0xa011000 1048625 INH Session ID: 0x5dc - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Int Ext - </rt-entry-state> - <inactive-reason> - Route Preference - </inactive-reason> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="27419"> - 7:36:59 - </age> - <metric> - 0 - </metric> - <metric2> - 1000 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 1000 - </med-plus-igp> - <task-name> - BGP_14525.199.34.94.1 - </task-name> - <as-path> - AS path: 3356 13293 29414 41580 I - AS path: Recorded - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 3356 13293 29414 41580 I - </attr-value> - <flags> - </flags> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 3356:2 - </community> - <community> - 3356:22 - </community> - <community> - 3356:100 - </community> - <community> - 3356:123 - </community> - <community> - 3356:501 - </community> - <community> - 3356:903 - </community> - <community> - 3356:2071 - </community> - <community> - 8501:1014 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3003 - </community> - <community> - 14525:4003 - </community> - <community> - 14525:9014 - </community> - <community> - 29414:1020 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.94.1 - </peer-id> - </rt-entry> - <rt-entry> - <active-tag> - </active-tag> - <protocol-name> - BGP - </protocol-name> - <preference> - 200 - </preference> - <preference2> - -151 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x1104e0dc - </nh-address> - <nh-reference-count> - 600499 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.94.2 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 1280 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.22 - </to> - <via> - et-0/0/2.3601 - </via> - <selected-next-hop /> - <label-element> - 0x4265080 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 4 - </label-element-refcount> - <label-element-childcount> - 2 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 532 - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.94.2 - </to> - <indirect-nh> - 0xa010800 1048619 INH Session ID: 0x5e1 - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Int Ext - </rt-entry-state> - <inactive-reason> - Route Preference - </inactive-reason> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="3536"> - 58:56 - </age> - <metric> - 0 - </metric> - <metric2> - 1000 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 1000 - </med-plus-igp> - <task-name> - BGP_14525.199.34.94.2 - </task-name> - <as-path> - AS path: 6939 196844 29414 41580 I - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 6939 196844 29414 41580 I - </attr-value> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 6939:7082 - </community> - <community> - 6939:8826 - </community> - <community> - 6939:9002 - </community> - <community> - 14525:0 - </community> - <community> - 14525:40 - </community> - <community> - 14525:601 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3003 - </community> - <community> - 14525:4003 - </community> - <community> - 14525:9002 - </community> - <community> - large:8714:1000:2 - </community> - <community> - large:8714:1001:1 - </community> - <community> - large:8714:1001:2 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 150 - </local-preference> - <peer-id> - 199.34.94.2 - </peer-id> - </rt-entry> - </rt> - </route-table> - </route-information> - <cli> - <banner> - </banner> - </cli> -</rpc-reply> diff --git a/hyperglass/models/parsing/juniper_route_direct.xml b/hyperglass/models/parsing/juniper_route_direct.xml deleted file mode 100644 index a96084a..0000000 --- a/hyperglass/models/parsing/juniper_route_direct.xml +++ /dev/null @@ -1,774 +0,0 @@ -<rpc-reply xmlns:junos="http://xml.juniper.net/junos/18.2R3/junos"> - <route-information xmlns="http://xml.juniper.net/junos/18.2R3/junos-routing"> - <!-- keepalive --> - <route-table> - <table-name> - inet.0 - </table-name> - <destination-count> - 851482 - </destination-count> - <total-route-count> - 3145808 - </total-route-count> - <active-route-count> - 851445 - </active-route-count> - <holddown-route-count> - 1 - </holddown-route-count> - <hidden-route-count> - 94 - </hidden-route-count> - <rt junos:style="detail"> - <rt-destination> - 1.1.1.0 - </rt-destination> - <rt-prefix-length> - 24 - </rt-prefix-length> - <rt-entry-count junos:format="4 entries"> - 4 - </rt-entry-count> - <rt-announced-count> - 1 - </rt-announced-count> - <rt-entry> - <active-tag> - * - </active-tag> - <current-active /> - <last-active /> - <protocol-name> - BGP - </protocol-name> - <preference> - 170 - </preference> - <preference2> - -176 - </preference2> - <nh-type> - Router - </nh-type> - <nh-index> - 1007 - </nh-index> - <nh-address> - 0x36d576ac - </nh-address> - <nh-reference-count> - 1337511 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 62.115.189.136 - </gateway> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 62.115.189.136 - </to> - <via> - xe-0/1/1.0 - </via> - <selected-next-hop /> - <session> - 4e3 - </session> - </nh> - <rt-entry-state> - Active Ext - </rt-entry-state> - <local-as> - 14525 - </local-as> - <peer-as> - 1299 - </peer-as> - <age junos:seconds="2634431"> - 4w2d 11:47:11 - </age> - <validation-state> - valid - </validation-state> - <med-plus-igp> - 0 - </med-plus-igp> - <task-name> - BGP_1299.62.115.189.136 - </task-name> - <announce-bits> - 5 - </announce-bits> - <announce-tasks> - 0-KRT 6-BGP_RT_Background 8-Resolve tree 3 10-Aggregate 12-RT - </announce-tasks> - <as-path> - AS path: 1299 13335 I - Aggregator: 13335 141.101.72.1 - AS path: Recorded - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 1299 13335 I - </attr-value> - <flags> - </flags> - </attr-as-path-effective> - <attr-aggregator> - <attr-length> - 11 - </attr-length> - <attr-value> - <aggr-as-number> - 13335 - </aggr-as-number> - <aggr-router-id> - 141.101.72.1 - </aggr-router-id> - </attr-value> - </attr-aggregator> - </bgp-path-attributes> - <communities> - <community> - 1299:35000 - </community> - <community> - 14525:0 - </community> - <community> - 14525:41 - </community> - <community> - 14525:600 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3001 - </community> - <community> - 14525:4001 - </community> - <community> - 14525:9003 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 175 - </local-preference> - <peer-id> - 2.255.254.43 - </peer-id> - </rt-entry> - <rt-entry> - <active-tag> - </active-tag> - <protocol-name> - BGP - </protocol-name> - <preference> - 200 - </preference> - <preference2> - -251 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x159d47bc - </nh-address> - <nh-reference-count> - 546747 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.94.1 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 897 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.21 - </to> - <via> - et-0/0/2.3601 - </via> - <selected-next-hop /> - <label-element> - 0x4261200 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 4 - </label-element-refcount> - <label-element-childcount> - 2 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 53c - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.94.1 - </to> - <indirect-nh> - 0xa010e00 1048620 INH Session ID: 0x53e - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Int Ext - </rt-entry-state> - <inactive-reason> - Route Preference - </inactive-reason> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="1766791"> - 2w6d 10:46:31 - </age> - <metric> - 0 - </metric> - <metric2> - 1000 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 1000 - </med-plus-igp> - <task-name> - BGP_14525.199.34.94.1 - </task-name> - <as-path> - AS path: 13335 I - Aggregator: 13335 172.68.129.1 - AS path: Recorded - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 13335 I - </attr-value> - <flags> - </flags> - </attr-as-path-effective> - <attr-aggregator> - <attr-length> - 11 - </attr-length> - <attr-value> - <aggr-as-number> - 13335 - </aggr-as-number> - <aggr-router-id> - 172.68.129.1 - </aggr-router-id> - </attr-value> - </attr-aggregator> - </bgp-path-attributes> - <communities> - <community> - 13335:10232 - </community> - <community> - 13335:19000 - </community> - <community> - 13335:20050 - </community> - <community> - 13335:20500 - </community> - <community> - 13335:20530 - </community> - <community> - 14525:0 - </community> - <community> - 14525:20 - </community> - <community> - 14525:600 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3003 - </community> - <community> - 14525:4003 - </community> - <community> - 14525:9009 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 250 - </local-preference> - <peer-id> - 199.34.94.1 - </peer-id> - </rt-entry> - <rt-entry> - <active-tag> - </active-tag> - <protocol-name> - BGP - </protocol-name> - <preference> - 200 - </preference> - <preference2> - -251 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x20040a2c - </nh-address> - <nh-reference-count> - 600203 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.94.2 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 1243 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.22 - </to> - <via> - et-0/0/2.3601 - </via> - <selected-next-hop /> - <label-element> - 0x8b6e880 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 4 - </label-element-refcount> - <label-element-childcount> - 2 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 532 - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.94.2 - </to> - <indirect-nh> - 0xa010800 1048619 INH Session ID: 0x5c1 - </indirect-nh> - </protocol-nh> - <rt-entry-state> - NotBest Int Ext - </rt-entry-state> - <inactive-reason> - Not Best in its group - Router ID - </inactive-reason> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="242"> - 4:02 - </age> - <metric> - 0 - </metric> - <metric2> - 1000 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 1000 - </med-plus-igp> - <task-name> - BGP_14525.199.34.94.2 - </task-name> - <as-path> - AS path: 13335 I - Aggregator: 13335 172.68.129.1 - AS path: Recorded - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 13335 I - </attr-value> - <flags> - </flags> - </attr-as-path-effective> - <attr-aggregator> - <attr-length> - 11 - </attr-length> - <attr-value> - <aggr-as-number> - 13335 - </aggr-as-number> - <aggr-router-id> - 172.68.129.1 - </aggr-router-id> - </attr-value> - </attr-aggregator> - </bgp-path-attributes> - <communities> - <community> - 13335:10232 - </community> - <community> - 13335:19000 - </community> - <community> - 13335:20050 - </community> - <community> - 13335:20500 - </community> - <community> - 13335:20530 - </community> - <community> - 14525:0 - </community> - <community> - 14525:20 - </community> - <community> - 14525:600 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3003 - </community> - <community> - 14525:4003 - </community> - <community> - 14525:9009 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 250 - </local-preference> - <peer-id> - 199.34.94.2 - </peer-id> - </rt-entry> - <rt-entry> - <active-tag> - </active-tag> - <protocol-name> - BGP - </protocol-name> - <preference> - 200 - </preference> - <preference2> - -251 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x1e049e7c - </nh-address> - <nh-reference-count> - 135307 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 216.250.230.2 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 0 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.52 - </to> - <via> - et-0/0/1.3605 - </via> - <weight> - 0x1 - </weight> - <selected-next-hop /> - <label-element> - 0x8b6f980 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 13 - </label-element-refcount> - <label-element-childcount> - 5 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 0 - </session> - </nh> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.140 - </to> - <via> - et-0/0/2.3607 - </via> - <weight> - 0x1 - </weight> - <label-element> - 0x8b6f980 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 13 - </label-element-refcount> - <label-element-childcount> - 5 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 0 - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 216.250.230.2 - </to> - <indirect-nh> - 0xa00f600 1048607 INH Session ID: 0x54c - </indirect-nh> - </protocol-nh> - <rt-entry-state> - NotBest Int Ext - </rt-entry-state> - <inactive-reason> - Not Best in its group - Router ID - </inactive-reason> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="1367556"> - 2w1d 19:52:36 - </age> - <metric> - 0 - </metric> - <metric2> - 1000 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 1000 - </med-plus-igp> - <task-name> - BGP_14525.216.250.230.2 - </task-name> - <as-path> - AS path: 13335 I - Aggregator: 13335 141.101.73.1 - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - 13335 I - </attr-value> - </attr-as-path-effective> - <attr-aggregator> - <attr-length> - 11 - </attr-length> - <attr-value> - <aggr-as-number> - 13335 - </aggr-as-number> - <aggr-router-id> - 141.101.73.1 - </aggr-router-id> - </attr-value> - </attr-aggregator> - </bgp-path-attributes> - <communities> - <community> - 13335:10014 - </community> - <community> - 13335:19000 - </community> - <community> - 13335:20050 - </community> - <community> - 13335:20500 - </community> - <community> - 13335:20530 - </community> - <community> - 14525:0 - </community> - <community> - 14525:20 - </community> - <community> - 14525:600 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3003 - </community> - <community> - 14525:4002 - </community> - <community> - 14525:9009 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 250 - </local-preference> - <peer-id> - 216.250.230.2 - </peer-id> - </rt-entry> - </rt> - </route-table> - </route-information> - <cli> - <banner> - </banner> - </cli> -</rpc-reply> diff --git a/hyperglass/models/parsing/juniper_route_indirect.xml b/hyperglass/models/parsing/juniper_route_indirect.xml deleted file mode 100644 index ba2f651..0000000 --- a/hyperglass/models/parsing/juniper_route_indirect.xml +++ /dev/null @@ -1,201 +0,0 @@ -<rpc-reply xmlns:junos="http://xml.juniper.net/junos/18.2R3/junos"> - <route-information xmlns="http://xml.juniper.net/junos/18.2R3/junos-routing"> - <!-- keepalive --> - <route-table> - <table-name> - inet.0 - </table-name> - <destination-count> - 851462 - </destination-count> - <total-route-count> - 3145810 - </total-route-count> - <active-route-count> - 851425 - </active-route-count> - <holddown-route-count> - 1 - </holddown-route-count> - <hidden-route-count> - 94 - </hidden-route-count> - <rt junos:style="detail"> - <rt-destination> - 199.34.94.96 - </rt-destination> - <rt-prefix-length> - 30 - </rt-prefix-length> - <rt-entry-count junos:format="1 entry"> - 1 - </rt-entry-count> - <rt-announced-count> - 1 - </rt-announced-count> - <rt-state> - </rt-state> - <rt-entry> - <active-tag> - * - </active-tag> - <current-active /> - <last-active /> - <protocol-name> - BGP - </protocol-name> - <preference> - 200 - </preference> - <preference2> - -451 - </preference2> - <nh-type> - Indirect - </nh-type> - <nh-index> - 0 - </nh-index> - <nh-address> - 0x159d47bc - </nh-address> - <nh-reference-count> - 546728 - </nh-reference-count> - <nh-kernel-id> - 0 - </nh-kernel-id> - <gateway> - 199.34.94.1 - </gateway> - <nh-type> - Router - </nh-type> - <nh-index> - 897 - </nh-index> - <nh junos:indent="16"> - <nh-string> - Next hop - </nh-string> - <to> - 100.64.0.21 - </to> - <via> - et-0/0/2.3601 - </via> - <selected-next-hop /> - <label-element> - 0x4261200 - </label-element> - <label-element-parent> - 0x0 - </label-element-parent> - <label-element-refcount> - 4 - </label-element-refcount> - <label-element-childcount> - 2 - </label-element-childcount> - <label-element-lspid> - 0 - </label-element-lspid> - <session> - 53c - </session> - </nh> - <protocol-nh junos:indent="16"> - <to> - 199.34.94.1 - </to> - <indirect-nh> - 0xa010e00 1048620 INH Session ID: 0x53e - </indirect-nh> - </protocol-nh> - <rt-entry-state> - Active Int Ext - </rt-entry-state> - <local-as> - 14525 - </local-as> - <peer-as> - 14525 - </peer-as> - <age junos:seconds="1767263"> - 2w6d 10:54:23 - </age> - <metric> - 0 - </metric> - <metric2> - 1000 - </metric2> - <validation-state> - unverified - </validation-state> - <med-plus-igp> - 1000 - </med-plus-igp> - <task-name> - BGP_14525.199.34.94.1 - </task-name> - <announce-bits> - 4 - </announce-bits> - <announce-tasks> - 0-KRT 8-Resolve tree 3 10-Aggregate 12-RT - </announce-tasks> - <as-path> - AS path: I - AS path: Recorded - </as-path> - <bgp-path-attributes> - <attr-as-path-effective> - <aspath-effective-string> - AS path: - </aspath-effective-string> - <attr-value> - I - </attr-value> - <flags> - </flags> - </attr-as-path-effective> - </bgp-path-attributes> - <communities> - <community> - 14525:0 - </community> - <community> - 14525:1 - </community> - <community> - 14525:1021 - </community> - <community> - 14525:2840 - </community> - <community> - 14525:3003 - </community> - <community> - 14525:4003 - </community> - </communities> - <bgp-rt-flag> - Accepted - </bgp-rt-flag> - <local-preference> - 450 - </local-preference> - <peer-id> - 199.34.94.1 - </peer-id> - </rt-entry> - </rt> - </route-table> - </route-information> - <cli> - <banner> - </banner> - </cli> -</rpc-reply> diff --git a/hyperglass/models/parsing/serialized.py b/hyperglass/models/parsing/serialized.py deleted file mode 100644 index c4c0bca..0000000 --- a/hyperglass/models/parsing/serialized.py +++ /dev/null @@ -1,109 +0,0 @@ -"""Device-Agnostic Parsed Response Data Model.""" - -# Standard Library -import re -from typing import List -from ipaddress import ip_network - -# Third Party -from pydantic import StrictInt, StrictStr, StrictBool, constr, validator - -# Project -from hyperglass.configuration import params -from hyperglass.external.rpki import rpki_state - -# Local -from ..main import HyperglassModel - -WinningWeight = constr(regex=r"(low|high)") - - -class ParsedRouteEntry(HyperglassModel): - """Per-Route Response Model.""" - - prefix: StrictStr - active: StrictBool - age: StrictInt - weight: StrictInt - med: StrictInt - local_preference: StrictInt - as_path: List[StrictInt] - communities: List[StrictStr] - next_hop: StrictStr - source_as: StrictInt - source_rid: StrictStr - peer_rid: StrictStr - rpki_state: StrictInt - - @validator("communities") - def validate_communities(cls, value): - """Filter returned communities against configured policy. - - Actions: - permit: only permit matches - deny: only deny matches - """ - - def _permit(comm): - """Only allow matching patterns.""" - valid = False - for pattern in params.structured.communities.items: - if re.match(pattern, comm): - valid = True - break - return valid - - def _deny(comm): - """Allow any except matching patterns.""" - valid = True - for pattern in params.structured.communities.items: - if re.match(pattern, comm): - valid = False - break - return valid - - func_map = {"permit": _permit, "deny": _deny} - func = func_map[params.structured.communities.mode] - - return [c for c in value if func(c)] - - @validator("rpki_state") - def validate_rpki_state(cls, value, values): - """If external RPKI validation is enabled, get validation state.""" - - if params.structured.rpki.mode == "router": - # If router validation is enabled, return the value as-is. - return value - - elif params.structured.rpki.mode == "external": - # If external validation is enabled, validate the prefix - # & asn with Cloudflare's RPKI API. - as_path = values["as_path"] - - if len(as_path) == 0: - # If the AS_PATH length is 0, i.e. for an internal route, - # return RPKI Unknown state. - return 3 - else: - # Get last ASN in path - asn = as_path[-1] - - try: - net = ip_network(values["prefix"]) - except ValueError: - return 3 - - # Only do external RPKI lookups for global prefixes. - if net.is_global: - return rpki_state(prefix=values["prefix"], asn=asn) - else: - return value - - -class ParsedRoutes(HyperglassModel): - """Parsed Response Model.""" - - vrf: StrictStr - count: StrictInt = 0 - routes: List[ParsedRouteEntry] - winning_weight: WinningWeight diff --git a/hyperglass/models/webhook.py b/hyperglass/models/webhook.py deleted file mode 100644 index a61e273..0000000 --- a/hyperglass/models/webhook.py +++ /dev/null @@ -1,192 +0,0 @@ -"""Data models used throughout hyperglass.""" - -# Standard Library -from typing import Optional -from datetime import datetime - -# Third Party -from pydantic import StrictStr, root_validator - -# Project -from hyperglass.log import log - -# Local -from .main import HyperglassModel, HyperglassModelExtra - -_WEBHOOK_TITLE = "hyperglass received a valid query with the following data" -_ICON_URL = "https://res.cloudinary.com/hyperglass/image/upload/v1593192484/icon.png" - - -class WebhookHeaders(HyperglassModel): - """Webhook data model.""" - - user_agent: Optional[StrictStr] - referer: Optional[StrictStr] - accept_encoding: Optional[StrictStr] - accept_language: Optional[StrictStr] - x_real_ip: Optional[StrictStr] - x_forwarded_for: Optional[StrictStr] - - class Config: - """Pydantic model config.""" - - fields = { - "user_agent": "user-agent", - "accept_encoding": "accept-encoding", - "accept_language": "accept-language", - "x_real_ip": "x-real-ip", - "x_forwarded_for": "x-forwarded-for", - } - - -class WebhookNetwork(HyperglassModelExtra): - """Webhook data model.""" - - prefix: StrictStr = "Unknown" - asn: StrictStr = "Unknown" - org: StrictStr = "Unknown" - country: StrictStr = "Unknown" - - -class Webhook(HyperglassModel): - """Webhook data model.""" - - query_location: StrictStr - query_type: StrictStr - query_vrf: StrictStr - query_target: StrictStr - headers: WebhookHeaders - source: StrictStr = "Unknown" - network: WebhookNetwork - timestamp: datetime - - @root_validator(pre=True) - def validate_webhook(cls, values): - """Reset network attributes if the source is localhost.""" - if values.get("source") in ("127.0.0.1", "::1"): - values["network"] = {} - return values - - def msteams(self): - """Format the webhook data as a Microsoft Teams card.""" - - def code(value): - """Wrap argument in backticks for markdown inline code formatting.""" - return f"`{str(value)}`" - - header_data = [ - {"name": k, "value": code(v)} - for k, v in self.headers.dict(by_alias=True).items() - ] - time_fmt = self.timestamp.strftime("%Y %m %d %H:%M:%S") - payload = { - "@type": "MessageCard", - "@context": "http://schema.org/extensions", - "themeColor": "118ab2", - "summary": _WEBHOOK_TITLE, - "sections": [ - { - "activityTitle": _WEBHOOK_TITLE, - "activitySubtitle": f"{time_fmt} UTC", - "activityImage": _ICON_URL, - "facts": [ - {"name": "Query Location", "value": self.query_location}, - {"name": "Query Target", "value": code(self.query_target)}, - {"name": "Query Type", "value": self.query_type}, - {"name": "Query VRF", "value": self.query_vrf}, - ], - }, - {"markdown": True, "text": "**Source Information**"}, - {"markdown": True, "text": "---"}, - { - "markdown": True, - "facts": [ - {"name": "IP", "value": code(self.source)}, - {"name": "Prefix", "value": code(self.network.prefix)}, - {"name": "ASN", "value": code(self.network.asn)}, - {"name": "Country", "value": self.network.country}, - {"name": "Organization", "value": self.network.org}, - ], - }, - {"markdown": True, "text": "**Request Headers**"}, - {"markdown": True, "text": "---"}, - {"markdown": True, "facts": header_data}, - ], - } - log.debug("Created MS Teams webhook: {}", str(payload)) - - return payload - - def slack(self): - """Format the webhook data as a Slack message.""" - - def make_field(key, value, code=False): - if code: - value = f"`{value}`" - return f"*{key}*\n{value}" - - header_data = [] - for k, v in self.headers.dict(by_alias=True).items(): - field = make_field(k, v, code=True) - header_data.append(field) - - query_data = [ - { - "type": "mrkdwn", - "text": make_field("Query Location", self.query_location), - }, - { - "type": "mrkdwn", - "text": make_field("Query Target", self.query_target, code=True), - }, - {"type": "mrkdwn", "text": make_field("Query Type", self.query_type)}, - {"type": "mrkdwn", "text": make_field("Query VRF", self.query_vrf)}, - ] - - source_data = [ - { - "type": "mrkdwn", - "text": make_field("Source IP", self.source, code=True), - }, - { - "type": "mrkdwn", - "text": make_field("Source Prefix", self.network.prefix, code=True), - }, - { - "type": "mrkdwn", - "text": make_field("Source ASN", self.network.asn, code=True), - }, - { - "type": "mrkdwn", - "text": make_field("Source Country", self.network.country), - }, - { - "type": "mrkdwn", - "text": make_field("Source Organization", self.network.org), - }, - ] - - time_fmt = self.timestamp.strftime("%Y %m %d %H:%M:%S") - - payload = { - "text": _WEBHOOK_TITLE, - "blocks": [ - { - "type": "section", - "text": {"type": "mrkdwn", "text": f"*{time_fmt} UTC*"}, - }, - {"type": "section", "fields": query_data}, - {"type": "divider"}, - {"type": "section", "fields": source_data}, - {"type": "divider"}, - { - "type": "section", - "text": { - "type": "mrkdwn", - "text": "*Headers*\n" + "\n".join(header_data), - }, - }, - ], - } - log.debug("Created Slack webhook: {}", str(payload)) - return payload diff --git a/hyperglass/parsing/__init__.py b/hyperglass/parsing/__init__.py deleted file mode 100644 index a3270f0..0000000 --- a/hyperglass/parsing/__init__.py +++ /dev/null @@ -1 +0,0 @@ -"""Parsing utilities for command output.""" diff --git a/hyperglass/parsing/arista.py b/hyperglass/parsing/arista.py deleted file mode 100644 index e1eaabe..0000000 --- a/hyperglass/parsing/arista.py +++ /dev/null @@ -1,57 +0,0 @@ -"""Parse Arista JSON Response to Structured Data.""" - -# Standard Library -import json -from typing import Dict, Sequence - -# Third Party -from pydantic import ValidationError - -# Project -from hyperglass.log import log -from hyperglass.exceptions import ParsingError -from hyperglass.models.parsing.arista_eos import AristaRoute - - -def parse_arista(output: Sequence[str]) -> Dict: # noqa: C901 - """Parse a Arista BGP JSON response.""" - data = {} - - for i, response in enumerate(output): - - try: - data: Dict = json.loads(response) - - log.debug("Pre-parsed data: {}", data) - - vrf = list(data["vrfs"].keys())[0] - routes = data["vrfs"][vrf] - - log.debug("Pre-validated data: {}", routes) - - validated = AristaRoute(**routes) - serialized = validated.serialize().export_dict() - - if i == 0: - data.update(serialized) - else: - data["routes"].extend(serialized["routes"]) - - except json.JSONDecodeError as err: - log.critical("Error decoding JSON: {}", str(err)) - raise ParsingError("Error parsing response data") - - except KeyError as err: - log.critical("'{}' was not found in the response", str(err)) - raise ParsingError("Error parsing response data") - - except IndexError as err: - log.critical(str(err)) - raise ParsingError("Error parsing response data") - - except ValidationError as err: - log.critical(str(err)) - raise ParsingError(err.errors()) - - log.debug("Serialzed: {}", data) - return data diff --git a/hyperglass/parsing/common.py b/hyperglass/parsing/common.py deleted file mode 100644 index 252f47b..0000000 --- a/hyperglass/parsing/common.py +++ /dev/null @@ -1,17 +0,0 @@ -"""Command parsers applied to all unstructured output.""" - - -def remove_command(commands: str, output: str) -> str: - """Remove anything before the command if found in output.""" - _output = output.strip().split("\n") - - for command in commands: - for line in _output: - if command in line: - idx = _output.index(line) + 1 - _output = _output[idx:] - - return "\n".join(_output) - - -parsers = (remove_command,) diff --git a/hyperglass/parsing/juniper.py b/hyperglass/parsing/juniper.py deleted file mode 100644 index 3f2ad9b..0000000 --- a/hyperglass/parsing/juniper.py +++ /dev/null @@ -1,105 +0,0 @@ -"""Parse Juniper XML Response to Structured Data.""" - -# Standard Library -import re -from typing import Dict, List, Sequence, Generator - -# Third Party -import xmltodict -from pydantic import ValidationError - -# Project -from hyperglass.log import log -from hyperglass.exceptions import ParsingError -from hyperglass.models.parsing.juniper import JuniperRoute - -REMOVE_PATTERNS = ( - # The XML response can a CLI banner appended to the end of the XML - # string. For example: - # ``` - # <rpc-reply> - # ... - # <cli> - # <banner>{master}</banner> - # </cli> - # </rpc-reply> - # - # {master} noqa: E800 - # ``` - # - # This pattern will remove anything inside braces, including the braces. - r"\{.+\}", -) - - -def clean_xml_output(output: str) -> str: - """Remove Juniper-specific patterns from output.""" - - def scrub(lines: List[str]) -> Generator[str, None, None]: - """Clean & remove each pattern from each line.""" - for pattern in REMOVE_PATTERNS: - for line in lines: - # Remove the pattern & strip extra newlines - scrubbed = re.sub(pattern, "", line.strip()) - # Only return non-empty and non-newline lines - if scrubbed and scrubbed != "\n": - yield scrubbed - - lines = scrub(output.splitlines()) - - return "\n".join(lines) - - -def parse_juniper(output: Sequence) -> Dict: # noqa: C901 - """Parse a Juniper BGP XML response.""" - data = {} - - for i, response in enumerate(output): - cleaned = clean_xml_output(response) - - try: - parsed = xmltodict.parse( - cleaned, force_list=("rt", "rt-entry", "community") - ) - - log.debug("Initially Parsed Response: \n{}", parsed) - - if "rpc-reply" in parsed.keys(): - if "xnm:error" in parsed["rpc-reply"]: - if "message" in parsed["rpc-reply"]["xnm:error"]: - err = parsed["rpc-reply"]["xnm:error"]["message"] - raise ParsingError('Error from device: "{}"', err) - - parsed_base = parsed["rpc-reply"]["route-information"] - elif "route-information" in parsed.keys(): - parsed_base = parsed["route-information"] - - if "route-table" not in parsed_base: - return data - - if "rt" not in parsed_base["route-table"]: - return data - - parsed = parsed_base["route-table"] - - validated = JuniperRoute(**parsed) - serialized = validated.serialize().export_dict() - - if i == 0: - data.update(serialized) - else: - data["routes"].extend(serialized["routes"]) - - except xmltodict.expat.ExpatError as err: - log.critical(str(err)) - raise ParsingError("Error parsing response data") from err - - except KeyError as err: - log.critical("{} was not found in the response", str(err)) - raise ParsingError("Error parsing response data") - - except ValidationError as err: - log.critical(str(err)) - raise ParsingError(err.errors()) - - return data diff --git a/hyperglass/parsing/linux.py b/hyperglass/parsing/linux.py deleted file mode 100644 index 2aba430..0000000 --- a/hyperglass/parsing/linux.py +++ /dev/null @@ -1,81 +0,0 @@ -# flake8: noqa -# WORK IN PROGRESS - -"""Linux-style parsers for ping & traceroute.""" - -# Standard Library -import re - -# Project -from hyperglass.exceptions import ParsingError - - -def _process_numbers(numbers): - """Convert string to float or int.""" - for num in numbers: - num = float(num) - if num.is_integer(): - num = int(num) - yield num - - -def parse_linux_ping(output): - """Parse standard Linux-style ping output to structured data. - - Example: - 64 bytes from 1.1.1.1: icmp_seq=0 ttl=59 time=1.151 ms - 64 bytes from 1.1.1.1: icmp_seq=1 ttl=59 time=1.180 ms - 64 bytes from 1.1.1.1: icmp_seq=2 ttl=59 time=1.170 ms - 64 bytes from 1.1.1.1: icmp_seq=3 ttl=59 time=1.338 ms - 64 bytes from 1.1.1.1: icmp_seq=4 ttl=59 time=4.913 ms - - --- 1.1.1.1 ping statistics --- - 5 packets transmitted, 5 packets received, 0% packet loss - round-trip min/avg/max/stddev = 1.151/1.950/4.913/1.483 ms - """ - try: - # Extract target host - host = re.findall(r"^PING (.+) \(.+\): \d+ data bytes", output)[0] - - # Separate echo replies from summary info - replies, _stats = re.split(r"--- .+ ---", output) - replies = [l for l in replies.splitlines()[1:] if l] - - reply_stats = [] - for line in replies: - # Extract the numerical values from each echo reply line - bytes_seq_ttl_rtt = re.findall( - r"(\d+) bytes.+ icmp_seq=(\d+) ttl=(\d+) time=(\d+\.\d+).*", line - )[0] - - _bytes, seq, ttl, rtt = _process_numbers(bytes_seq_ttl_rtt) - - reply_stats.append( - {"bytes": _bytes, "sequence": seq, "ttl": ttl, "rtt": rtt} - ) - - stats = [l for l in _stats.splitlines() if l] - - # Extract the top summary line numbers & process - tx_rx_loss = re.findall(r"(\d+) .+, (\d+) .+, (\d+)\%.+", stats[0])[0] - tx, rx, loss = _process_numbers(tx_rx_loss) - - # Extract the bottom summary line numbers & process - rt = stats[1].split(" = ")[1] - min_max_avg = rt.split("/")[:-1] - _min, _max, _avg = _process_numbers(min_max_avg) - - return { - "host": host, - "transmitted": tx, - "received": rx, - "loss_percent": loss, - "min_rtt": _min, - "max_rtt": _max, - "avg_rtt": _avg, - "replies": reply_stats, - } - - except (KeyError, ValueError) as err: - # KeyError for empty findalls, ValueError for regex errors - raise ParsingError("Error parsing ping response: {e}", e=str(err)) diff --git a/hyperglass/parsing/mikrotik.py b/hyperglass/parsing/mikrotik.py deleted file mode 100644 index 422862c..0000000 --- a/hyperglass/parsing/mikrotik.py +++ /dev/null @@ -1,52 +0,0 @@ -"""Mikrotik Output Parsing Functions.""" - -# Standard Library -import re - -END_COLUMNS = ("DISTANCE", "STATUS") - - -def parse_mikrotik(output: str): - """Parse Mikrotik output to remove garbage.""" - if output.split()[-1] in END_COLUMNS: - # Mikrotik shows the columns with no rows if there is no data. - # Rather than send back an empty table, send back an empty - # response which is handled with a warning message. - output = "" - else: - remove_lines = () - all_lines = output.splitlines() - # Starting index for rows (after the column row). - start = 1 - # Extract the column row. - column_line = " ".join(all_lines[0].split()) - - for i, line in enumerate(all_lines[1:]): - # Remove all the newline characters (which differ line to - # line) for comparison purposes. - normalized = " ".join(line.split()) - - # Remove ansii characters that aren't caught by Netmiko. - normalized = re.sub(r"\\x1b\[\S{2}\s", "", normalized) - - if column_line in normalized: - # Mikrotik often re-inserts the column row in the output, - # effectively 'starting over'. In that case, re-assign - # the column row and starting index to that point. - column_line = re.sub(r"\[\S{2}\s", "", line) - start = i + 2 - - if "[Q quit|D dump|C-z pause]" in normalized: - # Remove Mikrotik's unhelpful helpers from the output. - remove_lines += (i + 1,) - - # Combine the column row and the data rows from the starting - # index onward. - lines = [column_line, *all_lines[start:]] - - # Remove any lines marked for removal and re-join with a single - # newline character. - lines = [l for i, l in enumerate(lines) if i not in remove_lines] - output = "\n".join(lines) - - return output diff --git a/hyperglass/parsing/nos.py b/hyperglass/parsing/nos.py deleted file mode 100644 index eefed69..0000000 --- a/hyperglass/parsing/nos.py +++ /dev/null @@ -1,36 +0,0 @@ -"""Map NOS and Commands to Parsing Functions.""" - -# Local -from .arista import parse_arista -from .juniper import parse_juniper -from .mikrotik import parse_mikrotik - -structured_parsers = { - "juniper": { - "bgp_route": parse_juniper, - "bgp_aspath": parse_juniper, - "bgp_community": parse_juniper, - }, - "arista_eos": { - "bgp_route": parse_arista, - "bgp_aspath": parse_arista, - "bgp_community": parse_arista, - }, -} - -scrape_parsers = { - "mikrotik_routeros": { - "bgp_route": parse_mikrotik, - "bgp_aspath": parse_mikrotik, - "bgp_community": parse_mikrotik, - "ping": parse_mikrotik, - "traceroute": parse_mikrotik, - }, - "mikrotik_switchos": { - "bgp_route": parse_mikrotik, - "bgp_aspath": parse_mikrotik, - "bgp_community": parse_mikrotik, - "ping": parse_mikrotik, - "traceroute": parse_mikrotik, - }, -} diff --git a/hyperglass/parsing/test_arista.py b/hyperglass/parsing/test_arista.py deleted file mode 100644 index 218fec3..0000000 --- a/hyperglass/parsing/test_arista.py +++ /dev/null @@ -1,25 +0,0 @@ -"""Test Arista JSON Parsing.""" - -# Standard Library -import sys -import json -from pathlib import Path - -# Project -from hyperglass.log import log - -# Local -from .arista import parse_arista - -SAMPLE_FILE = Path(__file__).parent.parent / "models" / "parsing" / "arista_route.json" - -if __name__ == "__main__": - if len(sys.argv) == 2: - sample = sys.argv[1] - else: - with SAMPLE_FILE.open("r") as file: - sample = file.read() - - parsed = parse_arista([sample]) - log.info(json.dumps(parsed, indent=2)) - sys.exit(0) diff --git a/hyperglass/parsing/test_juniper.py b/hyperglass/parsing/test_juniper.py deleted file mode 100644 index 10d2fe9..0000000 --- a/hyperglass/parsing/test_juniper.py +++ /dev/null @@ -1,39 +0,0 @@ -"""Test Juniper XML Parsing.""" - -# Standard Library -import sys -import json -from pathlib import Path - -# Project -from hyperglass.log import log - -# Local -from .juniper import parse_juniper - -SAMPLE_FILES = ( - Path(__file__).parent.parent / "models" / "parsing" / "juniper_route_direct.xml", - Path(__file__).parent.parent / "models" / "parsing" / "juniper_route_indirect.xml", - Path(__file__).parent.parent / "models" / "parsing" / "juniper_route_aspath.xml", -) - - -@log.catch -def run(): - """Run tests.""" - samples = () - if len(sys.argv) == 2: - samples += (sys.argv[1],) - else: - for sample_file in SAMPLE_FILES: - with sample_file.open("r") as file: - samples += (file.read(),) - - for sample in samples: - parsed = parse_juniper([sample]) - log.info(json.dumps(parsed, indent=2)) - sys.exit(0) - - -if __name__ == "__main__": - run() diff --git a/hyperglass/ui/.eslintrc b/hyperglass/ui/.eslintrc deleted file mode 100644 index bbf8f1e..0000000 --- a/hyperglass/ui/.eslintrc +++ /dev/null @@ -1,60 +0,0 @@ -{ - "root": true, - "extends": [ - "eslint:recommended", - "plugin:@typescript-eslint/eslint-recommended", - "plugin:@typescript-eslint/recommended", - "plugin:react/recommended", - "plugin:prettier/recommended", - "prettier/@typescript-eslint" - ], - "parser": "@typescript-eslint/parser", - "env": { - "browser": true, - "es6": true, - "node": true - }, - "parserOptions": { - "ecmaVersion": 2020, - "sourceType": "module", - "ecmaFeatures": { - "jsx": true, - "arrowFunctions": true - }, - "project": "./tsconfig.json" - }, - "plugins": ["react", "@typescript-eslint", "prettier"], - "settings": { - "react": { - "version": "detect" - }, - "import/resolver": { - "node": { - "extensions": [".js", ".jsx", ".ts", ".tsx"], - "paths": ["./src"] - } - } - }, - "rules": { - "@typescript-eslint/no-unused-vars": "off", - "@typescript-eslint/no-unused-vars-experimental": "error", - "no-unused-vars": "off", - "react/jsx-uses-react": "off", - "react/react-in-jsx-scope": "off", - "comma-dangle": ["error", "always-multiline"], - "global-require": "off", - "import/no-dynamic-require": "off", - "import/prefer-default-export": "off", - "@typescript-eslint/no-inferrable-types": "off", - "@typescript-eslint/explicit-function-return-type": "off", - "@typescript-eslint/no-var-requires": "off", - "@typescript-eslint/no-non-null-assertion": "off", - "@typescript-eslint/no-namespace": "off", - "@typescript-eslint/no-empty-interface": [ - "error", - { - "allowSingleExtends": true - } - ] - } -} diff --git a/hyperglass/ui/.gitignore b/hyperglass/ui/.gitignore deleted file mode 100644 index 35328e3..0000000 --- a/hyperglass/ui/.gitignore +++ /dev/null @@ -1,16 +0,0 @@ -.DS_Store -# dev/test files -TODO.txt -*.tmp* -test* -*.log -# generated theme file from hyperglass/hyperglass/render/templates/theme.sass.j2 -theme.sass -# generated JSON file from ingested & validated YAML config -frontend.json -# NPM modules -node_modules/ -# Downloaded Google Fonts -fonts/ -.next -out diff --git a/hyperglass/ui/.prettierignore b/hyperglass/ui/.prettierignore deleted file mode 100644 index b1e1b18..0000000 --- a/hyperglass/ui/.prettierignore +++ /dev/null @@ -1,8 +0,0 @@ -node_modules -dist -package.json -yarn.lock -package-lock.json -.eslintrc -tsconfig.json -.next/ \ No newline at end of file diff --git a/hyperglass/ui/.prettierrc b/hyperglass/ui/.prettierrc deleted file mode 100644 index 354b46a..0000000 --- a/hyperglass/ui/.prettierrc +++ /dev/null @@ -1,11 +0,0 @@ -{ - "semi": true, - "printWidth": 100, - "tabWidth": 2, - "singleQuote": true, - "bracketSpacing": true, - "jsxBracketSameLine": false, - "useTabs": false, - "arrowParens": "avoid", - "trailingComma": "all" -} diff --git a/hyperglass/ui/README.md b/hyperglass/ui/README.md deleted file mode 100644 index 7bb61f2..0000000 --- a/hyperglass/ui/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# hyperglass-ui - -[hyperglass](https://github.com/thatmattlove/hyperglass) UI, written in [React](https://reactjs.org/), on [Next.js](https://nextjs.org/), with [Chakra UI](https://chakra-ui.com/). diff --git a/hyperglass/ui/components/card/body.tsx b/hyperglass/ui/components/card/body.tsx deleted file mode 100644 index f6aa4e8..0000000 --- a/hyperglass/ui/components/card/body.tsx +++ /dev/null @@ -1,23 +0,0 @@ -import { Flex } from '@chakra-ui/react'; -import { useColorValue } from '~/context'; - -import type { TCardBody } from './types'; - -export const CardBody: React.FC<TCardBody> = (props: TCardBody) => { - const { onClick, ...rest } = props; - const bg = useColorValue('white', 'dark.500'); - const color = useColorValue('dark.500', 'white'); - return ( - <Flex - bg={bg} - w="100%" - rounded="md" - color={color} - onClick={onClick} - overflow="hidden" - borderWidth="1px" - direction="column" - {...rest} - /> - ); -}; diff --git a/hyperglass/ui/components/card/footer.tsx b/hyperglass/ui/components/card/footer.tsx deleted file mode 100644 index 13024ff..0000000 --- a/hyperglass/ui/components/card/footer.tsx +++ /dev/null @@ -1,18 +0,0 @@ -import { Flex } from '@chakra-ui/react'; - -import type { TCardFooter } from './types'; - -export const CardFooter: React.FC<TCardFooter> = (props: TCardFooter) => ( - <Flex - p={4} - direction="column" - overflowX="hidden" - overflowY="hidden" - flexDirection="row" - borderTopWidth="1px" - roundedBottomLeft={4} - roundedBottomRight={4} - justifyContent="space-between" - {...props} - /> -); diff --git a/hyperglass/ui/components/card/header.tsx b/hyperglass/ui/components/card/header.tsx deleted file mode 100644 index 275aa9f..0000000 --- a/hyperglass/ui/components/card/header.tsx +++ /dev/null @@ -1,22 +0,0 @@ -import { Flex, Text } from '@chakra-ui/react'; -import { useColorValue } from '~/context'; - -import type { TCardHeader } from './types'; - -export const CardHeader: React.FC<TCardHeader> = (props: TCardHeader) => { - const { children, ...rest } = props; - const bg = useColorValue('blackAlpha.50', 'whiteAlpha.100'); - return ( - <Flex - p={4} - bg={bg} - direction="column" - roundedTopLeft={4} - roundedTopRight={4} - borderBottomWidth="1px" - {...rest} - > - <Text fontWeight="bold">{children}</Text> - </Flex> - ); -}; diff --git a/hyperglass/ui/components/card/index.ts b/hyperglass/ui/components/card/index.ts deleted file mode 100644 index 9f66b54..0000000 --- a/hyperglass/ui/components/card/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export * from './body'; -export * from './footer'; -export * from './header'; diff --git a/hyperglass/ui/components/card/types.ts b/hyperglass/ui/components/card/types.ts deleted file mode 100644 index 739e24e..0000000 --- a/hyperglass/ui/components/card/types.ts +++ /dev/null @@ -1,9 +0,0 @@ -import type { FlexProps } from '@chakra-ui/react'; - -export interface TCardBody extends Omit<FlexProps, 'onClick'> { - onClick?: () => boolean; -} - -export interface TCardFooter extends FlexProps {} - -export interface TCardHeader extends FlexProps {} diff --git a/hyperglass/ui/components/codeBlock.tsx b/hyperglass/ui/components/codeBlock.tsx deleted file mode 100644 index 7b8868f..0000000 --- a/hyperglass/ui/components/codeBlock.tsx +++ /dev/null @@ -1,25 +0,0 @@ -import { Box } from '@chakra-ui/react'; -import { useColorValue } from '~/context'; - -import type { BoxProps } from '@chakra-ui/react'; - -export const CodeBlock: React.FC<BoxProps> = (props: BoxProps) => { - const bg = useColorValue('blackAlpha.100', 'gray.800'); - const color = useColorValue('black', 'white'); - return ( - <Box - p={3} - mt={5} - bg={bg} - as="pre" - border="1px" - rounded="md" - color={color} - fontSize="sm" - fontFamily="mono" - borderColor="inherit" - whiteSpace="pre-wrap" - {...props} - /> - ); -}; diff --git a/hyperglass/ui/components/countdown/countdown.tsx b/hyperglass/ui/components/countdown/countdown.tsx deleted file mode 100644 index 6c5b869..0000000 --- a/hyperglass/ui/components/countdown/countdown.tsx +++ /dev/null @@ -1,41 +0,0 @@ -import { Text } from '@chakra-ui/react'; -import ReactCountdown, { zeroPad } from 'react-countdown'; -import { If } from '~/components'; -import { useColorValue } from '~/context'; - -import type { TCountdown, TRenderer } from './types'; - -const Renderer: React.FC<TRenderer> = (props: TRenderer) => { - const { hours, minutes, seconds, completed, text } = props; - const time = [zeroPad(seconds)]; - minutes !== 0 && time.unshift(zeroPad(minutes)); - hours !== 0 && time.unshift(zeroPad(hours)); - const bg = useColorValue('black', 'white'); - return ( - <> - <If c={completed}> - <Text fontSize="xs" /> - </If> - <If c={!completed}> - <Text fontSize="xs" color="gray.500"> - {text} - <Text as="span" fontSize="xs" color={bg}> - {time.join(':')} - </Text> - </Text> - </If> - </> - ); -}; - -export const Countdown: React.FC<TCountdown> = (props: TCountdown) => { - const { timeout, text } = props; - const then = timeout * 1000; - return ( - <ReactCountdown - date={Date.now() + then} - daysInHours - renderer={renderProps => <Renderer {...renderProps} text={text} />} - /> - ); -}; diff --git a/hyperglass/ui/components/countdown/index.ts b/hyperglass/ui/components/countdown/index.ts deleted file mode 100644 index c1ddcb5..0000000 --- a/hyperglass/ui/components/countdown/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './countdown'; diff --git a/hyperglass/ui/components/countdown/types.ts b/hyperglass/ui/components/countdown/types.ts deleted file mode 100644 index c056e9d..0000000 --- a/hyperglass/ui/components/countdown/types.ts +++ /dev/null @@ -1,10 +0,0 @@ -import type { CountdownRenderProps } from 'react-countdown'; - -export interface TRenderer extends CountdownRenderProps { - text: string; -} - -export interface TCountdown { - timeout: number; - text: string; -} diff --git a/hyperglass/ui/components/debugger.tsx b/hyperglass/ui/components/debugger.tsx deleted file mode 100644 index dd4b732..0000000 --- a/hyperglass/ui/components/debugger.tsx +++ /dev/null @@ -1,90 +0,0 @@ -import { - Tag, - Modal, - HStack, - Button, - useTheme, - ModalBody, - ModalHeader, - ModalOverlay, - ModalContent, - useColorMode, - useDisclosure, - ModalCloseButton, -} from '@chakra-ui/react'; -import { useConfig, useColorValue, useBreakpointValue } from '~/context'; -import { CodeBlock } from '~/components'; -import type { UseDisclosureReturn } from '@chakra-ui/react'; - -interface TViewer extends Pick<UseDisclosureReturn, 'isOpen' | 'onClose'> { - title: string; - children: React.ReactNode; -} - -const Viewer: React.FC<TViewer> = (props: TViewer) => { - const { title, isOpen, onClose, children } = props; - const bg = useColorValue('white', 'black'); - const color = useColorValue('black', 'white'); - return ( - <Modal isOpen={isOpen} onClose={onClose} size="full" scrollBehavior="inside"> - <ModalOverlay /> - <ModalContent bg={bg} color={color} py={4} borderRadius="md" maxW="90%"> - <ModalHeader>{title}</ModalHeader> - <ModalCloseButton /> - <ModalBody> - <CodeBlock>{children}</CodeBlock> - </ModalBody> - </ModalContent> - </Modal> - ); -}; - -export const Debugger: React.FC = () => { - const { isOpen: configOpen, onOpen: onConfigOpen, onClose: configClose } = useDisclosure(); - const { isOpen: themeOpen, onOpen: onThemeOpen, onClose: themeClose } = useDisclosure(); - const { colorMode } = useColorMode(); - const config = useConfig(); - const theme = useTheme(); - const borderColor = useColorValue('gray.100', 'gray.600'); - const mediaSize = - useBreakpointValue({ base: 'SMALL', md: 'MEDIUM', lg: 'LARGE', xl: 'X-LARGE' }) ?? 'UNKNOWN'; - const tagSize = useBreakpointValue({ base: 'sm', lg: 'lg' }) ?? 'lg'; - const btnSize = useBreakpointValue({ base: 'xs', lg: 'sm' }) ?? 'sm'; - return ( - <> - <HStack - py={4} - px={4} - left={0} - right={0} - bottom={0} - maxW="100%" - zIndex={1000} - borderWidth="1px" - position="relative" - justifyContent="center" - borderColor={borderColor} - spacing={{ base: 2, lg: 8 }} - > - <Tag size={tagSize} colorScheme="gray"> - {colorMode.toUpperCase()} - </Tag> - <Button size={btnSize} colorScheme="blue" onClick={onConfigOpen}> - View Config - </Button> - <Button size={btnSize} colorScheme="red" onClick={onThemeOpen}> - View Theme - </Button> - <Tag size={tagSize} colorScheme="teal"> - {mediaSize} - </Tag> - </HStack> - <Viewer isOpen={configOpen} onClose={configClose} title="Config"> - {JSON.stringify(config, null, 4)} - </Viewer> - <Viewer isOpen={themeOpen} onClose={themeClose} title="Theme"> - {JSON.stringify(theme, null, 4)} - </Viewer> - </> - ); -}; diff --git a/hyperglass/ui/components/footer/button.tsx b/hyperglass/ui/components/footer/button.tsx deleted file mode 100644 index a67193d..0000000 --- a/hyperglass/ui/components/footer/button.tsx +++ /dev/null @@ -1,65 +0,0 @@ -import { useMemo } from 'react'; -import { Button, Menu, MenuButton, MenuList } from '@chakra-ui/react'; -import { Markdown } from '~/components'; -import { useColorValue, useBreakpointValue, useConfig } from '~/context'; -import { useOpposingColor, useStrf } from '~/hooks'; - -import type { IConfig } from '~/types'; -import type { TFooterButton } from './types'; - -/** - * Filter the configuration object based on values that are strings for formatting. - */ -function getConfigFmt(config: IConfig): Record<string, string> { - const fmt = {} as Record<string, string>; - for (const [k, v] of Object.entries(config)) { - if (typeof v === 'string') { - fmt[k] = v; - } - } - return fmt; -} - -export const FooterButton: React.FC<TFooterButton> = (props: TFooterButton) => { - const { content, title, side, ...rest } = props; - - const config = useConfig(); - const fmt = useMemo(() => getConfigFmt(config), []); - const fmtContent = useStrf(content, fmt); - - const placement = side === 'left' ? 'top' : side === 'right' ? 'top-end' : undefined; - const bg = useColorValue('white', 'gray.900'); - const color = useOpposingColor(bg); - const size = useBreakpointValue({ base: 'xs', lg: 'sm' }); - - return ( - <Menu placement={placement} preventOverflow isLazy> - <MenuButton - zIndex={2} - as={Button} - size={size} - variant="ghost" - aria-label={typeof title === 'string' ? title : undefined} - > - {title} - </MenuButton> - <MenuList - px={6} - py={4} - bg={bg} - // Ensure the height doesn't overtake the viewport, especially on mobile. See overflow also. - maxH="50vh" - color={color} - boxShadow="2xl" - textAlign="left" - overflowY="auto" - whiteSpace="normal" - mx={{ base: 1, lg: 2 }} - maxW={{ base: '100%', lg: '50vw' }} - {...rest} - > - <Markdown content={fmtContent} /> - </MenuList> - </Menu> - ); -}; diff --git a/hyperglass/ui/components/footer/colorMode.tsx b/hyperglass/ui/components/footer/colorMode.tsx deleted file mode 100644 index feee0dd..0000000 --- a/hyperglass/ui/components/footer/colorMode.tsx +++ /dev/null @@ -1,46 +0,0 @@ -import { forwardRef } from 'react'; -import dynamic from 'next/dynamic'; -import { Button, Icon, Tooltip } from '@chakra-ui/react'; -import { If } from '~/components'; -import { useColorMode, useColorValue, useBreakpointValue } from '~/context'; -import { useOpposingColor } from '~/hooks'; - -import type { TColorModeToggle } from './types'; - -const Sun = dynamic<MeronexIcon>(() => import('@meronex/icons/hi').then(i => i.HiSun)); -const Moon = dynamic<MeronexIcon>(() => import('@meronex/icons/hi').then(i => i.HiMoon)); - -export const ColorModeToggle = forwardRef<HTMLButtonElement, TColorModeToggle>( - (props: TColorModeToggle, ref) => { - const { size = '1.5rem', ...rest } = props; - const { colorMode, toggleColorMode } = useColorMode(); - - const bg = useColorValue('primary.500', 'yellow.300'); - const color = useOpposingColor(bg); - const label = useColorValue('Switch to dark mode', 'Switch to light mode'); - const btnSize = useBreakpointValue({ base: 'xs', lg: 'sm' }); - - return ( - <Tooltip hasArrow placement="top-end" label={label} bg={bg} color={color}> - <Button - ref={ref} - size={btnSize} - title={label} - variant="ghost" - aria-label={label} - _hover={{ color: bg }} - color="currentColor" - onClick={toggleColorMode} - {...rest} - > - <If c={colorMode === 'light'}> - <Icon as={Moon} boxSize={size} /> - </If> - <If c={colorMode === 'dark'}> - <Icon as={Sun} boxSize={size} /> - </If> - </Button> - </Tooltip> - ); - }, -); diff --git a/hyperglass/ui/components/footer/footer.tsx b/hyperglass/ui/components/footer/footer.tsx deleted file mode 100644 index 80a28a9..0000000 --- a/hyperglass/ui/components/footer/footer.tsx +++ /dev/null @@ -1,95 +0,0 @@ -import { useMemo } from 'react'; -import dynamic from 'next/dynamic'; -import { Flex, Icon, HStack, useToken } from '@chakra-ui/react'; -import { If } from '~/components'; -import { useConfig, useMobile, useColorValue, useBreakpointValue } from '~/context'; -import { useStrf } from '~/hooks'; -import { FooterButton } from './button'; -import { ColorModeToggle } from './colorMode'; -import { FooterLink } from './link'; -import { isLink, isMenu } from './types'; - -import type { ButtonProps, LinkProps } from '@chakra-ui/react'; -import type { TLink, TMenu } from '~/types'; - -const CodeIcon = dynamic<MeronexIcon>(() => import('@meronex/icons/fi').then(i => i.FiCode)); -const ExtIcon = dynamic<MeronexIcon>(() => import('@meronex/icons/go').then(i => i.GoLinkExternal)); - -function buildItems(links: TLink[], menus: TMenu[]): [(TLink | TMenu)[], (TLink | TMenu)[]] { - const leftLinks = links.filter(link => link.side === 'left'); - const leftMenus = menus.filter(menu => menu.side === 'left'); - const rightLinks = links.filter(link => link.side === 'right'); - const rightMenus = menus.filter(menu => menu.side === 'right'); - - const left = [...leftLinks, ...leftMenus].sort((a, b) => (a.order > b.order ? 1 : -1)); - const right = [...rightLinks, ...rightMenus].sort((a, b) => (a.order > b.order ? 1 : -1)); - return [left, right]; -} - -export const Footer: React.FC = () => { - const { web, content, primary_asn } = useConfig(); - - const footerBg = useColorValue('blackAlpha.50', 'whiteAlpha.100'); - const footerColor = useColorValue('black', 'white'); - - const size = useBreakpointValue({ base: useToken('sizes', 4), lg: useToken('sizes', 6) }); - - const isMobile = useMobile(); - - const [left, right] = useMemo(() => buildItems(web.links, web.menus), []); - - return ( - <HStack - px={6} - py={4} - w="100%" - zIndex={1} - as="footer" - bg={footerBg} - whiteSpace="nowrap" - color={footerColor} - spacing={{ base: 8, lg: 6 }} - d={{ base: 'inline-block', lg: 'flex' }} - overflowY={{ base: 'auto', lg: 'unset' }} - justifyContent={{ base: 'center', lg: 'space-between' }} - > - {left.map(item => { - if (isLink(item)) { - const url = useStrf(item.url, { primary_asn }) ?? '/'; - const icon: Partial<ButtonProps & LinkProps> = {}; - - if (item.show_icon) { - icon.rightIcon = <ExtIcon />; - } - return <FooterLink key={item.title} href={url} title={item.title} {...icon} />; - } else if (isMenu(item)) { - return ( - <FooterButton key={item.title} side="left" content={item.content} title={item.title} /> - ); - } - })} - {!isMobile && <Flex p={0} flex="1 0 auto" maxWidth="100%" mr="auto" />} - {right.map(item => { - if (isLink(item)) { - const url = useStrf(item.url, { primary_asn }) ?? '/'; - const icon: Partial<ButtonProps & LinkProps> = {}; - - if (item.show_icon) { - icon.rightIcon = <ExtIcon />; - } - return <FooterLink href={url} title={item.title} {...icon} />; - } else if (isMenu(item)) { - return <FooterButton side="right" content={item.content} title={item.title} />; - } - })} - <If c={web.credit.enable}> - <FooterButton - side="right" - content={content.credit} - title={<Icon as={CodeIcon} boxSize={size} />} - /> - </If> - <ColorModeToggle size={size} /> - </HStack> - ); -}; diff --git a/hyperglass/ui/components/footer/index.ts b/hyperglass/ui/components/footer/index.ts deleted file mode 100644 index a058eae..0000000 --- a/hyperglass/ui/components/footer/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './footer'; diff --git a/hyperglass/ui/components/footer/link.tsx b/hyperglass/ui/components/footer/link.tsx deleted file mode 100644 index 83d34c0..0000000 --- a/hyperglass/ui/components/footer/link.tsx +++ /dev/null @@ -1,13 +0,0 @@ -import { Button, Link, useBreakpointValue } from '@chakra-ui/react'; - -import type { TFooterLink } from './types'; - -export const FooterLink: React.FC<TFooterLink> = (props: TFooterLink) => { - const { title } = props; - const btnSize = useBreakpointValue({ base: 'xs', lg: 'sm' }); - return ( - <Button as={Link} isExternal size={btnSize} variant="ghost" aria-label={title} {...props}> - {title} - </Button> - ); -}; diff --git a/hyperglass/ui/components/footer/types.ts b/hyperglass/ui/components/footer/types.ts deleted file mode 100644 index 8f6143d..0000000 --- a/hyperglass/ui/components/footer/types.ts +++ /dev/null @@ -1,26 +0,0 @@ -import type { ButtonProps, LinkProps, MenuListProps } from '@chakra-ui/react'; -import type { TLink, TMenu } from '~/types'; - -type TFooterSide = 'left' | 'right'; - -export interface TFooterButton extends Omit<MenuListProps, 'title'> { - side: TFooterSide; - title?: MenuListProps['children']; - content: string; -} - -export type TFooterLink = ButtonProps & LinkProps & { title: string }; - -export type TFooterItems = 'help' | 'credit' | 'terms'; - -export interface TColorModeToggle extends ButtonProps { - size?: string; -} - -export function isLink(item: TLink | TMenu): item is TLink { - return 'url' in item; -} - -export function isMenu(item: TLink | TMenu): item is TMenu { - return 'content' in item; -} diff --git a/hyperglass/ui/components/form/field.tsx b/hyperglass/ui/components/form/field.tsx deleted file mode 100644 index 5ea6fe3..0000000 --- a/hyperglass/ui/components/form/field.tsx +++ /dev/null @@ -1,60 +0,0 @@ -import { Flex, FormControl, FormLabel, FormErrorMessage } from '@chakra-ui/react'; -import { useFormContext } from 'react-hook-form'; -import { If } from '~/components'; -import { useColorValue } from '~/context'; -import { useBooleanValue } from '~/hooks'; - -import type { FieldError } from 'react-hook-form'; -import type { TField } from './types'; - -export const FormField: React.FC<TField> = (props: TField) => { - const { name, label, children, labelAddOn, fieldAddOn, hiddenLabels = false, ...rest } = props; - const labelColor = useColorValue('blackAlpha.700', 'whiteAlpha.700'); - const errorColor = useColorValue('red.500', 'red.300'); - const opacity = useBooleanValue(hiddenLabels, 0, undefined); - - const { - formState: { errors }, - } = useFormContext(); - - const error = name in errors && (errors[name] as FieldError); - - if (error !== false) { - console.warn(`Error on field '${label}': ${error.message}`); - } - - return ( - <FormControl - mx={2} - d="flex" - w="100%" - maxW="100%" - flexDir="column" - my={{ base: 2, lg: 4 }} - isInvalid={error !== false} - flex={{ base: '1 0 100%', lg: '1 0 33.33%' }} - {...rest} - > - <FormLabel - pl={1} - pr={0} - htmlFor={name} - display="flex" - opacity={opacity} - alignItems="center" - justifyContent="space-between" - color={error !== false ? errorColor : labelColor} - > - {label} - <If c={typeof labelAddOn !== 'undefined'}>{labelAddOn}</If> - </FormLabel> - {children} - <If c={typeof fieldAddOn !== 'undefined'}> - <Flex justify="flex-end" pt={3}> - {fieldAddOn} - </Flex> - </If> - <FormErrorMessage opacity={opacity}>{error && error.message}</FormErrorMessage> - </FormControl> - ); -}; diff --git a/hyperglass/ui/components/form/index.ts b/hyperglass/ui/components/form/index.ts deleted file mode 100644 index c315715..0000000 --- a/hyperglass/ui/components/form/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -export * from './field'; -export * from './queryLocation'; -export * from './queryTarget'; -export * from './queryType'; -export * from './queryVrf'; -export * from './resolvedTarget'; -export * from './row'; diff --git a/hyperglass/ui/components/form/queryLocation.tsx b/hyperglass/ui/components/form/queryLocation.tsx deleted file mode 100644 index f5dec8b..0000000 --- a/hyperglass/ui/components/form/queryLocation.tsx +++ /dev/null @@ -1,64 +0,0 @@ -import { useMemo } from 'react'; -import { useFormContext } from 'react-hook-form'; -import { Select } from '~/components'; -import { useConfig } from '~/context'; -import { useLGState, useLGMethods } from '~/hooks'; - -import type { TNetwork, TSelectOption } from '~/types'; -import type { TQuerySelectField } from './types'; - -function buildOptions(networks: TNetwork[]) { - return networks - .map(net => { - const label = net.display_name; - const options = net.locations - .map(loc => ({ - label: loc.name, - value: loc._id, - group: net.display_name, - })) - .sort((a, b) => (a.label < b.label ? -1 : a.label > b.label ? 1 : 0)); - return { label, options }; - }) - .sort((a, b) => (a.label < b.label ? -1 : a.label > b.label ? 1 : 0)); -} - -export const QueryLocation: React.FC<TQuerySelectField> = (props: TQuerySelectField) => { - const { onChange, label } = props; - - const { networks } = useConfig(); - const { - formState: { errors }, - } = useFormContext(); - const { selections } = useLGState(); - const { exportState } = useLGMethods(); - - const options = useMemo(() => buildOptions(networks), [networks.length]); - - function handleChange(e: TSelectOption | TSelectOption[]): void { - if (e === null) { - e = []; - } else if (typeof e === 'string') { - e = [e]; - } - if (Array.isArray(e)) { - const value = e.map(sel => sel!.value); - onChange({ field: 'query_location', value }); - selections.queryLocation.set(e); - } - } - - return ( - <Select - isMulti - size="lg" - options={options} - aria-label={label} - name="query_location" - onChange={handleChange} - closeMenuOnSelect={false} - value={exportState(selections.queryLocation.value)} - isError={typeof errors.query_location !== 'undefined'} - /> - ); -}; diff --git a/hyperglass/ui/components/form/queryTarget.tsx b/hyperglass/ui/components/form/queryTarget.tsx deleted file mode 100644 index f604afa..0000000 --- a/hyperglass/ui/components/form/queryTarget.tsx +++ /dev/null @@ -1,89 +0,0 @@ -import { useMemo } from 'react'; -import { Input, Text } from '@chakra-ui/react'; -import { components } from 'react-select'; -import { If, Select } from '~/components'; -import { useConfig, useColorValue } from '~/context'; -import { useLGState } from '~/hooks'; - -import type { OptionProps } from 'react-select'; -import type { TBGPCommunity, TSelectOption } from '~/types'; -import type { TQueryTarget } from './types'; - -function buildOptions(communities: TBGPCommunity[]): TSelectOption[] { - return communities.map(c => ({ - value: c.community, - label: c.display_name, - description: c.description, - })); -} - -const Option = (props: OptionProps<Dict, false>) => { - const { label, data } = props; - return ( - <components.Option {...props}> - <Text as="span">{label}</Text> - <br /> - <Text fontSize="xs" as="span"> - {data.description} - </Text> - </components.Option> - ); -}; - -export const QueryTarget: React.FC<TQueryTarget> = (props: TQueryTarget) => { - const { name, register, onChange, placeholder } = props; - - const bg = useColorValue('white', 'whiteAlpha.100'); - const color = useColorValue('gray.400', 'whiteAlpha.800'); - const border = useColorValue('gray.100', 'whiteAlpha.50'); - const placeholderColor = useColorValue('gray.600', 'whiteAlpha.700'); - - const { queryType, queryTarget, displayTarget } = useLGState(); - - const { queries } = useConfig(); - - const options = useMemo(() => buildOptions(queries.bgp_community.communities), []); - - function handleInputChange(e: React.ChangeEvent<HTMLInputElement>): void { - displayTarget.set(e.target.value); - onChange({ field: name, value: e.target.value }); - } - - function handleSelectChange(e: TSelectOption | TSelectOption[]): void { - if (!Array.isArray(e) && e !== null) { - onChange({ field: name, value: e.value }); - displayTarget.set(e.value); - } - } - - return ( - <> - <input {...register} hidden readOnly value={queryTarget.value} /> - <If c={queryType.value === 'bgp_community' && queries.bgp_community.mode === 'select'}> - <Select - size="lg" - name={name} - options={options} - innerRef={register} - components={{ Option }} - onChange={handleSelectChange} - /> - </If> - <If c={!(queryType.value === 'bgp_community' && queries.bgp_community.mode === 'select')}> - <Input - bg={bg} - size="lg" - color={color} - borderRadius="md" - borderColor={border} - aria-label={placeholder} - placeholder={placeholder} - value={displayTarget.value} - name="query_target_display" - onChange={handleInputChange} - _placeholder={{ color: placeholderColor }} - /> - </If> - </> - ); -}; diff --git a/hyperglass/ui/components/form/queryType.tsx b/hyperglass/ui/components/form/queryType.tsx deleted file mode 100644 index 4464a70..0000000 --- a/hyperglass/ui/components/form/queryType.tsx +++ /dev/null @@ -1,47 +0,0 @@ -import { useMemo } from 'react'; -import { useFormContext } from 'react-hook-form'; -import { Select } from '~/components'; -import { useConfig } from '~/context'; -import { useLGState, useLGMethods } from '~/hooks'; - -import type { TQuery, TSelectOption } from '~/types'; -import type { TQuerySelectField } from './types'; - -function buildOptions(queryTypes: TQuery[]): TSelectOption[] { - return queryTypes - .filter(q => q.enable === true) - .map(q => ({ value: q.name, label: q.display_name })); -} - -export const QueryType: React.FC<TQuerySelectField> = (props: TQuerySelectField) => { - const { onChange, label } = props; - const { queries } = useConfig(); - const { - formState: { errors }, - } = useFormContext(); - const { selections } = useLGState(); - const { exportState } = useLGMethods(); - - const options = useMemo(() => buildOptions(queries.list), [queries.list.length]); - - function handleChange(e: TSelectOption | TSelectOption[]): void { - if (!Array.isArray(e) && e !== null) { - selections.queryType.set(e); - onChange({ field: 'query_type', value: e.value }); - } else { - selections.queryType.set(null); - } - } - - return ( - <Select - size="lg" - name="query_type" - options={options} - aria-label={label} - onChange={handleChange} - value={exportState(selections.queryType.value)} - isError={typeof errors.query_type !== 'undefined'} - /> - ); -}; diff --git a/hyperglass/ui/components/form/queryVrf.tsx b/hyperglass/ui/components/form/queryVrf.tsx deleted file mode 100644 index 4c7d2ed..0000000 --- a/hyperglass/ui/components/form/queryVrf.tsx +++ /dev/null @@ -1,38 +0,0 @@ -import { useMemo } from 'react'; -import { Select } from '~/components'; -import { useLGMethods, useLGState } from '~/hooks'; - -import type { TDeviceVrf, TSelectOption } from '~/types'; -import type { TQueryVrf } from './types'; - -function buildOptions(queryVrfs: TDeviceVrf[]): TSelectOption[] { - return queryVrfs.map(q => ({ value: q._id, label: q.display_name })); -} - -export const QueryVrf: React.FC<TQueryVrf> = (props: TQueryVrf) => { - const { vrfs, onChange, label } = props; - const { selections } = useLGState(); - const { exportState } = useLGMethods(); - - const options = useMemo(() => buildOptions(vrfs), [vrfs.length]); - - function handleChange(e: TSelectOption | TSelectOption[]): void { - if (!Array.isArray(e) && e !== null) { - selections.queryVrf.set(e); - onChange({ field: 'query_vrf', value: e.value }); - } else { - selections.queryVrf.set(null); - } - } - - return ( - <Select - size="lg" - name="query_vrf" - options={options} - aria-label={label} - onChange={handleChange} - value={exportState(selections.queryVrf.value)} - /> - ); -}; diff --git a/hyperglass/ui/components/form/resolvedTarget.tsx b/hyperglass/ui/components/form/resolvedTarget.tsx deleted file mode 100644 index eab1e76..0000000 --- a/hyperglass/ui/components/form/resolvedTarget.tsx +++ /dev/null @@ -1,140 +0,0 @@ -import { useEffect, useMemo } from 'react'; -import dynamic from 'next/dynamic'; -import { Button, chakra, Stack, Text, VStack } from '@chakra-ui/react'; -import { useConfig, useColorValue } from '~/context'; -import { useStrf, useLGState, useDNSQuery } from '~/hooks'; - -const RightArrow = chakra( - dynamic<MeronexIcon>(() => import('@meronex/icons/fa').then(i => i.FaArrowCircleRight)), -); - -const LeftArrow = chakra( - dynamic<MeronexIcon>(() => import('@meronex/icons/fa').then(i => i.FaArrowCircleLeft)), -); - -import type { DnsOverHttps } from '~/types'; -import type { TResolvedTarget } from './types'; - -function findAnswer(data: DnsOverHttps.Response | undefined): string { - let answer = ''; - if (typeof data !== 'undefined') { - answer = data?.Answer?.filter(answerData => answerData.type === data?.Question[0]?.type)[0] - ?.data; - } - return answer; -} - -export const ResolvedTarget: React.FC<TResolvedTarget> = (props: TResolvedTarget) => { - const { setTarget, errorClose } = props; - const { web } = useConfig(); - const { displayTarget, isSubmitting, families, queryTarget } = useLGState(); - - const color = useColorValue('secondary.500', 'secondary.300'); - const errorColor = useColorValue('red.500', 'red.300'); - - const query4 = Array.from(families.value).includes(4); - const query6 = Array.from(families.value).includes(6); - - const tooltip4 = useStrf(web.text.fqdn_tooltip, { protocol: 'IPv4' }); - const tooltip6 = useStrf(web.text.fqdn_tooltip, { protocol: 'IPv6' }); - - const [messageStart, messageEnd] = web.text.fqdn_message.split('{fqdn}'); - const [errorStart, errorEnd] = web.text.fqdn_error.split('{fqdn}'); - - const { data: data4, isLoading: isLoading4, isError: isError4, error: error4 } = useDNSQuery( - displayTarget.value, - 4, - ); - - const { data: data6, isLoading: isLoading6, isError: isError6, error: error6 } = useDNSQuery( - displayTarget.value, - 6, - ); - - isError4 && console.error(error4); - isError6 && console.error(error6); - - const answer4 = useMemo(() => findAnswer(data4), [data4]); - const answer6 = useMemo(() => findAnswer(data6), [data6]); - - function handleOverride(value: string): void { - setTarget({ field: 'query_target', value }); - } - function selectTarget(value: string): void { - queryTarget.set(value); - isSubmitting.set(true); - } - - useEffect(() => { - if (query6 && data6?.Answer) { - handleOverride(findAnswer(data6)); - } else if (query4 && data4?.Answer && !query6 && !data6?.Answer) { - handleOverride(findAnswer(data4)); - } else if (query4 && data4?.Answer) { - handleOverride(findAnswer(data4)); - } - }, [data4, data6]); - - return ( - <VStack w="100%" spacing={4} justify="center"> - {(answer4 || answer6) && ( - <Text fontSize="sm" textAlign="center"> - {messageStart} - <Text as="span" fontSize="sm" fontWeight="bold" color={color}> - {`${displayTarget.value}`.toLowerCase()} - </Text> - {messageEnd} - </Text> - )} - <Stack spacing={2}> - {!isLoading4 && !isError4 && query4 && answer4 && ( - <Button - size="sm" - fontSize="xs" - title={tooltip4} - fontFamily="mono" - colorScheme="primary" - justifyContent="space-between" - onClick={() => selectTarget(answer4)} - rightIcon={<RightArrow boxSize="18px" />} - > - {answer4} - </Button> - )} - {!isLoading6 && !isError6 && query6 && answer6 && ( - <Button - size="sm" - fontSize="xs" - title={tooltip6} - fontFamily="mono" - colorScheme="secondary" - justifyContent="space-between" - onClick={() => selectTarget(answer6)} - rightIcon={<RightArrow boxSize="18px" />} - > - {answer6} - </Button> - )} - {!answer4 && !answer6 && ( - <> - <Text fontSize="sm" textAlign="center" color={errorColor}> - {errorStart} - <Text as="span" fontSize="sm" fontWeight="bold"> - {`${displayTarget.value}`.toLowerCase()} - </Text> - {errorEnd} - </Text> - <Button - colorScheme="red" - variant="outline" - onClick={errorClose} - leftIcon={<LeftArrow />} - > - {web.text.fqdn_error_button} - </Button> - </> - )} - </Stack> - </VStack> - ); -}; diff --git a/hyperglass/ui/components/form/row.tsx b/hyperglass/ui/components/form/row.tsx deleted file mode 100644 index 2049c8a..0000000 --- a/hyperglass/ui/components/form/row.tsx +++ /dev/null @@ -1,15 +0,0 @@ -import { Flex } from '@chakra-ui/react'; - -import { FlexProps } from '@chakra-ui/react'; - -export const FormRow: React.FC<FlexProps> = (props: FlexProps) => { - return ( - <Flex - w="100%" - flexDir="row" - flexWrap="wrap" - justifyContent={{ base: 'center', lg: 'space-between' }} - {...props} - /> - ); -}; diff --git a/hyperglass/ui/components/form/types.ts b/hyperglass/ui/components/form/types.ts deleted file mode 100644 index 634edfd..0000000 --- a/hyperglass/ui/components/form/types.ts +++ /dev/null @@ -1,41 +0,0 @@ -import type { FormControlProps } from '@chakra-ui/react'; -import type { UseFormRegister } from 'react-hook-form'; -import type { TDeviceVrf, TBGPCommunity, OnChangeArgs, TFormData } from '~/types'; - -export interface TField extends FormControlProps { - name: string; - label: string; - hiddenLabels?: boolean; - labelAddOn?: React.ReactNode; - fieldAddOn?: React.ReactNode; -} - -export type OnChange = (f: OnChangeArgs) => void; - -export interface TQuerySelectField { - onChange: OnChange; - label: string; -} - -export interface TQueryVrf extends TQuerySelectField { - vrfs: TDeviceVrf[]; -} - -export interface TCommunitySelect { - name: string; - onChange: OnChange; - communities: TBGPCommunity[]; - register: UseFormRegister<TFormData>; -} - -export interface TQueryTarget { - name: string; - placeholder: string; - register: UseFormRegister<TFormData>; - onChange(e: OnChangeArgs): void; -} - -export interface TResolvedTarget { - setTarget(e: OnChangeArgs): void; - errorClose(): void; -} diff --git a/hyperglass/ui/components/greeting/greeting.tsx b/hyperglass/ui/components/greeting/greeting.tsx deleted file mode 100644 index 165eee8..0000000 --- a/hyperglass/ui/components/greeting/greeting.tsx +++ /dev/null @@ -1,77 +0,0 @@ -import { useEffect } from 'react'; -import { - Modal, - Button, - ModalBody, - ModalHeader, - ModalFooter, - ModalOverlay, - ModalContent, - ModalCloseButton, -} from '@chakra-ui/react'; -import { If, Markdown } from '~/components'; -import { useConfig, useColorValue } from '~/context'; -import { useGreeting, useOpposingColor } from '~/hooks'; - -import type { TGreeting } from './types'; - -export const Greeting: React.FC<TGreeting> = (props: TGreeting) => { - const { web, content } = useConfig(); - const { ack: greetingAck, isOpen, close } = useGreeting(); - - const bg = useColorValue('white', 'gray.800'); - const color = useOpposingColor(bg); - - function handleClose(ack: boolean = false): void { - if (web.greeting.required && !greetingAck.value && !ack) { - greetingAck.set(false); - } else if (web.greeting.required && !greetingAck.value && ack) { - greetingAck.set(true); - close(); - } else if (web.greeting.required && greetingAck.value) { - close(); - } else if (!web.greeting.required) { - greetingAck.set(true); - close(); - } - } - useEffect(() => { - if (!greetingAck.value && web.greeting.enable) { - isOpen.set(true); - } - }, []); - return ( - <Modal - size="lg" - isCentered - onClose={handleClose} - isOpen={isOpen.value} - motionPreset="slideInBottom" - closeOnEsc={web.greeting.required} - closeOnOverlayClick={web.greeting.required} - > - <ModalOverlay /> - <ModalContent - py={4} - bg={bg} - color={color} - borderRadius="md" - maxW={{ base: '95%', md: '75%' }} - {...props} - > - <ModalHeader>{web.greeting.title}</ModalHeader> - <If c={!web.greeting.required}> - <ModalCloseButton /> - </If> - <ModalBody> - <Markdown content={content.greeting} /> - </ModalBody> - <ModalFooter> - <Button colorScheme="primary" onClick={() => handleClose(true)}> - {web.greeting.button} - </Button> - </ModalFooter> - </ModalContent> - </Modal> - ); -}; diff --git a/hyperglass/ui/components/greeting/index.ts b/hyperglass/ui/components/greeting/index.ts deleted file mode 100644 index fe2d50b..0000000 --- a/hyperglass/ui/components/greeting/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './greeting'; diff --git a/hyperglass/ui/components/greeting/types.ts b/hyperglass/ui/components/greeting/types.ts deleted file mode 100644 index 1568d2a..0000000 --- a/hyperglass/ui/components/greeting/types.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { BoxProps } from '@chakra-ui/react'; - -export interface TGreeting extends BoxProps {} diff --git a/hyperglass/ui/components/header/header.tsx b/hyperglass/ui/components/header/header.tsx deleted file mode 100644 index 07aba3b..0000000 --- a/hyperglass/ui/components/header/header.tsx +++ /dev/null @@ -1,43 +0,0 @@ -import { useRef } from 'react'; -import { Flex, ScaleFade } from '@chakra-ui/react'; -import { AnimatedDiv } from '~/components'; -import { useBreakpointValue } from '~/context'; -import { useBooleanValue, useLGState } from '~/hooks'; -import { Title } from './title'; - -import type { THeader } from './types'; - -export const Header: React.FC<THeader> = (props: THeader) => { - const { resetForm, ...rest } = props; - - const { isSubmitting } = useLGState(); - - const titleRef = useRef({} as HTMLDivElement); - - const titleWidth = useBooleanValue( - isSubmitting.value, - { base: '75%', lg: '50%' }, - { base: '75%', lg: '75%' }, - ); - - const justify = useBreakpointValue({ base: 'flex-start', lg: 'center' }); - - return ( - <Flex px={4} pt={6} minH={16} zIndex={4} as="header" width="full" flex="0 1 auto" {...rest}> - <ScaleFade in initialScale={0.5} style={{ width: '100%' }}> - <AnimatedDiv - layout - height="100%" - display="flex" - ref={titleRef} - maxW={titleWidth} - // This is here for the logo - justifyContent={justify} - mx={{ base: isSubmitting.value ? 'auto' : 0, lg: 'auto' }} - > - <Title /> - </AnimatedDiv> - </ScaleFade> - </Flex> - ); -}; diff --git a/hyperglass/ui/components/header/index.ts b/hyperglass/ui/components/header/index.ts deleted file mode 100644 index 677ca79..0000000 --- a/hyperglass/ui/components/header/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './header'; diff --git a/hyperglass/ui/components/header/logo.tsx b/hyperglass/ui/components/header/logo.tsx deleted file mode 100644 index d26a8bb..0000000 --- a/hyperglass/ui/components/header/logo.tsx +++ /dev/null @@ -1,73 +0,0 @@ -import { useMemo, useState } from 'react'; -import { Image, Skeleton } from '@chakra-ui/react'; -import { useColorValue, useConfig, useColorMode } from '~/context'; - -import type { TLogo } from './types'; - -/** - * Custom hook to handle loading the user's logo, errors loading the logo, and color mode changes. - */ -function useLogo(): [string, () => void] { - const { web } = useConfig(); - const { dark_format, light_format } = web.logo; - const { colorMode } = useColorMode(); - - const src = useColorValue(`/images/dark${dark_format}`, `/images/light${light_format}`); - - // Use the hyperglass logo if the user's logo can't be loaded for whatever reason. - const fallbackSrc = useColorValue( - 'https://res.cloudinary.com/hyperglass/image/upload/v1593916013/logo-dark.svg', - 'https://res.cloudinary.com/hyperglass/image/upload/v1593916013/logo-light.svg', - ); - - const [fallback, setSource] = useState<string | null>(null); - - /** - * If the user image cannot be loaded, log an error to the console and set the fallback image. - */ - function setFallback() { - console.warn(`Error loading image from '${src}'`); - setSource(fallbackSrc); - } - - // Only return the fallback image if it's been set. - return useMemo(() => [fallback ?? src, setFallback], [colorMode]); -} - -export const Logo: React.FC<TLogo> = (props: TLogo) => { - const { web } = useConfig(); - const { width } = web.logo; - - const skeletonA = useColorValue('whiteSolid.100', 'blackSolid.800'); - const skeletonB = useColorValue('light.500', 'dark.500'); - - const [source, setFallback] = useLogo(); - - return ( - <Image - src={source} - alt={web.text.title} - onError={setFallback} - width={width ?? 'auto'} - css={{ - userDrag: 'none', - userSelect: 'none', - msUserSelect: 'none', - MozUserSelect: 'none', - WebkitUserDrag: 'none', - WebkitUserSelect: 'none', - }} - fallback={ - <Skeleton - isLoaded={false} - borderRadius="md" - endColor={skeletonB} - startColor={skeletonA} - width={{ base: 64, lg: 80 }} - height={{ base: 12, lg: 16 }} - /> - } - {...props} - /> - ); -}; diff --git a/hyperglass/ui/components/header/subtitleOnly.tsx b/hyperglass/ui/components/header/subtitleOnly.tsx deleted file mode 100644 index 4f2d09f..0000000 --- a/hyperglass/ui/components/header/subtitleOnly.tsx +++ /dev/null @@ -1,21 +0,0 @@ -import { Heading } from '@chakra-ui/react'; -import { useConfig, useBreakpointValue } from '~/context'; -import { useTitleSize } from './useTitleSize'; - -export const SubtitleOnly: React.FC = () => { - const { web } = useConfig(); - const sizeSm = useTitleSize(web.text.subtitle, 'sm'); - const fontSize = useBreakpointValue({ base: sizeSm, lg: 'xl' }); - - return ( - <Heading - as="h3" - fontWeight="normal" - fontSize={fontSize} - whiteSpace="break-spaces" - textAlign={{ base: 'left', xl: 'center' }} - > - {web.text.subtitle} - </Heading> - ); -}; diff --git a/hyperglass/ui/components/header/title.tsx b/hyperglass/ui/components/header/title.tsx deleted file mode 100644 index d06dfea..0000000 --- a/hyperglass/ui/components/header/title.tsx +++ /dev/null @@ -1,162 +0,0 @@ -import { Flex, Button, VStack } from '@chakra-ui/react'; -import { motion } from 'framer-motion'; -import { isSafari } from 'react-device-detect'; -import { If } from '~/components'; -import { useConfig, useMobile } from '~/context'; -import { useBooleanValue, useLGState, useLGMethods } from '~/hooks'; -import { SubtitleOnly } from './subtitleOnly'; -import { TitleOnly } from './titleOnly'; -import { Logo } from './logo'; - -import type { TTitle, TTitleWrapper, TDWrapper, TMWrapper } from './types'; - -const AnimatedVStack = motion(VStack); - -/** - * Title wrapper for mobile devices, breakpoints sm & md. - */ -const MWrapper: React.FC<TMWrapper> = (props: TMWrapper) => { - const { isSubmitting } = useLGState(); - return ( - <AnimatedVStack - layout - spacing={1} - alignItems={isSubmitting.value ? 'center' : 'flex-start'} - {...props} - /> - ); -}; - -/** - * Title wrapper for desktop devices, breakpoints lg & xl. - */ -const DWrapper: React.FC<TDWrapper> = (props: TDWrapper) => { - const { isSubmitting } = useLGState(); - return ( - <AnimatedVStack - spacing={1} - initial="main" - alignItems="center" - animate={isSubmitting.value ? 'submitting' : 'main'} - transition={{ damping: 15, type: 'spring', stiffness: 100 }} - variants={{ submitting: { scale: 0.5 }, main: { scale: 1 } }} - {...props} - /> - ); -}; - -/** - * Universal wrapper for title sub-components, which will be different depending on the - * `title_mode` configuration variable. - */ -const TitleWrapper: React.FC<TDWrapper | TMWrapper> = (props: TDWrapper | TMWrapper) => { - const isMobile = useMobile(); - return ( - <> - {isMobile ? <MWrapper {...(props as TMWrapper)} /> : <DWrapper {...(props as TDWrapper)} />} - </> - ); -}; - -/** - * Title sub-component if `title_mode` is set to `text_only`. - */ -const TextOnly: React.FC<TTitleWrapper> = (props: TTitleWrapper) => { - return ( - <TitleWrapper {...props}> - <TitleOnly /> - <SubtitleOnly /> - </TitleWrapper> - ); -}; - -/** - * Title sub-component if `title_mode` is set to `logo_only`. Renders only the logo. - */ -const LogoOnly: React.FC = () => ( - <TitleWrapper> - <Logo /> - </TitleWrapper> -); - -/** - * Title sub-component if `title_mode` is set to `logo_subtitle`. Renders the logo with the - * subtitle underneath. - */ -const LogoSubtitle: React.FC = () => ( - <TitleWrapper> - <Logo /> - <SubtitleOnly /> - </TitleWrapper> -); - -/** - * Title sub-component if `title_mode` is set to `all`. Renders the logo, title, and subtitle. - */ -const All: React.FC = () => ( - <TitleWrapper> - <Logo /> - <TextOnly mt={2} /> - </TitleWrapper> -); - -/** - * Title component which renders sub-components based on the `title_mode` configuration variable. - */ -export const Title: React.FC<TTitle> = (props: TTitle) => { - const { fontSize, ...rest } = props; - const { web } = useConfig(); - const titleMode = web.text.title_mode; - - const { isSubmitting } = useLGState(); - const { resetForm } = useLGMethods(); - - const titleHeight = useBooleanValue(isSubmitting.value, undefined, { md: '20vh' }); - - function handleClick(): void { - isSubmitting.set(false); - resetForm(); - } - - return ( - <Flex - px={0} - flexWrap="wrap" - flexDir="column" - minH={titleHeight} - justifyContent="center" - /* flexBasis - This is a fix for Safari specifically. LMGTFY: Safari flex-basis width. Nutshell: Safari - is stupid, in that it infers the default flex-basis from the width, 100%. Other browsers - don't do this. Without the below fix, the logo will appear gigantic, filling the entire - div up to the parent's max-width. The fix is to hard-code a flex-basis width. - */ - flexBasis={{ base: '100%', lg: isSafari ? '33%' : '100%' }} - mt={[null, isSubmitting.value ? null : 'auto']} - {...rest} - > - <Button - px={0} - variant="link" - flexWrap="wrap" - flexDir="column" - onClick={handleClick} - _focus={{ boxShadow: 'none' }} - _hover={{ textDecoration: 'none' }} - > - <If c={titleMode === 'text_only'}> - <TextOnly /> - </If> - <If c={titleMode === 'logo_only'}> - <LogoOnly /> - </If> - <If c={titleMode === 'logo_subtitle'}> - <LogoSubtitle /> - </If> - <If c={titleMode === 'all'}> - <All /> - </If> - </Button> - </Flex> - ); -}; diff --git a/hyperglass/ui/components/header/titleOnly.tsx b/hyperglass/ui/components/header/titleOnly.tsx deleted file mode 100644 index c263999..0000000 --- a/hyperglass/ui/components/header/titleOnly.tsx +++ /dev/null @@ -1,18 +0,0 @@ -import { Heading } from '@chakra-ui/react'; -import { useConfig } from '~/context'; -import { useBooleanValue, useLGState } from '~/hooks'; -import { useTitleSize } from './useTitleSize'; - -export const TitleOnly: React.FC = () => { - const { web } = useConfig(); - const { isSubmitting } = useLGState(); - - const margin = useBooleanValue(isSubmitting.value, 0, 2); - const sizeSm = useTitleSize(web.text.title, '2xl', []); - - return ( - <Heading as="h1" mb={margin} fontSize={{ base: sizeSm, lg: '5xl' }}> - {web.text.title} - </Heading> - ); -}; diff --git a/hyperglass/ui/components/header/types.ts b/hyperglass/ui/components/header/types.ts deleted file mode 100644 index afdcf4c..0000000 --- a/hyperglass/ui/components/header/types.ts +++ /dev/null @@ -1,29 +0,0 @@ -import type { FlexProps, HeadingProps, ImageProps, StackProps } from '@chakra-ui/react'; -import type { MotionProps } from 'framer-motion'; - -export interface THeader extends FlexProps { - resetForm(): void; -} - -export type THeaderLayout = { - sm: [JSX.Element, JSX.Element]; - md: [JSX.Element, JSX.Element]; - lg: [JSX.Element, JSX.Element]; - xl: [JSX.Element, JSX.Element]; -}; -export type TDWrapper = Omit<StackProps, 'transition'> & MotionProps; - -export type TMWrapper = Omit<StackProps, 'transition'> & MotionProps; - -export interface TTitle extends FlexProps {} - -export interface TTitleOnly extends HeadingProps {} - -export interface TLogo extends ImageProps {} - -export interface TTitleWrapper extends Partial<MotionProps & Omit<StackProps, 'transition'>> {} - -export interface THeaderCtx { - showSubtitle: boolean; - titleRef: React.MutableRefObject<HTMLHeadingElement>; -} diff --git a/hyperglass/ui/components/header/useTitleSize.ts b/hyperglass/ui/components/header/useTitleSize.ts deleted file mode 100644 index 23d00a7..0000000 --- a/hyperglass/ui/components/header/useTitleSize.ts +++ /dev/null @@ -1,59 +0,0 @@ -import { useMemo, useState } from 'react'; -import { useToken } from '@chakra-ui/react'; -import { useMobile } from '~/context'; - -// Mobile: -// xs: 32 -// sm: 28 -// md: 24 -// lg: 20 -// xl: 16 -// 2xl: 14 -// 3xl: 12 -// 4xl: 10 -// 5xl: 7 -type Sizes = 'xs' | 'sm' | 'md' | 'lg' | 'xl' | '2xl' | '3xl' | '4xl' | '5xl'; - -export function useTitleSize(title: string, defaultSize: Sizes, deps: unknown[] = []): string { - const [size, setSize] = useState<Sizes>(defaultSize); - const realSize = useToken('fontSizes', size) as string; - const isMobile = useMobile(); - function getSize(l: number): void { - switch (true) { - case l > 32: - setSize('xs'); - break; - case l <= 32 && l > 28: - setSize('xs'); - break; - case l <= 28 && l > 24: - setSize('sm'); - break; - case l <= 24 && l > 20: - setSize('md'); - break; - case l <= 20 && l > 16: - setSize('lg'); - break; - case l <= 16 && l > 14: - setSize('xl'); - break; - case l <= 14 && l > 12: - setSize('2xl'); - break; - case l <= 12 && l > 10: - setSize('3xl'); - break; - case l <= 10 && l > 7: - setSize('4xl'); - break; - case l <= 7: - setSize('5xl'); - break; - } - } - return useMemo(() => { - getSize(title.length); - return realSize; - }, [title, isMobile, ...deps]); -} diff --git a/hyperglass/ui/components/help/index.ts b/hyperglass/ui/components/help/index.ts deleted file mode 100644 index 133aa74..0000000 --- a/hyperglass/ui/components/help/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './modal'; diff --git a/hyperglass/ui/components/help/modal.tsx b/hyperglass/ui/components/help/modal.tsx deleted file mode 100644 index faff30a..0000000 --- a/hyperglass/ui/components/help/modal.tsx +++ /dev/null @@ -1,57 +0,0 @@ -import dynamic from 'next/dynamic'; -import { - Modal, - ScaleFade, - ModalBody, - IconButton, - ModalHeader, - ModalOverlay, - ModalContent, - useDisclosure, - ModalCloseButton, -} from '@chakra-ui/react'; -import { Markdown } from '~/components'; -import { useColorValue } from '~/context'; -import { isQueryContent } from '~/types'; - -import type { THelpModal } from './types'; - -const Info = dynamic<MeronexIcon>(() => import('@meronex/icons/fi').then(i => i.FiInfo)); - -export const HelpModal: React.FC<THelpModal> = (props: THelpModal) => { - const { visible, item, name, ...rest } = props; - const { isOpen, onOpen, onClose } = useDisclosure(); - const bg = useColorValue('whiteSolid.50', 'blackSolid.800'); - const color = useColorValue('black', 'white'); - if (!isQueryContent(item)) { - return null; - } - return ( - <> - <ScaleFade in={visible} unmountOnExit> - <IconButton - mb={1} - ml={1} - minH={3} - minW={3} - size="md" - variant="link" - icon={<Info />} - onClick={onOpen} - colorScheme="blue" - aria-label={`${name}_help`} - /> - </ScaleFade> - <Modal isOpen={isOpen} onClose={onClose} size="xl" motionPreset="slideInRight"> - <ModalOverlay /> - <ModalContent bg={bg} color={color} py={4} borderRadius="md" {...rest}> - <ModalHeader>{item.params.title}</ModalHeader> - <ModalCloseButton /> - <ModalBody> - <Markdown content={item.content} /> - </ModalBody> - </ModalContent> - </Modal> - </> - ); -}; diff --git a/hyperglass/ui/components/help/types.ts b/hyperglass/ui/components/help/types.ts deleted file mode 100644 index 2a47dfc..0000000 --- a/hyperglass/ui/components/help/types.ts +++ /dev/null @@ -1,8 +0,0 @@ -import type { ModalContentProps } from '@chakra-ui/react'; -import type { TQueryContent, TQueryFields } from '~/types'; - -export interface THelpModal extends ModalContentProps { - item: TQueryContent | null; - name: TQueryFields; - visible: boolean; -} diff --git a/hyperglass/ui/components/index.ts b/hyperglass/ui/components/index.ts deleted file mode 100644 index 17216b1..0000000 --- a/hyperglass/ui/components/index.ts +++ /dev/null @@ -1,22 +0,0 @@ -export * from './card'; -export * from './codeBlock'; -export * from './countdown'; -export * from './debugger'; -export * from './footer'; -export * from './form'; -export * from './greeting'; -export * from './header'; -export * from './help'; -export * from './label'; -export * from './layout'; -export * from './loading'; -export * from './lookingGlass'; -export * from './markdown'; -export * from './meta'; -export * from './output'; -export * from './path'; -export * from './results'; -export * from './select'; -export * from './submit'; -export * from './table'; -export * from './util'; diff --git a/hyperglass/ui/components/label/index.ts b/hyperglass/ui/components/label/index.ts deleted file mode 100644 index 301fbde..0000000 --- a/hyperglass/ui/components/label/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './label'; diff --git a/hyperglass/ui/components/label/label.tsx b/hyperglass/ui/components/label/label.tsx deleted file mode 100644 index 5d8a0a7..0000000 --- a/hyperglass/ui/components/label/label.tsx +++ /dev/null @@ -1,66 +0,0 @@ -import { forwardRef } from 'react'; -import { Flex } from '@chakra-ui/react'; -import { useColorValue } from '~/context'; -import { useOpposingColor } from '~/hooks'; - -import type { TLabel } from './types'; - -const _Label: React.ForwardRefRenderFunction<HTMLDivElement, TLabel> = (props: TLabel, ref) => { - const { value, label, labelColor, bg = 'primary.600', valueColor, ...rest } = props; - - const valueColorAuto = useOpposingColor(bg); - const defaultLabelColor = useColorValue('blackAlpha.700', 'whiteAlpha.700'); - - return ( - <Flex - my={2} - ref={ref} - flexWrap="nowrap" - alignItems="center" - mx={{ base: 1, md: 2 }} - justifyContent="flex-start" - {...rest} - > - <Flex - mb={2} - mr={0} - bg={bg} - lineHeight="1.5" - fontWeight="bold" - whiteSpace="nowrap" - display="inline-flex" - px={{ base: 1, md: 3 }} - justifyContent="center" - borderTopLeftRadius={4} - borderTopRightRadius={0} - borderBottomLeftRadius={4} - borderBottomRightRadius={0} - fontSize={{ base: 'xs', md: 'sm' }} - color={valueColor ?? valueColorAuto} - > - {value} - </Flex> - <Flex - px={3} - mb={2} - ml={0} - mr={0} - lineHeight="1.5" - whiteSpace="nowrap" - display="inline-flex" - justifyContent="center" - borderTopLeftRadius={0} - borderTopRightRadius={4} - borderBottomLeftRadius={0} - borderBottomRightRadius={4} - fontSize={{ base: 'xs', md: 'sm' }} - color={labelColor ?? defaultLabelColor} - boxShadow={`inset 0px 0px 0px 1px ${bg}`} - > - {label} - </Flex> - </Flex> - ); -}; - -export const Label = forwardRef(_Label); diff --git a/hyperglass/ui/components/label/types.ts b/hyperglass/ui/components/label/types.ts deleted file mode 100644 index 2069c4c..0000000 --- a/hyperglass/ui/components/label/types.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { FlexProps } from '@chakra-ui/react'; - -export interface TLabel extends FlexProps { - value: string; - label: string; - bg: string; - valueColor?: string; - labelColor?: string; -} diff --git a/hyperglass/ui/components/layout/frame.tsx b/hyperglass/ui/components/layout/frame.tsx deleted file mode 100644 index d84f7f9..0000000 --- a/hyperglass/ui/components/layout/frame.tsx +++ /dev/null @@ -1,61 +0,0 @@ -import { useRef } from 'react'; -import { Flex } from '@chakra-ui/react'; -import { isSafari } from 'react-device-detect'; -import { If, Debugger, Greeting, Footer, Header } from '~/components'; -import { useConfig } from '~/context'; -import { useLGState, useLGMethods } from '~/hooks'; -import { ResetButton } from './resetButton'; - -import type { TFrame } from './types'; - -export const Frame: React.FC<TFrame> = (props: TFrame) => { - const { developer_mode } = useConfig(); - const { isSubmitting } = useLGState(); - const { resetForm } = useLGMethods(); - - const containerRef = useRef<HTMLDivElement>({} as HTMLDivElement); - - function handleReset(): void { - containerRef.current.scrollIntoView({ behavior: 'smooth', block: 'start' }); - isSubmitting.set(false); - resetForm(); - } - - return ( - <> - <Flex - w="100%" - flex="1 0 auto" - flexDir="column" - id="__hyperglass" - ref={containerRef} - /** minHeight - * This is a Safari-specific fix. Without it, the footer will appear to be "under" the - * viewport. Safari needs `-webkit-fill-available`, but other browsers need `100vh`. - * @see https://allthingssmitty.com/2020/05/11/css-fix-for-100vh-in-mobile-webkit/ - */ - minHeight={isSafari ? '-webkit-fill-available' : '100vh'} - > - <Header resetForm={handleReset} /> - <Flex - px={4} - py={0} - w="100%" - as="main" - align="center" - flex="1 1 auto" - justify="start" - flexDir="column" - textAlign="center" - {...props} - /> - <Footer /> - <If c={developer_mode}> - <Debugger /> - </If> - <ResetButton developerMode={developer_mode} resetForm={handleReset} /> - </Flex> - <Greeting /> - </> - ); -}; diff --git a/hyperglass/ui/components/layout/index.ts b/hyperglass/ui/components/layout/index.ts deleted file mode 100644 index aee1748..0000000 --- a/hyperglass/ui/components/layout/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './frame'; -export * from './layout'; diff --git a/hyperglass/ui/components/layout/layout.tsx b/hyperglass/ui/components/layout/layout.tsx deleted file mode 100644 index 6810f3f..0000000 --- a/hyperglass/ui/components/layout/layout.tsx +++ /dev/null @@ -1,19 +0,0 @@ -import { AnimatePresence } from 'framer-motion'; -import { LookingGlass, Results } from '~/components'; -import { useLGMethods } from '~/hooks'; -import { Frame } from './frame'; - -export const Layout: React.FC = () => { - const { formReady } = useLGMethods(); - return ( - <Frame> - {formReady() ? ( - <Results /> - ) : ( - <AnimatePresence> - <LookingGlass /> - </AnimatePresence> - )} - </Frame> - ); -}; diff --git a/hyperglass/ui/components/layout/resetButton.tsx b/hyperglass/ui/components/layout/resetButton.tsx deleted file mode 100644 index 145ea61..0000000 --- a/hyperglass/ui/components/layout/resetButton.tsx +++ /dev/null @@ -1,48 +0,0 @@ -import dynamic from 'next/dynamic'; -import { Flex, Icon, IconButton } from '@chakra-ui/react'; -import { AnimatePresence } from 'framer-motion'; -import { AnimatedDiv } from '~/components'; -import { useColorValue } from '~/context'; -import { useLGState, useOpposingColor } from '~/hooks'; - -import type { TResetButton } from './types'; - -const LeftArrow = dynamic<MeronexIcon>(() => import('@meronex/icons/fa').then(i => i.FaAngleLeft)); - -export const ResetButton: React.FC<TResetButton> = (props: TResetButton) => { - const { developerMode, resetForm, ...rest } = props; - const { isSubmitting } = useLGState(); - const bg = useColorValue('primary.500', 'primary.300'); - const color = useOpposingColor(bg); - return ( - <AnimatePresence> - {isSubmitting.value && ( - <AnimatedDiv - bg={bg} - left={0} - zIndex={4} - bottom={24} - boxSize={12} - color={color} - position="fixed" - animate={{ x: 0 }} - exit={{ x: '-100%' }} - borderRightRadius="md" - initial={{ x: '-100%' }} - mb={developerMode ? { base: 0, lg: 14 } : undefined} - transition={{ duration: 0.15, ease: [0.4, 0, 0.2, 1] }} - > - <Flex boxSize="100%" justifyContent="center" alignItems="center" {...rest}> - <IconButton - variant="unstyled" - color="current" - aria-label="Reset" - onClick={resetForm} - icon={<Icon as={LeftArrow} boxSize={8} />} - /> - </Flex> - </AnimatedDiv> - )} - </AnimatePresence> - ); -}; diff --git a/hyperglass/ui/components/layout/types.ts b/hyperglass/ui/components/layout/types.ts deleted file mode 100644 index bf3ee75..0000000 --- a/hyperglass/ui/components/layout/types.ts +++ /dev/null @@ -1,8 +0,0 @@ -import type { FlexProps } from '@chakra-ui/react'; - -export interface TFrame extends FlexProps {} - -export interface TResetButton extends FlexProps { - developerMode: boolean; - resetForm(): void; -} diff --git a/hyperglass/ui/components/loading.tsx b/hyperglass/ui/components/loading.tsx deleted file mode 100644 index 44b3202..0000000 --- a/hyperglass/ui/components/loading.tsx +++ /dev/null @@ -1,25 +0,0 @@ -import { Flex, Spinner } from '@chakra-ui/react'; - -import type { LoadableBaseOptions } from 'next/dynamic'; - -export const Loading: LoadableBaseOptions['loading'] = () => ( - <Flex flexDirection="column" minHeight="100vh" w="100%"> - <Flex - px={2} - py={0} - w="100%" - bg="white" - color="black" - flex="1 1 auto" - textAlign="center" - alignItems="center" - justifyContent="center" - flexDirection="column" - css={{ - '@media (prefers-color-scheme: dark)': { backgroundColor: 'black', color: 'white' }, - }} - > - <Spinner color="primary.500" w="6rem" h="6rem" /> - </Flex> - </Flex> -); diff --git a/hyperglass/ui/components/lookingGlass.tsx b/hyperglass/ui/components/lookingGlass.tsx deleted file mode 100644 index 6645f0b..0000000 --- a/hyperglass/ui/components/lookingGlass.tsx +++ /dev/null @@ -1,318 +0,0 @@ -import { useCallback, useEffect, useMemo } from 'react'; -import { Flex } from '@chakra-ui/react'; -import { FormProvider, useForm } from 'react-hook-form'; -import { intersectionWith } from 'lodash'; -import { vestResolver } from '@hookform/resolvers/vest'; -import vest, { test, enforce } from 'vest'; -import { - If, - FormRow, - QueryVrf, - FormField, - HelpModal, - QueryType, - AnimatedDiv, - QueryTarget, - SubmitButton, - QueryLocation, -} from '~/components'; -import { useConfig } from '~/context'; -import { useStrf, useGreeting, useDevice, useLGState, useLGMethods } from '~/hooks'; -import { isQueryType, isQueryContent, isString, isQueryField } from '~/types'; - -import type { TFormData, TDeviceVrf, OnChangeArgs } from '~/types'; - -/** - * Don't set the global flag on this. - * @see https://stackoverflow.com/questions/24084926/javascript-regexp-cant-use-twice - * - * TLDR: the test() will pass the first time, but not the second. In React Strict Mode & in a dev - * environment, this will mean isFqdn will be true the first time, then false the second time, - * submitting the FQDN to hyperglass the second time. - */ -const fqdnPattern = new RegExp( - /^(?!:\/\/)([a-zA-Z0-9-]+\.)?[a-zA-Z0-9-][a-zA-Z0-9-]+\.[a-zA-Z-]{2,6}?$/im, -); - -function useIsFqdn(target: string, _type: string) { - return useCallback( - (): boolean => ['bgp_route', 'ping', 'traceroute'].includes(_type) && fqdnPattern.test(target), - [target, _type], - ); -} - -export const LookingGlass: React.FC = () => { - const { web, content, messages } = useConfig(); - - const { ack, greetingReady } = useGreeting(); - const getDevice = useDevice(); - - const noQueryType = useStrf(messages.no_input, { field: web.text.query_type }); - const noQueryLoc = useStrf(messages.no_input, { field: web.text.query_location }); - const noQueryTarget = useStrf(messages.no_input, { field: web.text.query_target }); - - const formSchema = vest.create((data: TFormData = {} as TFormData) => { - test('query_location', noQueryLoc, () => { - enforce(data.query_location).isArrayOf(enforce.isString()).isNotEmpty(); - }); - test('query_target', noQueryTarget, () => { - enforce(data.query_target).longerThan(1); - }); - test('query_type', noQueryType, () => { - enforce(data.query_type).anyOf( - enforce.equals('bgp_route'), - enforce.equals('bgp_community'), - enforce.equals('bgp_aspath'), - enforce.equals('ping'), - enforce.equals('traceroute'), - ); - }); - test('query_vrf', 'Query VRF is empty', () => { - enforce(data.query_vrf).isString(); - }); - }); - - const formInstance = useForm<TFormData>({ - resolver: vestResolver(formSchema), - defaultValues: { query_vrf: 'default', query_target: '', query_location: [], query_type: '' }, - }); - - const { handleSubmit, register, setValue, setError, clearErrors } = formInstance; - - const { - queryVrf, - families, - queryType, - availVrfs, - btnLoading, - queryTarget, - isSubmitting, - queryLocation, - displayTarget, - } = useLGState(); - - const { resolvedOpen, resetForm } = useLGMethods(); - - const isFqdnQuery = useIsFqdn(queryTarget.value, queryType.value); - - function submitHandler() { - /** - * Before submitting a query, make sure the greeting is acknowledged if required. This should - * be handled before loading the app, but people be sneaky. - */ - if (!greetingReady()) { - resetForm(); - location.reload(); - } - - // Determine if queryTarget is an FQDN. - const isFqdn = isFqdnQuery(); - - if (greetingReady() && !isFqdn) { - return isSubmitting.set(true); - } - - if (greetingReady() && isFqdn) { - btnLoading.set(true); - return resolvedOpen(); - } else { - console.group('%cSomething went wrong', 'color:red;'); - console.table({ - 'Greeting Required': web.greeting.required, - 'Greeting Ready': greetingReady(), - 'Greeting Acknowledged': ack.value, - 'Query Target': queryTarget.value, - 'Query Type': queryType.value, - 'Is FQDN': isFqdn, - }); - console.groupEnd(); - } - } - - function handleLocChange(locations: string[]): void { - clearErrors('query_location'); - const allVrfs = [] as TDeviceVrf[][]; - const locationNames = [] as string[]; - - queryLocation.set(locations); - - // Create an array of each device's VRFs. - for (const loc of locations) { - const device = getDevice(loc); - locationNames.push(device.name); - allVrfs.push(device.vrfs); - } - - // Use _.intersectionWith to create an array of VRFs common to all selected locations. - const intersecting = intersectionWith( - ...allVrfs, - (a: TDeviceVrf, b: TDeviceVrf) => a._id === b._id, - ); - - availVrfs.set(intersecting); - - // If there is more than one location selected, but there are no intersecting VRFs, show an error. - if (locations.length > 1 && intersecting.length === 0) { - setError('query_location', { - message: `${locationNames.join(', ')} have no VRFs in common.`, - }); - } - // If there is only one intersecting VRF, set it as the form value so the user doesn't have to. - else if (intersecting.length === 1) { - queryVrf.set(intersecting[0]._id); - } - - // Determine which address families are available in the intersecting VRFs. - let ipv4 = 0; - let ipv6 = 0; - - for (const intersection of intersecting) { - if (intersection.ipv4) { - // If IPv4 is enabled in this VRF, count it. - ipv4++; - } - if (intersection.ipv6) { - // If IPv6 is enabled in this VRF, count it. - ipv6++; - } - } - - if (ipv4 !== 0 && ipv4 === ipv6) { - /** - * If ipv4 & ipv6 are equal, this means every VRF has both IPv4 & IPv6 enabled. In that - * case, signal that both A & AAAA records should be queried if the query is an FQDN. - */ - families.set([4, 6]); - } else if (ipv4 > ipv6) { - /** - * If ipv4 is greater than ipv6, this means that IPv6 is not enabled on all VRFs, i.e. there - * are some VRFs with IPv4 enabled but IPv6 disabled. In that case, only query A records. - */ - families.set([4]); - } else if (ipv4 < ipv6) { - /** - * If ipv6 is greater than ipv4, this means that IPv4 is not enabled on all VRFs, i.e. there - * are some VRFs with IPv6 enabled but IPv4 disabled. In that case, only query AAAA records. - */ - families.set([6]); - } else { - /** - * If both ipv4 and ipv6 are 0, then both ipv4 and ipv6 are disabled, and why does that VRF - * even exist? - */ - families.set([]); - } - } - - function handleChange(e: OnChangeArgs): void { - // Signal the field & value to react-hook-form. - if (isQueryField(e.field)) { - setValue(e.field, e.value); - } else { - throw new Error(`Field '${e.field}' is not a valid form field.`); - } - - if (e.field === 'query_location' && Array.isArray(e.value)) { - handleLocChange(e.value); - } else if (e.field === 'query_type' && isQueryType(e.value)) { - queryType.set(e.value); - if (queryTarget.value !== '') { - /** - * Reset queryTarget as well, so that, for example, selecting BGP Community, and selecting - * a community, then changing the queryType to BGP Route doesn't preserve the selected - * community as the queryTarget. - */ - queryTarget.set(''); - displayTarget.set(''); - } - } else if (e.field === 'query_vrf' && isString(e.value)) { - queryVrf.set(e.value); - } else if (e.field === 'query_target' && isString(e.value)) { - queryTarget.set(e.value); - } - } - - /** - * Select the correct help content based on the selected VRF & Query Type. Also remove the icon - * if no locations are set. - */ - const vrfContent = useMemo(() => { - if (queryLocation.value.length === 0) { - return null; - } - if (Object.keys(content.vrf).includes(queryVrf.value) && queryType.value !== '') { - return content.vrf[queryVrf.value][queryType.value]; - } else { - return null; - } - }, [queryVrf.value, queryLocation.value, queryType.value]); - - useEffect(() => { - register('query_location', { required: true }); - register('query_target', { required: true }); - register('query_type', { required: true }); - register('query_vrf'); - }, [register]); - - return ( - <FormProvider {...formInstance}> - <AnimatedDiv - p={0} - my={4} - w="100%" - as="form" - mx="auto" - textAlign="left" - animate={{ opacity: 1, y: 0 }} - transition={{ duration: 0.3 }} - exit={{ opacity: 0, x: -300 }} - initial={{ opacity: 0, y: 300 }} - maxW={{ base: '100%', lg: '75%' }} - onSubmit={handleSubmit(submitHandler)} - > - <FormRow> - <FormField name="query_location" label={web.text.query_location}> - <QueryLocation onChange={handleChange} label={web.text.query_location} /> - </FormField> - <FormField - name="query_type" - label={web.text.query_type} - labelAddOn={ - <HelpModal visible={isQueryContent(vrfContent)} item={vrfContent} name="query_type" /> - } - > - <QueryType onChange={handleChange} label={web.text.query_type} /> - </FormField> - </FormRow> - <FormRow> - <If c={availVrfs.length > 1}> - <FormField label={web.text.query_vrf} name="query_vrf"> - <QueryVrf label={web.text.query_vrf} vrfs={availVrfs.value} onChange={handleChange} /> - </FormField> - </If> - <FormField name="query_target" label={web.text.query_target}> - <QueryTarget - name="query_target" - register={register} - onChange={handleChange} - placeholder={web.text.query_target} - /> - </FormField> - </FormRow> - <FormRow mt={0} justifyContent="flex-end"> - <Flex - my={2} - w="100%" - ml="auto" - maxW="100%" - flex="0 0 0" - flexDir="column" - mr={{ base: 0, lg: 2 }} - > - <SubmitButton handleChange={handleChange} /> - </Flex> - </FormRow> - </AnimatedDiv> - </FormProvider> - ); -}; diff --git a/hyperglass/ui/components/markdown/elements.tsx b/hyperglass/ui/components/markdown/elements.tsx deleted file mode 100644 index 1cb1d16..0000000 --- a/hyperglass/ui/components/markdown/elements.tsx +++ /dev/null @@ -1,160 +0,0 @@ -import { - Th, - Tr, - Td, - Box, - Tbody, - Thead, - useToken, - OrderedList, - UnorderedList, - Code as ChakraCode, - Link as ChakraLink, - Text as ChakraText, - Table as ChakraTable, - Divider as ChakraDivider, - Heading as ChakraHeading, - Checkbox as ChakraCheckbox, - ListItem as ChakraListItem, -} from '@chakra-ui/react'; -import { CodeBlock as CustomCodeBlock, If } from '~/components'; -import { useColorValue } from '~/context'; - -import type { - BoxProps, - TextProps, - CodeProps, - LinkProps, - TableProps, - ChakraProps, - HeadingProps, - DividerProps, - TableRowProps, - TableBodyProps, - TableCellProps, - TableHeadProps, -} from '@chakra-ui/react'; -import type { TCheckbox, TList, THeading, TCodeBlock, TTableData, TListItem } from './types'; - -type MDProps = { - node: Dict; -}; - -/* eslint @typescript-eslint/no-explicit-any: off */ -function hasNode<C>(p: any): p is C & MDProps { - return 'node' in p; -} - -function clean<P extends ChakraProps>(props: P): P { - if (hasNode<P>(props)) { - const { node, ...rest } = props; - const r = (rest as unknown) as P; - return r; - } - return props; -} - -export const Checkbox: React.FC<TCheckbox & MDProps> = (props: TCheckbox & MDProps) => { - const { checked, node, ...rest } = props; - return <ChakraCheckbox isChecked={checked} {...rest} />; -}; - -export const List: React.FC<TList> = (props: TList) => { - const { ordered, ...rest } = props; - return ( - <> - <If c={ordered}> - <OrderedList {...rest} /> - </If> - <If c={!ordered}> - <UnorderedList {...rest} /> - </If> - </> - ); -}; - -export const ListItem: React.FC<TListItem & MDProps> = (props: TListItem & MDProps) => { - const { checked, node, ...rest } = props; - return checked ? ( - <Checkbox checked={checked} node={node} {...rest} /> - ) : ( - <ChakraListItem {...rest} /> - ); -}; - -export const Heading: React.FC<THeading> = (props: THeading) => { - const { level, ...rest } = props; - - const levelMap = { - 1: { as: 'h1', size: 'lg', fontWeight: 'bold' }, - 2: { as: 'h2', size: 'lg', fontWeight: 'normal' }, - 3: { as: 'h3', size: 'lg', fontWeight: 'bold' }, - 4: { as: 'h4', size: 'md', fontWeight: 'normal' }, - 5: { as: 'h5', size: 'md', fontWeight: 'bold' }, - 6: { as: 'h6', size: 'sm', fontWeight: 'bold' }, - } as { [i: number]: HeadingProps }; - - return <ChakraHeading {...levelMap[level]} {...clean<Omit<THeading, 'level'>>(rest)} />; -}; - -export const Link: React.FC<LinkProps> = (props: LinkProps) => { - const color = useColorValue('blue.500', 'blue.300'); - return <ChakraLink isExternal color={color} {...clean<LinkProps>(props)} />; -}; - -export const CodeBlock: React.FC<TCodeBlock> = (props: TCodeBlock) => ( - <CustomCodeBlock>{props.value}</CustomCodeBlock> -); - -export const Paragraph: React.FC<TextProps> = (props: TextProps) => ( - <ChakraText - my={4} - css={{ - '&:first-of-type': { marginTop: useToken('space', 2) }, - '&:last-of-type': { marginBottom: 0 }, - }} - {...clean<TextProps>(props)} - /> -); - -export const InlineCode: React.FC<CodeProps> = (props: CodeProps) => ( - <ChakraCode borderRadius="md" px={1} {...clean<CodeProps>(props)} /> -); - -export const Divider: React.FC<DividerProps> = (props: DividerProps) => ( - <ChakraDivider my={2} {...clean<DividerProps>(props)} /> -); - -export const Table: React.FC<TableProps> = (props: TableProps) => ( - <ChakraTable my={4} variant="simple" size="md" {...clean<TableProps>(props)} /> -); - -export const TableRow: React.FC<TableRowProps> = (props: TableRowProps) => ( - <Tr {...clean<TableRowProps>(props)} /> -); - -export const TableBody: React.FC<TableBodyProps> = (props: TableBodyProps) => ( - <Tbody {...clean<TableBodyProps>(props)} /> -); - -export const TableHead: React.FC<TableHeadProps> = (props: TableHeadProps) => ( - <Thead {...clean<TableHeadProps>(props)} /> -); - -export const TableCell: React.FC<TTableData> = (props: TTableData) => { - const { isHeader, ...rest } = props; - return ( - <> - <If c={isHeader}> - <Th {...clean<TableCellProps>(rest)} /> - </If> - <If c={!isHeader}> - <Td {...clean<TableCellProps>(rest)} /> - </If> - </> - ); -}; - -export const Br: React.FC<BoxProps> = (props: BoxProps) => ( - <Box as="br" m={16} {...clean<BoxProps>(props)} /> -); diff --git a/hyperglass/ui/components/markdown/index.ts b/hyperglass/ui/components/markdown/index.ts deleted file mode 100644 index 99334b5..0000000 --- a/hyperglass/ui/components/markdown/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './markdown'; diff --git a/hyperglass/ui/components/markdown/markdown.tsx b/hyperglass/ui/components/markdown/markdown.tsx deleted file mode 100644 index 8266d8b..0000000 --- a/hyperglass/ui/components/markdown/markdown.tsx +++ /dev/null @@ -1,42 +0,0 @@ -import ReactMarkdown from 'react-markdown'; -import gfm from 'remark-gfm'; -import { - Br, - List, - Link, - Table, - Heading, - Divider, - ListItem, - TableRow, - CodeBlock, - TableCell, - Paragraph, - TableBody, - TableHead, - InlineCode, -} from './elements'; - -import type { ReactMarkdownProps } from 'react-markdown'; -import type { TMarkdown } from './types'; - -const renderers = { - break: Br, - link: Link, - list: List, - table: Table, - code: CodeBlock, - heading: Heading, - tableRow: TableRow, - listItem: ListItem, - tableHead: TableHead, - tableBody: TableBody, - paragraph: Paragraph, - tableCell: TableCell, - inlineCode: InlineCode, - thematicBreak: Divider, -} as ReactMarkdownProps['renderers']; - -export const Markdown: React.FC<TMarkdown> = (props: TMarkdown) => ( - <ReactMarkdown plugins={[gfm]} renderers={renderers} source={props.content} /> -); diff --git a/hyperglass/ui/components/markdown/types.ts b/hyperglass/ui/components/markdown/types.ts deleted file mode 100644 index b5e15aa..0000000 --- a/hyperglass/ui/components/markdown/types.ts +++ /dev/null @@ -1,31 +0,0 @@ -import type { BoxProps, CheckboxProps, HeadingProps, ListProps } from '@chakra-ui/react'; - -export interface TMarkdown { - content: string; -} - -export interface TCheckbox extends CheckboxProps { - checked: boolean; -} - -export interface TListItem { - checked: boolean; - children?: React.ReactNode; -} - -export interface TList extends ListProps { - ordered: boolean; - children?: React.ReactNode; -} - -export interface THeading extends HeadingProps { - level: 1 | 2 | 3 | 4 | 5 | 6; -} - -export interface TCodeBlock { - value: React.ReactNode; -} - -export interface TTableData extends BoxProps { - isHeader: boolean; -} diff --git a/hyperglass/ui/components/meta.tsx b/hyperglass/ui/components/meta.tsx deleted file mode 100644 index 70ab813..0000000 --- a/hyperglass/ui/components/meta.tsx +++ /dev/null @@ -1,59 +0,0 @@ -import { useEffect, useMemo, useState } from 'react'; -import Head from 'next/head'; -import { useTheme } from '@chakra-ui/react'; -import { useConfig } from '~/context'; -import { googleFontUrl } from '~/util'; - -export const Meta: React.FC = () => { - const config = useConfig(); - const { fonts } = useTheme(); - const [location, setLocation] = useState('/'); - - const { - site_title: title = 'hyperglass', - site_description: description = 'Network Looking Glass', - site_keywords: keywords = [ - 'hyperglass', - 'looking glass', - 'lg', - 'peer', - 'peering', - 'ipv4', - 'ipv6', - 'transit', - 'community', - 'communities', - 'bgp', - 'routing', - 'network', - 'isp', - ], - } = useConfig(); - - const siteName = `${title} - ${description}`; - const primaryFont = useMemo(() => googleFontUrl(fonts.body), []); - const monoFont = useMemo(() => googleFontUrl(fonts.mono), []); - - useEffect(() => { - if (typeof window !== 'undefined' && location === '/') { - setLocation(window.location.href); - } - }, []); - - return ( - <Head> - <title>{title} - - - - - - - - - - - - - ); -}; diff --git a/hyperglass/ui/components/output/cell.tsx b/hyperglass/ui/components/output/cell.tsx deleted file mode 100644 index 0bcb6d9..0000000 --- a/hyperglass/ui/components/output/cell.tsx +++ /dev/null @@ -1,24 +0,0 @@ -import { MonoField, Active, Weight, Age, Communities, RPKIState, ASPath } from './fields'; - -import type { TCell } from './types'; - -export const Cell: React.FC = (props: TCell) => { - const { data, rawData } = props; - const cellId = data.column.id as keyof TRoute; - const component = { - med: , - age: , - prefix: , - next_hop: , - peer_rid: , - source_as: , - active: , - source_rid: , - local_preference: , - communities: , - as_path: , - rpki_state: , - weight: , - }; - return component[cellId] ?? <> ; -}; diff --git a/hyperglass/ui/components/output/fields.tsx b/hyperglass/ui/components/output/fields.tsx deleted file mode 100644 index f372bd9..0000000 --- a/hyperglass/ui/components/output/fields.tsx +++ /dev/null @@ -1,190 +0,0 @@ -import { forwardRef } from 'react'; -import { Icon, Text, Box, Tooltip, Menu, MenuButton, MenuList, Link } from '@chakra-ui/react'; -import { CgMoreO as More } from '@meronex/icons/cg'; -import { BisError as Warning } from '@meronex/icons/bi'; -import { MdCancel as NotAllowed } from '@meronex/icons/md'; -import { RiHome2Fill as End } from '@meronex/icons/ri'; -import { BsQuestionCircleFill as Question } from '@meronex/icons/bs'; -import { FaCheckCircle as Check, FaChevronRight as ChevronRight } from '@meronex/icons/fa'; -import dayjs from 'dayjs'; -import relativeTimePlugin from 'dayjs/plugin/relativeTime'; -import utcPlugin from 'dayjs/plugin/utc'; -import { If } from '~/components'; -import { useConfig, useColorValue } from '~/context'; -import { useOpposingColor } from '~/hooks'; - -import type { - TAge, - TActive, - TWeight, - TASPath, - TMonoField, - TRPKIState, - TCommunities, -} from './types'; - -dayjs.extend(relativeTimePlugin); -dayjs.extend(utcPlugin); - -export const MonoField: React.FC = (props: TMonoField) => { - const { v, ...rest } = props; - return ( - - {v} - - ); -}; - -export const Active: React.FC = (props: TActive) => { - const { isActive } = props; - const color = useColorValue(['gray.500', 'green.500'], ['whiteAlpha.300', 'blackAlpha.500']); - return ( - <> - - - - - - - - ); -}; - -export const Age: React.FC = (props: TAge) => { - const { inSeconds, ...rest } = props; - const now = dayjs.utc(); - const then = now.subtract(inSeconds, 'second'); - return ( - - - {now.to(then, true)} - - - ); -}; - -export const Weight: React.FC = (props: TWeight) => { - const { weight, winningWeight, ...rest } = props; - const fixMeText = - winningWeight === 'low' ? 'Lower Weight is Preferred' : 'Higher Weight is Preferred'; - return ( - - - {weight} - - - ); -}; - -export const ASPath: React.FC = (props: TASPath) => { - const { path, active } = props; - const color = useColorValue( - // light: inactive, active - ['blackAlpha.500', 'blackAlpha.500'], - // dark: inactive, active - ['whiteAlpha.600', 'blackAlpha.700'], - ); - - if (path.length === 0) { - return ; - } - - const paths = [] as JSX.Element[]; - - path.map((asn, i) => { - const asnStr = String(asn); - i !== 0 && - paths.push( - , - ); - paths.push( - - {asnStr} - , - ); - }); - - return <>{paths}; -}; - -export const Communities: React.FC = (props: TCommunities) => { - const { communities } = props; - const { web } = useConfig(); - const bg = useColorValue('white', 'gray.900'); - const color = useOpposingColor(bg); - return ( - <> - - - - - - - - - - - - - - {communities.join('\n')} - - - - - ); -}; - -const _RPKIState: React.ForwardRefRenderFunction = ( - props: TRPKIState, - ref, -) => { - const { state, active } = props; - const { web } = useConfig(); - const bg = useColorValue( - [ - ['red.400', 'green.500', 'yellow.400', 'gray.500'], - ['red.500', 'green.500', 'yellow.600', 'gray.600'], - ], - [ - ['red.300', 'green.300', 'yellow.300', 'gray.300'], - ['red.500', 'green.600', 'yellow.600', 'gray.800'], - ], - ); - const color = useOpposingColor(bg[+active][state]); - const icon = [NotAllowed, Check, Warning, Question]; - - const text = [ - web.text.rpki_invalid, - web.text.rpki_valid, - web.text.rpki_unknown, - web.text.rpki_unverified, - ]; - - return ( - - - - - - ); -}; - -export const RPKIState = forwardRef(_RPKIState); diff --git a/hyperglass/ui/components/output/index.ts b/hyperglass/ui/components/output/index.ts deleted file mode 100644 index c22d499..0000000 --- a/hyperglass/ui/components/output/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './table'; -export * from './text'; diff --git a/hyperglass/ui/components/output/table.tsx b/hyperglass/ui/components/output/table.tsx deleted file mode 100644 index a56a6fd..0000000 --- a/hyperglass/ui/components/output/table.tsx +++ /dev/null @@ -1,45 +0,0 @@ -import { Flex } from '@chakra-ui/react'; -import { useConfig } from '~/context'; -import { Table } from '~/components'; -import { Cell } from './cell'; - -import type { TColumn, TParsedDataField, TCellRender } from '~/types'; -import type { TBGPTable } from './types'; - -function makeColumns(fields: TParsedDataField[]): TColumn[] { - return fields.map(pair => { - const [header, accessor, align] = pair; - - const columnConfig = { - align, - accessor, - hidden: false, - Header: header, - } as TColumn; - - if (align === null) { - columnConfig.hidden = true; - } - - return columnConfig; - }); -} - -export const BGPTable: React.FC = (props: TBGPTable) => { - const { children: data, ...rest } = props; - const { parsed_data_fields } = useConfig(); - const columns = makeColumns(parsed_data_fields); - - return ( - - } - /> - - ); -}; diff --git a/hyperglass/ui/components/output/text.tsx b/hyperglass/ui/components/output/text.tsx deleted file mode 100644 index 8fa794c..0000000 --- a/hyperglass/ui/components/output/text.tsx +++ /dev/null @@ -1,39 +0,0 @@ -import { Box } from '@chakra-ui/react'; -import { useColorValue } from '~/context'; - -import type { TTextOutput } from './types'; - -export const TextOutput: React.FC = (props: TTextOutput) => { - const { children, ...rest } = props; - - const bg = useColorValue('blackAlpha.100', 'gray.800'); - const color = useColorValue('black', 'white'); - const selectionBg = useColorValue('black', 'white'); - const selectionColor = useColorValue('white', 'black'); - - return ( - - {children.split('\\n').join('\n').replace(/\n\n/g, '\n')} - - ); -}; diff --git a/hyperglass/ui/components/output/types.ts b/hyperglass/ui/components/output/types.ts deleted file mode 100644 index a492625..0000000 --- a/hyperglass/ui/components/output/types.ts +++ /dev/null @@ -1,50 +0,0 @@ -import type { BoxProps, FlexProps, TextProps } from '@chakra-ui/react'; -import type { TCellRender } from '~/types'; - -export interface TTextOutput extends Omit { - children: string; -} - -export interface TActive { - isActive: boolean; -} - -export interface TMonoField extends TextProps { - v: React.ReactNode; -} - -export interface TAge extends TextProps { - inSeconds: number; -} - -export interface TWeight extends TextProps { - weight: number; - winningWeight: 'low' | 'high'; -} - -export interface TASPath { - path: number[]; - active: boolean; -} - -export interface TCommunities { - communities: string[]; -} - -export interface TRPKIState { - state: - | 0 // Invalid - | 1 // Valid - | 2 // Unknown - | 3; // Unverified - active: boolean; -} - -export interface TCell { - data: TCellRender; - rawData: TStructuredResponse; -} - -export interface TBGPTable extends Omit { - children: TStructuredResponse; -} diff --git a/hyperglass/ui/components/path/button.tsx b/hyperglass/ui/components/path/button.tsx deleted file mode 100644 index 94723b4..0000000 --- a/hyperglass/ui/components/path/button.tsx +++ /dev/null @@ -1,19 +0,0 @@ -import dynamic from 'next/dynamic'; -import { Button, Icon, Tooltip } from '@chakra-ui/react'; - -import type { TPathButton } from './types'; - -const PathIcon = dynamic(() => - import('@meronex/icons/bi').then(i => i.BisNetworkChart), -); - -export const PathButton: React.FC = (props: TPathButton) => { - const { onOpen } = props; - return ( - - - - ); -}; diff --git a/hyperglass/ui/components/path/chart.tsx b/hyperglass/ui/components/path/chart.tsx deleted file mode 100644 index 9f6cff4..0000000 --- a/hyperglass/ui/components/path/chart.tsx +++ /dev/null @@ -1,70 +0,0 @@ -import { Box, Flex, SkeletonText, Badge, VStack } from '@chakra-ui/react'; -import ReactFlow from 'react-flow-renderer'; -import { Background, ReactFlowProvider } from 'react-flow-renderer'; -import { Handle, Position } from 'react-flow-renderer'; -import { useConfig, useColorValue, useColorToken } from '~/context'; -import { useASNDetail } from '~/hooks'; -import { Controls } from './controls'; -import { useElements } from './useElements'; - -import type { TChart, TNode, TNodeData } from './types'; - -export const Chart: React.FC = (props: TChart) => { - const { data } = props; - const { primary_asn, org_name } = useConfig(); - - const dots = useColorToken('colors', 'blackAlpha.500', 'whiteAlpha.400'); - - const elements = useElements({ asn: primary_asn, name: org_name }, data); - - return ( - - - setTimeout(() => inst.fitView(), 0)} - > - - - - - - ); -}; - -const ASNode: React.FC> = (props: TNode) => { - const { data } = props; - const { asn, name, hasChildren, hasParents } = data; - - const color = useColorValue('black', 'white'); - const bg = useColorValue('white', 'whiteAlpha.100'); - - const { data: asnData, isError, isLoading } = useASNDetail(String(asn)); - - return ( - <> - {hasChildren && } - - - - {isLoading ? ( - - - - ) : !isError && asnData?.data?.asn.organization?.orgName ? ( - asnData.data.asn.organization.orgName - ) : ( - name - )} - - - {asn} - - - - {hasParents && } - - ); -}; diff --git a/hyperglass/ui/components/path/controls.tsx b/hyperglass/ui/components/path/controls.tsx deleted file mode 100644 index 4d6e13d..0000000 --- a/hyperglass/ui/components/path/controls.tsx +++ /dev/null @@ -1,28 +0,0 @@ -import dynamic from 'next/dynamic'; -import { ButtonGroup, IconButton } from '@chakra-ui/react'; -import { useZoomPanHelper } from 'react-flow-renderer'; - -const Plus = dynamic(() => import('@meronex/icons/fi').then(i => i.FiPlus)); -const Minus = dynamic(() => import('@meronex/icons/fi').then(i => i.FiMinus)); -const Square = dynamic(() => import('@meronex/icons/fi').then(i => i.FiSquare)); - -export const Controls: React.FC = () => { - const { fitView, zoomIn, zoomOut } = useZoomPanHelper(); - return ( - - } onClick={() => zoomIn()} aria-label="Zoom In" /> - } onClick={() => zoomOut()} aria-label="Zoom Out" /> - } onClick={() => fitView()} aria-label="Fit Nodes" /> - - ); -}; diff --git a/hyperglass/ui/components/path/index.ts b/hyperglass/ui/components/path/index.ts deleted file mode 100644 index 44bb0aa..0000000 --- a/hyperglass/ui/components/path/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './path'; diff --git a/hyperglass/ui/components/path/path.tsx b/hyperglass/ui/components/path/path.tsx deleted file mode 100644 index 96886e2..0000000 --- a/hyperglass/ui/components/path/path.tsx +++ /dev/null @@ -1,47 +0,0 @@ -import { - Modal, - Skeleton, - ModalBody, - ModalHeader, - ModalOverlay, - ModalContent, - useDisclosure, - ModalCloseButton, -} from '@chakra-ui/react'; -import { useColorValue, useBreakpointValue } from '~/context'; -import { useLGState, useLGMethods } from '~/hooks'; -import { PathButton } from './button'; -import { Chart } from './chart'; - -import type { TPath } from './types'; - -export const Path: React.FC = (props: TPath) => { - const { device } = props; - const { displayTarget } = useLGState(); - const { getResponse } = useLGMethods(); - const { isOpen, onClose, onOpen } = useDisclosure(); - const response = getResponse(device); - const output = response?.output as TStructuredResponse; - const bg = useColorValue('light.50', 'dark.900'); - const centered = useBreakpointValue({ base: false, lg: true }) ?? true; - return ( - <> - - - - - {`Path to ${displayTarget.value}`} - - - {response !== null ? : } - - - - - ); -}; diff --git a/hyperglass/ui/components/path/types.ts b/hyperglass/ui/components/path/types.ts deleted file mode 100644 index dd0f4ba..0000000 --- a/hyperglass/ui/components/path/types.ts +++ /dev/null @@ -1,29 +0,0 @@ -import type { NodeProps } from 'react-flow-renderer'; - -export interface TChart { - data: TStructuredResponse; -} - -export interface TPath { - device: string; -} - -export interface TNode extends Omit { - data: D; -} - -export interface TNodeData { - asn: string; - name: string; - hasChildren: boolean; - hasParents?: boolean; -} - -export interface BasePath { - asn: string; - name: string; -} - -export interface TPathButton { - onOpen(): void; -} diff --git a/hyperglass/ui/components/path/useElements.ts b/hyperglass/ui/components/path/useElements.ts deleted file mode 100644 index e0916b4..0000000 --- a/hyperglass/ui/components/path/useElements.ts +++ /dev/null @@ -1,115 +0,0 @@ -import dagre from 'dagre'; -import { useMemo } from 'react'; -import isEqual from 'react-fast-compare'; - -import type { FlowElement } from 'react-flow-renderer'; -import type { BasePath } from './types'; - -const NODE_WIDTH = 200; -const NODE_HEIGHT = 48; - -export function useElements(base: BasePath, data: TStructuredResponse): FlowElement[] { - return useMemo(() => { - return [...buildElements(base, data)]; - }, [data.routes.length]); -} - -/** - * Calculate the positions for each AS Path. - * @see https://github.com/MrBlenny/react-flow-chart/issues/61 - */ -function* buildElements(base: BasePath, data: TStructuredResponse): Generator { - const { routes } = data; - // Eliminate empty AS paths & deduplicate non-empty AS paths. Length should be same as count minus empty paths. - const asPaths = routes.filter(r => r.as_path.length !== 0).map(r => [...new Set(r.as_path)]); - - const totalPaths = asPaths.length - 1; - - const g = new dagre.graphlib.Graph(); - g.setGraph({ marginx: 20, marginy: 20 }); - g.setDefaultEdgeLabel(() => ({})); - - // Set the origin (i.e., the hyperglass user) at the base. - g.setNode(base.asn, { width: NODE_WIDTH, height: NODE_HEIGHT }); - - for (const [groupIdx, pathGroup] of asPaths.entries()) { - // For each ROUTE's AS Path: - - // Find the route after this one. - const nextGroup = groupIdx < totalPaths ? asPaths[groupIdx + 1] : []; - - // Connect the first hop in the AS Path to the base (for dagre). - g.setEdge(base.asn, `${groupIdx}-${pathGroup[0]}`); - - // Eliminate duplicate AS Paths. - if (!isEqual(pathGroup, nextGroup)) { - for (const [idx, asn] of pathGroup.entries()) { - // For each ASN in the ROUTE: - - const node = `${groupIdx}-${asn}`; - const endIdx = pathGroup.length - 1; - - // Add the AS as a node. - g.setNode(node, { width: NODE_WIDTH, height: NODE_HEIGHT }); - - // Connect the first hop in the AS Path to the base (for react-flow). - if (idx === 0) { - yield { - id: `e${base.asn}-${node}`, - source: base.asn, - target: node, - }; - } - // Connect every intermediate hop to each other. - if (idx !== endIdx) { - const next = `${groupIdx}-${pathGroup[idx + 1]}`; - g.setEdge(node, next); - yield { - id: `e${node}-${next}`, - source: node, - target: next, - }; - } - } - } - } - - // Now that that nodes are added, create the layout. - dagre.layout(g, { rankdir: 'BT', align: 'UR' }); - - // Get the base ASN's positions. - const x = g.node(base.asn).x - NODE_WIDTH / 2; - const y = g.node(base.asn).y + NODE_HEIGHT * 6; - - yield { - id: base.asn, - type: 'ASNode', - position: { x, y }, - data: { asn: base.asn, name: base.name, hasChildren: true, hasParents: false }, - }; - - for (const [groupIdx, pathGroup] of asPaths.entries()) { - const nextGroup = groupIdx < totalPaths ? asPaths[groupIdx + 1] : []; - if (!isEqual(pathGroup, nextGroup)) { - for (const [idx, asn] of pathGroup.entries()) { - const node = `${groupIdx}-${asn}`; - const endIdx = pathGroup.length - 1; - const x = g.node(node).x - NODE_WIDTH / 2; - const y = g.node(node).y - NODE_HEIGHT * (idx * 6); - - // Get each ASN's positions. - yield { - id: node, - type: 'ASNode', - position: { x, y }, - data: { - asn, - name: `AS${asn}`, - hasChildren: idx < endIdx, - hasParents: true, - }, - }; - } - } - } -} diff --git a/hyperglass/ui/components/results/copyButton.tsx b/hyperglass/ui/components/results/copyButton.tsx deleted file mode 100644 index bc031c3..0000000 --- a/hyperglass/ui/components/results/copyButton.tsx +++ /dev/null @@ -1,27 +0,0 @@ -import dynamic from 'next/dynamic'; -import { Button, Icon, Tooltip, useClipboard } from '@chakra-ui/react'; - -const Copy = dynamic(() => import('@meronex/icons/fi').then(i => i.FiCopy)); -const Check = dynamic(() => import('@meronex/icons/fi').then(i => i.FiCheck)); - -import type { TCopyButton } from './types'; - -export const CopyButton: React.FC = (props: TCopyButton) => { - const { copyValue, ...rest } = props; - const { onCopy, hasCopied } = useClipboard(copyValue); - return ( - - - - ); -}; diff --git a/hyperglass/ui/components/results/error.tsx b/hyperglass/ui/components/results/error.tsx deleted file mode 100644 index a8292d3..0000000 --- a/hyperglass/ui/components/results/error.tsx +++ /dev/null @@ -1,34 +0,0 @@ -import { Text } from '@chakra-ui/react'; - -import type { TFormattedError } from './types'; - -type TFormatError = string | JSX.Element; - -function formatError(text: string, values: string[], regex: RegExp): TFormatError[] | TFormatError { - if (!values.length) { - return text; - } - - const parts = text.split(regex); - - return parts.reduce((prev, current, i) => { - if (!i) { - return [current]; - } - - return prev.concat( - values.includes(current) ? {current} : current, - ); - }, [] as TFormatError[]); -} - -export const FormattedError: React.FC = (props: TFormattedError) => { - const { keywords, message } = props; - const pattern = new RegExp(keywords.map(kw => `(${kw})`).join('|'), 'gi'); - const things = formatError(message, keywords, pattern); - return ( - - {keywords.length !== 0 ? things : message} - - ); -}; diff --git a/hyperglass/ui/components/results/group.tsx b/hyperglass/ui/components/results/group.tsx deleted file mode 100644 index 564d2c1..0000000 --- a/hyperglass/ui/components/results/group.tsx +++ /dev/null @@ -1,61 +0,0 @@ -import { useEffect } from 'react'; -import { Accordion } from '@chakra-ui/react'; -import { AnimatePresence } from 'framer-motion'; -import { AnimatedDiv } from '~/components'; -import { useDevice, useLGState } from '~/hooks'; -import { Result } from './individual'; -import { Tags } from './tags'; - -export const Results: React.FC = () => { - const { queryLocation, queryTarget, queryType, queryVrf } = useLGState(); - - const getDevice = useDevice(); - - // Scroll to the top of the page when results load - primarily for mobile. - useEffect(() => { - if (typeof window !== 'undefined') { - window.scrollTo(0, 0); - } - }, []); - - return ( - <> - - - - - {queryLocation.value && - queryLocation.map((loc, i) => { - const device = getDevice(loc.value); - return ( - - ); - })} - - - - - ); -}; diff --git a/hyperglass/ui/components/results/guards.ts b/hyperglass/ui/components/results/guards.ts deleted file mode 100644 index 5000fe8..0000000 --- a/hyperglass/ui/components/results/guards.ts +++ /dev/null @@ -1,21 +0,0 @@ -/* eslint @typescript-eslint/no-explicit-any: 0 */ -/* eslint @typescript-eslint/explicit-module-boundary-types: 0 */ - -export function isStackError(error: any): error is Error { - return typeof error !== 'undefined' && error !== null && 'message' in error; -} - -export function isFetchError(error: any): error is Response { - return typeof error !== 'undefined' && error !== null && 'statusText' in error; -} - -export function isLGError(error: any): error is TQueryResponse { - return typeof error !== 'undefined' && error !== null && 'output' in error; -} - -/** - * Returns true if the response is an LG error, false if not. - */ -export function isLGOutputOrError(data: any): data is TQueryResponse { - return typeof data !== 'undefined' && data !== null && data?.level !== 'success'; -} diff --git a/hyperglass/ui/components/results/header.tsx b/hyperglass/ui/components/results/header.tsx deleted file mode 100644 index 070dbf2..0000000 --- a/hyperglass/ui/components/results/header.tsx +++ /dev/null @@ -1,59 +0,0 @@ -import { useMemo } from 'react'; -import { AccordionIcon, Box, Spinner, HStack, Text, Tooltip } from '@chakra-ui/react'; -import { BisError as Warning } from '@meronex/icons/bi'; -import { FaCheckCircle as Check } from '@meronex/icons/fa'; -import { useConfig, useColorValue } from '~/context'; -import { useOpposingColor, useStrf } from '~/hooks'; - -import type { TResultHeader } from './types'; - -const runtimeText = (runtime: number, text: string): string => { - let unit = 'seconds'; - if (runtime === 1) { - unit = 'second'; - } - return `${text} ${unit}`; -}; - -export const ResultHeader: React.FC = (props: TResultHeader) => { - const { title, loading, isError, errorMsg, errorLevel, runtime } = props; - - const status = useColorValue('primary.500', 'primary.300'); - const warning = useColorValue(`${errorLevel}.500`, `${errorLevel}.300`); - const defaultStatus = useColorValue('success.500', 'success.300'); - - const { web } = useConfig(); - const text = useStrf(web.text.complete_time, { seconds: runtime }, [runtime]); - const label = useMemo(() => runtimeText(runtime, text), [runtime]); - - const color = useOpposingColor(isError ? warning : defaultStatus); - - return ( - - - - {loading ? ( - - ) : ( - - )} - - - - {title} - - - ); -}; diff --git a/hyperglass/ui/components/results/index.ts b/hyperglass/ui/components/results/index.ts deleted file mode 100644 index 8a78f59..0000000 --- a/hyperglass/ui/components/results/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './group'; diff --git a/hyperglass/ui/components/results/individual.tsx b/hyperglass/ui/components/results/individual.tsx deleted file mode 100644 index a5d52cb..0000000 --- a/hyperglass/ui/components/results/individual.tsx +++ /dev/null @@ -1,258 +0,0 @@ -import { forwardRef, useEffect, useMemo } from 'react'; -import { - Box, - Flex, - chakra, - Icon, - Alert, - HStack, - Tooltip, - AccordionItem, - AccordionPanel, - useAccordionContext, - AccordionButton, -} from '@chakra-ui/react'; -import { motion } from 'framer-motion'; -import { BsLightningFill } from '@meronex/icons/bs'; -import { startCase } from 'lodash'; -import { BGPTable, Countdown, TextOutput, If, Path } from '~/components'; -import { useColorValue, useConfig, useMobile } from '~/context'; -import { useStrf, useLGQuery, useLGState, useTableToString } from '~/hooks'; -import { isStructuredOutput, isStringOutput } from '~/types'; -import { isStackError, isFetchError, isLGError, isLGOutputOrError } from './guards'; -import { RequeryButton } from './requeryButton'; -import { CopyButton } from './copyButton'; -import { FormattedError } from './error'; -import { ResultHeader } from './header'; - -import type { TResult, TErrorLevels } from './types'; - -const AnimatedAccordionItem = motion(AccordionItem); - -const AccordionHeaderWrapper = chakra('div', { - baseStyle: { - display: 'flex', - justifyContent: 'space-between', - _hover: { bg: 'blackAlpha.50' }, - _focus: { boxShadow: 'outline' }, - }, -}); - -const _Result: React.ForwardRefRenderFunction = (props: TResult, ref) => { - const { index, device, queryVrf, queryType, queryTarget, queryLocation } = props; - - const { web, cache, messages } = useConfig(); - const { index: indices, setIndex } = useAccordionContext(); - - const isMobile = useMobile(); - const color = useColorValue('black', 'white'); - const scrollbar = useColorValue('blackAlpha.300', 'whiteAlpha.300'); - const scrollbarHover = useColorValue('blackAlpha.400', 'whiteAlpha.400'); - const scrollbarBg = useColorValue('blackAlpha.50', 'whiteAlpha.50'); - - const { responses } = useLGState(); - - const { data, error, isError, isLoading, refetch, isFetching, isFetchedAfterMount } = useLGQuery({ - queryLocation, - queryTarget, - queryType, - queryVrf, - }); - - const isCached = useMemo(() => data?.cached || !isFetchedAfterMount, [ - data, - isLoading, - isFetching, - ]); - - if (typeof data !== 'undefined') { - responses.merge({ [device._id]: data }); - } - - const cacheLabel = useStrf(web.text.cache_icon, { time: data?.timestamp }, [data?.timestamp]); - - const errorKeywords = useMemo(() => { - let kw = [] as string[]; - if (isLGError(data)) { - kw = data.keywords; - } - return kw; - }, [data]); - - // Parse the the response and/or the error to determine from where to extract the error message. - const errorMsg = useMemo(() => { - if (isLGError(error)) { - return error.output as string; - } else if (isLGOutputOrError(data)) { - return data.output as string; - } else if (isFetchError(error)) { - return startCase(error.statusText); - } else if (isStackError(error) && error.message.toLowerCase().startsWith('timeout')) { - return messages.request_timeout; - } else if (isStackError(error)) { - return startCase(error.message); - } else { - return messages.general; - } - }, [isError, error, data]); - - isError && console.error(error); - - const errorLevel = useMemo(() => { - const statusMap = { - success: 'success', - warning: 'warning', - error: 'warning', - danger: 'error', - } as { [k in TResponseLevel]: 'success' | 'warning' | 'error' }; - - let e: TErrorLevels = 'error'; - - if (isLGError(error)) { - const idx = error.level as TResponseLevel; - e = statusMap[idx]; - } - return e; - }, [isError, isLoading, data]); - - const tableComponent = useMemo(() => { - let result = false; - if (typeof queryType.match(/^bgp_\w+$/) !== null && data?.format === 'application/json') { - result = true; - } - return result; - }, [queryType, data?.format]); - - let copyValue = data?.output as string; - - const formatData = useTableToString(queryTarget, data, [data?.format]); - - if (data?.format === 'application/json') { - copyValue = formatData(); - } - - if (error) { - copyValue = errorMsg; - } - - // Signal to the group that this result is done loading. - useEffect(() => { - // Only set the index if it's not already set and the query is finished loading. - if (Array.isArray(indices) && indices.length === 0 && !isLoading) { - // Only set the index if the response has data or an error. - if (data || isError) { - setIndex([index]); - } - } - }, [data, isError]); - - return ( - - <> - - - - - - {isStructuredOutput(data) && data.level === 'success' && tableComponent && ( - - )} - - - - - - - - {!isError && typeof data !== 'undefined' ? ( - <> - {isStructuredOutput(data) && data.level === 'success' && tableComponent ? ( - {data.output} - ) : isStringOutput(data) && data.level === 'success' && !tableComponent ? ( - {data.output} - ) : isStringOutput(data) && data.level !== 'success' ? ( - - - - ) : ( - - - - )} - - ) : ( - - - - )} - - - - - - - - - - - - - - - - - - - - - - - - ); -}; - -export const Result = forwardRef(_Result); diff --git a/hyperglass/ui/components/results/requeryButton.tsx b/hyperglass/ui/components/results/requeryButton.tsx deleted file mode 100644 index 1a691a2..0000000 --- a/hyperglass/ui/components/results/requeryButton.tsx +++ /dev/null @@ -1,34 +0,0 @@ -import { forwardRef } from 'react'; -import dynamic from 'next/dynamic'; -import { Button, Icon, Tooltip } from '@chakra-ui/react'; - -import type { TRequeryButton } from './types'; - -const Repeat = dynamic(() => import('@meronex/icons/fi').then(i => i.FiRepeat)); - -const _RequeryButton: React.ForwardRefRenderFunction = ( - props: TRequeryButton, - ref, -) => { - const { requery, ...rest } = props; - - return ( - - - - ); -}; - -export const RequeryButton = forwardRef(_RequeryButton); diff --git a/hyperglass/ui/components/results/tags.tsx b/hyperglass/ui/components/results/tags.tsx deleted file mode 100644 index 26de570..0000000 --- a/hyperglass/ui/components/results/tags.tsx +++ /dev/null @@ -1,128 +0,0 @@ -import { Box, Stack, useToken } from '@chakra-ui/react'; -import { motion, AnimatePresence } from 'framer-motion'; -import { Label } from '~/components'; -import { useConfig, useBreakpointValue } from '~/context'; -import { useLGState, useVrf } from '~/hooks'; -import { isQueryType } from '~/types'; - -import type { Transition } from 'framer-motion'; - -const transition = { duration: 0.3, delay: 0.5 } as Transition; - -export const Tags: React.FC = () => { - const { queries, web } = useConfig(); - const { queryLocation, queryTarget, queryType, queryVrf } = useLGState(); - - const targetBg = useToken('colors', 'teal.600'); - const queryBg = useToken('colors', 'cyan.500'); - const vrfBg = useToken('colors', 'blue.500'); - - const animateLeft = useBreakpointValue({ - base: { opacity: 1, x: 0 }, - md: { opacity: 1, x: 0 }, - lg: { opacity: 1, x: 0 }, - xl: { opacity: 1, x: 0 }, - }); - - const animateCenter = useBreakpointValue({ - base: { opacity: 1 }, - md: { opacity: 1 }, - lg: { opacity: 1 }, - xl: { opacity: 1 }, - }); - - const animateRight = useBreakpointValue({ - base: { opacity: 1, x: 0 }, - md: { opacity: 1, x: 0 }, - lg: { opacity: 1, x: 0 }, - xl: { opacity: 1, x: 0 }, - }); - - const initialLeft = useBreakpointValue({ - base: { opacity: 0, x: '-100%' }, - md: { opacity: 0, x: '-100%' }, - lg: { opacity: 0, x: '-100%' }, - xl: { opacity: 0, x: '-100%' }, - }); - - const initialCenter = useBreakpointValue({ - base: { opacity: 0 }, - md: { opacity: 0 }, - lg: { opacity: 0 }, - xl: { opacity: 0 }, - }); - - const initialRight = useBreakpointValue({ - base: { opacity: 0, x: '100%' }, - md: { opacity: 0, x: '100%' }, - lg: { opacity: 0, x: '100%' }, - xl: { opacity: 0, x: '100%' }, - }); - - let queryTypeLabel = ''; - if (isQueryType(queryType.value)) { - queryTypeLabel = queries[queryType.value].display_name; - } - - const getVrf = useVrf(); - const vrf = getVrf(queryVrf.value); - - return ( - - - - {queryLocation.value && ( - <> - - - - - - - - )} - - - - ); -}; diff --git a/hyperglass/ui/components/results/types.ts b/hyperglass/ui/components/results/types.ts deleted file mode 100644 index 10efab5..0000000 --- a/hyperglass/ui/components/results/types.ts +++ /dev/null @@ -1,52 +0,0 @@ -import type { State } from '@hookstate/core'; -import type { ButtonProps } from '@chakra-ui/react'; -import type { UseQueryResult } from 'react-query'; -import type { TDevice, TQueryTypes } from '~/types'; - -export interface TResultHeader { - title: string; - loading: boolean; - isError?: boolean; - errorMsg: string; - errorLevel: 'success' | 'warning' | 'error'; - runtime: number; -} - -export interface TFormattedError { - keywords: string[]; - message: string; -} - -export interface TResult { - index: number; - device: TDevice; - queryVrf: string; - queryTarget: string; - queryLocation: string; - queryType: TQueryTypes; -} - -export type TErrorLevels = 'success' | 'warning' | 'error'; - -export interface TCopyButton extends ButtonProps { - copyValue: string; -} - -export interface TRequeryButton extends ButtonProps { - requery: UseQueryResult['refetch']; -} - -export type TUseResults = { - firstOpen: number | null; - locations: { [k: string]: { complete: boolean; open: boolean; index: number } }; -}; - -export type TUseResultsMethods = { - toggle(loc: string): void; - setComplete(loc: string): void; - getOpen(): number[]; -}; - -export type UseResultsReturn = { - results: State; -} & TUseResultsMethods; diff --git a/hyperglass/ui/components/results/useResults.ts b/hyperglass/ui/components/results/useResults.ts deleted file mode 100644 index 63fb6cf..0000000 --- a/hyperglass/ui/components/results/useResults.ts +++ /dev/null @@ -1,100 +0,0 @@ -import { useEffect } from 'react'; -import { createState, useState } from '@hookstate/core'; - -import type { Plugin, State, PluginStateControl } from '@hookstate/core'; -import type { TUseResults, TUseResultsMethods, UseResultsReturn } from './types'; - -const MethodsId = Symbol('UseResultsMethods'); - -/** - * Plugin methods. - */ -class MethodsInstance { - /** - * Toggle a location's open/closed state. - */ - public toggle(state: State, loc: string) { - state.locations[loc].open.set(p => !p); - } - /** - * Set a location's completion state. - */ - public setComplete(state: State, loc: string) { - state.locations[loc].merge({ complete: true }); - const thisLoc = state.locations[loc]; - if ( - state.firstOpen.value === null && - state.locations.keys.includes(loc) && - state.firstOpen.value !== thisLoc.index.value - ) { - state.firstOpen.set(thisLoc.index.value); - this.toggle(state, loc); - } - } - /** - * Get the currently open panels. Passed to Chakra UI's index prop for internal state management. - */ - public getOpen(state: State) { - const open = state.locations.keys - .filter(k => state.locations[k].complete.value && state.locations[k].open.value) - .map(k => state.locations[k].index.value); - return open; - } -} - -/** - * hookstate plugin to provide convenience functions & tracking for the useResults hook. - */ -function Methods(inst?: State): Plugin | TUseResultsMethods { - if (inst) { - const [instance] = inst.attach(MethodsId) as [ - MethodsInstance | Error, - PluginStateControl, - ]; - - if (instance instanceof Error) { - throw instance; - } - - return { - toggle: (loc: string) => instance.toggle(inst, loc), - setComplete: (loc: string) => instance.setComplete(inst, loc), - getOpen: () => instance.getOpen(inst), - } as TUseResultsMethods; - } - return { - id: MethodsId, - init: () => { - /* eslint @typescript-eslint/ban-types: 0 */ - return new MethodsInstance() as {}; - }, - } as Plugin; -} -const initialState = { firstOpen: null, locations: {} } as TUseResults; -const resultsState = createState(initialState); - -/** - * Track the state of each result, and whether or not each panel is open. - */ -export function useResults(initial: TUseResults['locations']): UseResultsReturn { - // Initialize the global state before instantiating the hook, only once. - useEffect(() => { - if (resultsState.firstOpen.value === null && resultsState.locations.keys.length === 0) { - resultsState.set({ firstOpen: null, locations: initial }); - } - }, []); - - const results = useState(resultsState); - results.attach(Methods as () => Plugin); - - const methods = Methods(results) as TUseResultsMethods; - - // Reset the state on unmount. - useEffect(() => { - return () => { - results.set(initialState); - }; - }, []); - - return { results, ...methods }; -} diff --git a/hyperglass/ui/components/select/index.ts b/hyperglass/ui/components/select/index.ts deleted file mode 100644 index c739673..0000000 --- a/hyperglass/ui/components/select/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './select'; diff --git a/hyperglass/ui/components/select/select.tsx b/hyperglass/ui/components/select/select.tsx deleted file mode 100644 index 1f73afc..0000000 --- a/hyperglass/ui/components/select/select.tsx +++ /dev/null @@ -1,82 +0,0 @@ -import { createContext, useContext, useMemo } from 'react'; -import ReactSelect from 'react-select'; -import { chakra, useDisclosure } from '@chakra-ui/react'; -import { useColorMode } from '~/context'; -import { - useRSTheme, - useMenuStyle, - useMenuPortal, - useOptionStyle, - useControlStyle, - useMenuListStyle, - useMultiValueStyle, - usePlaceholderStyle, - useSingleValueStyle, - useMultiValueLabelStyle, - useMultiValueRemoveStyle, - useIndicatorSeparatorStyle, -} from './styles'; - -import type { TSelectOption } from '~/types'; -import type { TSelectBase, TSelectContext, TReactSelectChakra } from './types'; - -const SelectContext = createContext(Object()); -export const useSelectContext = (): TSelectContext => useContext(SelectContext); - -const ReactSelectChakra = chakra(ReactSelect); - -export const Select: React.FC = (props: TSelectBase) => { - const { options, multi, onSelect, isError = false, ...rest } = props; - const { isOpen, onOpen, onClose } = useDisclosure(); - - const { colorMode } = useColorMode(); - - const selectContext = useMemo(() => ({ colorMode, isOpen, isError }), [ - colorMode, - isError, - isOpen, - ]); - - const defaultOnChange = (changed: TSelectOption | TSelectOption[]) => { - if (!Array.isArray(changed)) { - changed = [changed]; - } - if (typeof onSelect === 'function') { - onSelect(changed); - } - }; - - const multiValue = useMultiValueStyle({ colorMode }); - const multiValueLabel = useMultiValueLabelStyle({ colorMode }); - const multiValueRemove = useMultiValueRemoveStyle({ colorMode }); - const menuPortal = useMenuPortal(); - const rsTheme = useRSTheme(); - - return ( - - - - ); -}; diff --git a/hyperglass/ui/components/select/styles.tsx b/hyperglass/ui/components/select/styles.tsx deleted file mode 100644 index 0dfc6e1..0000000 --- a/hyperglass/ui/components/select/styles.tsx +++ /dev/null @@ -1,194 +0,0 @@ -import { useCallback, useMemo } from 'react'; -import { useToken } from '@chakra-ui/react'; -import { mergeWith } from '@chakra-ui/utils'; -import { useOpposingColor } from '~/hooks'; -import { useColorValue, useColorToken, useMobile } from '~/context'; -import { useSelectContext } from './select'; - -import type { - TMenu, - TOption, - TStyles, - TControl, - TRSTheme, - TMultiValue, - TRSThemeCallback, - TRSStyleCallback, -} from './types'; - -export const useControlStyle = (base: TStyles, state: TControl): TStyles => { - const { isFocused } = state; - const { colorMode, isError } = useSelectContext(); - - const minHeight = useToken('space', 12); - const borderRadius = useToken('radii', 'md'); - const color = useColorToken('colors', 'black', 'whiteAlpha.800'); - const focusBorder = useColorToken('colors', 'blue.500', 'blue.300'); - const invalidBorder = useColorToken('colors', 'red.500', 'red.300'); - const borderColor = useColorToken('colors', 'gray.100', 'whiteAlpha.50'); - const borderHover = useColorToken('colors', 'gray.300', 'whiteAlpha.400'); - const backgroundColor = useColorToken('colors', 'white', 'whiteAlpha.100'); - - const styles = { - backgroundColor, - borderRadius, - color, - minHeight, - transition: 'all 0.2s', - borderColor: isError ? invalidBorder : isFocused ? focusBorder : borderColor, - boxShadow: isError - ? `0 0 0 1px ${invalidBorder}` - : isFocused - ? `0 0 0 1px ${focusBorder}` - : undefined, - '&:hover': { borderColor: isFocused ? focusBorder : borderHover }, - '&:hover > div > span': { backgroundColor: borderHover }, - '&:focus': { borderColor: isError ? invalidBorder : focusBorder }, - '&.invalid': { borderColor: invalidBorder, boxShadow: `0 0 0 1px ${invalidBorder}` }, - }; - return useMemo(() => mergeWith({}, base, styles), [colorMode, isFocused, isError]); -}; - -export const useMenuStyle = (base: TStyles, _: TMenu): TStyles => { - const { colorMode, isOpen } = useSelectContext(); - const backgroundColor = useColorToken('colors', 'white', 'blackSolid.700'); - const styles = { backgroundColor }; - return useMemo(() => mergeWith({}, base, styles), [colorMode, isOpen]); -}; - -export const useMenuListStyle = (base: TStyles): TStyles => { - const { colorMode, isOpen } = useSelectContext(); - const borderRadius = useToken('radii', 'md'); - const backgroundColor = useColorToken('colors', 'white', 'blackSolid.700'); - const scrollbarTrack = useColorToken('colors', 'blackAlpha.50', 'whiteAlpha.50'); - const scrollbarThumb = useColorToken('colors', 'blackAlpha.300', 'whiteAlpha.300'); - const scrollbarThumbHover = useColorToken('colors', 'blackAlpha.400', 'whiteAlpha.400'); - - const styles = { - borderRadius, - backgroundColor, - '&::-webkit-scrollbar': { width: '5px' }, - '&::-webkit-scrollbar-track': { backgroundColor: scrollbarTrack }, - '&::-webkit-scrollbar-thumb': { backgroundColor: scrollbarThumb }, - '&::-webkit-scrollbar-thumb:hover': { backgroundColor: scrollbarThumbHover }, - '-ms-overflow-style': { display: 'none' }, - }; - return useMemo(() => mergeWith({}, base, styles), [colorMode, isOpen]); -}; - -export const useOptionStyle = (base: TStyles, state: TOption): TStyles => { - const { isFocused, isSelected, isDisabled } = state; - const { colorMode, isOpen } = useSelectContext(); - - const fontSize = useToken('fontSizes', 'lg'); - const disabled = useToken('colors', 'whiteAlpha.400'); - const active = useColorToken('colors', 'primary.600', 'primary.400'); - const focused = useColorToken('colors', 'primary.500', 'primary.300'); - const selected = useColorToken('colors', 'blackAlpha.400', 'whiteAlpha.400'); - - const activeColor = useOpposingColor(active); - - const backgroundColor = useMemo(() => { - let bg = 'transparent'; - switch (true) { - case isDisabled: - bg = disabled; - break; - case isSelected: - bg = selected; - break; - case isFocused: - bg = focused; - break; - } - return bg; - }, [isDisabled, isFocused, isSelected]); - - const color = useOpposingColor(backgroundColor); - - const styles = { - color: backgroundColor === 'transparent' ? 'currentColor' : color, - '&:active': { backgroundColor: active, color: activeColor }, - '&:focus': { backgroundColor: active, color: activeColor }, - backgroundColor, - fontSize, - }; - - return useMemo(() => mergeWith({}, base, styles), [ - isOpen, - colorMode, - isFocused, - isDisabled, - isSelected, - ]); -}; - -export const useIndicatorSeparatorStyle = (base: TStyles): TStyles => { - const { colorMode } = useSelectContext(); - const backgroundColor = useColorToken('colors', 'whiteAlpha.700', 'gray.600'); - const styles = { backgroundColor }; - return useMemo(() => mergeWith({}, base, styles), [colorMode]); -}; - -export const usePlaceholderStyle = (base: TStyles): TStyles => { - const { colorMode } = useSelectContext(); - const color = useColorToken('colors', 'gray.600', 'whiteAlpha.700'); - const fontSize = useToken('fontSizes', 'lg'); - return useMemo(() => mergeWith({}, base, { color, fontSize }), [colorMode]); -}; - -export const useSingleValueStyle = (): TRSStyleCallback => { - const { colorMode } = useSelectContext(); - - const color = useColorValue('black', 'whiteAlpha.800'); - const fontSize = useToken('fontSizes', 'lg'); - - const styles = { color, fontSize }; - return useCallback((base: TStyles) => mergeWith({}, base, styles), [color, colorMode]); -}; - -export const useMultiValueStyle = (props: TMultiValue): TRSStyleCallback => { - const { colorMode } = props; - - const backgroundColor = useColorToken('colors', 'primary.500', 'primary.300'); - const color = useOpposingColor(backgroundColor); - - const styles = { backgroundColor, color }; - return useCallback((base: TStyles) => mergeWith({}, base, styles), [backgroundColor, colorMode]); -}; - -export const useMultiValueLabelStyle = (props: TMultiValue): TRSStyleCallback => { - const { colorMode } = props; - - const backgroundColor = useColorToken('colors', 'primary.500', 'primary.300'); - const color = useOpposingColor(backgroundColor); - - const styles = { color }; - return useCallback((base: TStyles) => mergeWith({}, base, styles), [colorMode]); -}; - -export const useMultiValueRemoveStyle = (props: TMultiValue): TRSStyleCallback => { - const { colorMode } = props; - - const backgroundColor = useColorToken('colors', 'primary.500', 'primary.300'); - const color = useOpposingColor(backgroundColor); - - const styles = { - color, - '&:hover': { backgroundColor: 'inherit', color, opacity: 0.7 }, - }; - return useCallback((base: TStyles) => mergeWith({}, base, styles), [colorMode]); -}; - -export const useRSTheme = (): TRSThemeCallback => { - const borderRadius = useToken('radii', 'md'); - return useCallback((t: TRSTheme): TRSTheme => ({ ...t, borderRadius }), []); -}; - -export const useMenuPortal = (): TRSStyleCallback => { - const isMobile = useMobile(); - const styles = { - zIndex: isMobile ? 1500 : 1, - }; - return useCallback((base: TStyles) => mergeWith({}, base, styles), [isMobile]); -}; diff --git a/hyperglass/ui/components/select/types.ts b/hyperglass/ui/components/select/types.ts deleted file mode 100644 index d717a7a..0000000 --- a/hyperglass/ui/components/select/types.ts +++ /dev/null @@ -1,81 +0,0 @@ -/* eslint @typescript-eslint/no-explicit-any: 0 */ -/* eslint @typescript-eslint/explicit-module-boundary-types: 0 */ - -import type { - Props as IReactSelect, - ControlProps, - MenuProps, - MenuListComponentProps, - OptionProps, - MultiValueProps, - IndicatorProps, - Theme as RSTheme, - PlaceholderProps, - Styles as RSStyles, -} from 'react-select'; -import type { BoxProps } from '@chakra-ui/react'; -import type { Theme, TSelectOption, TSelectOptionMulti, TSelectOptionGroup } from '~/types'; - -export interface TSelectState { - [k: string]: string[]; -} - -export type TOptions = Array; - -export type TReactSelectChakra = Omit & - Omit; - -export interface TSelectBase extends TReactSelectChakra { - name: string; - multi?: boolean; - isError?: boolean; - options: TOptions; - required?: boolean; - onSelect?: (s: TSelectOption[]) => void; - onChange?: (c: TSelectOption | TSelectOptionMulti) => void; - colorScheme?: Theme.ColorNames; -} - -export interface TSelectContext { - colorMode: 'light' | 'dark'; - isOpen: boolean; - isError: boolean; -} - -export interface TMultiValueRemoveProps { - children: Node; - data: any; - innerProps: { - className: string; - onTouchEnd: (e: any) => void; - onClick: (e: any) => void; - onMouseDown: (e: any) => void; - }; - selectProps: any; -} - -export interface TRSTheme extends Omit { - borderRadius: string | number; -} - -export type TControl = ControlProps; - -export type TMenu = MenuProps; - -export type TMenuList = MenuListComponentProps; - -export type TOption = OptionProps; - -export type TMultiValueState = MultiValueProps; - -export type TIndicator = IndicatorProps; - -export type TPlaceholder = PlaceholderProps; - -export type TMultiValue = Pick; - -export type TRSStyleCallback = (base: TStyles) => TStyles; - -export type TRSThemeCallback = (theme: TRSTheme) => TRSTheme; - -export type TStyles = RSStyles; diff --git a/hyperglass/ui/components/submit/index.ts b/hyperglass/ui/components/submit/index.ts deleted file mode 100644 index e9be2e3..0000000 --- a/hyperglass/ui/components/submit/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './submit'; diff --git a/hyperglass/ui/components/submit/submit.tsx b/hyperglass/ui/components/submit/submit.tsx deleted file mode 100644 index 4e718e8..0000000 --- a/hyperglass/ui/components/submit/submit.tsx +++ /dev/null @@ -1,125 +0,0 @@ -import { forwardRef } from 'react'; -import { - Modal, - Popover, - ModalBody, - IconButton, - PopoverBody, - ModalOverlay, - ModalContent, - PopoverArrow, - PopoverTrigger, - PopoverContent, - ModalCloseButton, - PopoverCloseButton, -} from '@chakra-ui/react'; -import { FiSearch } from '@meronex/icons/fi'; -import { useFormContext } from 'react-hook-form'; -import { If, ResolvedTarget } from '~/components'; -import { useMobile, useColorValue } from '~/context'; -import { useLGState, useLGMethods } from '~/hooks'; - -import type { IconButtonProps } from '@chakra-ui/react'; -import type { TSubmitButton, TRSubmitButton } from './types'; - -const _SubmitIcon: React.ForwardRefRenderFunction< - HTMLButtonElement, - Omit -> = (props: Omit, ref) => { - const { isLoading, ...rest } = props; - return ( - } - title="Submit Query" - colorScheme="primary" - isLoading={isLoading} - aria-label="Submit Query" - {...rest} - /> - ); -}; -const SubmitIcon = forwardRef>(_SubmitIcon); - -/** - * Mobile Submit Button - */ -const MSubmitButton: React.FC = (props: TRSubmitButton) => { - const { children, isOpen, onClose, onChange } = props; - const bg = useColorValue('white', 'gray.900'); - return ( - <> - {children} - - - - - - {isOpen && } - - - - - ); -}; - -/** - * Desktop Submit Button - */ -const DSubmitButton: React.FC = (props: TRSubmitButton) => { - const { children, isOpen, onClose, onChange } = props; - const bg = useColorValue('white', 'gray.900'); - return ( - - {children} - - - - - {isOpen && } - - - - ); -}; - -export const SubmitButton: React.FC = (props: TSubmitButton) => { - const { handleChange } = props; - const isMobile = useMobile(); - const { resolvedIsOpen, btnLoading } = useLGState(); - const { resolvedClose, resetForm } = useLGMethods(); - - const { reset } = useFormContext(); - - function handleClose(): void { - reset(); - resetForm(); - resolvedClose(); - } - - return ( - <> - - - - - - - - - - - - ); -}; diff --git a/hyperglass/ui/components/submit/types.ts b/hyperglass/ui/components/submit/types.ts deleted file mode 100644 index 91ca90b..0000000 --- a/hyperglass/ui/components/submit/types.ts +++ /dev/null @@ -1,13 +0,0 @@ -import type { IconButtonProps } from '@chakra-ui/react'; -import type { OnChangeArgs } from '~/types'; - -export interface TSubmitButton extends Omit { - handleChange(e: OnChangeArgs): void; -} - -export interface TRSubmitButton { - isOpen: boolean; - onClose(): void; - onChange(e: OnChangeArgs): void; - children: React.ReactNode; -} diff --git a/hyperglass/ui/components/table/body.tsx b/hyperglass/ui/components/table/body.tsx deleted file mode 100644 index 2d62a4f..0000000 --- a/hyperglass/ui/components/table/body.tsx +++ /dev/null @@ -1,16 +0,0 @@ -import { Box } from '@chakra-ui/react'; - -import type { BoxProps } from '@chakra-ui/react'; - -export const TableBody: React.FC = (props: BoxProps) => ( - -); diff --git a/hyperglass/ui/components/table/button.tsx b/hyperglass/ui/components/table/button.tsx deleted file mode 100644 index a4e1553..0000000 --- a/hyperglass/ui/components/table/button.tsx +++ /dev/null @@ -1,7 +0,0 @@ -import { IconButton } from '@chakra-ui/react'; - -import type { TTableIconButton } from './types'; - -export const TableIconButton: React.FC = (props: TTableIconButton) => ( - -); diff --git a/hyperglass/ui/components/table/cell.tsx b/hyperglass/ui/components/table/cell.tsx deleted file mode 100644 index 618d094..0000000 --- a/hyperglass/ui/components/table/cell.tsx +++ /dev/null @@ -1,28 +0,0 @@ -import { Box } from '@chakra-ui/react'; -import { useColorValue } from '~/context'; - -import type { TTableCell } from './types'; - -export const TableCell: React.FC = (props: TTableCell) => { - const { bordersVertical = [false, 0], align, ...rest } = props; - const [doVerticalBorders, index] = bordersVertical; - const borderLeftColor = useColorValue('blackAlpha.100', 'whiteAlpha.100'); - - let borderProps = {}; - if (doVerticalBorders && index !== 0) { - borderProps = { borderLeft: '1px solid', borderLeftColor }; - } - - return ( - - ); -}; diff --git a/hyperglass/ui/components/table/head.tsx b/hyperglass/ui/components/table/head.tsx deleted file mode 100644 index 37abe0f..0000000 --- a/hyperglass/ui/components/table/head.tsx +++ /dev/null @@ -1,9 +0,0 @@ -import { Box } from '@chakra-ui/react'; -import { useColorValue } from '~/context'; - -import type { BoxProps } from '@chakra-ui/react'; - -export const TableHead: React.FC = (props: BoxProps) => { - const bg = useColorValue('blackAlpha.100', 'whiteAlpha.100'); - return ; -}; diff --git a/hyperglass/ui/components/table/index.ts b/hyperglass/ui/components/table/index.ts deleted file mode 100644 index 7285324..0000000 --- a/hyperglass/ui/components/table/index.ts +++ /dev/null @@ -1,8 +0,0 @@ -export * from './body'; -export * from './button'; -export * from './cell'; -export * from './head'; -export * from './main'; -export * from './main'; -export * from './pageSelect'; -export * from './row'; diff --git a/hyperglass/ui/components/table/main.tsx b/hyperglass/ui/components/table/main.tsx deleted file mode 100644 index 41bd90a..0000000 --- a/hyperglass/ui/components/table/main.tsx +++ /dev/null @@ -1,208 +0,0 @@ -// This rule isn't needed because react-table does this for us, for better or worse. -/* eslint react/jsx-key: 0 */ - -import dynamic from 'next/dynamic'; -import { Flex, Icon, Text } from '@chakra-ui/react'; -import { usePagination, useSortBy, useTable } from 'react-table'; -import { useMobile } from '~/context'; -import { CardBody, CardFooter, CardHeader, If } from '~/components'; -import { TableMain } from './table'; -import { TableCell } from './cell'; -import { TableHead } from './head'; -import { TableRow } from './row'; -import { TableBody } from './body'; -import { TableIconButton } from './button'; -import { TableSelectShow } from './pageSelect'; - -import type { TableOptions, PluginHook } from 'react-table'; -import type { TCellRender } from '~/types'; -import type { TTable } from './types'; - -const ChevronRight = dynamic(() => - import('@meronex/icons/fa').then(i => i.FaChevronRight), -); - -const ChevronLeft = dynamic(() => - import('@meronex/icons/fa').then(i => i.FaChevronLeft), -); - -const ChevronDown = dynamic(() => - import('@meronex/icons/fa').then(i => i.FaChevronDown), -); - -const DoubleChevronRight = dynamic(() => - import('@meronex/icons/fi').then(i => i.FiChevronsRight), -); -const DoubleChevronLeft = dynamic(() => - import('@meronex/icons/fi').then(i => i.FiChevronsLeft), -); - -export const Table: React.FC = (props: TTable) => { - const { - data, - columns, - heading, - Cell, - rowHighlightBg, - striped = false, - rowHighlightProp, - bordersVertical = false, - bordersHorizontal = false, - } = props; - - const isMobile = useMobile(); - - const defaultColumn = { - minWidth: 100, - width: 150, - maxWidth: 300, - }; - - const hiddenColumns = [] as string[]; - - for (const col of columns) { - if (col.hidden) { - hiddenColumns.push(col.accessor); - } - } - - const options = { - columns, - defaultColumn, - data, - initialState: { hiddenColumns }, - } as TableOptions; - - const plugins = [useSortBy, usePagination] as PluginHook[]; - - const instance = useTable(options, ...plugins); - - const { - page, - gotoPage, - nextPage, - pageCount, - prepareRow, - canNextPage, - pageOptions, - setPageSize, - headerGroups, - previousPage, - getTableProps, - canPreviousPage, - state: { pageIndex, pageSize }, - } = instance; - - return ( - - {heading && {heading}} - - - {headerGroups.map((headerGroup, i) => ( - - {headerGroup.headers.map(column => ( - - - {column.render('Header')} - - - - - - - - - - {''} - - ))} - - ))} - - - {page.map((row, key) => { - prepareRow(row); - return ( - - {row.cells.map((cell, i) => { - const { column, row, value } = cell as TCellRender; - return ( - - {typeof Cell !== 'undefined' ? ( - - ) : ( - cell.render('Cell') - )} - - ); - })} - - ); - })} - - - - - gotoPage(0)} - isDisabled={!canPreviousPage} - icon={} - /> - previousPage()} - isDisabled={!canPreviousPage} - icon={} - /> - - - - Page{' '} - - {pageIndex + 1} of {pageOptions.length} - {' '} - - {!isMobile && ( - { - setPageSize(Number(e.target.value)); - }} - /> - )} - - - } - /> - } - onClick={() => gotoPage(pageCount ? pageCount - 1 : 1)} - /> - - - - ); -}; diff --git a/hyperglass/ui/components/table/pageSelect.tsx b/hyperglass/ui/components/table/pageSelect.tsx deleted file mode 100644 index fafa6d9..0000000 --- a/hyperglass/ui/components/table/pageSelect.tsx +++ /dev/null @@ -1,15 +0,0 @@ -import { Select } from '@chakra-ui/react'; -import { SelectProps } from '@chakra-ui/react'; - -export const TableSelectShow: React.FC = (props: SelectProps) => { - const { value, ...rest } = props; - return ( - - ); -}; diff --git a/hyperglass/ui/components/table/row.tsx b/hyperglass/ui/components/table/row.tsx deleted file mode 100644 index 47e4111..0000000 --- a/hyperglass/ui/components/table/row.tsx +++ /dev/null @@ -1,51 +0,0 @@ -import { Box } from '@chakra-ui/react'; -import { useColorValue } from '~/context'; -import { useOpposingColor } from '~/hooks'; - -import type { TTableRow } from './types'; - -export const TableRow: React.FC = (props: TTableRow) => { - const { - index = 0, - doStripe = false, - highlight = false, - highlightBg = 'primary', - doHorizontalBorders = false, - ...rest - } = props; - - const alpha = useColorValue('100', '200'); - const alphaHover = useColorValue('200', '100'); - const bgStripe = useColorValue('blackAlpha.50', 'whiteAlpha.50'); - let hoverBg = useColorValue('blackAlpha.50', 'whiteAlpha.50'); - const rowBorder = useColorValue( - { borderTop: '1px', borderTopColor: 'blackAlpha.100' }, - { borderTop: '1px', borderTopColor: 'whiteAlpha.100' }, - ); - let bg; - - if (highlight) { - bg = `${String(highlightBg)}.${alpha}`; - hoverBg = `${String(highlightBg)}.${alphaHover}`; - } else if (doStripe && index % 2 !== 0) { - bg = bgStripe; - } - const defaultBg = useColorValue('white', 'black'); - const color = useOpposingColor(bg ?? defaultBg); - const borderProps = doHorizontalBorders && index !== 0 ? rowBorder : {}; - - return ( - td': { color } }} - fontWeight={highlight ? 'bold' : undefined} - _hover={{ - cursor: 'pointer', - backgroundColor: highlight ? `${String(highlightBg)}.${alphaHover}` : hoverBg, - }} - {...borderProps} - {...rest} - /> - ); -}; diff --git a/hyperglass/ui/components/table/table.tsx b/hyperglass/ui/components/table/table.tsx deleted file mode 100644 index 9fb1c84..0000000 --- a/hyperglass/ui/components/table/table.tsx +++ /dev/null @@ -1,34 +0,0 @@ -import { Box } from '@chakra-ui/react'; -import { useColorValue } from '~/context'; - -import type { BoxProps } from '@chakra-ui/react'; - -export const TableMain: React.FC = (props: BoxProps) => { - const scrollbar = useColorValue('blackAlpha.300', 'whiteAlpha.300'); - const scrollbarHover = useColorValue('blackAlpha.400', 'whiteAlpha.400'); - const scrollbarBg = useColorValue('blackAlpha.50', 'whiteAlpha.50'); - return ( - - ); -}; diff --git a/hyperglass/ui/components/table/types.ts b/hyperglass/ui/components/table/types.ts deleted file mode 100644 index 341d566..0000000 --- a/hyperglass/ui/components/table/types.ts +++ /dev/null @@ -1,30 +0,0 @@ -import type { BoxProps, IconButtonProps } from '@chakra-ui/react'; - -import type { Theme, TColumn, TCellRender } from '~/types'; - -export interface TTable { - data: TRoute[]; - striped?: boolean; - columns: TColumn[]; - heading?: React.ReactNode; - bordersVertical?: boolean; - bordersHorizontal?: boolean; - Cell?: React.FC; - rowHighlightProp?: keyof IRoute; - rowHighlightBg?: Theme.ColorNames; -} - -export interface TTableCell extends Omit { - bordersVertical?: [boolean, number]; - align?: 'left' | 'right' | 'center'; -} - -export interface TTableRow extends BoxProps { - highlightBg?: Theme.ColorNames; - doHorizontalBorders?: boolean; - highlight?: boolean; - doStripe?: boolean; - index: number; -} - -export type TTableIconButton = Omit; diff --git a/hyperglass/ui/components/util/animated.tsx b/hyperglass/ui/components/util/animated.tsx deleted file mode 100644 index 901fe89..0000000 --- a/hyperglass/ui/components/util/animated.tsx +++ /dev/null @@ -1,18 +0,0 @@ -/* eslint react/display-name: off */ -import { Box, forwardRef } from '@chakra-ui/react'; -import { motion, isValidMotionProp } from 'framer-motion'; - -import type { BoxProps } from '@chakra-ui/react'; - -/** - * Combined Chakra + Framer Motion component. - * @see https://chakra-ui.com/guides/integrations/with-framer - */ -export const AnimatedDiv = motion( - forwardRef>((props, ref) => { - const chakraProps = Object.fromEntries( - Object.entries(props).filter(([key]) => !isValidMotionProp(key)), - ); - return ; - }), -); diff --git a/hyperglass/ui/components/util/if.tsx b/hyperglass/ui/components/util/if.tsx deleted file mode 100644 index f518819..0000000 --- a/hyperglass/ui/components/util/if.tsx +++ /dev/null @@ -1,6 +0,0 @@ -import type { TIf } from './types'; - -export const If: React.FC = (props: TIf) => { - const { c, children } = props; - return c ? <>{children} : null; -}; diff --git a/hyperglass/ui/components/util/index.ts b/hyperglass/ui/components/util/index.ts deleted file mode 100644 index d7a1522..0000000 --- a/hyperglass/ui/components/util/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './animated'; -export * from './if'; diff --git a/hyperglass/ui/components/util/types.ts b/hyperglass/ui/components/util/types.ts deleted file mode 100644 index 106caa5..0000000 --- a/hyperglass/ui/components/util/types.ts +++ /dev/null @@ -1,4 +0,0 @@ -export interface TIf { - c: boolean; - children?: React.ReactNode; -} diff --git a/hyperglass/ui/context/HyperglassProvider.tsx b/hyperglass/ui/context/HyperglassProvider.tsx deleted file mode 100644 index 0efc403..0000000 --- a/hyperglass/ui/context/HyperglassProvider.tsx +++ /dev/null @@ -1,62 +0,0 @@ -import { createContext, useContext, useMemo } from 'react'; -import { - useToken, - ChakraProvider, - useColorModeValue, - useBreakpointValue, - useTheme as useChakraTheme, -} from '@chakra-ui/react'; -import { QueryClient, QueryClientProvider } from 'react-query'; -import { makeTheme, defaultTheme } from '~/util'; - -import type { IConfig, Theme } from '~/types'; -import type { THyperglassProvider } from './types'; - -const HyperglassContext = createContext(Object()); - -const queryClient = new QueryClient(); - -export const HyperglassProvider: React.FC = (props: THyperglassProvider) => { - const { config, children } = props; - const value = useMemo(() => config, []); - const userTheme = value && makeTheme(value.web.theme, value.web.theme.default_color_mode); - const theme = value ? userTheme : defaultTheme; - return ( - - - {children} - - - ); -}; - -/** - * Get the current configuration. - */ -export const useConfig = (): IConfig => useContext(HyperglassContext); - -/** - * Get the current theme object. - */ -export const useTheme = (): Theme.Full => useChakraTheme(); - -/** - * Determine if device is mobile or desktop based on Chakra UI theme breakpoints. - */ -export const useMobile = (): boolean => - useBreakpointValue({ base: true, md: true, lg: false, xl: false }) ?? true; - -/** - * Convenience function to combine Chakra UI's useToken & useColorModeValue. - */ -export const useColorToken = ( - token: keyof Theme.Full, - light: L, - dark: D, -): L | D => useColorModeValue(useToken(token, light), useToken(token, dark)); - -export { - useColorMode, - useBreakpointValue, - useColorModeValue as useColorValue, -} from '@chakra-ui/react'; diff --git a/hyperglass/ui/context/index.ts b/hyperglass/ui/context/index.ts deleted file mode 100644 index 757b5cf..0000000 --- a/hyperglass/ui/context/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './HyperglassProvider'; diff --git a/hyperglass/ui/context/types.ts b/hyperglass/ui/context/types.ts deleted file mode 100644 index 9168636..0000000 --- a/hyperglass/ui/context/types.ts +++ /dev/null @@ -1,18 +0,0 @@ -import type { State } from '@hookstate/core'; -import type { IConfig, TFormData } from '~/types'; - -export interface THyperglassProvider { - config: IConfig; - children: React.ReactNode; -} - -export interface TGlobalState { - isSubmitting: boolean; - formData: TFormData; -} - -export interface TUseGlobalState { - isSubmitting: State; - formData: State; - resetForm(): void; -} diff --git a/hyperglass/ui/hooks/index.ts b/hyperglass/ui/hooks/index.ts deleted file mode 100644 index 882d53c..0000000 --- a/hyperglass/ui/hooks/index.ts +++ /dev/null @@ -1,12 +0,0 @@ -export * from './useASNDetail'; -export * from './useBooleanValue'; -export * from './useDevice'; -export * from './useDNSQuery'; -export * from './useGoogleAnalytics'; -export * from './useGreeting'; -export * from './useLGQuery'; -export * from './useLGState'; -export * from './useOpposingColor'; -export * from './useStrf'; -export * from './useTableToString'; -export * from './useVrf'; diff --git a/hyperglass/ui/hooks/types.ts b/hyperglass/ui/hooks/types.ts deleted file mode 100644 index 7fc3bc2..0000000 --- a/hyperglass/ui/hooks/types.ts +++ /dev/null @@ -1,102 +0,0 @@ -import type { State } from '@hookstate/core'; -import type * as ReactGA from 'react-ga'; -import type { - TDevice, - Families, - TFormQuery, - TDeviceVrf, - TQueryTypes, - TSelectOption, -} from '~/types'; - -export type LGQueryKey = [string, TFormQuery]; -export type DNSQueryKey = [string, { target: string | null; family: 4 | 6 }]; - -export interface TOpposingOptions { - light?: string; - dark?: string; -} - -export type TUseGreetingReturn = { - ack: State; - isOpen: State; - open(): void; - close(): void; - greetingReady(): boolean; -}; - -export type TUseDevice = ( - /** - * Device's ID, e.g. the device.name field. - */ - deviceId: string, -) => TDevice; - -export type TUseVrf = (vrfId: string) => TDeviceVrf; - -export interface TSelections { - queryLocation: TSelectOption[] | []; - queryType: TSelectOption | null; - queryVrf: TSelectOption | null; -} - -export interface TMethodsExtension { - getResponse(d: string): TQueryResponse | null; - resolvedClose(): void; - resolvedOpen(): void; - formReady(): boolean; - resetForm(): void; - stateExporter(o: O): O | null; -} - -export type TLGState = { - queryVrf: string; - families: Families; - queryTarget: string; - btnLoading: boolean; - isSubmitting: boolean; - displayTarget: string; - queryType: TQueryTypes; - queryLocation: string[]; - availVrfs: TDeviceVrf[]; - resolvedIsOpen: boolean; - selections: TSelections; - responses: { [d: string]: TQueryResponse }; -}; - -export type TLGStateHandlers = { - exportState(s: S): S | null; - getResponse(d: string): TQueryResponse | null; - resolvedClose(): void; - resolvedOpen(): void; - formReady(): boolean; - resetForm(): void; - stateExporter(o: O): O | null; -}; - -export type UseStrfArgs = { [k: string]: unknown } | string; - -export type TTableToStringFormatter = - | ((v: string) => string) - | ((v: number) => string) - | ((v: number[]) => string) - | ((v: string[]) => string) - | ((v: boolean) => string); - -export type TTableToStringFormatted = { - age: (v: number) => string; - active: (v: boolean) => string; - as_path: (v: number[]) => string; - communities: (v: string[]) => string; - rpki_state: (v: number, n: TRPKIStates) => string; -}; - -export type GAEffect = (ga: typeof ReactGA) => void; - -export interface GAReturn { - ga: typeof ReactGA; - initialize(trackingId: string | null, debug: boolean): void; - trackPage(path: string): void; - trackModal(path: string): void; - trackEvent(event: ReactGA.EventArgs): void; -} diff --git a/hyperglass/ui/hooks/useASNDetail.ts b/hyperglass/ui/hooks/useASNDetail.ts deleted file mode 100644 index 6504c35..0000000 --- a/hyperglass/ui/hooks/useASNDetail.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { useQuery } from 'react-query'; - -import type { QueryFunctionContext, QueryObserverResult, QueryFunction } from 'react-query'; -import type { TASNQuery } from '~/types'; - -const query: QueryFunction = async (ctx: QueryFunctionContext) => { - const asn = ctx.queryKey; - const res = await fetch('https://api.asrank.caida.org/v2/graphql', { - mode: 'cors', - method: 'POST', - headers: { 'content-type': 'application/json' }, - /* eslint no-useless-escape: 0 */ - body: JSON.stringify({ query: `{ asn(asn:\"${asn}\"){ organization { orgName } } }` }), - }); - return await res.json(); -}; - -/** - * Query the Caida AS Rank API to get an ASN's organization name for the AS Path component. - * @see https://api.asrank.caida.org/v2/docs - */ -export function useASNDetail(asn: string): QueryObserverResult { - return useQuery({ - queryKey: asn, - queryFn: query, - refetchOnWindowFocus: false, - refetchInterval: false, - refetchOnMount: false, - cacheTime: Infinity, - }); -} diff --git a/hyperglass/ui/hooks/useBooleanValue.ts b/hyperglass/ui/hooks/useBooleanValue.ts deleted file mode 100644 index eb17e99..0000000 --- a/hyperglass/ui/hooks/useBooleanValue.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { useMemo } from 'react'; - -/** - * Track the state of a boolean and return values based on its state. - */ -export function useBooleanValue( - status: boolean, - ifTrue: T, - ifFalse: F, -): T | F { - return useMemo(() => { - if (status) { - return ifTrue; - } else { - return ifFalse; - } - }, [status]); -} diff --git a/hyperglass/ui/hooks/useDNSQuery.ts b/hyperglass/ui/hooks/useDNSQuery.ts deleted file mode 100644 index cbf2c95..0000000 --- a/hyperglass/ui/hooks/useDNSQuery.ts +++ /dev/null @@ -1,66 +0,0 @@ -import { useQuery } from 'react-query'; -import { useConfig } from '~/context'; -import { fetchWithTimeout } from '~/util'; -import { useGoogleAnalytics } from './useGoogleAnalytics'; - -import type { QueryFunction, QueryFunctionContext, QueryObserverResult } from 'react-query'; -import type { DnsOverHttps } from '~/types'; -import type { DNSQueryKey } from './types'; - -/** - * Perform a DNS over HTTPS query using the application/dns-json MIME type. - */ -const query: QueryFunction = async ( - ctx: QueryFunctionContext, -) => { - const [url, { target, family }] = ctx.queryKey; - - const controller = new AbortController(); - - let json; - const type = family === 4 ? 'A' : family === 6 ? 'AAAA' : ''; - - if (url !== null) { - const res = await fetchWithTimeout( - `${url}?name=${target}&type=${type}`, - { - headers: { accept: 'application/dns-json' }, - mode: 'cors', - }, - 5000, - controller, - ); - - json = await res.json(); - } - - return json; -}; - -/** - * Query the configured DNS over HTTPS provider for the provided target. If `family` is `4`, only - * an A record will be queried. If `family` is `6`, only a AAAA record will be queried. - */ -export function useDNSQuery( - /** - * Hostname for DNS query. - */ - target: string | null, - /** - * Address family, e.g. IPv4 or IPv6. - */ - family: 4 | 6, -): QueryObserverResult { - const { cache, web } = useConfig(); - const { trackEvent } = useGoogleAnalytics(); - - if (typeof target === 'string') { - trackEvent({ category: 'DNS', action: 'Query', label: target, dimension1: `IPv${family}` }); - } - - return useQuery({ - queryKey: [web.dns_provider.url, { target, family }], - queryFn: query, - cacheTime: cache.timeout * 1000, - }); -} diff --git a/hyperglass/ui/hooks/useDevice.ts b/hyperglass/ui/hooks/useDevice.ts deleted file mode 100644 index 09f48f2..0000000 --- a/hyperglass/ui/hooks/useDevice.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { useCallback, useMemo } from 'react'; -import { useConfig } from '~/context'; - -import type { TDevice } from '~/types'; -import type { TUseDevice } from './types'; - -/** - * Get a device's configuration from the global configuration context based on its name. - */ -export function useDevice(): TUseDevice { - const { networks } = useConfig(); - - const devices = useMemo(() => networks.map(n => n.locations).flat(), []); - - function getDevice(id: string): TDevice { - return devices.filter(dev => dev._id === id)[0]; - } - - return useCallback(getDevice, []); -} diff --git a/hyperglass/ui/hooks/useGoogleAnalytics.tsx b/hyperglass/ui/hooks/useGoogleAnalytics.tsx deleted file mode 100644 index 61659d1..0000000 --- a/hyperglass/ui/hooks/useGoogleAnalytics.tsx +++ /dev/null @@ -1,81 +0,0 @@ -import { useCallback } from 'react'; -import { createState, useState } from '@hookstate/core'; -import * as ReactGA from 'react-ga'; - -import type { GAEffect, GAReturn } from './types'; - -const enabledState = createState(false); - -export function useGoogleAnalytics(): GAReturn { - const enabled = useState(enabledState); - - const useAnalytics = useCallback((effect: GAEffect): void => { - if (typeof window !== 'undefined' && enabled.value) { - if (typeof effect === 'function') { - effect(ReactGA); - } - } - }, []); - - const trackEvent = useCallback((e: ReactGA.EventArgs) => { - useAnalytics(ga => { - if (process.env.NODE_ENV === 'production') { - ga.event(e); - } else { - console.log( - `%cEvent %c${JSON.stringify(e)}`, - 'background: green; color: black; padding: 0.5rem; font-size: 0.75rem;', - 'background: black; color: green; padding: 0.5rem; font-size: 0.75rem; font-weight: bold;', - ); - } - }); - }, []); - - const trackPage = useCallback((path: string) => { - useAnalytics(ga => { - if (process.env.NODE_ENV === 'production') { - ga.pageview(path); - } else { - console.log( - `%cPage View %c${path}`, - 'background: blue; color: white; padding: 0.5rem; font-size: 0.75rem;', - 'background: white; color: blue; padding: 0.5rem; font-size: 0.75rem; font-weight: bold;', - ); - } - }); - }, []); - - const trackModal = useCallback((path: string) => { - useAnalytics(ga => { - if (process.env.NODE_ENV === 'production') { - ga.modalview(path); - } else { - console.log( - `%cModal View %c${path}`, - 'background: red; color: white; padding: 0.5rem; font-size: 0.75rem;', - 'background: white; color: red; padding: 0.5rem; font-size: 0.75rem; font-weight: bold;', - ); - } - }); - }, []); - - const initialize = useCallback((trackingId: string, debug: boolean) => { - if (typeof trackingId !== 'string') { - return; - } - - enabled.set(true); - - const initializeOpts = { titleCase: false } as ReactGA.InitializeOptions; - - if (debug) { - initializeOpts.debug = true; - } - - useAnalytics(ga => { - ga.initialize(trackingId, initializeOpts); - }); - }, []); - - return { trackEvent, trackModal, trackPage, initialize, ga: ReactGA }; -} diff --git a/hyperglass/ui/hooks/useGreeting.ts b/hyperglass/ui/hooks/useGreeting.ts deleted file mode 100644 index ea25777..0000000 --- a/hyperglass/ui/hooks/useGreeting.ts +++ /dev/null @@ -1,45 +0,0 @@ -import { createState, useState } from '@hookstate/core'; -import { Persistence } from '@hookstate/persistence'; -import { useConfig } from '~/context'; - -import type { TUseGreetingReturn } from './types'; - -const ackState = createState(false); -const openState = createState(false); - -/** - * Hook to manage the greeting, a.k.a. the popup at config path web.greeting. - */ -export function useGreeting(): TUseGreetingReturn { - const ack = useState(ackState); - const isOpen = useState(openState); - const { web } = useConfig(); - - if (typeof window !== 'undefined') { - ack.attach(Persistence('hyperglass-greeting')); - } - - function open() { - return isOpen.set(true); - } - function close() { - return isOpen.set(false); - } - - function greetingReady(): boolean { - if (ack.get()) { - // If the acknowledgement is already set, no further evaluation is needed. - return true; - } else if (!web.greeting.required && !ack.get()) { - // If the acknowledgement is not set, but is also not required, then pass. - return true; - } else if (web.greeting.required && !ack.get()) { - // If the acknowledgement is not set, but is required, then fail. - return false; - } else { - return false; - } - } - - return { ack, isOpen, greetingReady, open, close }; -} diff --git a/hyperglass/ui/hooks/useLGQuery.ts b/hyperglass/ui/hooks/useLGQuery.ts deleted file mode 100644 index a103d0a..0000000 --- a/hyperglass/ui/hooks/useLGQuery.ts +++ /dev/null @@ -1,77 +0,0 @@ -import { useEffect } from 'react'; -import { useQuery } from 'react-query'; -import { useConfig } from '~/context'; -import { useGoogleAnalytics } from './useGoogleAnalytics'; -import { fetchWithTimeout } from '~/util'; - -import type { QueryFunction, QueryFunctionContext, QueryObserverResult } from 'react-query'; -import type { TFormQuery } from '~/types'; -import type { LGQueryKey } from './types'; - -/** - * Custom hook handle submission of a query to the hyperglass backend. - */ -export function useLGQuery(query: TFormQuery): QueryObserverResult { - const { request_timeout, cache } = useConfig(); - const controller = new AbortController(); - - const { trackEvent } = useGoogleAnalytics(); - - trackEvent({ - category: 'Query', - action: 'submit', - dimension1: query.queryLocation, - dimension2: query.queryTarget, - dimension3: query.queryType, - dimension4: query.queryVrf, - }); - - const runQuery: QueryFunction = async ( - ctx: QueryFunctionContext, - ): Promise => { - const [url, data] = ctx.queryKey; - const { queryLocation, queryTarget, queryType, queryVrf } = data; - const res = await fetchWithTimeout( - url, - { - method: 'POST', - headers: { 'content-type': 'application/json' }, - body: JSON.stringify({ - query_location: queryLocation, - query_target: queryTarget, - query_type: queryType, - query_vrf: queryVrf, - }), - mode: 'cors', - }, - request_timeout * 1000, - controller, - ); - try { - return await res.json(); - } catch (err) { - throw new Error(res.statusText); - } - }; - - // Cancel any still-running queries on unmount. - useEffect( - () => () => { - controller.abort(); - }, - [], - ); - - return useQuery({ - queryKey: ['/api/query/', query], - queryFn: runQuery, - // Invalidate react-query's cache just shy of the configured cache timeout. - cacheTime: cache.timeout * 1000 * 0.95, - // Don't refetch when window refocuses. - refetchOnWindowFocus: false, - // Don't automatically refetch query data (queries should be on-off). - refetchInterval: false, - // Don't refetch on component remount. - refetchOnMount: false, - }); -} diff --git a/hyperglass/ui/hooks/useLGState.ts b/hyperglass/ui/hooks/useLGState.ts deleted file mode 100644 index bbad925..0000000 --- a/hyperglass/ui/hooks/useLGState.ts +++ /dev/null @@ -1,162 +0,0 @@ -import { useCallback } from 'react'; -import { useState, createState } from '@hookstate/core'; -import isEqual from 'react-fast-compare'; -import { all } from '~/util'; - -import type { State, PluginStateControl, Plugin } from '@hookstate/core'; -import type { TLGState, TLGStateHandlers, TMethodsExtension } from './types'; - -const MethodsId = Symbol('Methods'); - -/** - * hookstate plugin to provide convenience functions for the useLGState hook. - */ -class MethodsInstance { - /** - * Set the DNS resolver Popover to opened. - */ - public resolvedOpen(state: State) { - state.resolvedIsOpen.set(true); - } - /** - * Set the DNS resolver Popover to closed. - */ - public resolvedClose(state: State) { - state.resolvedIsOpen.set(false); - } - /** - * Find a response based on the device ID. - */ - public getResponse(state: State, device: string): TQueryResponse | null { - if (device in state.responses) { - return state.responses[device].value; - } else { - return null; - } - } - /** - * Determine if the form is ready for submission, e.g. all fields have values and isSubmitting - * has been set to true. This ultimately controls the UI layout. - */ - public formReady(state: State): boolean { - return ( - state.isSubmitting.value && - all( - ...[ - state.queryVrf.value !== '', - state.queryType.value !== '', - state.queryTarget.value !== '', - state.queryLocation.length !== 0, - ], - ) - ); - } - /** - * Reset form values affected by the form state to their default values. - */ - public resetForm(state: State) { - state.merge({ - queryVrf: '', - families: [], - queryType: '', - responses: {}, - queryTarget: '', - queryLocation: [], - displayTarget: '', - btnLoading: false, - isSubmitting: false, - resolvedIsOpen: false, - availVrfs: [], - selections: { queryLocation: [], queryType: null, queryVrf: null }, - }); - } - public stateExporter(obj: O): O | null { - let result = null; - if (obj === null) { - return result; - } - try { - result = JSON.parse(JSON.stringify(obj)); - } catch (err) { - console.error(err.message); - } - return result; - } -} - -/** - * Plugin Initialization. - */ -function Methods(): Plugin; -/** - * Plugin Attachment. - */ -function Methods(inst: State): TMethodsExtension; -/** - * Plugin Instance. - */ -function Methods(inst?: State): Plugin | TMethodsExtension { - if (inst) { - const [instance] = inst.attach(MethodsId) as [ - MethodsInstance | Error, - PluginStateControl, - ]; - - if (instance instanceof Error) { - throw instance; - } - - return { - resetForm: () => instance.resetForm(inst), - formReady: () => instance.formReady(inst), - resolvedOpen: () => instance.resolvedOpen(inst), - resolvedClose: () => instance.resolvedClose(inst), - getResponse: device => instance.getResponse(inst, device), - stateExporter: obj => instance.stateExporter(obj), - }; - } - return { - id: MethodsId, - init: () => { - /* eslint @typescript-eslint/ban-types: 0 */ - return new MethodsInstance() as {}; - }, - }; -} - -const LGState = createState({ - selections: { queryLocation: [], queryType: null, queryVrf: null }, - resolvedIsOpen: false, - isSubmitting: false, - displayTarget: '', - queryLocation: [], - btnLoading: false, - queryTarget: '', - queryType: '', - availVrfs: [], - responses: {}, - queryVrf: '', - families: [], -}); - -/** - * Global state hook for state used throughout hyperglass. - */ -export function useLGState(): State { - return useState(LGState); -} - -/** - * Plugin for useLGState() that provides convenience methods for its state. - */ -export function useLGMethods(): TLGStateHandlers { - const state = useLGState(); - state.attach(Methods); - const exporter = useCallback(Methods(state).stateExporter, [isEqual]); - return { - exportState(s) { - return exporter(s); - }, - ...Methods(state), - }; -} diff --git a/hyperglass/ui/hooks/useOpposingColor.ts b/hyperglass/ui/hooks/useOpposingColor.ts deleted file mode 100644 index 4f2bf4d..0000000 --- a/hyperglass/ui/hooks/useOpposingColor.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { useMemo } from 'react'; -import { getColor, isLight } from '@chakra-ui/theme-tools'; -import { useTheme } from '~/context'; - -import type { TOpposingOptions } from './types'; - -/** - * Parse the color string to determine if it's a Chakra UI theme key, and determine if the - * opposing color should be black or white. - */ -export function useIsDark(color: string): boolean { - const theme = useTheme(); - if (typeof color === 'string' && color.match(/[a-zA-Z]+\.[a-zA-Z0-9]+/g)) { - color = getColor(theme, color, color); - } - let opposingShouldBeDark = true; - try { - opposingShouldBeDark = isLight(color)(theme); - } catch (err) { - console.error(err); - } - return opposingShouldBeDark; -} - -/** - * Determine if the foreground color for `color` should be white or black. - */ -export function useOpposingColor(color: string, options?: TOpposingOptions): string { - const isBlack = useIsDark(color); - - return useMemo(() => { - if (isBlack) { - return options?.dark ?? 'black'; - } else { - return options?.light ?? 'white'; - } - }, [color]); -} diff --git a/hyperglass/ui/hooks/useStrf.ts b/hyperglass/ui/hooks/useStrf.ts deleted file mode 100644 index f790e8f..0000000 --- a/hyperglass/ui/hooks/useStrf.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { useMemo } from 'react'; -import format from 'string-format'; - -import type { UseStrfArgs } from './types'; - -/** - * Format a string with variables, like Python's string.format() - */ -export function useStrf(str: string, fmt: UseStrfArgs, ...deps: unknown[]): string { - return useMemo(() => format(str, fmt), deps); -} diff --git a/hyperglass/ui/hooks/useTableToString.ts b/hyperglass/ui/hooks/useTableToString.ts deleted file mode 100644 index 174f4fa..0000000 --- a/hyperglass/ui/hooks/useTableToString.ts +++ /dev/null @@ -1,109 +0,0 @@ -import { useCallback } from 'react'; -import dayjs from 'dayjs'; -import relativeTimePlugin from 'dayjs/plugin/relativeTime'; -import utcPlugin from 'dayjs/plugin/utc'; -import { useConfig } from '~/context'; -import { isStructuredOutput } from '~/types'; - -import type { TTableToStringFormatter, TTableToStringFormatted } from './types'; - -dayjs.extend(relativeTimePlugin); -dayjs.extend(utcPlugin); - -function formatAsPath(path: number[]): string { - return path.join(' → '); -} - -function formatCommunities(comms: string[]): string { - const commsStr = comms.map(c => ` - ${c}`); - return '\n' + commsStr.join('\n'); -} - -function formatBool(val: boolean): string { - let fmt = ''; - if (val === true) { - fmt = 'yes'; - } else if (val === false) { - fmt = 'no'; - } - return fmt; -} - -function formatTime(val: number): string { - const now = dayjs.utc(); - const then = now.subtract(val, 'second'); - const timestamp = then.toString().replace('GMT', 'UTC'); - const relative = now.to(then, true); - return `${relative} (${timestamp})`; -} - -/** - * Get a function to convert table data to string, for use in the copy button component. - */ -export function useTableToString( - target: string, - data: TQueryResponse | undefined, - ...deps: unknown[] -): () => string { - const { web, parsed_data_fields, messages } = useConfig(); - - function formatRpkiState(val: number): string { - const rpkiStates = [ - web.text.rpki_invalid, - web.text.rpki_valid, - web.text.rpki_unknown, - web.text.rpki_unverified, - ]; - return rpkiStates[val]; - } - - const tableFormatMap = { - age: formatTime, - active: formatBool, - as_path: formatAsPath, - communities: formatCommunities, - rpki_state: formatRpkiState, - }; - - function isFormatted(key: string): key is keyof TTableToStringFormatted { - return key in tableFormatMap; - } - - function getFmtFunc(accessor: keyof TRoute): TTableToStringFormatter { - if (isFormatted(accessor)) { - return tableFormatMap[accessor]; - } else { - return String; - } - } - - function doFormat(target: string, data: TQueryResponse | undefined): string { - let result = messages.no_output; - try { - if (typeof data !== 'undefined' && isStructuredOutput(data)) { - const tableStringParts = [`Routes For: ${target}`, `Timestamp: ${data.timestamp} UTC`]; - for (const route of data.output.routes) { - for (const field of parsed_data_fields) { - const [header, accessor, align] = field; - if (align !== null) { - let value = route[accessor]; - const fmtFunc = getFmtFunc(accessor) as (v: typeof value) => string; - value = fmtFunc(value); - if (accessor === 'prefix') { - tableStringParts.push(` - ${header}: ${value}`); - } else { - tableStringParts.push(` - ${header}: ${value}`); - } - } - } - } - result = tableStringParts.join('\n'); - } - return result; - } catch (err) { - console.error(err); - return `An error occurred while parsing the output: '${err.message}'`; - } - } - return useCallback(() => doFormat(target, data), deps); -} diff --git a/hyperglass/ui/hooks/useVrf.ts b/hyperglass/ui/hooks/useVrf.ts deleted file mode 100644 index 662ecf2..0000000 --- a/hyperglass/ui/hooks/useVrf.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { useCallback, useMemo } from 'react'; -import { useConfig } from '~/context'; - -import type { TDeviceVrf } from '~/types'; -import type { TUseVrf } from './types'; - -/** - * Get a VRF configuration from the global configuration context based on its name. - */ -export function useVrf(): TUseVrf { - const { networks } = useConfig(); - - const vrfs = useMemo(() => networks.map(n => n.locations.map(l => l.vrfs).flat()).flat(), []); - - function getVrf(id: string): TDeviceVrf { - const matching = vrfs.find(vrf => vrf._id === id); - if (typeof matching === 'undefined') { - if (id === '__hyperglass_default') { - const anyDefault = vrfs.find(vrf => vrf.default === true); - if (typeof anyDefault !== 'undefined') { - return anyDefault; - } else { - throw new Error(`No matching VRF found for '${id}'`); - } - } else { - throw new Error(`No matching VRF found for '${id}'`); - } - } - return matching; - } - - return useCallback(getVrf, []); -} diff --git a/hyperglass/ui/next-env.d.ts b/hyperglass/ui/next-env.d.ts deleted file mode 100644 index 7b7aa2c..0000000 --- a/hyperglass/ui/next-env.d.ts +++ /dev/null @@ -1,2 +0,0 @@ -/// -/// diff --git a/hyperglass/ui/next.config.js b/hyperglass/ui/next.config.js deleted file mode 100644 index bd7f634..0000000 --- a/hyperglass/ui/next.config.js +++ /dev/null @@ -1,17 +0,0 @@ -const envVars = require('/tmp/hyperglass.env.json'); -const { configFile } = envVars; -const config = require(String(configFile)); - -module.exports = { - reactStrictMode: true, - poweredByHeader: false, - env: { - _NODE_ENV_: config.NODE_ENV, - _HYPERGLASS_URL_: config._HYPERGLASS_URL_, - _HYPERGLASS_CONFIG_: config._HYPERGLASS_CONFIG_, - _HYPERGLASS_FAVICONS_: config._HYPERGLASS_FAVICONS_, - }, - future: { - webpack5: true, - }, -}; diff --git a/hyperglass/ui/nextdev.js b/hyperglass/ui/nextdev.js deleted file mode 100644 index 0facba9..0000000 --- a/hyperglass/ui/nextdev.js +++ /dev/null @@ -1,52 +0,0 @@ -/* eslint-disable no-console */ -const express = require('express'); -const proxyMiddleware = require('http-proxy-middleware'); -const next = require('next'); -const envVars = require('/tmp/hyperglass.env.json'); -const { configFile } = envVars; -const config = require(String(configFile)); - -const { NODE_ENV: env, _HYPERGLASS_URL_: envUrl } = config; - -const devProxy = { - '/api/query/': { target: envUrl + 'api/query/', pathRewrite: { '^/api/query/': '' } }, - '/images': { target: envUrl + 'images', pathRewrite: { '^/images': '' } }, - '/custom': { target: envUrl + 'custom', pathRewrite: { '^/custom': '' } }, -}; - -const port = parseInt(process.env.PORT, 10) || 3000; -const dev = env !== 'production'; -const app = next({ - dir: '.', // base directory where everything is, could move to src later - dev, -}); - -const handle = app.getRequestHandler(); - -let server; -app - .prepare() - .then(() => { - server = express(); - - // Set up the proxy. - if (dev && devProxy) { - Object.keys(devProxy).forEach(function (context) { - server.use(proxyMiddleware(context, devProxy[context])); - }); - } - - // Default catch-all handler to allow Next.js to handle all other routes - server.all('*', (req, res) => handle(req, res)); - - server.listen(port, err => { - if (err) { - throw err; - } - console.log(`> Ready on port ${port} [${env}]`); - }); - }) - .catch(err => { - console.log('An error occurred, unable to start the server'); - console.log(err); - }); diff --git a/hyperglass/ui/package.json b/hyperglass/ui/package.json deleted file mode 100644 index a53d6a6..0000000 --- a/hyperglass/ui/package.json +++ /dev/null @@ -1,82 +0,0 @@ -{ - "name": "ui", - "version": "1.0.0", - "description": "UI for hyperglass, the modern network looking glass", - "author": "Matt Love", - "license": "BSD-3-Clause-Clear", - "private": true, - "scripts": { - "lint": "eslint . --ext .ts --ext .tsx", - "dev": "node nextdev", - "start": "next start", - "typecheck": "tsc --noEmit", - "format": "prettier -c .", - "clean": "rimraf --no-glob ./.next ./out", - "check:es:export": "es-check es5 './out/**/*.js' -v", - "check:es:build": "es-check es5 './.next/static/**/*.js' -v", - "build": "next build && next export -o ../hyperglass/static/ui" - }, - "browserslist": "> 0.25%, not dead", - "dependencies": { - "@chakra-ui/react": "^1.6.3", - "@emotion/react": "^11.4.0", - "@emotion/styled": "^11.3.0", - "@hookform/devtools": "^3.1.0", - "@hookform/resolvers": "^2.5.1", - "@hookstate/core": "^3.0.7", - "@hookstate/persistence": "^3.0.0", - "@meronex/icons": "^4.0.0", - "dagre": "^0.8.5", - "dayjs": "^1.10.4", - "framer-motion": "^4.1.17", - "lodash": "^4.17.21", - "next": "^10.2.3", - "palette-by-numbers": "^0.1.5", - "react": "^17.0.2", - "react-countdown": "^2.2.1", - "react-device-detect": "^1.15.0", - "react-dom": "^17.0.2", - "react-fast-compare": "^3.2.0", - "react-flow-renderer": "^9.6.0", - "react-ga": "^3.3.0", - "react-hook-form": "^7.7.0", - "react-markdown": "^5.0.3", - "react-query": "^3.16.0", - "react-select": "^4.3.1", - "react-table": "^7.7.0", - "remark-gfm": "^1.0.0", - "string-format": "^2.0.0", - "vest": "^3.2.3" - }, - "devDependencies": { - "@hookstate/devtools": "^3.0.0", - "@types/dagre": "^0.7.44", - "@types/node": "^14.14.41", - "@types/react": "^17.0.3", - "@types/react-select": "^4.0.15", - "@types/react-table": "^7.7.1", - "@types/string-format": "^2.0.0", - "@typescript-eslint/eslint-plugin": "^4.11.1", - "@typescript-eslint/parser": "^4.11.1", - "@upstatement/eslint-config": "^0.4.3", - "@upstatement/prettier-config": "^0.3.0", - "babel-eslint": "^10.1.0", - "eslint": "^6.8.0", - "eslint-config-prettier": "^7.1.0", - "eslint-config-react-app": "^5.2.0", - "eslint-import-resolver-typescript": "^2.3.0", - "eslint-plugin-import": "^2.22.1", - "eslint-plugin-jest": "^24.1.3", - "eslint-plugin-json": "^2.1.2", - "eslint-plugin-jsx-a11y": "^6.2.3", - "eslint-plugin-prettier": "^3.3.0", - "eslint-plugin-react": "^7.22.0", - "eslint-plugin-react-hooks": "^4.2.0", - "express": "^4.17.1", - "http-proxy-middleware": "0.20.0", - "onchange": "^7.1.0", - "prettier": "^2.2.1", - "prettier-eslint": "^12.0.0", - "typescript": "^4.3.2" - } -} diff --git a/hyperglass/ui/pages/_app.tsx b/hyperglass/ui/pages/_app.tsx deleted file mode 100644 index 1377a83..0000000 --- a/hyperglass/ui/pages/_app.tsx +++ /dev/null @@ -1,59 +0,0 @@ -import { useEffect } from 'react'; -import Head from 'next/head'; -import { HyperglassProvider } from '~/context'; -import { useGoogleAnalytics } from '~/hooks'; -import { IConfig } from '~/types'; - -import type { AppProps, AppInitialProps, AppContext } from 'next/app'; - -if (process.env.NODE_ENV === 'development') { - require('@hookstate/devtools'); -} - -type TApp = { config: IConfig }; - -type GetInitialPropsReturn = AppProps & AppInitialProps & { appProps: IP }; - -type NextApp = React.FC> & { - getInitialProps(c?: AppContext): Promise<{ appProps: IP }>; -}; - -const App: NextApp = (props: GetInitialPropsReturn) => { - const { Component, pageProps, appProps, router } = props; - const { config } = appProps; - const { initialize, trackPage } = useGoogleAnalytics(); - - initialize(config.google_analytics, config.developer_mode); - - useEffect(() => { - router.events.on('routeChangeComplete', trackPage); - }, []); - - return ( - <> - - hyperglass - - - - - - - - - - - - - ); -}; - -App.getInitialProps = async function getInitialProps() { - const config = (process.env._HYPERGLASS_CONFIG_ as unknown) as IConfig; - return { appProps: { config } }; -}; - -export default App; diff --git a/hyperglass/ui/pages/_document.tsx b/hyperglass/ui/pages/_document.tsx deleted file mode 100644 index f54a823..0000000 --- a/hyperglass/ui/pages/_document.tsx +++ /dev/null @@ -1,28 +0,0 @@ -import Document, { Html, Head, Main, NextScript } from 'next/document'; -import type { DocumentContext, DocumentInitialProps } from 'next/document'; - -class MyDocument extends Document { - static async getInitialProps(ctx: DocumentContext): Promise { - const initialProps = await Document.getInitialProps(ctx); - return { ...initialProps }; - } - - render(): JSX.Element { - return ( - - - - - - - - -
- - - - ); - } -} - -export default MyDocument; diff --git a/hyperglass/ui/pages/index.tsx b/hyperglass/ui/pages/index.tsx deleted file mode 100644 index bbe4adc..0000000 --- a/hyperglass/ui/pages/index.tsx +++ /dev/null @@ -1,48 +0,0 @@ -import Head from 'next/head'; -import dynamic from 'next/dynamic'; -import { Meta, Loading } from '~/components'; - -import type { GetStaticProps } from 'next'; -import type { Favicon, FaviconComponent } from '~/types'; - -const Layout = dynamic(() => import('~/components').then(i => i.Layout), { - loading: Loading, -}); - -interface TIndex { - favicons: FaviconComponent[]; -} - -const Index: React.FC = (props: TIndex) => { - const { favicons } = props; - return ( - <> - - {favicons.map((icon, idx) => { - const { rel, href, type } = icon; - return ; - })} - - - - - ); -}; - -export const getStaticProps: GetStaticProps = async () => { - const faviconConfig = (process.env._HYPERGLASS_FAVICONS_ as unknown) as Favicon[]; - const favicons = faviconConfig.map(icon => { - const { image_format, dimensions, prefix } = icon; - let { rel } = icon; - if (rel === null) { - rel = ''; - } - const src = `/images/favicons/${prefix}-${dimensions[0]}x${dimensions[1]}.${image_format}`; - return { rel, href: src, type: `image/${image_format}` }; - }); - return { - props: { favicons }, - }; -}; - -export default Index; diff --git a/hyperglass/ui/public/robots.txt b/hyperglass/ui/public/robots.txt deleted file mode 100644 index 3f49e23..0000000 --- a/hyperglass/ui/public/robots.txt +++ /dev/null @@ -1,2 +0,0 @@ -User-agent: * -Disallow: /*__* \ No newline at end of file diff --git a/hyperglass/ui/tsconfig.json b/hyperglass/ui/tsconfig.json deleted file mode 100644 index 8d3a05c..0000000 --- a/hyperglass/ui/tsconfig.json +++ /dev/null @@ -1,42 +0,0 @@ -{ - "compilerOptions": { - "target": "ES5", - "module": "esnext", - "downlevelIteration": true, - "strict": true, - "baseUrl": "." /* Base directory to resolve non-absolute module names. */, - "paths": { - "~/components": ["components/index"], - "~/components/*": ["components/*"], - "~/context": ["context/index"], - "~/context/*": ["context/*"], - "~/hooks": ["hooks/index"], - "~/hooks/*": ["hooks/*"], - "~/state": ["state/index"], - "~/state/*": ["state/*"], - "~/types": ["types/index"], - "~/types/*": ["types/*"], - "~/util": ["util/index"], - "~/util/*": ["util/*"] - }, - "esModuleInterop": true, - "skipLibCheck": true, - "forceConsistentCasingInFileNames": true, - "lib": ["dom", "dom.iterable", "esnext"], - "allowJs": true, - "noEmit": true, - "moduleResolution": "node", - "resolveJsonModule": true, - "isolatedModules": true, - "jsx": "preserve" - }, - "exclude": ["node_modules", ".next"], - "include": [ - "next-env.d.ts", - "**/*.ts", - "**/*.tsx", - "types/globals.d.ts", - "next.config.js", - "nextdev.js" - ] -} diff --git a/hyperglass/ui/types/caida.ts b/hyperglass/ui/types/caida.ts deleted file mode 100644 index accd0a7..0000000 --- a/hyperglass/ui/types/caida.ts +++ /dev/null @@ -1,9 +0,0 @@ -export interface TASNQuery { - data: { - asn: { - organization: { - orgName: string; - } | null; - }; - }; -} diff --git a/hyperglass/ui/types/common.ts b/hyperglass/ui/types/common.ts deleted file mode 100644 index 5efd424..0000000 --- a/hyperglass/ui/types/common.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { State } from '@hookstate/core'; - -export type TSelectOptionBase = { - label: string; - value: string; - group?: string; -}; - -export type TSelectOption = TSelectOptionBase | null; - -export type TSelectOptionMulti = TSelectOptionBase[] | null; - -export type TSelectOptionState = State; - -export type TSelectOptionGroup = { - label: string; - options: TSelectOption[]; -}; - -export type OnChangeArgs = { field: string; value: string | string[] }; - -export type Families = [4] | [6] | [4, 6] | []; diff --git a/hyperglass/ui/types/config.ts b/hyperglass/ui/types/config.ts deleted file mode 100644 index 0e7d36d..0000000 --- a/hyperglass/ui/types/config.ts +++ /dev/null @@ -1,216 +0,0 @@ -import type { Theme } from './theme'; - -export type TQueryFields = 'query_type' | 'query_target' | 'query_location' | 'query_vrf'; - -type TSide = 'left' | 'right'; - -export interface IConfigMessages { - no_input: string; - acl_denied: string; - acl_not_allowed: string; - feature_not_enabled: string; - invalid_input: string; - invalid_field: string; - general: string; - request_timeout: string; - connection_error: string; - authentication_error: string; - no_response: string; - vrf_not_associated: string; - vrf_not_found: string; - no_output: string; - parsing_error: string; -} - -export interface IConfigTheme { - colors: { [k: string]: string }; - default_color_mode: 'light' | 'dark' | null; - fonts: Theme.Fonts; -} - -export interface IConfigWebText { - title_mode: string; - title: string; - subtitle: string; - query_location: string; - query_type: string; - query_target: string; - query_vrf: string; - fqdn_tooltip: string; - fqdn_message: string; - fqdn_error: string; - fqdn_error_button: string; - cache_prefix: string; - cache_icon: string; - complete_time: string; - rpki_invalid: string; - rpki_valid: string; - rpki_unknown: string; - rpki_unverified: string; - no_communities: string; -} - -export interface TConfigGreeting { - enable: boolean; - title: string; - button: string; - required: boolean; -} - -export interface TConfigWebLogo { - width: string; - height: string | null; - light_format: string; - dark_format: string; -} - -export interface TLink { - title: string; - url: string; - show_icon: boolean; - side: TSide; - order: number; -} - -export interface TMenu { - title: string; - content: string; - side: TSide; - order: number; -} - -export interface IConfigWeb { - credit: { enable: boolean }; - dns_provider: { name: string; url: string }; - links: TLink[]; - menus: TMenu[]; - greeting: TConfigGreeting; - help_menu: { enable: boolean; title: string }; - logo: TConfigWebLogo; - terms: { enable: boolean; title: string }; - text: IConfigWebText; - theme: IConfigTheme; -} - -export interface TQuery { - name: string; - enable: boolean; - display_name: string; -} - -export interface TBGPCommunity { - community: string; - display_name: string; - description: string; -} - -export interface IQueryBGPRoute extends TQuery {} -export interface IQueryBGPASPath extends TQuery {} -export interface IQueryPing extends TQuery {} -export interface IQueryTraceroute extends TQuery {} -export interface IQueryBGPCommunity extends TQuery { - mode: 'input' | 'select'; - communities: TBGPCommunity[]; -} - -export interface TConfigQueries { - bgp_route: IQueryBGPRoute; - bgp_community: IQueryBGPCommunity; - bgp_aspath: IQueryBGPASPath; - ping: IQueryPing; - traceroute: IQueryTraceroute; - list: TQuery[]; -} - -interface TDeviceVrfBase { - _id: string; - display_name: string; - default: boolean; -} - -export interface TDeviceVrf extends TDeviceVrfBase { - ipv4: boolean; - ipv6: boolean; -} - -interface TDeviceBase { - _id: string; - name: string; - network: string; -} - -export interface TDevice extends TDeviceBase { - vrfs: TDeviceVrf[]; -} - -export interface TNetworkLocation extends TDeviceBase { - vrfs: TDeviceVrf[]; -} - -export interface TNetwork { - display_name: string; - locations: TDevice[]; -} - -export type TParsedDataField = [string, keyof TRoute, 'left' | 'right' | 'center' | null]; - -export interface TQueryContent { - content: string; - enable: boolean; - params: { - primary_asn: IConfig['primary_asn']; - org_name: IConfig['org_name']; - site_title: IConfig['site_title']; - title: string; - [k: string]: string; - }; -} - -export interface IConfigContent { - credit: string; - greeting: string; - vrf: { - [k: string]: { - bgp_route: TQueryContent; - bgp_community: TQueryContent; - bgp_aspath: TQueryContent; - ping: TQueryContent; - traceroute: TQueryContent; - }; - }; -} - -export interface IConfig { - cache: { show_text: boolean; timeout: number }; - debug: boolean; - developer_mode: boolean; - primary_asn: string; - request_timeout: number; - org_name: string; - google_analytics: string | null; - site_title: string; - site_keywords: string[]; - site_description: string; - web: IConfigWeb; - messages: IConfigMessages; - hyperglass_version: string; - queries: TConfigQueries; - devices: TDevice[]; - networks: TNetwork[]; - vrfs: TDeviceVrfBase[]; - parsed_data_fields: TParsedDataField[]; - content: IConfigContent; -} - -export interface Favicon { - rel: string | null; - dimensions: [number, number]; - image_format: string; - prefix: string; -} - -export interface FaviconComponent { - rel: string; - href: string; - type: string; -} diff --git a/hyperglass/ui/types/data.ts b/hyperglass/ui/types/data.ts deleted file mode 100644 index 87adbcf..0000000 --- a/hyperglass/ui/types/data.ts +++ /dev/null @@ -1,28 +0,0 @@ -export type TQueryTypes = '' | TValidQueryTypes; -export type TValidQueryTypes = 'bgp_route' | 'bgp_community' | 'bgp_aspath' | 'ping' | 'traceroute'; - -export interface TFormData { - query_location: string[]; - query_type: TQueryTypes; - query_vrf: string; - query_target: string; -} - -export interface TFormState { - queryLocation: string[]; - queryType: TQueryTypes; - queryVrf: string; - queryTarget: string; -} - -export interface TFormQuery extends Omit { - queryLocation: string; -} - -export interface TStringTableData extends Omit { - output: TStructuredResponse; -} - -export interface TQueryResponseString extends Omit { - output: string; -} diff --git a/hyperglass/ui/types/dns-over-https.ts b/hyperglass/ui/types/dns-over-https.ts deleted file mode 100644 index 26719af..0000000 --- a/hyperglass/ui/types/dns-over-https.ts +++ /dev/null @@ -1,204 +0,0 @@ -/** - * DNS Over HTTPS Types, primarily adapted from: - * - * @see https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml - * @see https://developers.cloudflare.com/1.1.1.1/dns-over-https/json-format - * @see https://developers.google.com/speed/public-dns/docs/doh/json - */ -export namespace DnsOverHttps { - /** - * DNS RCODEs - * @see https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-6 - */ - export enum Status { - /** - * No Error - */ - NO_ERROR = 0, - /** - * Format Error - */ - FORM_ERR = 1, - /** - * Server Failure - */ - SERV_FAIL = 2, - /** - * Non-Existent Domain - */ - NX_DOMAIN = 3, - /** - * Not Implemented - */ - NOT_IMP = 4, - /** - * Query Refused - */ - REFUSED = 5, - /** - * Name Exists when it should not - */ - YX_DOMAIN = 6, - /** - * RR Set Exists when it should not - */ - YXRR_SET = 7, - /** - * RR Set that should exist does not - */ - NXRR_SET = 8, - /** - * Server Not Authoritative for zone - */ - NOT_AUTH = 9, - /** - * Name not contained in zone - */ - NOT_ZONE = 10, - /** - * DSO-TYPE Not Implemented - */ - DSO_TYPE_NI = 11, - /** - * TSIG Signature Failure - */ - BADSIG = 16, - /** - * Key not recognized - */ - BADKEY = 17, - /** - * Signature out of time window - */ - BADTIME = 18, - /** - * Bad TKEY Mode - */ - BADMODE = 19, - /** - * Duplicate key name - */ - BADNAME = 20, - /** - * Algorithm not supported - */ - BADALG = 21, - /** - * Bad Truncation - */ - BADTRUNC = 22, - /** - * Bad/missing Server Cookie - */ - BADCOOKIE = 23, - } - /** - * Resource Record (RR) Types - * @see https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-4 - */ - export enum Type { - /** - * IPv4 Host Address Record. - */ - A = 1, - /** - * Name Server Record. - */ - NS = 2, - /** - * Canonical Alias Name Record. - */ - CNAME = 5, - /** - * Start of Zone Authority Record. - */ - SOA = 6, - /** - * Well Know Service Description Record. - */ - WKS = 11, - /** - * Domain Name Pointer Record. - */ - PTR = 12, - /** - * Mail Exchange Record. - */ - MX = 15, - /** - * IPv6 Host Address Record. - */ - AAAA = 28, - /** - * Server Selection Record. - */ - SRV = 33, - /** - * DNAME Record. - */ - DNAME = 39, - /** - * DNSKEY Record. - */ - DNSKEY = 48, - } - export interface Question { - /** - * FQDN with trailing dot. - */ - name: string; - /** - * DNS RR Type. - */ - type: Type; - } - export interface Answer { - /** - * FQDN with trailing dot. - */ - name: string; - /** - * DNS RR Type. - */ - type: Type; - /** - * Time to live in seconds. - */ - TTL: number; - /** - * Response data. - */ - data: string; - } - export interface Response { - Status: Status; - /** - * Truncated bit was set. - */ - TC: boolean; - /** - * Recursive Desired bit was set. - */ - RD: boolean; - /** - * Recursion Available bit was set. - */ - RA: boolean; - /** - * If true, it means that every record in the answer was verified with DNSSEC. - */ - AD: boolean; - /** - * If true, the client asked to disable DNSSEC validation. - */ - CD: boolean; - /** - * Queried Resources. - */ - Question: Question[]; - /** - * Response Data. - */ - Answer: Answer[]; - } -} diff --git a/hyperglass/ui/types/globals.d.ts b/hyperglass/ui/types/globals.d.ts deleted file mode 100644 index fd8d66c..0000000 --- a/hyperglass/ui/types/globals.d.ts +++ /dev/null @@ -1,66 +0,0 @@ -import type { MotionProps } from 'framer-motion'; - -declare global { - type Dict = Record; - type ValueOf = T[keyof T]; - - type TRPKIStates = 0 | 1 | 2 | 3; - - type TResponseLevel = 'success' | 'warning' | 'error' | 'danger'; - - interface IRoute { - prefix: string; - active: boolean; - age: number; - weight: number; - med: number; - local_preference: number; - as_path: number[]; - communities: string[]; - next_hop: string; - source_as: number; - source_rid: string; - peer_rid: string; - rpki_state: TRPKIStates; - } - - type TRoute = { - prefix: string; - active: boolean; - age: number; - weight: number; - med: number; - local_preference: number; - as_path: number[]; - communities: string[]; - next_hop: string; - source_as: number; - source_rid: string; - peer_rid: string; - rpki_state: TRPKIStates; - }; - type TRouteField = { [k in keyof TRoute]: ValueOf }; - - type TStructuredResponse = { - vrf: string; - count: number; - routes: TRoute[]; - winning_weight: 'high' | 'low'; - }; - type TQueryResponse = { - random: string; - cached: boolean; - runtime: number; - level: TResponseLevel; - timestamp: string; - keywords: string[]; - output: string | TStructuredResponse; - format: 'text/plain' | 'application/json'; - }; - type ReactRef = MutableRefObject; - - type Animated = Omit & - Omit & { transition?: MotionProps['transition'] }; - - type MeronexIcon = import('@meronex/icons').IconBaseProps; -} diff --git a/hyperglass/ui/types/guards.ts b/hyperglass/ui/types/guards.ts deleted file mode 100644 index f6439b5..0000000 --- a/hyperglass/ui/types/guards.ts +++ /dev/null @@ -1,66 +0,0 @@ -/* eslint @typescript-eslint/explicit-module-boundary-types: off */ -/* eslint @typescript-eslint/no-explicit-any: off */ -import type { State } from '@hookstate/core'; -import type { TFormData, TValidQueryTypes, TStringTableData, TQueryResponseString } from './data'; -import type { TSelectOption } from './common'; -import type { TQueryContent } from './config'; - -export function isQueryType(q: unknown): q is TValidQueryTypes { - let result = false; - if ( - typeof q === 'string' && - ['bgp_route', 'bgp_community', 'bgp_aspath', 'ping', 'traceroute'].includes(q) - ) { - result = true; - } - return result; -} - -export function isString(a: unknown): a is string { - return typeof a === 'string'; -} - -export function isStructuredOutput(data: any): data is TStringTableData { - return typeof data !== 'undefined' && 'output' in data && typeof data.output !== 'string'; -} - -export function isStringOutput(data: any): data is TQueryResponseString { - return typeof data !== 'undefined' && 'output' in data && typeof data.output === 'string'; -} - -export function isQueryContent(c: any): c is TQueryContent { - return typeof c !== 'undefined' && c !== null && 'content' in c; -} - -/** - * Determine if an object is a Select option. - */ -export function isSelectOption(a: any): a is NonNullable { - return typeof a !== 'undefined' && a !== null && 'label' in a && 'value' in a; -} - -/** - * Determine if an object is a HookState Proxy. - */ -export function isState(a: any): a is State> { - let result = false; - if (typeof a !== 'undefined' && a !== null) { - if ( - 'get' in a && - typeof a.get === 'function' && - 'set' in a && - typeof a.set === 'function' && - 'promised' in a - ) { - result = true; - } - } - return result; -} - -/** - * Determine if a form field name is a valid form key name. - */ -export function isQueryField(field: string): field is keyof TFormData { - return ['query_location', 'query_type', 'query_vrf', 'query_target'].includes(field); -} diff --git a/hyperglass/ui/types/index.ts b/hyperglass/ui/types/index.ts deleted file mode 100644 index 637512e..0000000 --- a/hyperglass/ui/types/index.ts +++ /dev/null @@ -1,9 +0,0 @@ -export * from './caida'; -export * from './common'; -export * from './config'; -export * from './data'; -export * from './dns-over-https'; -export * from './guards'; -export * from './table'; -export * from './theme'; -export * from './util'; diff --git a/hyperglass/ui/types/react-table-config.d.ts b/hyperglass/ui/types/react-table-config.d.ts deleted file mode 100644 index 57a0a3e..0000000 --- a/hyperglass/ui/types/react-table-config.d.ts +++ /dev/null @@ -1,122 +0,0 @@ -/* eslint-disable */ - -import type { - TableInstance, - UseSortByHooks, - UseSortByState, - UseFiltersState, - UseGroupByHooks, - UseGroupByState, - UseExpandedHooks, - UseExpandedState, - UseSortByOptions, - UseFiltersOptions, - UseGroupByOptions, - UseRowSelectHooks, - UseRowSelectState, - UseExpandedOptions, - UseGroupByRowProps, - UsePaginationState, - UseColumnOrderState, - UseExpandedRowProps, - UseGroupByCellProps, - UseRowSelectOptions, - UsePaginationOptions, - UseRowSelectRowProps, - UseSortByColumnProps, - UseFiltersColumnProps, - UseGlobalFiltersState, - UseGroupByColumnProps, - UseResizeColumnsState, - UseSortByColumnOptions, - UseSortByInstanceProps, - UseFiltersColumnOptions, - UseFiltersInstanceProps, - UseGlobalFiltersOptions, - UseGroupByColumnOptions, - UseGroupByInstanceProps, - UseResizeColumnsOptions, - UseExpandedInstanceProps, - UseRowSelectInstanceProps, - UsePaginationInstanceProps, - UseColumnOrderInstanceProps, - UseResizeColumnsColumnProps, - UseGlobalFiltersInstanceProps, - UseResizeColumnsColumnOptions, -} from 'react-table'; - -declare module 'react-table' { - export interface UseFlexLayoutInstanceProps { - totalColumnsMinWidth: number; - } - - export interface UseFlexLayoutColumnProps { - totalMinWidth: number; - } - - export interface TableOptions - extends UseExpandedOptions, - UseFiltersOptions, - UseFiltersOptions, - UseGlobalFiltersOptions, - UseGroupByOptions, - UsePaginationOptions, - UseResizeColumnsOptions, - UseRowSelectOptions, - UseSortByOptions {} - - export interface Hooks - extends UseExpandedHooks, - UseGroupByHooks, - UseRowSelectHooks, - UseSortByHooks {} - - export interface TableInstance - extends UseColumnOrderInstanceProps, - UseExpandedInstanceProps, - UseFiltersInstanceProps, - UseGlobalFiltersInstanceProps, - UseGroupByInstanceProps, - UsePaginationInstanceProps, - UseRowSelectInstanceProps, - UseFlexLayoutInstanceProps, - UsePaginationInstanceProps, - UseSortByInstanceProps {} - - export interface TableState - extends UseColumnOrderState, - UseExpandedState, - UseFiltersState, - UseGlobalFiltersState, - UseGroupByState, - UsePaginationState, - UseResizeColumnsState, - UseRowSelectState, - UseSortByState { - rowCount: number; - } - - export interface ColumnInterface - extends UseFiltersColumnOptions, - UseGroupByColumnOptions, - UseResizeColumnsColumnOptions, - UseSortByColumnOptions { - align?: 'left' | 'right' | 'center'; - } - - export interface ColumnInstance - extends UseFiltersColumnProps, - UseGroupByColumnProps, - UseResizeColumnsColumnProps, - UseFlexLayoutColumnProps, - UseSortByColumnProps {} - - export interface Cell extends UseGroupByCellProps {} - - export interface Row - extends UseExpandedRowProps, - UseGroupByRowProps, - UseRowSelectRowProps {} -} - -export type TableMouseEventHandler = (instance: TableInstance) => React.MouseEventHandler; diff --git a/hyperglass/ui/types/table.ts b/hyperglass/ui/types/table.ts deleted file mode 100644 index ff73652..0000000 --- a/hyperglass/ui/types/table.ts +++ /dev/null @@ -1,14 +0,0 @@ -import type { CellProps } from 'react-table'; - -export interface TColumn { - Header: string; - accessor: keyof TRoute; - align: string; - hidden: boolean; -} - -export type TCellRender = { - column: CellProps['column']; - row: CellProps['row']; - value: CellProps['value']; -}; diff --git a/hyperglass/ui/types/theme.ts b/hyperglass/ui/types/theme.ts deleted file mode 100644 index a82317b..0000000 --- a/hyperglass/ui/types/theme.ts +++ /dev/null @@ -1,18 +0,0 @@ -import type { ChakraTheme } from '@chakra-ui/theme'; - -export namespace Theme { - export type Colors = ChakraTheme['colors']; - - export type ColorNames = keyof Colors; - - export type Fonts = { - body: string; - mono: string; - }; - - export type FontWeights = Partial; - - export interface Full extends Omit { - colors: Colors; - } -} diff --git a/hyperglass/ui/types/util.ts b/hyperglass/ui/types/util.ts deleted file mode 100644 index 0d909cc..0000000 --- a/hyperglass/ui/types/util.ts +++ /dev/null @@ -1,4 +0,0 @@ -export interface PathPart { - base: number; - children: PathPart[]; -} diff --git a/hyperglass/ui/util/common.ts b/hyperglass/ui/util/common.ts deleted file mode 100644 index 6d2fd2d..0000000 --- a/hyperglass/ui/util/common.ts +++ /dev/null @@ -1,101 +0,0 @@ -export function all(...iter: I[]): boolean { - for (const i of iter) { - if (!i) { - return false; - } - } - return true; -} - -export function chunkArray(array: A[], size: number): A[][] { - const result = [] as A[][]; - for (let i = 0; i < array.length; i += size) { - const chunk = array.slice(i, i + size); - result.push(chunk); - } - return result; -} - -type PathPart = { - base: number; - children: PathPart[]; -}; - -/** - * Arrange an array of arrays into a tree of nodes. - * - * Blatantly stolen from: - * @see https://gist.github.com/stephanbogner/4b590f992ead470658a5ebf09167b03d - */ -export function arrangeIntoTree

(paths: P[][]): PathPart[] { - const tree = [] as PathPart[]; - - for (let i = 0; i < paths.length; i++) { - const path = paths[i]; - let currentLevel = tree; - - for (let j = 0; j < path.length; j++) { - const part = path[j]; - - const existingPath = findWhere(currentLevel, 'base', part); - - if (existingPath !== false) { - currentLevel = existingPath.children; - } else { - const newPart = { - base: part, - children: [], - } as PathPart; - - currentLevel.push(newPart); - currentLevel = newPart.children; - } - } - } - return tree; - - function findWhere, V extends unknown>( - array: A[], - idx: string, - value: V, - ): A | false { - let t = 0; - - while (t < array.length && array[t][idx] !== value) { - t++; - } - - if (t < array.length) { - return array[t]; - } else { - return false; - } - } -} - -/** - * Fetch Wrapper that incorporates a timeout via a passed AbortController instance. - * - * Adapted from: https://lowmess.com/blog/fetch-with-timeout - */ -export async function fetchWithTimeout( - uri: string, - options: RequestInit = {}, - timeout: number, - controller: AbortController, -): Promise { - /** - * Lets set up our `AbortController`, and create a request options object that includes the - * controller's `signal` to pass to `fetch`. - */ - const { signal = new AbortController().signal, ...allOptions } = options; - const config = { ...allOptions, signal }; - /** - * Set a timeout limit for the request using `setTimeout`. If the body of this timeout is - * reached before the request is completed, it will be cancelled. - */ - setTimeout(() => { - controller.abort(); - }, timeout); - return await fetch(uri, config); -} diff --git a/hyperglass/ui/util/index.ts b/hyperglass/ui/util/index.ts deleted file mode 100644 index 6d81607..0000000 --- a/hyperglass/ui/util/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './common'; -export * from './theme'; diff --git a/hyperglass/ui/util/theme.ts b/hyperglass/ui/util/theme.ts deleted file mode 100644 index 844a7e2..0000000 --- a/hyperglass/ui/util/theme.ts +++ /dev/null @@ -1,115 +0,0 @@ -import { extendTheme } from '@chakra-ui/react'; -import { mode } from '@chakra-ui/theme-tools'; -import { generateFontFamily, generatePalette } from 'palette-by-numbers'; - -import type { ChakraTheme } from '@chakra-ui/react'; -import type { IConfigTheme, Theme } from '~/types'; - -function importFonts(userFonts: Theme.Fonts): ChakraTheme['fonts'] { - const { body: userBody, mono: userMono } = userFonts; - - return { - body: generateFontFamily('sans-serif', userBody), - heading: generateFontFamily('sans-serif', userBody), - mono: generateFontFamily('monospace', userMono), - }; -} - -function importColors(userColors: IConfigTheme['colors']): Theme.Colors { - const generatedColors = {} as Theme.Colors; - for (const [k, v] of Object.entries(userColors)) { - generatedColors[k] = generatePalette(v); - } - - generatedColors.blackSolid = { - 50: '#444444', - 100: '#3c3c3c', - 200: '#353535', - 300: '#2d2d2d', - 400: '#262626', - 500: '#1e1e1e', - 600: '#171717', - 700: '#0f0f0f', - 800: '#080808', - 900: '#000000', - }; - generatedColors.whiteSolid = { - 50: '#ffffff', - 100: '#f7f7f7', - 200: '#f0f0f0', - 300: '#e8e8e8', - 400: '#e1e1e1', - 500: '#d9d9d9', - 600: '#d2d2d2', - 700: '#cacaca', - 800: '#c3c3c3', - 900: '#bbbbbb', - }; - - return { - ...generatedColors, - transparent: 'transparent', - current: 'currentColor', - }; -} - -export function makeTheme( - userTheme: IConfigTheme, - defaultColorMode: 'dark' | 'light' | null, -): Theme.Full { - const fonts = importFonts(userTheme.fonts); - const { white, black, ...otherColors } = userTheme.colors; - const colors = importColors(otherColors); - const config = {} as Theme.Full['config']; - const fontWeights = { - hairline: 300, - thin: 300, - light: 300, - normal: 400, - medium: 400, - semibold: 700, - bold: 700, - extrabold: 700, - black: 700, - } as ChakraTheme['fontWeights']; - - switch (defaultColorMode) { - case null: - config.useSystemColorMode = true; - break; - case 'light': - config.initialColorMode = 'light'; - break; - case 'dark': - config.initialColorMode = 'dark'; - break; - } - - const defaultTheme = extendTheme({ - fonts, - colors, - config, - fontWeights, - styles: { - global: props => ({ - html: { scrollBehavior: 'smooth', height: '-webkit-fill-available' }, - body: { - background: mode('light.500', 'dark.500')(props), - color: mode('black', 'white')(props), - overflowX: 'hidden', - }, - }), - }, - }); - - return defaultTheme; -} - -export function googleFontUrl(fontFamily: string, weights: number[] = [300, 400, 700]): string { - const urlWeights = weights.join(','); - const fontName = fontFamily.split(/, /)[0].trim().replace(/'|"/g, ''); - const urlFont = fontName.split(/ /).join('+'); - return `https://fonts.googleapis.com/css?family=${urlFont}:${urlWeights}&display=swap`; -} - -export { theme as defaultTheme } from '@chakra-ui/react'; diff --git a/hyperglass/ui/yarn.lock b/hyperglass/ui/yarn.lock deleted file mode 100644 index a6768dd..0000000 --- a/hyperglass/ui/yarn.lock +++ /dev/null @@ -1,6532 +0,0 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. -# yarn lockfile v1 - - -"@babel/code-frame@7.12.11": - version "7.12.11" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.12.11.tgz#f4ad435aa263db935b8f10f2c552d23fb716a63f" - integrity sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw== - dependencies: - "@babel/highlight" "^7.10.4" - -"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.10.4.tgz#168da1a36e90da68ae8d49c0f1b48c7c6249213a" - integrity sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg== - dependencies: - "@babel/highlight" "^7.10.4" - -"@babel/generator@^7.12.1": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.12.1.tgz#0d70be32bdaa03d7c51c8597dda76e0df1f15468" - integrity sha512-DB+6rafIdc9o72Yc3/Ph5h+6hUjeOp66pF0naQBgUFFuPqzQwIlPTm3xZR7YNvduIMtkDIj2t21LSQwnbCrXvg== - dependencies: - "@babel/types" "^7.12.1" - jsesc "^2.5.1" - source-map "^0.5.0" - -"@babel/helper-function-name@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.10.4.tgz#d2d3b20c59ad8c47112fa7d2a94bc09d5ef82f1a" - integrity sha512-YdaSyz1n8gY44EmN7x44zBn9zQ1Ry2Y+3GTA+3vH6Mizke1Vw0aWDM66FOYEPw8//qKkmqOckrGgTYa+6sceqQ== - dependencies: - "@babel/helper-get-function-arity" "^7.10.4" - "@babel/template" "^7.10.4" - "@babel/types" "^7.10.4" - -"@babel/helper-get-function-arity@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.4.tgz#98c1cbea0e2332f33f9a4661b8ce1505b2c19ba2" - integrity sha512-EkN3YDB+SRDgiIUnNgcmiD361ti+AVbL3f3Henf6dqqUyr5dMsorno0lJWJuLhDhkI5sYEpgj6y9kB8AOU1I2A== - dependencies: - "@babel/types" "^7.10.4" - -"@babel/helper-module-imports@^7.12.13": - version "7.13.12" - resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.13.12.tgz#c6a369a6f3621cb25da014078684da9196b61977" - integrity sha512-4cVvR2/1B693IuOvSI20xqqa/+bl7lqAMR59R4iu39R9aOX8/JoYY1sFaNvUMyMBGnHdwvJgUrzNLoUZxXypxA== - dependencies: - "@babel/types" "^7.13.12" - -"@babel/helper-plugin-utils@^7.12.13": - version "7.13.0" - resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.13.0.tgz#806526ce125aed03373bc416a828321e3a6a33af" - integrity sha512-ZPafIPSwzUlAoWT8DKs1W2VyF2gOWthGd5NGFMsBcMMol+ZhK+EQY/e6V96poa6PA/Bh+C9plWN0hXO1uB8AfQ== - -"@babel/helper-split-export-declaration@^7.11.0": - version "7.11.0" - resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.11.0.tgz#f8a491244acf6a676158ac42072911ba83ad099f" - integrity sha512-74Vejvp6mHkGE+m+k5vHY93FX2cAtrw1zXrZXRlG4l410Nm9PxfEiVTn1PjDPV5SnmieiueY4AFg2xqhNFuuZg== - dependencies: - "@babel/types" "^7.11.0" - -"@babel/helper-validator-identifier@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz#a78c7a7251e01f616512d31b10adcf52ada5e0d2" - integrity sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw== - -"@babel/helper-validator-identifier@^7.12.11": - version "7.12.11" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz#c9a1f021917dcb5ccf0d4e453e399022981fc9ed" - integrity sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw== - -"@babel/highlight@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.10.4.tgz#7d1bdfd65753538fabe6c38596cdb76d9ac60143" - integrity sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA== - dependencies: - "@babel/helper-validator-identifier" "^7.10.4" - chalk "^2.0.0" - js-tokens "^4.0.0" - -"@babel/parser@^7.10.4", "@babel/parser@^7.12.1", "@babel/parser@^7.7.0": - version "7.12.3" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.12.3.tgz#a305415ebe7a6c7023b40b5122a0662d928334cd" - integrity sha512-kFsOS0IbsuhO5ojF8Hc8z/8vEIOkylVBrjiZUbLTE3XFe0Qi+uu6HjzQixkFaqr0ZPAMZcBVxEwmsnsLPZ2Xsw== - -"@babel/plugin-syntax-jsx@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.12.13.tgz#044fb81ebad6698fe62c478875575bcbb9b70f15" - integrity sha512-d4HM23Q1K7oq/SLNmG6mRt85l2csmQ0cHRaxRXjKW0YFdEXqlZ5kzFQKH5Uc3rDJECgu+yCRgPkG04Mm98R/1g== - dependencies: - "@babel/helper-plugin-utils" "^7.12.13" - -"@babel/runtime-corejs3@^7.10.2": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/runtime-corejs3/-/runtime-corejs3-7.12.1.tgz#51b9092befbeeed938335a109dbe0df51451e9dc" - integrity sha512-umhPIcMrlBZ2aTWlWjUseW9LjQKxi1dpFlQS8DzsxB//5K+u6GLTC/JliPKHsd5kJVPIU6X/Hy0YvWOYPcMxBw== - dependencies: - core-js-pure "^3.0.0" - regenerator-runtime "^0.13.4" - -"@babel/runtime@7.12.5", "@babel/runtime@^7.0.0": - version "7.12.5" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.12.5.tgz#410e7e487441e1b360c29be715d870d9b985882e" - integrity sha512-plcc+hbExy3McchJCEQG3knOsuh3HH+Prx1P6cLIkET/0dLuQDEnrT+s27Axgc9bqfsmNUNHfscgMUdBpC9xfg== - dependencies: - regenerator-runtime "^0.13.4" - -"@babel/runtime@^7.10.2", "@babel/runtime@^7.5.5", "@babel/runtime@^7.7.2", "@babel/runtime@^7.8.7": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.12.1.tgz#b4116a6b6711d010b2dad3b7b6e43bf1b9954740" - integrity sha512-J5AIf3vPj3UwXaAzb5j1xM4WAQDX3EMgemF8rjCP3SoW09LfRKAXQKt6CoVYl230P6iWdRcBbnLDDdnqWxZSCA== - dependencies: - regenerator-runtime "^0.13.4" - -"@babel/runtime@^7.12.0": - version "7.13.9" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.13.9.tgz#97dbe2116e2630c489f22e0656decd60aaa1fcee" - integrity sha512-aY2kU+xgJ3dJ1eU6FMB9EH8dIe8dmusF1xEku52joLvw6eAFN0AI+WxCLDnpev2LEejWBAy2sBvBOBAjI3zmvA== - dependencies: - regenerator-runtime "^0.13.4" - -"@babel/runtime@^7.12.1", "@babel/runtime@^7.12.5", "@babel/runtime@^7.13.10", "@babel/runtime@^7.9.2": - version "7.13.17" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.13.17.tgz#8966d1fc9593bf848602f0662d6b4d0069e3a7ec" - integrity sha512-NCdgJEelPTSh+FEFylhnP1ylq848l1z9t9N0j1Lfbcw0+KXGjsTvUmkxy+voLLXB5SOKMbLLx4jxYliGrYQseA== - dependencies: - regenerator-runtime "^0.13.4" - -"@babel/runtime@^7.14.0", "@babel/runtime@^7.6.2": - version "7.14.0" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.14.0.tgz#46794bc20b612c5f75e62dd071e24dfd95f1cbe6" - integrity sha512-JELkvo/DlpNdJ7dlyw/eY7E0suy5i5GQH+Vlxaq1nsNJ+H7f4Vtv3jMeCEgRhZZQFXTjldYfQgv2qmM6M1v5wA== - dependencies: - regenerator-runtime "^0.13.4" - -"@babel/template@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.10.4.tgz#3251996c4200ebc71d1a8fc405fba940f36ba278" - integrity sha512-ZCjD27cGJFUB6nmCB1Enki3r+L5kJveX9pq1SvAUKoICy6CZ9yD8xO086YXdYhvNjBdnekm4ZnaP5yC8Cs/1tA== - dependencies: - "@babel/code-frame" "^7.10.4" - "@babel/parser" "^7.10.4" - "@babel/types" "^7.10.4" - -"@babel/traverse@^7.7.0": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.12.1.tgz#941395e0c5cc86d5d3e75caa095d3924526f0c1e" - integrity sha512-MA3WPoRt1ZHo2ZmoGKNqi20YnPt0B1S0GTZEPhhd+hw2KGUzBlHuVunj6K4sNuK+reEvyiPwtp0cpaqLzJDmAw== - dependencies: - "@babel/code-frame" "^7.10.4" - "@babel/generator" "^7.12.1" - "@babel/helper-function-name" "^7.10.4" - "@babel/helper-split-export-declaration" "^7.11.0" - "@babel/parser" "^7.12.1" - "@babel/types" "^7.12.1" - debug "^4.1.0" - globals "^11.1.0" - lodash "^4.17.19" - -"@babel/types@7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.8.3.tgz#5a383dffa5416db1b73dedffd311ffd0788fb31c" - integrity sha512-jBD+G8+LWpMBBWvVcdr4QysjUE4mU/syrhN17o1u3gx0/WzJB1kwiVZAXRtWbsIPOwW8pF/YJV5+nmetPzepXg== - dependencies: - esutils "^2.0.2" - lodash "^4.17.13" - to-fast-properties "^2.0.0" - -"@babel/types@^7.10.4", "@babel/types@^7.11.0", "@babel/types@^7.12.1", "@babel/types@^7.7.0": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.12.1.tgz#e109d9ab99a8de735be287ee3d6a9947a190c4ae" - integrity sha512-BzSY3NJBKM4kyatSOWh3D/JJ2O3CVzBybHWxtgxnggaxEuaSTTDqeiSb/xk9lrkw2Tbqyivw5ZU4rT+EfznQsA== - dependencies: - "@babel/helper-validator-identifier" "^7.10.4" - lodash "^4.17.19" - to-fast-properties "^2.0.0" - -"@babel/types@^7.13.12": - version "7.13.17" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.13.17.tgz#48010a115c9fba7588b4437dd68c9469012b38b4" - integrity sha512-RawydLgxbOPDlTLJNtoIypwdmAy//uQIzlKt2+iBiJaRlVuI6QLUxVAyWGNfOzp8Yu4L4lLIacoCyTNtpb4wiA== - dependencies: - "@babel/helper-validator-identifier" "^7.12.11" - to-fast-properties "^2.0.0" - -"@blakeembrey/deque@^1.0.5": - version "1.0.5" - resolved "https://registry.yarnpkg.com/@blakeembrey/deque/-/deque-1.0.5.tgz#f4fa17fc5ee18317ec01a763d355782c7b395eaf" - integrity sha512-6xnwtvp9DY1EINIKdTfvfeAtCYw4OqBZJhtiqkT3ivjnEfa25VQ3TsKvaFfKm8MyGIEfE95qLe+bNEt3nB0Ylg== - -"@blakeembrey/template@^1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@blakeembrey/template/-/template-1.0.0.tgz#bf8828bc3ae8004d97904d78f64e3cc2cd216438" - integrity sha512-J6WGZqCLdRMHUkyRG6fBSIFJ0rL60/nsQNh5rQvsYZ5u0PsKw6XQcJcA3DWvd9cN3j/IQx5yB1fexhCafwwUUw== - -"@chakra-ui/accordion@1.3.2": - version "1.3.2" - resolved "https://registry.yarnpkg.com/@chakra-ui/accordion/-/accordion-1.3.2.tgz#7a397ad85ff33704b02b947d45c5297c5da1491e" - integrity sha512-YUgdWz1+ofeDXZIOZNTPYgCNM4KUv5bxYc5vzGzW8lJc6xQQ6pCyknUfL6aaVRVCuYYpVkE2yvaXynFnnQxpqg== - dependencies: - "@chakra-ui/descendant" "2.0.1" - "@chakra-ui/hooks" "1.5.2" - "@chakra-ui/icon" "1.1.9" - "@chakra-ui/react-utils" "1.1.2" - "@chakra-ui/transition" "1.3.1" - "@chakra-ui/utils" "1.8.0" - -"@chakra-ui/alert@1.2.5": - version "1.2.5" - resolved "https://registry.yarnpkg.com/@chakra-ui/alert/-/alert-1.2.5.tgz#d8ab0fdf75fa61625c368bd1979d2989a9fa1907" - integrity sha512-S+YaqaACteSOhGlBFygOeYsQC2FYO6m37g6M+N23kbUHKtT7I4gYsxczLuUwKJ65u4T2Bt1qNSVokjmKCMhE9w== - dependencies: - "@chakra-ui/icon" "1.1.9" - "@chakra-ui/react-utils" "1.1.2" - "@chakra-ui/utils" "1.8.0" - -"@chakra-ui/avatar@1.2.5": - version "1.2.5" - resolved "https://registry.yarnpkg.com/@chakra-ui/avatar/-/avatar-1.2.5.tgz#c11026a9e9e977d43e92212f0b27f43c52d42bd5" - integrity sha512-+BiCKZO/+oM7C5wYGKWttRQZTapVH6RSXxqhASgFBN1iz7H0mH1JtSSib7eBNKXZLM+RQcGrLPJBjQnc2TLVKA== - dependencies: - "@chakra-ui/image" "1.0.15" - "@chakra-ui/react-utils" "1.1.2" - "@chakra-ui/utils" "1.8.0" - -"@chakra-ui/breadcrumb@1.2.5": - version "1.2.5" - resolved "https://registry.yarnpkg.com/@chakra-ui/breadcrumb/-/breadcrumb-1.2.5.tgz#e8eac928df24b6ec06945b343f6a74551bf862f4" - integrity sha512-cD68feXlxyKkYqXbdWcc/Y78pLf8tFaHf6Vc5lTcgEYAxav5vq8TZqhzDwqMS84mOvuD6kd1wUbyBHff5h2Czw== - dependencies: - "@chakra-ui/react-utils" "1.1.2" - "@chakra-ui/utils" "1.8.0" - -"@chakra-ui/button@1.3.2": - version "1.3.2" - resolved "https://registry.yarnpkg.com/@chakra-ui/button/-/button-1.3.2.tgz#7a119ec94795d130375c1440d2dbcc9d768bcd50" - integrity sha512-ED23SD7smL9MdfkQE4CK+X6L7vRvhWwSsopuppqV8oQV+iktjY+lAMDIGlz9w7FPkNpv0q68yZ++qxPZRRv8xw== - dependencies: - "@chakra-ui/react-utils" "1.1.2" - "@chakra-ui/spinner" "1.1.9" - "@chakra-ui/utils" "1.8.0" - -"@chakra-ui/checkbox@1.5.2": - version "1.5.2" - resolved "https://registry.yarnpkg.com/@chakra-ui/checkbox/-/checkbox-1.5.2.tgz#a90240126d51ade0551de7f66c1f66bc6ed191cb" - integrity sha512-o1uuQOY87N6xKGGUB+2Bh6qREwYch2Jl6rIc+/zhVogEEfBJ5M2lCqmQNr+hepsD2Nw466/AjQM+dNuPHuWfhg== - dependencies: - "@chakra-ui/hooks" "1.5.2" - "@chakra-ui/react-utils" "1.1.2" - "@chakra-ui/utils" "1.8.0" - "@chakra-ui/visually-hidden" "1.0.12" - -"@chakra-ui/clickable@1.1.5": - version "1.1.5" - resolved "https://registry.yarnpkg.com/@chakra-ui/clickable/-/clickable-1.1.5.tgz#21c439aee65880a133c91413c08dcf17095890ab" - integrity sha512-nC6vLxh7cYrYyuMdrotiq+CUqG+KGND+RLeE3WiWyP0JDivX6t7S1EtRENnskKyWaLvjMDFsLU0wDAZm18vQNA== - dependencies: - "@chakra-ui/react-utils" "1.1.2" - "@chakra-ui/utils" "1.8.0" - -"@chakra-ui/close-button@1.1.9": - version "1.1.9" - resolved "https://registry.yarnpkg.com/@chakra-ui/close-button/-/close-button-1.1.9.tgz#f6f0aba2de0e15881e4ec20dd1ba2e7d6cac4630" - integrity sha512-Wj1nuNUw93AkswwQM+ifOi0guJddRavu4mJS4F15+Vv8d30BQo/O6NOGPFutJK4Fm48WA9QjqydCMb1n8umDxA== - dependencies: - "@chakra-ui/icon" "1.1.9" - "@chakra-ui/utils" "1.8.0" - -"@chakra-ui/color-mode@1.1.8": - version "1.1.8" - resolved "https://registry.yarnpkg.com/@chakra-ui/color-mode/-/color-mode-1.1.8.tgz#a5648c017868d22947827009e5ea4f0cd0d0ad87" - integrity sha512-hmSK02Eozu42g1yaQIXfJg+8Dag/YoeaQLS8Ygk6OEGEZrILMxLbFEBvzxaCJt5GCKOuVc/9aGsn31N7c4SNrA== - dependencies: - "@chakra-ui/hooks" "1.5.2" - "@chakra-ui/utils" "1.8.0" - -"@chakra-ui/control-box@1.0.12": - version "1.0.12" - resolved "https://registry.yarnpkg.com/@chakra-ui/control-box/-/control-box-1.0.12.tgz#2038d2f62d0640342930b19ee4b91b955cd4c575" - integrity sha512-CZCqrm0rMj72/9i5raaKgxdJm0uGdES+8p9TdVesfSXZnsNmOquDY9TsI5fYMhG16yRRoiQK/dmX/j2VcD7tvA== - dependencies: - "@chakra-ui/utils" "1.8.0" - -"@chakra-ui/counter@1.1.5": - version "1.1.5" - resolved "https://registry.yarnpkg.com/@chakra-ui/counter/-/counter-1.1.5.tgz#9355a231bb0929e22627cf3d51a9de0d782002bf" - integrity sha512-qKUaQgCXWutLpEYz0fuBOQz+tfk4Lt8EN+ePikgxN6LPoisw/1Nbo+HE7l1A9YQ06wUG0HBt7s8CcupT/LzRug== - dependencies: - "@chakra-ui/hooks" "1.5.2" - "@chakra-ui/utils" "1.8.0" - -"@chakra-ui/css-reset@1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@chakra-ui/css-reset/-/css-reset-1.0.0.tgz#8395921b35ef27bee0579a4d730c5ab7f7b39734" - integrity sha512-UaPsImGHvCgFO3ayp6Ugafu2/3/EG8wlW/8Y9Ihfk1UFv8cpV+3BfWKmuZ7IcmxcBL9dkP6E8p3/M1T0FB92hg== - -"@chakra-ui/descendant@2.0.1": - version "2.0.1" - resolved "https://registry.yarnpkg.com/@chakra-ui/descendant/-/descendant-2.0.1.tgz#fc3bc9081aa01503035b2c9296bc4b9f87ceaae0" - integrity sha512-TeYp94iOhu5Gs2oVzewJaep0qft/JKMKfmcf4PGgzJF+h6TWZm6NGohk6Jq7JOh+y0rExa1ulknIgnMzFx5xaA== - dependencies: - "@chakra-ui/react-utils" "^1.1.2" - -"@chakra-ui/editable@1.2.5": - version "1.2.5" - resolved "https://registry.yarnpkg.com/@chakra-ui/editable/-/editable-1.2.5.tgz#ec02ab8e2ec47612ef105476dfbf1bbdf8b62ea5" - integrity sha512-rSsBj/X2Ta0tTFm61TSgI2wsrhWydlEPROcDAcV8IB4UTOFyCf/fSKDMPN20qj0gLh6OV52d4JTSwgeLpFluRQ== - dependencies: - "@chakra-ui/hooks" "1.5.2" - "@chakra-ui/react-utils" "1.1.2" - "@chakra-ui/utils" "1.8.0" - -"@chakra-ui/focus-lock@1.1.8": - version "1.1.8" - resolved "https://registry.yarnpkg.com/@chakra-ui/focus-lock/-/focus-lock-1.1.8.tgz#30139cc8ccc68038e3c148a5f5e57eccfdfcb54e" - integrity sha512-y2aZGFv5O8vWL/oxt3FhhQSD6lQO5TEUdIFwaKFCh1qqHMoWrQMx0n7aGny1E8IMGvs2fKMKr1lIA3HovE/sCw== - dependencies: - "@chakra-ui/utils" "1.8.0" - react-focus-lock "2.5.0" - -"@chakra-ui/form-control@1.3.6": - version "1.3.6" - resolved "https://registry.yarnpkg.com/@chakra-ui/form-control/-/form-control-1.3.6.tgz#f2356551d3bbe7ff50f024d2169a08132467b2a7" - integrity sha512-C8tFadZP0Gb8LRKTZWyFbmeGxr5tR6aL0KqIJyGWaUw06I6O2mJTOTsFKTlAN59eRz7C8r4S440eLbhWIgiYLg== - dependencies: - "@chakra-ui/hooks" "1.5.2" - "@chakra-ui/icon" "1.1.9" - "@chakra-ui/react-utils" "1.1.2" - "@chakra-ui/utils" "1.8.0" - -"@chakra-ui/hooks@1.5.2": - version "1.5.2" - resolved "https://registry.yarnpkg.com/@chakra-ui/hooks/-/hooks-1.5.2.tgz#9bde3c698790a0c94286701cad6ec2ce09c1484c" - integrity sha512-8rpZbrB3yFgKAjEwzafJkYOckRNYDQ6sSt0IWOFsfwGSGB3RxX19tKiGMziqU/djzKEGU85QErsVYVC1v0tJ3A== - dependencies: - "@chakra-ui/react-utils" "1.1.2" - "@chakra-ui/utils" "1.8.0" - compute-scroll-into-view "1.0.14" - copy-to-clipboard "3.3.1" - -"@chakra-ui/icon@1.1.9": - version "1.1.9" - resolved "https://registry.yarnpkg.com/@chakra-ui/icon/-/icon-1.1.9.tgz#fbd6e82abf58b890f5bcc728bb75dda25d7b6c63" - integrity sha512-lmZHK4O+Wo7LwxRsQb0KmtOwq2iACESxwQgackuj7NPHbAsdF2/y3t2f7KCD+dTKGxoauEMgU2nVLePZWjtpTQ== - dependencies: - "@chakra-ui/utils" "1.8.0" - -"@chakra-ui/image@1.0.15": - version "1.0.15" - resolved "https://registry.yarnpkg.com/@chakra-ui/image/-/image-1.0.15.tgz#57aaf7e22d2793b9278481aab56b27063a922e5b" - integrity sha512-bOmPspVXpgL70qJ5t1qxlAr4gLj3r1yulM3CByqj510mIZHt8vkh5zFu+8mN184V9U8Zw8fwL6W0FFg+ftmYCg== - dependencies: - "@chakra-ui/hooks" "1.5.2" - "@chakra-ui/utils" "1.8.0" - -"@chakra-ui/input@1.2.6": - version "1.2.6" - resolved "https://registry.yarnpkg.com/@chakra-ui/input/-/input-1.2.6.tgz#a3ca1e21a1435f28e62c25859b980e2ab2e5d470" - integrity sha512-rN/FdojBP/eUCNXNHw/4feWj7dt36ggiUXGhe5g6oDcInA2s7zlDIua7XYiIz19n2PNK+dXWbGjuAJnLCcTIfA== - dependencies: - "@chakra-ui/form-control" "1.3.6" - "@chakra-ui/react-utils" "1.1.2" - "@chakra-ui/utils" "1.8.0" - -"@chakra-ui/layout@1.4.5": - version "1.4.5" - resolved "https://registry.yarnpkg.com/@chakra-ui/layout/-/layout-1.4.5.tgz#89e6164a752a07b735f0a7a02437ae38ecada154" - integrity sha512-+9NczG/9vtditXHZdHSzBvr2k8Sfb59C6PQT1GaDVhwi693tpYDWZEc3vcin4XJbyRS5HNm8L9nwx6A6un/g5g== - dependencies: - "@chakra-ui/icon" "1.1.9" - "@chakra-ui/react-utils" "1.1.2" - "@chakra-ui/utils" "1.8.0" - -"@chakra-ui/live-region@1.0.12": - version "1.0.12" - resolved "https://registry.yarnpkg.com/@chakra-ui/live-region/-/live-region-1.0.12.tgz#ff9806c27f955eab5492fa89f186a7fb09c78b4a" - integrity sha512-NgIZuCLAX7FCyLc7+7wxQ0WCmlFS+SHutHf2QXezU6NjkoUmiZ02yVoBHltGn9f0jBVkVBZ4LL1ng2ruwRsJog== - dependencies: - "@chakra-ui/utils" "1.8.0" - -"@chakra-ui/media-query@1.0.14": - version "1.0.14" - resolved "https://registry.yarnpkg.com/@chakra-ui/media-query/-/media-query-1.0.14.tgz#da9de9eef049b0c52c9ac2fb00ef2114dea14629" - integrity sha512-PGg1Q7ifUSzObRHMHErQOhIeKBsJq7NFbubBNfVZ8ySJlefk6sv5XNd2RxIbPN2vHq0gniUpSihgO8Hc5Yrx4g== - dependencies: - "@chakra-ui/react-env" "1.0.4" - "@chakra-ui/utils" "1.8.0" - -"@chakra-ui/menu@1.6.3": - version "1.6.3" - resolved "https://registry.yarnpkg.com/@chakra-ui/menu/-/menu-1.6.3.tgz#1b6e0e37c40d48d28853484bc7bd406140af3ed3" - integrity sha512-3dyfd6rERFKrf+15YOE/fCk8Yw122o3A6eCW7F9YZvRp/iNOZ/Fqih+oTJ7eGDTpgu07DGh9RneZIDAKpr+jiQ== - dependencies: - "@chakra-ui/clickable" "1.1.5" - "@chakra-ui/descendant" "2.0.1" - "@chakra-ui/hooks" "1.5.2" - "@chakra-ui/popper" "2.2.0" - "@chakra-ui/react-utils" "1.1.2" - "@chakra-ui/transition" "1.3.1" - "@chakra-ui/utils" "1.8.0" - -"@chakra-ui/modal@1.8.7": - version "1.8.7" - resolved "https://registry.yarnpkg.com/@chakra-ui/modal/-/modal-1.8.7.tgz#7d90a48b6fdddbcacab6f22f362ea2c7a8849e5b" - integrity sha512-F19R/xyIXsF22jXN9yBeHp8EoDOvoHXCKshH/nJz06KoYfTdtONnhZls7iYhddJyqKEdiQfZ9AOktWZTUOxyQA== - dependencies: - "@chakra-ui/close-button" "1.1.9" - "@chakra-ui/focus-lock" "1.1.8" - "@chakra-ui/hooks" "1.5.2" - "@chakra-ui/portal" "1.2.5" - "@chakra-ui/react-utils" "1.1.2" - "@chakra-ui/transition" "1.3.1" - "@chakra-ui/utils" "1.8.0" - aria-hidden "^1.1.1" - react-remove-scroll "2.4.1" - -"@chakra-ui/number-input@1.2.6": - version "1.2.6" - resolved "https://registry.yarnpkg.com/@chakra-ui/number-input/-/number-input-1.2.6.tgz#423650f2c7dc8c96ef2b87bc8a8f98b96b8d90ee" - integrity sha512-pE7WFQyXKs6GcqESBvh90PHTpn24Gk/58R/sSttWTrMLuLz01MdDxEWVHG2Quto9On6BWZUPn5Tp043RHBYu2A== - dependencies: - "@chakra-ui/counter" "1.1.5" - "@chakra-ui/form-control" "1.3.6" - "@chakra-ui/hooks" "1.5.2" - "@chakra-ui/icon" "1.1.9" - "@chakra-ui/react-utils" "1.1.2" - "@chakra-ui/utils" "1.8.0" - -"@chakra-ui/pin-input@1.6.1": - version "1.6.1" - resolved "https://registry.yarnpkg.com/@chakra-ui/pin-input/-/pin-input-1.6.1.tgz#c86f0559779e79b789268c113f3f950237e2cffd" - integrity sha512-phgnyrbaYysuvv401eozqdxk5aw5bnlZnw9hFIAkA3NqngBuvAMuZlM9WziBUQ6URX7lLtrvtbLPTYrOdMEm1g== - dependencies: - "@chakra-ui/descendant" "2.0.1" - "@chakra-ui/hooks" "1.5.2" - "@chakra-ui/react-utils" "1.1.2" - "@chakra-ui/utils" "1.8.0" - -"@chakra-ui/popover@1.7.1": - version "1.7.1" - resolved "https://registry.yarnpkg.com/@chakra-ui/popover/-/popover-1.7.1.tgz#4ffc4b088b691c2658ef7c830722a5112a306dd5" - integrity sha512-8hBjBu16jegGLC36ydpcwSg7WwRTkkWV0ThEb0yeNmUri1VaawC9lbXRm8/o0jQG7SZgvSVNl+q/dKt0uGekRQ== - dependencies: - "@chakra-ui/close-button" "1.1.9" - "@chakra-ui/hooks" "1.5.2" - "@chakra-ui/popper" "2.2.0" - "@chakra-ui/react-utils" "1.1.2" - "@chakra-ui/utils" "1.8.0" - -"@chakra-ui/popper@2.2.0": - version "2.2.0" - resolved "https://registry.yarnpkg.com/@chakra-ui/popper/-/popper-2.2.0.tgz#108ebf9e73ec7a157911bfcd325cc978c683838d" - integrity sha512-gCwl39QSTnVDmkxEoXCIJFYC0Nv88msNyuoAaCpxE91SDsJaa69guSWUoDr0eJaEpzIcXG85nxdeo2gnysMG8Q== - dependencies: - "@chakra-ui/react-utils" "1.1.2" - "@popperjs/core" "2.4.4" - -"@chakra-ui/portal@1.2.5": - version "1.2.5" - resolved "https://registry.yarnpkg.com/@chakra-ui/portal/-/portal-1.2.5.tgz#2d966acb1e51c2d6be4eb5dc8a8a0affffc99513" - integrity sha512-yF78YaQI5MISo5sBqCVc51RXFcf5LeY+0C4Yvy7MoKtuyIMVGI3SvFfsCjZoMSw55MNTtqMrI7u5kIQKP37rzA== - dependencies: - "@chakra-ui/hooks" "1.5.2" - "@chakra-ui/react-utils" "1.1.2" - "@chakra-ui/utils" "1.8.0" - -"@chakra-ui/progress@1.1.9": - version "1.1.9" - resolved "https://registry.yarnpkg.com/@chakra-ui/progress/-/progress-1.1.9.tgz#382d9cec6b45516525bb3a5f5d44b096ee50e66e" - integrity sha512-htnBK3pS7ZYv3vBP+qvFWsjfK1+lJgEuj7SzlLxZKk4jF0gtuZ60STCEn1j3JVZg7gWHDGTJcylipSTzqoXP/w== - dependencies: - "@chakra-ui/theme-tools" "1.1.7" - "@chakra-ui/utils" "1.8.0" - -"@chakra-ui/radio@1.3.6": - version "1.3.6" - resolved "https://registry.yarnpkg.com/@chakra-ui/radio/-/radio-1.3.6.tgz#6304cec2e978a076832ae84e6b90188012b3b5e8" - integrity sha512-WNSVoJva3QJpY5sJbVTqbM2tzk5az/gAM3k8hhjevS4DU8LG3tVRq8geMasxuifUHuLxpEt+Jmx4gZfKw0R+qQ== - dependencies: - "@chakra-ui/form-control" "1.3.6" - "@chakra-ui/hooks" "1.5.2" - "@chakra-ui/react-utils" "1.1.2" - "@chakra-ui/utils" "1.8.0" - "@chakra-ui/visually-hidden" "1.0.12" - -"@chakra-ui/react-env@1.0.4": - version "1.0.4" - resolved "https://registry.yarnpkg.com/@chakra-ui/react-env/-/react-env-1.0.4.tgz#b053d44d61b63dcf5997b24bdf2454bdcdb1b1ed" - integrity sha512-FkZR/WW7WI6LR3Wgm+OeuDhTNCcD77U/yWAxSo1tvEqqL5uUvD6Bi/Ko9E3lI5yhdoJ4t99ksf1vUBlrMG92vw== - dependencies: - "@chakra-ui/utils" "1.8.0" - -"@chakra-ui/react-utils@1.1.2", "@chakra-ui/react-utils@^1.1.2": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@chakra-ui/react-utils/-/react-utils-1.1.2.tgz#7ea80b6ae25bd7b182095cc9ffaad23c464408b5" - integrity sha512-S8jPVKGZH2qF7ZGxl/0DF/dXXI2AxDNGf4Ahi2LGHqajMvqBB7vtYIRRmIA7+jAnErhzO8WUi3i4Z7oScp6xSA== - dependencies: - "@chakra-ui/utils" "^1.7.0" - -"@chakra-ui/react@^1.6.3": - version "1.6.3" - resolved "https://registry.yarnpkg.com/@chakra-ui/react/-/react-1.6.3.tgz#33b6a81727a506c2724d70d04d3ad9da43cef32f" - integrity sha512-bYyxtctgIx9aGEm1AUlFI2kcubtOUwCRPLxBoALX0frb7QT7wJ+NlUa0UJyixJrtUpujpKKI6rfJQoWgxArzXQ== - dependencies: - "@chakra-ui/accordion" "1.3.2" - "@chakra-ui/alert" "1.2.5" - "@chakra-ui/avatar" "1.2.5" - "@chakra-ui/breadcrumb" "1.2.5" - "@chakra-ui/button" "1.3.2" - "@chakra-ui/checkbox" "1.5.2" - "@chakra-ui/close-button" "1.1.9" - "@chakra-ui/control-box" "1.0.12" - "@chakra-ui/counter" "1.1.5" - "@chakra-ui/css-reset" "1.0.0" - "@chakra-ui/editable" "1.2.5" - "@chakra-ui/form-control" "1.3.6" - "@chakra-ui/hooks" "1.5.2" - "@chakra-ui/icon" "1.1.9" - "@chakra-ui/image" "1.0.15" - "@chakra-ui/input" "1.2.6" - "@chakra-ui/layout" "1.4.5" - "@chakra-ui/live-region" "1.0.12" - "@chakra-ui/media-query" "1.0.14" - "@chakra-ui/menu" "1.6.3" - "@chakra-ui/modal" "1.8.7" - "@chakra-ui/number-input" "1.2.6" - "@chakra-ui/pin-input" "1.6.1" - "@chakra-ui/popover" "1.7.1" - "@chakra-ui/popper" "2.2.0" - "@chakra-ui/portal" "1.2.5" - "@chakra-ui/progress" "1.1.9" - "@chakra-ui/radio" "1.3.6" - "@chakra-ui/react-env" "1.0.4" - "@chakra-ui/select" "1.1.10" - "@chakra-ui/skeleton" "1.1.14" - "@chakra-ui/slider" "1.2.5" - "@chakra-ui/spinner" "1.1.9" - "@chakra-ui/stat" "1.1.9" - "@chakra-ui/switch" "1.2.5" - "@chakra-ui/system" "1.6.7" - "@chakra-ui/table" "1.2.4" - "@chakra-ui/tabs" "1.5.1" - "@chakra-ui/tag" "1.1.9" - "@chakra-ui/textarea" "1.1.10" - "@chakra-ui/theme" "1.9.0" - "@chakra-ui/toast" "1.2.7" - "@chakra-ui/tooltip" "1.3.6" - "@chakra-ui/transition" "1.3.1" - "@chakra-ui/utils" "1.8.0" - "@chakra-ui/visually-hidden" "1.0.12" - -"@chakra-ui/select@1.1.10": - version "1.1.10" - resolved "https://registry.yarnpkg.com/@chakra-ui/select/-/select-1.1.10.tgz#172cc3120a5c93e6e7a0b169285aaf840391af5f" - integrity sha512-P2FIQnLNGHeULsQInE1GldbvqUZlDy2TbtEEPnaoTLmL9BiK5nqkIwndAMGd1fAeNiJun/auVE9NsItdfozxpA== - dependencies: - "@chakra-ui/form-control" "1.3.6" - "@chakra-ui/utils" "1.8.0" - -"@chakra-ui/skeleton@1.1.14": - version "1.1.14" - resolved "https://registry.yarnpkg.com/@chakra-ui/skeleton/-/skeleton-1.1.14.tgz#00f2d0a8542e5a7f6d4eaf2f736839130e318b3a" - integrity sha512-s2wxBPe2F5C45CkLMWH1ZLhCwXdW+YuENbPRMmxgE28BZKnrMHi0NOGPCBiznpBN6IvylQKg3mEh6Zy4mfo6og== - dependencies: - "@chakra-ui/hooks" "1.5.2" - "@chakra-ui/media-query" "1.0.14" - "@chakra-ui/system" "1.6.7" - "@chakra-ui/utils" "1.8.0" - -"@chakra-ui/slider@1.2.5": - version "1.2.5" - resolved "https://registry.yarnpkg.com/@chakra-ui/slider/-/slider-1.2.5.tgz#99bc1946036d8620ec59f3eecea2482fe6b38313" - integrity sha512-DLNWuwQ2n+OENZk98U70rwg6ZQ9/23ZW4j79yOMrBm7+StlVEfEDVwA8pJigLmgvq0D8mmvZSxZY4aZ/bkaguw== - dependencies: - "@chakra-ui/hooks" "1.5.2" - "@chakra-ui/react-utils" "1.1.2" - "@chakra-ui/utils" "1.8.0" - -"@chakra-ui/spinner@1.1.9": - version "1.1.9" - resolved "https://registry.yarnpkg.com/@chakra-ui/spinner/-/spinner-1.1.9.tgz#c66d9e2b988d8a6067ae6a47e59ddf59614ad04f" - integrity sha512-G0EEEkFaPCElGjetPmR5Uup4t3reUxKUUPQIBA9ZZzdYESGmdQG7PTDgJpo/p42IpPQqHBIG1fL+7y2IapYu0w== - dependencies: - "@chakra-ui/utils" "1.8.0" - "@chakra-ui/visually-hidden" "1.0.12" - -"@chakra-ui/stat@1.1.9": - version "1.1.9" - resolved "https://registry.yarnpkg.com/@chakra-ui/stat/-/stat-1.1.9.tgz#650bdb6575627c42e8aabcb4d54fa3c045ebb332" - integrity sha512-F/wXCyFNxkNY8irAvhE6qlkni3pkoxqLANLTGrLijINkVP48wHykAurAorfg5KH+3jrJjRxC4RPruWhGFzE+Cw== - dependencies: - "@chakra-ui/icon" "1.1.9" - "@chakra-ui/utils" "1.8.0" - "@chakra-ui/visually-hidden" "1.0.12" - -"@chakra-ui/styled-system@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@chakra-ui/styled-system/-/styled-system-1.11.1.tgz#f9571752fcb41f3621f8e2bb69dbf6e81808178c" - integrity sha512-bVR2g8vmQHyjVsj1QccH+d7I+mi1Whd6qJk25Nz2bl2UKO7z8hsxmV9KK3ZGGTQsY7/Kjy6wAas0waElJVdHyw== - dependencies: - "@chakra-ui/utils" "1.8.0" - csstype "^3.0.6" - -"@chakra-ui/switch@1.2.5": - version "1.2.5" - resolved "https://registry.yarnpkg.com/@chakra-ui/switch/-/switch-1.2.5.tgz#90beab9d8af78417006982312027753b038805d1" - integrity sha512-JzAlrQ/F18TzhwVGebr3IS4DaWiEVZfQ5ARKaOYKdgDfxNk39L6seTOheQVCczjk6fF/0Gweso9ivTACXv2dKg== - dependencies: - "@chakra-ui/checkbox" "1.5.2" - "@chakra-ui/utils" "1.8.0" - -"@chakra-ui/system@1.6.7": - version "1.6.7" - resolved "https://registry.yarnpkg.com/@chakra-ui/system/-/system-1.6.7.tgz#aca7f18e8932a87d6f3c77d619360fd1e403423a" - integrity sha512-dEZzEzrEF2p/b/9b+v/RNoTWCBcbzCz5aTYC5ZkOfYQt/BQ9hT0b4KGuklfvHkqXSbvbwMoTAGmgTV99h8YLcQ== - dependencies: - "@chakra-ui/color-mode" "1.1.8" - "@chakra-ui/react-utils" "1.1.2" - "@chakra-ui/styled-system" "1.11.1" - "@chakra-ui/utils" "1.8.0" - react-fast-compare "3.2.0" - -"@chakra-ui/table@1.2.4": - version "1.2.4" - resolved "https://registry.yarnpkg.com/@chakra-ui/table/-/table-1.2.4.tgz#f2de9cea0fa0b37f9abb35222bf3ba5b7636bdb5" - integrity sha512-nB+kSy07d5v4WCsiUB86P0tfajL847VD3GDDauW+x0HlJRI0Q7UFOnJZGANM3VliA/LDci5PjIIDDAL3cW3ISg== - dependencies: - "@chakra-ui/utils" "1.8.0" - -"@chakra-ui/tabs@1.5.1": - version "1.5.1" - resolved "https://registry.yarnpkg.com/@chakra-ui/tabs/-/tabs-1.5.1.tgz#ab3a3d20cba422304a42c23f3b8b19679774f1d0" - integrity sha512-SHDEKvVkGSX1okx5qV8tTBA74wdBeQkX3UnQTEnKckrie9lG98i2kzd8SdXoKrq/+38duv0oer4Cc2erVhobyA== - dependencies: - "@chakra-ui/clickable" "1.1.5" - "@chakra-ui/descendant" "2.0.1" - "@chakra-ui/hooks" "1.5.2" - "@chakra-ui/react-utils" "1.1.2" - "@chakra-ui/utils" "1.8.0" - -"@chakra-ui/tag@1.1.9": - version "1.1.9" - resolved "https://registry.yarnpkg.com/@chakra-ui/tag/-/tag-1.1.9.tgz#65357d2645ead56760bf14cf463602e9188a6a53" - integrity sha512-njANMXFoBaOWW4pNUDwwcUk1ejJ4OcPesTmYOBGjbVDBrag22kiAN3bSn8DKplKBhE/nHyJuhR2v9ndfb0BpLg== - dependencies: - "@chakra-ui/icon" "1.1.9" - "@chakra-ui/utils" "1.8.0" - -"@chakra-ui/textarea@1.1.10": - version "1.1.10" - resolved "https://registry.yarnpkg.com/@chakra-ui/textarea/-/textarea-1.1.10.tgz#ecd889721fa5aff9353dbd76a6d4b9037ae981f1" - integrity sha512-f5OIXVacCXgiV3G27ym0mEdhn88bePZn+aBzyNsL+Fk7xF28JLWTqO5NaALzTEWO2XeQOOy3/Otcd72glp0U0A== - dependencies: - "@chakra-ui/form-control" "1.3.6" - "@chakra-ui/utils" "1.8.0" - -"@chakra-ui/theme-tools@1.1.7": - version "1.1.7" - resolved "https://registry.yarnpkg.com/@chakra-ui/theme-tools/-/theme-tools-1.1.7.tgz#ffd3dc2d22a935e1a1df47b155c4cef60ff3f603" - integrity sha512-i8KpxjgoQPsoWAyHX+4kRMSioN9WVfyky+2sdFDHhEuDNL/iNYfKQMZjt8RR67apK/dSswMqh5UF2lWSM+lQhw== - dependencies: - "@chakra-ui/utils" "1.8.0" - "@types/tinycolor2" "1.4.2" - tinycolor2 "1.4.2" - -"@chakra-ui/theme@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@chakra-ui/theme/-/theme-1.9.0.tgz#667ddaf1c042b1c2ad22fc3b70fa0697c5f54fac" - integrity sha512-IOvp7vF1/XZwH4eCr8xOhp1J5UW26GoQqLR32YsHgdaDhcIMMsX/Q5RVWU25zTvkPqHT/nDetzVc6dkE6864XA== - dependencies: - "@chakra-ui/theme-tools" "1.1.7" - "@chakra-ui/utils" "1.8.0" - -"@chakra-ui/toast@1.2.7": - version "1.2.7" - resolved "https://registry.yarnpkg.com/@chakra-ui/toast/-/toast-1.2.7.tgz#bd8731aba2a873b9fcc57464561085669a73f8ec" - integrity sha512-IOOzWuBmCKEKi3S3EZOb7NG1nCmQ2AmDOdA8bC+DHA1IDdkAFckPVt7k/q3xX4B/6nPgiMMUyRzRvtGw1zSX9A== - dependencies: - "@chakra-ui/alert" "1.2.5" - "@chakra-ui/close-button" "1.1.9" - "@chakra-ui/hooks" "1.5.2" - "@chakra-ui/theme" "1.9.0" - "@chakra-ui/transition" "1.3.1" - "@chakra-ui/utils" "1.8.0" - "@reach/alert" "0.13.2" - -"@chakra-ui/tooltip@1.3.6": - version "1.3.6" - resolved "https://registry.yarnpkg.com/@chakra-ui/tooltip/-/tooltip-1.3.6.tgz#252d3a300caf82ae529629799362dd2e2607bd28" - integrity sha512-K3t07v7CiK8beJ8OOn7jcEEzVYb/mH+IyM7gGNAqJI1FyJyNvktenSHn5RkGJwUQmxMW8Z1USoubjEVEw9oGOQ== - dependencies: - "@chakra-ui/hooks" "1.5.2" - "@chakra-ui/popper" "2.2.0" - "@chakra-ui/portal" "1.2.5" - "@chakra-ui/react-utils" "1.1.2" - "@chakra-ui/utils" "1.8.0" - "@chakra-ui/visually-hidden" "1.0.12" - -"@chakra-ui/transition@1.3.1": - version "1.3.1" - resolved "https://registry.yarnpkg.com/@chakra-ui/transition/-/transition-1.3.1.tgz#531c6c876c2e0da482c98905ba07a24b80f4e4dd" - integrity sha512-ScUJy562HUj8VhXZt8HdVsdsbOhqgEEtb0fm9KHskI9Sd+fmNKFubdhRddr+Bbtlv4lgl2vtPVfP6tnU9P3EpA== - dependencies: - "@chakra-ui/utils" "1.8.0" - -"@chakra-ui/utils@1.8.0", "@chakra-ui/utils@^1.7.0": - version "1.8.0" - resolved "https://registry.yarnpkg.com/@chakra-ui/utils/-/utils-1.8.0.tgz#f7aad8175cc5a26a1d2795dc78691bbc21fd539e" - integrity sha512-BWIhKcXnLbOIwCTKeNcOStNwk9RyYVA9xRRFPGK6Kp3EhrxP0rDwAbu4D3o3qAc+yhIDhGmPaIj1jRXHB5DTfg== - dependencies: - "@types/lodash.mergewith" "4.6.6" - css-box-model "1.2.1" - framesync "5.3.0" - lodash.mergewith "4.6.2" - -"@chakra-ui/visually-hidden@1.0.12": - version "1.0.12" - resolved "https://registry.yarnpkg.com/@chakra-ui/visually-hidden/-/visually-hidden-1.0.12.tgz#9a5cf5c65c2e933a891442c4dd66767cf2f5f75f" - integrity sha512-CSRH1ySzI3QYP5QFrLFWgpy40rpddGn4Z+BjsZ5pf+FGp/KUEpFKUx8nZyGfHlT+flMCj6Tpu7ftPyWCh1HERg== - dependencies: - "@chakra-ui/utils" "1.8.0" - -"@emotion/babel-plugin@^11.3.0": - version "11.3.0" - resolved "https://registry.yarnpkg.com/@emotion/babel-plugin/-/babel-plugin-11.3.0.tgz#3a16850ba04d8d9651f07f3fb674b3436a4fb9d7" - integrity sha512-UZKwBV2rADuhRp+ZOGgNWg2eYgbzKzQXfQPtJbu/PLy8onurxlNCLvxMQEvlr1/GudguPI5IU9qIY1+2z1M5bA== - dependencies: - "@babel/helper-module-imports" "^7.12.13" - "@babel/plugin-syntax-jsx" "^7.12.13" - "@babel/runtime" "^7.13.10" - "@emotion/hash" "^0.8.0" - "@emotion/memoize" "^0.7.5" - "@emotion/serialize" "^1.0.2" - babel-plugin-macros "^2.6.1" - convert-source-map "^1.5.0" - escape-string-regexp "^4.0.0" - find-root "^1.1.0" - source-map "^0.5.7" - stylis "^4.0.3" - -"@emotion/cache@^11.1.3": - version "11.1.3" - resolved "https://registry.yarnpkg.com/@emotion/cache/-/cache-11.1.3.tgz#c7683a9484bcd38d5562f2b9947873cf66829afd" - integrity sha512-n4OWinUPJVaP6fXxWZD9OUeQ0lY7DvtmtSuqtRWT0Ofo/sBLCVSgb4/Oa0Q5eFxcwablRKjUXqXtNZVyEwCAuA== - dependencies: - "@emotion/memoize" "^0.7.4" - "@emotion/sheet" "^1.0.0" - "@emotion/utils" "^1.0.0" - "@emotion/weak-memoize" "^0.2.5" - stylis "^4.0.3" - -"@emotion/cache@^11.4.0": - version "11.4.0" - resolved "https://registry.yarnpkg.com/@emotion/cache/-/cache-11.4.0.tgz#293fc9d9a7a38b9aad8e9337e5014366c3b09ac0" - integrity sha512-Zx70bjE7LErRO9OaZrhf22Qye1y4F7iDl+ITjet0J+i+B88PrAOBkKvaAWhxsZf72tDLajwCgfCjJ2dvH77C3g== - dependencies: - "@emotion/memoize" "^0.7.4" - "@emotion/sheet" "^1.0.0" - "@emotion/utils" "^1.0.0" - "@emotion/weak-memoize" "^0.2.5" - stylis "^4.0.3" - -"@emotion/hash@^0.8.0": - version "0.8.0" - resolved "https://registry.yarnpkg.com/@emotion/hash/-/hash-0.8.0.tgz#bbbff68978fefdbe68ccb533bc8cbe1d1afb5413" - integrity sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow== - -"@emotion/is-prop-valid@^0.8.2": - version "0.8.8" - resolved "https://registry.yarnpkg.com/@emotion/is-prop-valid/-/is-prop-valid-0.8.8.tgz#db28b1c4368a259b60a97311d6a952d4fd01ac1a" - integrity sha512-u5WtneEAr5IDG2Wv65yhunPSMLIpuKsbuOktRojfrEiEvRyC85LgPMZI63cr7NUqT8ZIGdSVg8ZKGxIug4lXcA== - dependencies: - "@emotion/memoize" "0.7.4" - -"@emotion/is-prop-valid@^1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@emotion/is-prop-valid/-/is-prop-valid-1.1.0.tgz#29ef6be1e946fb4739f9707def860f316f668cde" - integrity sha512-9RkilvXAufQHsSsjQ3PIzSns+pxuX4EW8EbGeSPjZMHuMx6z/MOzb9LpqNieQX4F3mre3NWS2+X3JNRHTQztUQ== - dependencies: - "@emotion/memoize" "^0.7.4" - -"@emotion/memoize@0.7.4", "@emotion/memoize@^0.7.4": - version "0.7.4" - resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.7.4.tgz#19bf0f5af19149111c40d98bb0cf82119f5d9eeb" - integrity sha512-Ja/Vfqe3HpuzRsG1oBtWTHk2PGZ7GR+2Vz5iYGelAw8dx32K0y7PjVuxK6z1nMpZOqAFsRUPCkK1YjJ56qJlgw== - -"@emotion/memoize@^0.7.5": - version "0.7.5" - resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.7.5.tgz#2c40f81449a4e554e9fc6396910ed4843ec2be50" - integrity sha512-igX9a37DR2ZPGYtV6suZ6whr8pTFtyHL3K/oLUotxpSVO2ASaprmAe2Dkq7tBo7CRY7MMDrAa9nuQP9/YG8FxQ== - -"@emotion/react@^11.1.1": - version "11.1.5" - resolved "https://registry.yarnpkg.com/@emotion/react/-/react-11.1.5.tgz#15e78f9822894cdc296e6f4e0688bac8120dfe66" - integrity sha512-xfnZ9NJEv9SU9K2sxXM06lzjK245xSeHRpUh67eARBm3PBHjjKIZlfWZ7UQvD0Obvw6ZKjlC79uHrlzFYpOB/Q== - dependencies: - "@babel/runtime" "^7.7.2" - "@emotion/cache" "^11.1.3" - "@emotion/serialize" "^1.0.0" - "@emotion/sheet" "^1.0.1" - "@emotion/utils" "^1.0.0" - "@emotion/weak-memoize" "^0.2.5" - hoist-non-react-statics "^3.3.1" - -"@emotion/react@^11.1.5", "@emotion/react@^11.4.0": - version "11.4.0" - resolved "https://registry.yarnpkg.com/@emotion/react/-/react-11.4.0.tgz#2465ad7b073a691409b88dfd96dc17097ddad9b7" - integrity sha512-4XklWsl9BdtatLoJpSjusXhpKv9YVteYKh9hPKP1Sxl+mswEFoUe0WtmtWjxEjkA51DQ2QRMCNOvKcSlCQ7ivg== - dependencies: - "@babel/runtime" "^7.13.10" - "@emotion/cache" "^11.4.0" - "@emotion/serialize" "^1.0.2" - "@emotion/sheet" "^1.0.1" - "@emotion/utils" "^1.0.0" - "@emotion/weak-memoize" "^0.2.5" - hoist-non-react-statics "^3.3.1" - -"@emotion/serialize@^1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@emotion/serialize/-/serialize-1.0.0.tgz#1a61f4f037cf39995c97fc80ebe99abc7b191ca9" - integrity sha512-zt1gm4rhdo5Sry8QpCOpopIUIKU+mUSpV9WNmFILUraatm5dttNEaYzUWWSboSMUE6PtN2j1cAsuvcugfdI3mw== - dependencies: - "@emotion/hash" "^0.8.0" - "@emotion/memoize" "^0.7.4" - "@emotion/unitless" "^0.7.5" - "@emotion/utils" "^1.0.0" - csstype "^3.0.2" - -"@emotion/serialize@^1.0.2": - version "1.0.2" - resolved "https://registry.yarnpkg.com/@emotion/serialize/-/serialize-1.0.2.tgz#77cb21a0571c9f68eb66087754a65fa97bfcd965" - integrity sha512-95MgNJ9+/ajxU7QIAruiOAdYNjxZX7G2mhgrtDWswA21VviYIRP1R5QilZ/bDY42xiKsaktP4egJb3QdYQZi1A== - dependencies: - "@emotion/hash" "^0.8.0" - "@emotion/memoize" "^0.7.4" - "@emotion/unitless" "^0.7.5" - "@emotion/utils" "^1.0.0" - csstype "^3.0.2" - -"@emotion/sheet@^1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@emotion/sheet/-/sheet-1.0.0.tgz#a0ef06080f339477ad4ba7f56e1c931f7ba50822" - integrity sha512-cdCHfZtf/0rahPDCZ9zyq+36EqfD/6c0WUqTFZ/hv9xadTUv2lGE5QK7/Z6Dnx2oRxC0usfVM2/BYn9q9B9wZA== - -"@emotion/sheet@^1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@emotion/sheet/-/sheet-1.0.1.tgz#245f54abb02dfd82326e28689f34c27aa9b2a698" - integrity sha512-GbIvVMe4U+Zc+929N1V7nW6YYJtidj31lidSmdYcWozwoBIObXBnaJkKNDjZrLm9Nc0BR+ZyHNaRZxqNZbof5g== - -"@emotion/styled@^11.3.0": - version "11.3.0" - resolved "https://registry.yarnpkg.com/@emotion/styled/-/styled-11.3.0.tgz#d63ee00537dfb6ff612e31b0e915c5cf9925a207" - integrity sha512-fUoLcN3BfMiLlRhJ8CuPUMEyKkLEoM+n+UyAbnqGEsCd5IzKQ7VQFLtzpJOaCD2/VR2+1hXQTnSZXVJeiTNltA== - dependencies: - "@babel/runtime" "^7.13.10" - "@emotion/babel-plugin" "^11.3.0" - "@emotion/is-prop-valid" "^1.1.0" - "@emotion/serialize" "^1.0.2" - "@emotion/utils" "^1.0.0" - -"@emotion/unitless@^0.7.5": - version "0.7.5" - resolved "https://registry.yarnpkg.com/@emotion/unitless/-/unitless-0.7.5.tgz#77211291c1900a700b8a78cfafda3160d76949ed" - integrity sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg== - -"@emotion/utils@^1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@emotion/utils/-/utils-1.0.0.tgz#abe06a83160b10570816c913990245813a2fd6af" - integrity sha512-mQC2b3XLDs6QCW+pDQDiyO/EdGZYOygE8s5N5rrzjSI4M3IejPE/JPndCBwRT9z982aqQNi6beWs1UeayrQxxA== - -"@emotion/weak-memoize@^0.2.5": - version "0.2.5" - resolved "https://registry.yarnpkg.com/@emotion/weak-memoize/-/weak-memoize-0.2.5.tgz#8eed982e2ee6f7f4e44c253e12962980791efd46" - integrity sha512-6U71C2Wp7r5XtFtQzYrW5iKFT67OixrSxjI4MptCHzdSVlgabczzqLe0ZSgnub/5Kp4hSbpDB1tMytZY9pwxxA== - -"@eslint/eslintrc@^0.2.2": - version "0.2.2" - resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-0.2.2.tgz#d01fc791e2fc33e88a29d6f3dc7e93d0cd784b76" - integrity sha512-EfB5OHNYp1F4px/LI/FEnGylop7nOqkQ1LRzCM0KccA2U8tvV8w01KBv37LbO7nW4H+YhKyo2LcJhRwjjV17QQ== - dependencies: - ajv "^6.12.4" - debug "^4.1.1" - espree "^7.3.0" - globals "^12.1.0" - ignore "^4.0.6" - import-fresh "^3.2.1" - js-yaml "^3.13.1" - lodash "^4.17.19" - minimatch "^3.0.4" - strip-json-comments "^3.1.1" - -"@hapi/accept@5.0.2": - version "5.0.2" - resolved "https://registry.yarnpkg.com/@hapi/accept/-/accept-5.0.2.tgz#ab7043b037e68b722f93f376afb05e85c0699523" - integrity sha512-CmzBx/bXUR8451fnZRuZAJRlzgm0Jgu5dltTX/bszmR2lheb9BpyN47Q1RbaGTsvFzn0PXAEs+lXDKfshccYZw== - dependencies: - "@hapi/boom" "9.x.x" - "@hapi/hoek" "9.x.x" - -"@hapi/boom@9.x.x": - version "9.1.0" - resolved "https://registry.yarnpkg.com/@hapi/boom/-/boom-9.1.0.tgz#0d9517657a56ff1e0b42d0aca9da1b37706fec56" - integrity sha512-4nZmpp4tXbm162LaZT45P7F7sgiem8dwAh2vHWT6XX24dozNjGMg6BvKCRvtCUcmcXqeMIUqWN8Rc5X8yKuROQ== - dependencies: - "@hapi/hoek" "9.x.x" - -"@hapi/hoek@9.x.x": - version "9.1.0" - resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-9.1.0.tgz#6c9eafc78c1529248f8f4d92b0799a712b6052c6" - integrity sha512-i9YbZPN3QgfighY/1X1Pu118VUz2Fmmhd6b2n0/O8YVgGGfw0FbUYoA97k7FkpGJ+pLCFEDLUmAPPV4D1kpeFw== - -"@hookform/devtools@^3.1.0": - version "3.1.0" - resolved "https://registry.yarnpkg.com/@hookform/devtools/-/devtools-3.1.0.tgz#ba2dc7a627f53535db8d0ff7e65f7a00db815cf5" - integrity sha512-LCMOw8IrytV9z8nq5zwsM6056HXY0jwqZJjAOyh+GnCS7VUWKxMzYyC0ruvE76/Rs/wlVQB9EDuvgw6ZoyVEow== - dependencies: - "@emotion/react" "^11.1.5" - "@emotion/styled" "^11.3.0" - "@types/lodash" "^4.14.168" - little-state-machine "^4.1.0" - lodash "^4.17.21" - react-simple-animate "^3.3.12" - -"@hookform/resolvers@^2.5.1": - version "2.5.1" - resolved "https://registry.yarnpkg.com/@hookform/resolvers/-/resolvers-2.5.1.tgz#09f2228c9061c350819881dc11e4f65af90c5a1a" - integrity sha512-dNChuOJ7ker2ZALGhXO6KjeycwnBGcSslGsREgqTDSiBOgbEysupfGTJKzQsb0sXpNhrZLCGvQcT+qPmCdBEMw== - -"@hookstate/core@^3.0.7": - version "3.0.7" - resolved "https://registry.yarnpkg.com/@hookstate/core/-/core-3.0.7.tgz#aa91c3ca93771abda4a9729302c088d35bb7abaa" - integrity sha512-9aOGwD4tezrXJ7AkiPg0MJ8d9TiRCusf537zPOV4vOJmNn/tyMDMDxd1T4OlqKvNurVTzs9BEIMOuq5OduV7/w== - -"@hookstate/devtools@^3.0.0": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@hookstate/devtools/-/devtools-3.0.0.tgz#9b289503112f0f95221d0c86e602ada7793bbd3a" - integrity sha512-jXI9e+4+dr0FbdtHhQPa0/SmRwLM7twMU0Qf87AgM3DqqFDV9dRPD56jPXaTh8xD1Bt2R72TmGmqdkDhdKG8AQ== - dependencies: - redux "4.0.5" - redux-devtools-extension "2.13.8" - -"@hookstate/persistence@^3.0.0": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@hookstate/persistence/-/persistence-3.0.0.tgz#973b30d3a3bb1b29f4f59b1afe0d914e71a23882" - integrity sha512-xiN22IW0Wjw/uTV1OEUpTtqB8DAJyRobYR3+iv1TyMf72o98KpaZqQrLPvXkfrjlZac5s052BypjpkttX/Cmhw== - -"@meronex/icons@^4.0.0": - version "4.0.0" - resolved "https://registry.yarnpkg.com/@meronex/icons/-/icons-4.0.0.tgz#26e089a8a4ec176a5b6778fd54fcdd25b4746c67" - integrity sha512-WnoxUT02qawZSvsoPSwe7YOqOk0APysIHugiD3dYdc/QNeoigN4PD8mmmtmZFKlv8/Z7eERub0BmPkWcJ1BI+w== - dependencies: - camelcase "^5.0.0" - ncp "^2.0.0" - -"@next/env@10.2.3": - version "10.2.3" - resolved "https://registry.yarnpkg.com/@next/env/-/env-10.2.3.tgz#ede3bbe68cec9939c37168ea2077f9adbc68334e" - integrity sha512-uBOjRBjsWC4C8X3DfmWWP6ekwLnf2JCCwQX9KVnJtJkqfDsv1yQPakdOEwvJzXQc3JC/v5KKffYPVmV2wHXCgQ== - -"@next/polyfill-module@10.2.3": - version "10.2.3" - resolved "https://registry.yarnpkg.com/@next/polyfill-module/-/polyfill-module-10.2.3.tgz#5a29f50c3ce3a56b8268d3b8331c691d8039467a" - integrity sha512-OkeY4cLhzfYbXxM4fd+6V4s5pTPuyfKSlavItfNRA6PpS7t1/R6YjO7S7rB8tu1pbTGuDHGIdE1ioDv15bAbDQ== - -"@next/react-dev-overlay@10.2.3": - version "10.2.3" - resolved "https://registry.yarnpkg.com/@next/react-dev-overlay/-/react-dev-overlay-10.2.3.tgz#95313d10a8848f6c7b9e31ae3bd2a3627d136841" - integrity sha512-E6g2jws4YW94l0lMMopBVKIZK2mEHfSBvM0d9dmzKG9L/A/kEq6LZCB4SiwGJbNsAdlk2y3USDa0oNbpA+m5Kw== - dependencies: - "@babel/code-frame" "7.12.11" - anser "1.4.9" - chalk "4.0.0" - classnames "2.2.6" - css.escape "1.5.1" - data-uri-to-buffer "3.0.1" - platform "1.3.6" - shell-quote "1.7.2" - source-map "0.8.0-beta.0" - stacktrace-parser "0.1.10" - strip-ansi "6.0.0" - -"@next/react-refresh-utils@10.2.3": - version "10.2.3" - resolved "https://registry.yarnpkg.com/@next/react-refresh-utils/-/react-refresh-utils-10.2.3.tgz#2f3e42fe6680798f276e3621345c2886b231348b" - integrity sha512-qtBF56vPC6d6a8p7LYd0iRjW89fhY80kAIzmj+VonvIGjK/nymBjcFUhbKiMFqlhsarCksnhwX+Zmn95Dw9qvA== - -"@nodelib/fs.scandir@2.1.4": - version "2.1.4" - resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.4.tgz#d4b3549a5db5de2683e0c1071ab4f140904bbf69" - integrity sha512-33g3pMJk3bg5nXbL/+CY6I2eJDzZAni49PfJnL5fghPTggPvBd/pFNSgJsdAgWptuFu7qq/ERvOYFlhvsLTCKA== - dependencies: - "@nodelib/fs.stat" "2.0.4" - run-parallel "^1.1.9" - -"@nodelib/fs.stat@2.0.4", "@nodelib/fs.stat@^2.0.2": - version "2.0.4" - resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.4.tgz#a3f2dd61bab43b8db8fa108a121cfffe4c676655" - integrity sha512-IYlHJA0clt2+Vg7bccq+TzRdJvv19c2INqBSsoOLp1je7xjtr7J26+WXR72MCdvU9q1qTzIWDfhMf+DRvQJK4Q== - -"@nodelib/fs.walk@^1.2.3": - version "1.2.6" - resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.6.tgz#cce9396b30aa5afe9e3756608f5831adcb53d063" - integrity sha512-8Broas6vTtW4GIXTAHDoE32hnN2M5ykgCpWGbuXHQ15vEMqr23pB76e/GZcYsZCHALv50ktd24qhEyKr6wBtow== - dependencies: - "@nodelib/fs.scandir" "2.1.4" - fastq "^1.6.0" - -"@opentelemetry/api@0.14.0": - version "0.14.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/api/-/api-0.14.0.tgz#4e17d8d2f1da72b19374efa7b6526aa001267cae" - integrity sha512-L7RMuZr5LzMmZiQSQDy9O1jo0q+DaLy6XpYJfIGfYSfoJA5qzYwUP3sP1uMIQ549DvxAgM3ng85EaPTM/hUHwQ== - dependencies: - "@opentelemetry/context-base" "^0.14.0" - -"@opentelemetry/context-base@^0.14.0": - version "0.14.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/context-base/-/context-base-0.14.0.tgz#c67fc20a4d891447ca1a855d7d70fa79a3533001" - integrity sha512-sDOAZcYwynHFTbLo6n8kIbLiVF3a3BLkrmehJUyEbT9F+Smbi47kLGS2gG2g0fjBLR/Lr1InPD7kXL7FaTqEkw== - -"@popperjs/core@2.4.4": - version "2.4.4" - resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.4.4.tgz#11d5db19bd178936ec89cd84519c4de439574398" - integrity sha512-1oO6+dN5kdIA3sKPZhRGJTfGVP4SWV6KqlMOwry4J3HfyD68sl/3KmG7DeYUzvN+RbhXDnv/D8vNNB8168tAMg== - -"@reach/alert@0.13.2": - version "0.13.2" - resolved "https://registry.yarnpkg.com/@reach/alert/-/alert-0.13.2.tgz#71c4a848d51341f1d6d9eaae060975391c224870" - integrity sha512-LDz83AXCrClyq/MWe+0vaZfHp1Ytqn+kgL5VxG7rirUvmluWaj/snxzfNPWn0Ma4K2YENmXXRC/iHt5X95SqIg== - dependencies: - "@reach/utils" "0.13.2" - "@reach/visually-hidden" "0.13.2" - prop-types "^15.7.2" - tslib "^2.1.0" - -"@reach/utils@0.13.2": - version "0.13.2" - resolved "https://registry.yarnpkg.com/@reach/utils/-/utils-0.13.2.tgz#87e8fef8ebfe583fa48250238a1a3ed03189fcc8" - integrity sha512-3ir6cN60zvUrwjOJu7C6jec/samqAeyAB12ZADK+qjnmQPdzSYldrFWwDVV5H0WkhbYXR3uh+eImu13hCetNPQ== - dependencies: - "@types/warning" "^3.0.0" - tslib "^2.1.0" - warning "^4.0.3" - -"@reach/visually-hidden@0.13.2": - version "0.13.2" - resolved "https://registry.yarnpkg.com/@reach/visually-hidden/-/visually-hidden-0.13.2.tgz#ee21de376a7e57e60dc92d95a671073796caa17e" - integrity sha512-sPZwNS0/duOuG0mYwE5DmgEAzW9VhgU3aIt1+mrfT/xiT9Cdncqke+kRBQgU708q/Ttm9tWsoHni03nn/SuPTQ== - dependencies: - prop-types "^15.7.2" - tslib "^2.1.0" - -"@types/d3-array@*": - version "2.9.0" - resolved "https://registry.yarnpkg.com/@types/d3-array/-/d3-array-2.9.0.tgz#fb6c3d7d7640259e68771cd90cc5db5ac1a1a012" - integrity sha512-sdBMGfNvLUkBypPMEhOcKcblTQfgHbqbYrUqRE31jOwdDHBJBxz4co2MDAq93S4Cp++phk4UiwoEg/1hK3xXAQ== - -"@types/d3-axis@*": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@types/d3-axis/-/d3-axis-2.0.0.tgz#a3e7534d3c399c20ba42ec3093dd2a385659366e" - integrity sha512-gUdlEwGBLl3tXGiBnBNmNzph9W3bCfa4tBgWZD60Z1eDQKTY4zyCAcZ3LksignGfKawYatmDYcBdjJ5h/54sqA== - dependencies: - "@types/d3-selection" "*" - -"@types/d3-brush@*": - version "2.1.0" - resolved "https://registry.yarnpkg.com/@types/d3-brush/-/d3-brush-2.1.0.tgz#c51ad1ab93887b23be7637d2100540f1df0dac00" - integrity sha512-rLQqxQeXWF4ArXi81GlV8HBNwJw9EDpz0jcWvvzv548EDE4tXrayBTOHYi/8Q4FZ/Df8PGXFzxpAVQmJMjOtvQ== - dependencies: - "@types/d3-selection" "*" - -"@types/d3-chord@*": - version "2.0.1" - resolved "https://registry.yarnpkg.com/@types/d3-chord/-/d3-chord-2.0.1.tgz#45c72b28c9686eb4b02c8a1bb0fe174723053890" - integrity sha512-mqGww8qDtGZRnDsFizzobAVizd85hgaYNEri095ZI7/aYtW7hxa9a20enwuoVTWm0YqdCtLPoyV9ZPYgfyaTZw== - -"@types/d3-color@*": - version "2.0.1" - resolved "https://registry.yarnpkg.com/@types/d3-color/-/d3-color-2.0.1.tgz#570ea7f8b853461301804efa52bd790a640a26db" - integrity sha512-u7LTCL7RnaavFSmob2rIAJLNwu50i6gFwY9cHFr80BrQURYQBRkJ+Yv47nA3Fm7FeRhdWTiVTeqvSeOuMAOzBQ== - -"@types/d3-contour@*": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@types/d3-contour/-/d3-contour-2.0.0.tgz#6e079f281b29a8df3fcbd3ec193f2cf1d0b4a584" - integrity sha512-PS9UO6zBQqwHXsocbpdzZFONgK1oRUgWtjjh/iz2vM06KaXLInLiKZ9e3OLBRerc1cU2uJYpO+8zOnb6frvCGQ== - dependencies: - "@types/d3-array" "*" - "@types/geojson" "*" - -"@types/d3-delaunay@*": - version "5.3.0" - resolved "https://registry.yarnpkg.com/@types/d3-delaunay/-/d3-delaunay-5.3.0.tgz#416169bb5c67a510c87b55d092a404fcab49def3" - integrity sha512-gJYcGxLu0xDZPccbUe32OUpeaNtd1Lz0NYJtko6ZLMyG2euF4pBzrsQXms67LHZCDFzzszw+dMhSL/QAML3bXw== - -"@types/d3-dispatch@*": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@types/d3-dispatch/-/d3-dispatch-2.0.0.tgz#1f8803041b73b81f2c751e026b7bb63dd5f24ce0" - integrity sha512-Sh0KW6z/d7uxssD7K4s4uCSzlEG/+SP+U47q098NVdOfFvUKNTvKAIV4XqjxsUuhE/854ARAREHOxkr9gQOCyg== - -"@types/d3-drag@*": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@types/d3-drag/-/d3-drag-2.0.0.tgz#ef66acc422576fbe10b8bd66af45a9fb8525199a" - integrity sha512-VaUJPjbMnDn02tcRqsHLRAX5VjcRIzCjBfeXTLGe6QjMn5JccB5Cz4ztMRXMJfkbC45ovgJFWuj6DHvWMX1thA== - dependencies: - "@types/d3-selection" "*" - -"@types/d3-dsv@*": - version "2.0.1" - resolved "https://registry.yarnpkg.com/@types/d3-dsv/-/d3-dsv-2.0.1.tgz#44ce09b025cf365d27cbe11fc13cd10954369627" - integrity sha512-wovgiG9Mgkr/SZ/m/c0m+RwrIT4ozsuCWeLxJyoObDWsie2DeQT4wzMdHZPR9Ya5oZLQT3w3uSl0NehG0+0dCA== - -"@types/d3-ease@*": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@types/d3-ease/-/d3-ease-2.0.0.tgz#798cbd9908d26cfe9f1a295a3a75164da9a3666e" - integrity sha512-6aZrTyX5LG+ptofVHf+gTsThLRY1nhLotJjgY4drYqk1OkJMu2UvuoZRlPw2fffjRHeYepue3/fxTufqKKmvsA== - -"@types/d3-fetch@*": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@types/d3-fetch/-/d3-fetch-2.0.0.tgz#580846256ed0011b36a08ebb36924e0dff70e27e" - integrity sha512-WnLepGtxepFfXRdPI8I5FTgNiHn9p4vMTTqaNCzJJfAswXx0rOY2jjeolzEU063em3iJmGZ+U79InnEeFOrCRw== - dependencies: - "@types/d3-dsv" "*" - -"@types/d3-force@*": - version "2.1.1" - resolved "https://registry.yarnpkg.com/@types/d3-force/-/d3-force-2.1.1.tgz#a18b6f029d056eb0f8f84a09471e6228e4469b14" - integrity sha512-3r+CQv2K/uDTAVg0DGxsbBjV02vgOxb8RhPIv3gd6cp3pdPAZ7wEXpDjUZSoqycAQLSDOxG/AZ54Vx6YXZSbmQ== - -"@types/d3-format@*": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@types/d3-format/-/d3-format-2.0.0.tgz#607d261cb268f0a027f100575491031539a40ee6" - integrity sha512-uagdkftxnGkO4pZw5jEYOM5ZnZOEsh7z8j11Qxk85UkB2RzfUUxRl7R9VvvJZHwKn8l+x+rpS77Nusq7FkFmIg== - -"@types/d3-geo@*": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@types/d3-geo/-/d3-geo-2.0.0.tgz#6f179512343c2d30e06acde190abfacf44b2d264" - integrity sha512-DHHgYXW36lnAEQMYU2udKVOxxljHrn2EdOINeSC9jWCAXwOnGn7A19B8sNsHqgpu4F7O2bSD7//cqBXD3W0Deg== - dependencies: - "@types/geojson" "*" - -"@types/d3-hierarchy@*": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@types/d3-hierarchy/-/d3-hierarchy-2.0.0.tgz#92079d9dbcec1dfe2736fb050a8bf916e5850a1c" - integrity sha512-YxdskUvwzqggpnSnDQj4KVkicgjpkgXn/g/9M9iGsiToLS3nG6Ytjo1FoYhYVAAElV/fJBGVL3cQ9Hb7tcv+lw== - -"@types/d3-interpolate@*": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@types/d3-interpolate/-/d3-interpolate-2.0.0.tgz#325029216dc722c1c68c33ccda759f1209d35823" - integrity sha512-Wt1v2zTlEN8dSx8hhx6MoOhWQgTkz0Ukj7owAEIOF2QtI0e219paFX9rf/SLOr/UExWb1TcUzatU8zWwFby6gg== - dependencies: - "@types/d3-color" "*" - -"@types/d3-path@*": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@types/d3-path/-/d3-path-2.0.0.tgz#dcc7f5ecadf52b0c0c39f6c1def3733195e4b199" - integrity sha512-tXcR/9OtDdeCIsyl6eTNHC3XOAOdyc6ceF3QGBXOd9jTcK+ex/ecr00p9L9362e/op3UEPpxrToi1FHrtTSj7Q== - -"@types/d3-path@^1": - version "1.0.9" - resolved "https://registry.yarnpkg.com/@types/d3-path/-/d3-path-1.0.9.tgz#73526b150d14cd96e701597cbf346cfd1fd4a58c" - integrity sha512-NaIeSIBiFgSC6IGUBjZWcscUJEq7vpVu7KthHN8eieTV9d9MqkSOZLH4chq1PmcKy06PNe3axLeKmRIyxJ+PZQ== - -"@types/d3-polygon@*": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@types/d3-polygon/-/d3-polygon-2.0.0.tgz#8b1df0a1358016e62c4961b01e8dc8e5ab4c64e5" - integrity sha512-fISnMd8ePED1G4aa4V974Jmt+ajHSgPoxMa2D0ULxMybpx0Vw4WEzhQEaMIrL3hM8HVRcKTx669I+dTy/4PhAw== - -"@types/d3-quadtree@*": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@types/d3-quadtree/-/d3-quadtree-2.0.0.tgz#b17e953dc061e083966075bba0d3a9a259812150" - integrity sha512-YZuJuGBnijD0H+98xMJD4oZXgv/umPXy5deu3IimYTPGH3Kr8Th6iQUff0/6S80oNBD7KtOuIHwHUCymUiRoeQ== - -"@types/d3-random@*": - version "2.2.0" - resolved "https://registry.yarnpkg.com/@types/d3-random/-/d3-random-2.2.0.tgz#fc44cabb966917459490b758f31f5359adeabe5b" - integrity sha512-Hjfj9m68NmYZzushzEG7etPvKH/nj9b9s9+qtkNG3/dbRBjQZQg1XS6nRuHJcCASTjxXlyXZnKu2gDxyQIIu9A== - -"@types/d3-scale-chromatic@*": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@types/d3-scale-chromatic/-/d3-scale-chromatic-2.0.0.tgz#8d4a6f07cbbf2a9f2a4bec9c9476c27ed76a96ea" - integrity sha512-Y62+2clOwZoKua84Ha0xU77w7lePiaBoTjXugT4l8Rd5LAk+Mn/ZDtrgs087a+B5uJ3jYUHHtKw5nuEzp0WBHw== - -"@types/d3-scale@*": - version "3.2.2" - resolved "https://registry.yarnpkg.com/@types/d3-scale/-/d3-scale-3.2.2.tgz#5e28d0b1c599328aaec6094219f10a2570be6d74" - integrity sha512-qpQe8G02tzUwt9sdWX1h8A/W0Q1+N48wMnYXVOkrzeLUkCfvzJYV9Ee3aORCS4dN4ONRLFmMvaXdziQ29XGLjQ== - dependencies: - "@types/d3-time" "*" - -"@types/d3-selection@*": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@types/d3-selection/-/d3-selection-2.0.0.tgz#59df94a8e47ed1050a337d4ffb4d4d213aa590a8" - integrity sha512-EF0lWZ4tg7oDFg4YQFlbOU3936e3a9UmoQ2IXlBy1+cv2c2Pv7knhKUzGlH5Hq2sF/KeDTH1amiRPey2rrLMQA== - -"@types/d3-shape@*": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@types/d3-shape/-/d3-shape-2.0.0.tgz#61aa065726f3c2641aedc59c3603475ab11aeb2f" - integrity sha512-NLzD02m5PiD1KLEDjLN+MtqEcFYn4ZL9+Rqc9ZwARK1cpKZXd91zBETbe6wpBB6Ia0D0VZbpmbW3+BsGPGnCpA== - dependencies: - "@types/d3-path" "^1" - -"@types/d3-time-format@*": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@types/d3-time-format/-/d3-time-format-3.0.0.tgz#913e984362a59792dc8d8b122dd17625991eade2" - integrity sha512-UpLg1mn/8PLyjr+J/JwdQJM/GzysMvv2CS8y+WYAL5K0+wbvXv/pPSLEfdNaprCZsGcXTxPsFMy8QtkYv9ueew== - -"@types/d3-time@*": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@types/d3-time/-/d3-time-2.0.0.tgz#831dd093db91f16b83ba980e194bb8e4bcef44d6" - integrity sha512-Abz8bTzy8UWDeYs9pCa3D37i29EWDjNTjemdk0ei1ApYVNqulYlGUKip/jLOpogkPSsPz/GvZCYiC7MFlEk0iQ== - -"@types/d3-timer@*": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@types/d3-timer/-/d3-timer-2.0.0.tgz#9901bb02af38798764674df17d66b07329705632" - integrity sha512-l6stHr1VD1BWlW6u3pxrjLtJfpPZq9I3XmKIQtq7zHM/s6fwEtI1Yn6Sr5/jQTrUDCC5jkS6gWqlFGCDArDqNg== - -"@types/d3-transition@*": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@types/d3-transition/-/d3-transition-2.0.0.tgz#6f073f0b567c13b7a3dcd1d54214c89f48c5a873" - integrity sha512-UJDzI98utcZQUJt3uIit/Ho0/eBIANzrWJrTmi4+TaKIyWL2iCu7ShP0o4QajCskhyjOA7C8+4CE3b1YirTzEQ== - dependencies: - "@types/d3-selection" "*" - -"@types/d3-zoom@*": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@types/d3-zoom/-/d3-zoom-2.0.0.tgz#ef8b87464e8ebc7c66b70f6383d1ae841e78e7fc" - integrity sha512-daL0PJm4yT0ISTGa7p2lHX0kvv9FO/IR1ooWbHR/7H4jpbaKiLux5FslyS/OvISPiJ5SXb4sOqYhO6fMB6hKRw== - dependencies: - "@types/d3-interpolate" "*" - "@types/d3-selection" "*" - -"@types/d3@^6.7.0": - version "6.7.0" - resolved "https://registry.yarnpkg.com/@types/d3/-/d3-6.7.0.tgz#e801778cfcf3b5e52ad4dae0d21263b2511d314f" - integrity sha512-QOf+58QAvNcqpfIdAfdHe7wDWnIra1YvgCJh2Lxw5FY9dZ+6XVbN63DVoJLnDGpGNBycqUvj5rjHlKZkoz1PtQ== - dependencies: - "@types/d3-array" "*" - "@types/d3-axis" "*" - "@types/d3-brush" "*" - "@types/d3-chord" "*" - "@types/d3-color" "*" - "@types/d3-contour" "*" - "@types/d3-delaunay" "*" - "@types/d3-dispatch" "*" - "@types/d3-drag" "*" - "@types/d3-dsv" "*" - "@types/d3-ease" "*" - "@types/d3-fetch" "*" - "@types/d3-force" "*" - "@types/d3-format" "*" - "@types/d3-geo" "*" - "@types/d3-hierarchy" "*" - "@types/d3-interpolate" "*" - "@types/d3-path" "*" - "@types/d3-polygon" "*" - "@types/d3-quadtree" "*" - "@types/d3-random" "*" - "@types/d3-scale" "*" - "@types/d3-scale-chromatic" "*" - "@types/d3-selection" "*" - "@types/d3-shape" "*" - "@types/d3-time" "*" - "@types/d3-time-format" "*" - "@types/d3-timer" "*" - "@types/d3-transition" "*" - "@types/d3-zoom" "*" - -"@types/dagre@^0.7.44": - version "0.7.44" - resolved "https://registry.yarnpkg.com/@types/dagre/-/dagre-0.7.44.tgz#8f4b796b118ca29c132da7068fbc0d0351ee5851" - integrity sha512-N6HD+79w77ZVAaVO7JJDW5yJ9LAxM62FpgNGO9xEde+KVYjDRyhIMzfiErXpr1g0JPon9kwlBzoBK6s4fOww9Q== - -"@types/eslint-visitor-keys@^1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#1ee30d79544ca84d68d4b3cdb0af4f205663dd2d" - integrity sha512-OCutwjDZ4aFS6PB1UZ988C4YgwlBHJd6wCeQqaLdmadZ/7e+w79+hbMUFC1QXDNCmdyoRfAFdm0RypzwR+Qpag== - -"@types/geojson@*": - version "7946.0.7" - resolved "https://registry.yarnpkg.com/@types/geojson/-/geojson-7946.0.7.tgz#c8fa532b60a0042219cdf173ca21a975ef0666ad" - integrity sha512-wE2v81i4C4Ol09RtsWFAqg3BUitWbHSpSlIo+bNdsCJijO9sjme+zm+73ZMCa/qMC8UEERxzGbvmr1cffo2SiQ== - -"@types/hoist-non-react-statics@^3.3.0": - version "3.3.1" - resolved "https://registry.yarnpkg.com/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz#1124aafe5118cb591977aeb1ceaaed1070eb039f" - integrity sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA== - dependencies: - "@types/react" "*" - hoist-non-react-statics "^3.3.0" - -"@types/json-schema@^7.0.3": - version "7.0.6" - resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.6.tgz#f4c7ec43e81b319a9815115031709f26987891f0" - integrity sha512-3c+yGKvVP5Y9TYBEibGNR+kLtijnj7mYrXRg+WpFb2X9xm04g/DXYkfg4hmzJQosc9snFNUPkbYIhu+KAm6jJw== - -"@types/json5@^0.0.29": - version "0.0.29" - resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee" - integrity sha1-7ihweulOEdK4J7y+UnC86n8+ce4= - -"@types/lodash.mergewith@4.6.6": - version "4.6.6" - resolved "https://registry.yarnpkg.com/@types/lodash.mergewith/-/lodash.mergewith-4.6.6.tgz#c4698f5b214a433ff35cb2c75ee6ec7f99d79f10" - integrity sha512-RY/8IaVENjG19rxTZu9Nukqh0W2UrYgmBj5sdns4hWRZaV8PqR7wIKHFKzvOTjo4zVRV7sVI+yFhAJql12Kfqg== - dependencies: - "@types/lodash" "*" - -"@types/lodash@*": - version "4.14.165" - resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.165.tgz#74d55d947452e2de0742bad65270433b63a8c30f" - integrity sha512-tjSSOTHhI5mCHTy/OOXYIhi2Wt1qcbHmuXD1Ha7q70CgI/I71afO4XtLb/cVexki1oVYchpul/TOuu3Arcdxrg== - -"@types/lodash@^4.14.168": - version "4.14.170" - resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.170.tgz#0d67711d4bf7f4ca5147e9091b847479b87925d6" - integrity sha512-bpcvu/MKHHeYX+qeEN8GE7DIravODWdACVA1ctevD8CN24RhPZIKMn9ntfAsrvLfSX3cR5RrBKAbYm9bGs0A+Q== - -"@types/mdast@^3.0.0", "@types/mdast@^3.0.3": - version "3.0.3" - resolved "https://registry.yarnpkg.com/@types/mdast/-/mdast-3.0.3.tgz#2d7d671b1cd1ea3deb306ea75036c2a0407d2deb" - integrity sha512-SXPBMnFVQg1s00dlMCc/jCdvPqdE4mXaMMCeRlxLDmTAEoegHT53xKtkDnzDTOcmMHUfcjyf36/YYZ6SxRdnsw== - dependencies: - "@types/unist" "*" - -"@types/node@*", "@types/node@^14.14.41": - version "14.14.41" - resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.41.tgz#d0b939d94c1d7bd53d04824af45f1139b8c45615" - integrity sha512-dueRKfaJL4RTtSa7bWeTK1M+VH+Gns73oCgzvYfHZywRCoPSd8EkXBL0mZ9unPTveBn+D9phZBaxuzpwjWkW0g== - -"@types/parse-json@^4.0.0": - version "4.0.0" - resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.0.tgz#2f8bb441434d163b35fb8ffdccd7138927ffb8c0" - integrity sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA== - -"@types/prop-types@*": - version "15.7.3" - resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.3.tgz#2ab0d5da2e5815f94b0b9d4b95d1e5f243ab2ca7" - integrity sha512-KfRL3PuHmqQLOG+2tGpRO26Ctg+Cq1E01D2DMriKEATHgWLfeNDmq9e29Q9WIky0dQ3NPkd1mzYH8Lm936Z9qw== - -"@types/react-dom@*": - version "16.9.8" - resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-16.9.8.tgz#fe4c1e11dfc67155733dfa6aa65108b4971cb423" - integrity sha512-ykkPQ+5nFknnlU6lDd947WbQ6TE3NNzbQAkInC2EKY1qeYdTKp7onFusmYZb+ityzx2YviqT6BXSu+LyWWJwcA== - dependencies: - "@types/react" "*" - -"@types/react-redux@^7.1.16": - version "7.1.16" - resolved "https://registry.yarnpkg.com/@types/react-redux/-/react-redux-7.1.16.tgz#0fbd04c2500c12105494c83d4a3e45c084e3cb21" - integrity sha512-f/FKzIrZwZk7YEO9E1yoxIuDNRiDducxkFlkw/GNMGEnK9n4K8wJzlJBghpSuOVDgEUHoDkDF7Gi9lHNQR4siw== - dependencies: - "@types/hoist-non-react-statics" "^3.3.0" - "@types/react" "*" - hoist-non-react-statics "^3.3.0" - redux "^4.0.0" - -"@types/react-select@^4.0.15": - version "4.0.15" - resolved "https://registry.yarnpkg.com/@types/react-select/-/react-select-4.0.15.tgz#2e6a1cff22c4bbae6c95b8dbee5b5097c12eae54" - integrity sha512-GPyBFYGMVFCtF4eg9riodEco+s2mflR10Nd5csx69+bcdvX6Uo9H/jgrIqovBU9yxBppB9DS66OwD6xxgVqOYQ== - dependencies: - "@emotion/serialize" "^1.0.0" - "@types/react" "*" - "@types/react-dom" "*" - "@types/react-transition-group" "*" - -"@types/react-table@^7.7.1": - version "7.7.1" - resolved "https://registry.yarnpkg.com/@types/react-table/-/react-table-7.7.1.tgz#cac73133fc185e152e31435f8e6fce89ab868661" - integrity sha512-oed13swLIS4Ffyo4jAjl9lGbYMaY0uavKoI9GNMvf2R6vh8JfpRUpizQ90X1VI4WrhfaMb/HMsN7TTBvkGOQXQ== - dependencies: - "@types/react" "*" - -"@types/react-transition-group@*": - version "4.4.0" - resolved "https://registry.yarnpkg.com/@types/react-transition-group/-/react-transition-group-4.4.0.tgz#882839db465df1320e4753e6e9f70ca7e9b4d46d" - integrity sha512-/QfLHGpu+2fQOqQaXh8MG9q03bFENooTb/it4jr5kKaZlDQfWvjqWZg48AwzPVMBHlRuTRAY7hRHCEOXz5kV6w== - dependencies: - "@types/react" "*" - -"@types/react@*": - version "16.9.53" - resolved "https://registry.yarnpkg.com/@types/react/-/react-16.9.53.tgz#40cd4f8b8d6b9528aedd1fff8fcffe7a112a3d23" - integrity sha512-4nW60Sd4L7+WMXH1D6jCdVftuW7j4Za6zdp6tJ33Rqv0nk1ZAmQKML9ZLD4H0dehA3FZxXR/GM8gXplf82oNGw== - dependencies: - "@types/prop-types" "*" - csstype "^3.0.2" - -"@types/react@^17.0.3": - version "17.0.3" - resolved "https://registry.yarnpkg.com/@types/react/-/react-17.0.3.tgz#ba6e215368501ac3826951eef2904574c262cc79" - integrity sha512-wYOUxIgs2HZZ0ACNiIayItyluADNbONl7kt8lkLjVK8IitMH5QMyAh75Fwhmo37r1m7L2JaFj03sIfxBVDvRAg== - dependencies: - "@types/prop-types" "*" - "@types/scheduler" "*" - csstype "^3.0.2" - -"@types/scheduler@*": - version "0.16.1" - resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.1.tgz#18845205e86ff0038517aab7a18a62a6b9f71275" - integrity sha512-EaCxbanVeyxDRTQBkdLb3Bvl/HK7PBK6UJjsSixB0iHKoWxE5uu2Q/DgtpOhPIojN0Zl1whvOd7PoHs2P0s5eA== - -"@types/string-format@^2.0.0": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@types/string-format/-/string-format-2.0.0.tgz#c1588f507be7b8ef5eb5074a41e48e4538f3f6d5" - integrity sha512-mMwtmgN0ureESnJ3SuMM4W9lsi4CgOxs43YxNo14SDHgzJ+OPYO3yM7nOTJTh8x5YICseBdtrySUbvxnpb+NYQ== - -"@types/tinycolor2@1.4.2": - version "1.4.2" - resolved "https://registry.yarnpkg.com/@types/tinycolor2/-/tinycolor2-1.4.2.tgz#721ca5c5d1a2988b4a886e35c2ffc5735b6afbdf" - integrity sha512-PeHg/AtdW6aaIO2a+98Xj7rWY4KC1E6yOy7AFknJQ7VXUGNrMlyxDFxJo7HqLtjQms/ZhhQX52mLVW/EX3JGOw== - -"@types/unist@*", "@types/unist@^2.0.0", "@types/unist@^2.0.2", "@types/unist@^2.0.3": - version "2.0.3" - resolved "https://registry.yarnpkg.com/@types/unist/-/unist-2.0.3.tgz#9c088679876f374eb5983f150d4787aa6fb32d7e" - integrity sha512-FvUupuM3rlRsRtCN+fDudtmytGO6iHJuuRKS1Ss0pG5z8oX0diNEw94UEL7hgDbpN94rgaK5R7sWm6RrSkZuAQ== - -"@types/warning@^3.0.0": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@types/warning/-/warning-3.0.0.tgz#0d2501268ad8f9962b740d387c4654f5f8e23e52" - integrity sha1-DSUBJorY+ZYrdA04fEZU9fjiPlI= - -"@typescript-eslint/eslint-plugin@^4.11.1": - version "4.11.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.11.1.tgz#7579c6d17ad862154c10bc14b40e5427b729e209" - integrity sha512-fABclAX2QIEDmTMk6Yd7Muv1CzFLwWM4505nETzRHpP3br6jfahD9UUJkhnJ/g2m7lwfz8IlswcwGGPGiq9exw== - dependencies: - "@typescript-eslint/experimental-utils" "4.11.1" - "@typescript-eslint/scope-manager" "4.11.1" - debug "^4.1.1" - functional-red-black-tree "^1.0.1" - regexpp "^3.0.0" - semver "^7.3.2" - tsutils "^3.17.1" - -"@typescript-eslint/experimental-utils@3.10.1": - version "3.10.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-3.10.1.tgz#e179ffc81a80ebcae2ea04e0332f8b251345a686" - integrity sha512-DewqIgscDzmAfd5nOGe4zm6Bl7PKtMG2Ad0KG8CUZAHlXfAKTF9Ol5PXhiMh39yRL2ChRH1cuuUGOcVyyrhQIw== - dependencies: - "@types/json-schema" "^7.0.3" - "@typescript-eslint/types" "3.10.1" - "@typescript-eslint/typescript-estree" "3.10.1" - eslint-scope "^5.0.0" - eslint-utils "^2.0.0" - -"@typescript-eslint/experimental-utils@4.11.1", "@typescript-eslint/experimental-utils@^4.0.1": - version "4.11.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-4.11.1.tgz#2dad3535b878c25c7424e40bfa79d899f3f485bc" - integrity sha512-mAlWowT4A6h0TC9F+J5pdbEhjNiEMO+kqPKQ4sc3fVieKL71dEqfkKgtcFVSX3cjSBwYwhImaQ/mXQF0oaI38g== - dependencies: - "@types/json-schema" "^7.0.3" - "@typescript-eslint/scope-manager" "4.11.1" - "@typescript-eslint/types" "4.11.1" - "@typescript-eslint/typescript-estree" "4.11.1" - eslint-scope "^5.0.0" - eslint-utils "^2.0.0" - -"@typescript-eslint/parser@^3.0.0": - version "3.10.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-3.10.1.tgz#1883858e83e8b442627e1ac6f408925211155467" - integrity sha512-Ug1RcWcrJP02hmtaXVS3axPPTTPnZjupqhgj+NnZ6BCkwSImWk/283347+x9wN+lqOdK9Eo3vsyiyDHgsmiEJw== - dependencies: - "@types/eslint-visitor-keys" "^1.0.0" - "@typescript-eslint/experimental-utils" "3.10.1" - "@typescript-eslint/types" "3.10.1" - "@typescript-eslint/typescript-estree" "3.10.1" - eslint-visitor-keys "^1.1.0" - -"@typescript-eslint/parser@^4.11.1": - version "4.11.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-4.11.1.tgz#981e18de2e019d6ca312596615f92e8f6f6598ed" - integrity sha512-BJ3jwPQu1jeynJ5BrjLuGfK/UJu6uwHxJ/di7sanqmUmxzmyIcd3vz58PMR7wpi8k3iWq2Q11KMYgZbUpRoIPw== - dependencies: - "@typescript-eslint/scope-manager" "4.11.1" - "@typescript-eslint/types" "4.11.1" - "@typescript-eslint/typescript-estree" "4.11.1" - debug "^4.1.1" - -"@typescript-eslint/scope-manager@4.11.1": - version "4.11.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-4.11.1.tgz#72dc2b60b0029ab0888479b12bf83034920b4b69" - integrity sha512-Al2P394dx+kXCl61fhrrZ1FTI7qsRDIUiVSuN6rTwss6lUn8uVO2+nnF4AvO0ug8vMsy3ShkbxLu/uWZdTtJMQ== - dependencies: - "@typescript-eslint/types" "4.11.1" - "@typescript-eslint/visitor-keys" "4.11.1" - -"@typescript-eslint/types@3.10.1": - version "3.10.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-3.10.1.tgz#1d7463fa7c32d8a23ab508a803ca2fe26e758727" - integrity sha512-+3+FCUJIahE9q0lDi1WleYzjCwJs5hIsbugIgnbB+dSCYUxl8L6PwmsyOPFZde2hc1DlTo/xnkOgiTLSyAbHiQ== - -"@typescript-eslint/types@4.11.1": - version "4.11.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.11.1.tgz#3ba30c965963ef9f8ced5a29938dd0c465bd3e05" - integrity sha512-5kvd38wZpqGY4yP/6W3qhYX6Hz0NwUbijVsX2rxczpY6OXaMxh0+5E5uLJKVFwaBM7PJe1wnMym85NfKYIh6CA== - -"@typescript-eslint/typescript-estree@3.10.1": - version "3.10.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-3.10.1.tgz#fd0061cc38add4fad45136d654408569f365b853" - integrity sha512-QbcXOuq6WYvnB3XPsZpIwztBoquEYLXh2MtwVU+kO8jgYCiv4G5xrSP/1wg4tkvrEE+esZVquIPX/dxPlePk1w== - dependencies: - "@typescript-eslint/types" "3.10.1" - "@typescript-eslint/visitor-keys" "3.10.1" - debug "^4.1.1" - glob "^7.1.6" - is-glob "^4.0.1" - lodash "^4.17.15" - semver "^7.3.2" - tsutils "^3.17.1" - -"@typescript-eslint/typescript-estree@4.11.1": - version "4.11.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-4.11.1.tgz#a4416b4a65872a48773b9e47afabdf7519eb10bc" - integrity sha512-tC7MKZIMRTYxQhrVAFoJq/DlRwv1bnqA4/S2r3+HuHibqvbrPcyf858lNzU7bFmy4mLeIHFYr34ar/1KumwyRw== - dependencies: - "@typescript-eslint/types" "4.11.1" - "@typescript-eslint/visitor-keys" "4.11.1" - debug "^4.1.1" - globby "^11.0.1" - is-glob "^4.0.1" - lodash "^4.17.15" - semver "^7.3.2" - tsutils "^3.17.1" - -"@typescript-eslint/visitor-keys@3.10.1": - version "3.10.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-3.10.1.tgz#cd4274773e3eb63b2e870ac602274487ecd1e931" - integrity sha512-9JgC82AaQeglebjZMgYR5wgmfUdUc+EitGUUMW8u2nDckaeimzW+VsoLV6FoimPv2id3VQzfjwBxEMVz08ameQ== - dependencies: - eslint-visitor-keys "^1.1.0" - -"@typescript-eslint/visitor-keys@4.11.1": - version "4.11.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-4.11.1.tgz#4c050a4c1f7239786e2dd4e69691436143024e05" - integrity sha512-IrlBhD9bm4bdYcS8xpWarazkKXlE7iYb1HzRuyBP114mIaj5DJPo11Us1HgH60dTt41TCZXMaTCAW+OILIYPOg== - dependencies: - "@typescript-eslint/types" "4.11.1" - eslint-visitor-keys "^2.0.0" - -"@upstatement/eslint-config@^0.4.3": - version "0.4.3" - resolved "https://registry.yarnpkg.com/@upstatement/eslint-config/-/eslint-config-0.4.3.tgz#9cfbe22d15c0fee2f7154e9f61455c4e53718027" - integrity sha512-I5wYURRsCUpYyTkyq/AOF+aNglJAde2Kzlq297pQ2r61AatUgn84Jw4CsYR6rgQNmTinpLtb8uwi12mOIaM8zg== - -"@upstatement/prettier-config@^0.3.0": - version "0.3.0" - resolved "https://registry.yarnpkg.com/@upstatement/prettier-config/-/prettier-config-0.3.0.tgz#cf34332dfba90c7586cd0bde134b7fc771163323" - integrity sha512-/DCKpd5tsgZ7Mshb7MSLdFkPRXHxZhzEKJP9ZW58ix0ARw1nbrcdbyiovHEutiQqmh4OjdLJjIAJ2MVUiEaB+Q== - dependencies: - prettier "^1.x.x" - -accepts@~1.3.7: - version "1.3.7" - resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.7.tgz#531bc726517a3b2b41f850021c6cc15eaab507cd" - integrity sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA== - dependencies: - mime-types "~2.1.24" - negotiator "0.6.2" - -acorn-jsx@^5.2.0, acorn-jsx@^5.3.1: - version "5.3.1" - resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.1.tgz#fc8661e11b7ac1539c47dbfea2e72b3af34d267b" - integrity sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng== - -acorn@^7.1.1, acorn@^7.4.0: - version "7.4.1" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa" - integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A== - -ajv@^6.10.0, ajv@^6.10.2, ajv@^6.12.4: - version "6.12.6" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" - integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== - dependencies: - fast-deep-equal "^3.1.1" - fast-json-stable-stringify "^2.0.0" - json-schema-traverse "^0.4.1" - uri-js "^4.2.2" - -ajv@^7.0.2: - version "7.0.3" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-7.0.3.tgz#13ae747eff125cafb230ac504b2406cf371eece2" - integrity sha512-R50QRlXSxqXcQP5SvKUrw8VZeypvo12i2IX0EeR5PiZ7bEKeHWgzgo264LDadUsCU42lTJVhFikTqJwNeH34gQ== - dependencies: - fast-deep-equal "^3.1.1" - json-schema-traverse "^1.0.0" - require-from-string "^2.0.2" - uri-js "^4.2.2" - -anser@1.4.9: - version "1.4.9" - resolved "https://registry.yarnpkg.com/anser/-/anser-1.4.9.tgz#1f85423a5dcf8da4631a341665ff675b96845760" - integrity sha512-AI+BjTeGt2+WFk4eWcqbQ7snZpDBt8SaLlj0RT2h5xfdWaiy51OjYvqwMrNzJLGy8iOAL6nKDITWO+rd4MkYEA== - -ansi-colors@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348" - integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA== - -ansi-escapes@^4.2.1: - version "4.3.1" - resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.1.tgz#a5c47cc43181f1f38ffd7076837700d395522a61" - integrity sha512-JWF7ocqNrp8u9oqpgV+wH5ftbt+cfvv+PTjOvKLT3AdYly/LmORARfEVT1iyjwN+4MqE5UmVKoAdIBqeoCHgLA== - dependencies: - type-fest "^0.11.0" - -ansi-regex@^2.0.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" - integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8= - -ansi-regex@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" - integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg= - -ansi-regex@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997" - integrity sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg== - -ansi-regex@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.0.tgz#388539f55179bf39339c81af30a654d69f87cb75" - integrity sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg== - -ansi-styles@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" - integrity sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4= - -ansi-styles@^3.2.0, ansi-styles@^3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" - integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== - dependencies: - color-convert "^1.9.0" - -ansi-styles@^4.0.0, ansi-styles@^4.1.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" - integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== - dependencies: - color-convert "^2.0.1" - -anymatch@~3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.1.tgz#c55ecf02185e2469259399310c173ce31233b142" - integrity sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg== - dependencies: - normalize-path "^3.0.0" - picomatch "^2.0.4" - -arg@^4.1.3: - version "4.1.3" - resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089" - integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA== - -argparse@^1.0.7: - version "1.0.10" - resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" - integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== - dependencies: - sprintf-js "~1.0.2" - -aria-hidden@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/aria-hidden/-/aria-hidden-1.1.1.tgz#0c356026d3f65e2bd487a3adb73f0c586be2c37e" - integrity sha512-M7zYxCcOQPOaxGHoMTKUFD2UNcVFTp9ycrdStLcTPLf8zgTXC3+YcGe+UuzSh5X1BX/0/PtS8xTNy4xyH/6xtw== - dependencies: - tslib "^1.0.0" - -aria-query@^4.2.2: - version "4.2.2" - resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-4.2.2.tgz#0d2ca6c9aceb56b8977e9fed6aed7e15bbd2f83b" - integrity sha512-o/HelwhuKpTj/frsOsbNLNgnNGVIFsVP/SW2BSF14gVl7kAfMOJ6/8wUAUvG1R1NHKrfG+2sHZTu0yauT1qBrA== - dependencies: - "@babel/runtime" "^7.10.2" - "@babel/runtime-corejs3" "^7.10.2" - -array-filter@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/array-filter/-/array-filter-1.0.0.tgz#baf79e62e6ef4c2a4c0b831232daffec251f9d83" - integrity sha1-uveeYubvTCpMC4MSMtr/7CUfnYM= - -array-flatten@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" - integrity sha1-ml9pkFGx5wczKPKgCJaLZOopVdI= - -array-includes@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.1.tgz#cdd67e6852bdf9c1215460786732255ed2459348" - integrity sha512-c2VXaCHl7zPsvpkFsw4nxvFie4fh1ur9bpcgsVkIjqn0H/Xwdg+7fv3n2r/isyS8EBj5b06M9kHyZuIr4El6WQ== - dependencies: - define-properties "^1.1.3" - es-abstract "^1.17.0" - is-string "^1.0.5" - -array-union@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" - integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== - -array.prototype.flat@^1.2.3: - version "1.2.4" - resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.2.4.tgz#6ef638b43312bd401b4c6199fdec7e2dc9e9a123" - integrity sha512-4470Xi3GAPAjZqFcljX2xzckv1qeKPizoNkiS0+O4IoPR2ZNpcjE0pkhdihlDouK+x6QOast26B4Q/O9DJnwSg== - dependencies: - call-bind "^1.0.0" - define-properties "^1.1.3" - es-abstract "^1.18.0-next.1" - -array.prototype.flatmap@^1.2.3: - version "1.2.3" - resolved "https://registry.yarnpkg.com/array.prototype.flatmap/-/array.prototype.flatmap-1.2.3.tgz#1c13f84a178566042dd63de4414440db9222e443" - integrity sha512-OOEk+lkePcg+ODXIpvuU9PAryCikCJyo7GlDG1upleEpQRx6mzL9puEBkozQ5iAx20KV0l3DbyQwqciJtqe5Pg== - dependencies: - define-properties "^1.1.3" - es-abstract "^1.17.0-next.1" - function-bind "^1.1.1" - -asn1.js@^5.2.0: - version "5.4.1" - resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-5.4.1.tgz#11a980b84ebb91781ce35b0fdc2ee294e3783f07" - integrity sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA== - dependencies: - bn.js "^4.0.0" - inherits "^2.0.1" - minimalistic-assert "^1.0.0" - safer-buffer "^2.1.0" - -assert@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/assert/-/assert-2.0.0.tgz#95fc1c616d48713510680f2eaf2d10dd22e02d32" - integrity sha512-se5Cd+js9dXJnu6Ag2JFc00t+HmHOen+8Q+L7O9zI0PqQXr20uk2J0XQqMxZEeo5U50o8Nvmmx7dZrl+Ufr35A== - dependencies: - es6-object-assign "^1.1.0" - is-nan "^1.2.1" - object-is "^1.0.1" - util "^0.12.0" - -assert@^1.1.1: - version "1.5.0" - resolved "https://registry.yarnpkg.com/assert/-/assert-1.5.0.tgz#55c109aaf6e0aefdb3dc4b71240c70bf574b18eb" - integrity sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA== - dependencies: - object-assign "^4.1.1" - util "0.10.3" - -ast-types-flow@^0.0.7: - version "0.0.7" - resolved "https://registry.yarnpkg.com/ast-types-flow/-/ast-types-flow-0.0.7.tgz#f70b735c6bca1a5c9c22d982c3e39e7feba3bdad" - integrity sha1-9wtzXGvKGlycItmCw+Oef+ujva0= - -ast-types@0.13.2: - version "0.13.2" - resolved "https://registry.yarnpkg.com/ast-types/-/ast-types-0.13.2.tgz#df39b677a911a83f3a049644fb74fdded23cea48" - integrity sha512-uWMHxJxtfj/1oZClOxDEV1sQ1HCDkA4MG8Gr69KKeBjEVH0R84WlejZ0y2DcwyBlpAEMltmVYkVgqfLFb2oyiA== - -astral-regex@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-1.0.0.tgz#6c8c3fb827dd43ee3918f27b82782ab7658a6fd9" - integrity sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg== - -astral-regex@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31" - integrity sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ== - -available-typed-arrays@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.2.tgz#6b098ca9d8039079ee3f77f7b783c4480ba513f5" - integrity sha512-XWX3OX8Onv97LMk/ftVyBibpGwY5a8SmuxZPzeOxqmuEqUCOM9ZE+uIaD1VNJ5QnvU2UQusvmKbuM1FR8QWGfQ== - dependencies: - array-filter "^1.0.0" - -axe-core@^3.5.4: - version "3.5.5" - resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-3.5.5.tgz#84315073b53fa3c0c51676c588d59da09a192227" - integrity sha512-5P0QZ6J5xGikH780pghEdbEKijCTrruK9KxtPZCFWUpef0f6GipO+xEZ5GKCb020mmqgbiNO6TcA55CriL784Q== - -axobject-query@^2.1.2: - version "2.2.0" - resolved "https://registry.yarnpkg.com/axobject-query/-/axobject-query-2.2.0.tgz#943d47e10c0b704aa42275e20edf3722648989be" - integrity sha512-Td525n+iPOOyUQIeBfcASuG6uJsDOITl7Mds5gFyerkWiX7qhUTdYUBlSgNMyVqtSJqwpt1kXGLdUt6SykLMRA== - -babel-eslint@^10.1.0: - version "10.1.0" - resolved "https://registry.yarnpkg.com/babel-eslint/-/babel-eslint-10.1.0.tgz#6968e568a910b78fb3779cdd8b6ac2f479943232" - integrity sha512-ifWaTHQ0ce+448CYop8AdrQiBsGrnC+bMgfyKFdi6EsPLTAWG+QfyDeM6OH+FmWnKvEq5NnBMLvlBUPKQZoDSg== - dependencies: - "@babel/code-frame" "^7.0.0" - "@babel/parser" "^7.7.0" - "@babel/traverse" "^7.7.0" - "@babel/types" "^7.7.0" - eslint-visitor-keys "^1.0.0" - resolve "^1.12.0" - -babel-plugin-macros@^2.6.1: - version "2.8.0" - resolved "https://registry.yarnpkg.com/babel-plugin-macros/-/babel-plugin-macros-2.8.0.tgz#0f958a7cc6556b1e65344465d99111a1e5e10138" - integrity sha512-SEP5kJpfGYqYKpBrj5XU3ahw5p5GOHJ0U5ssOSQ/WBVdwkD2Dzlce95exQTs3jOVWPPKLBN2rlEWkCK7dSmLvg== - dependencies: - "@babel/runtime" "^7.7.2" - cosmiconfig "^6.0.0" - resolve "^1.12.0" - -babel-plugin-syntax-jsx@6.18.0: - version "6.18.0" - resolved "https://registry.yarnpkg.com/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz#0af32a9a6e13ca7a3fd5069e62d7b0f58d0d8946" - integrity sha1-CvMqmm4Tyno/1QaeYtew9Y0NiUY= - -bail@^1.0.0: - version "1.0.5" - resolved "https://registry.yarnpkg.com/bail/-/bail-1.0.5.tgz#b6fa133404a392cbc1f8c4bf63f5953351e7a776" - integrity sha512-xFbRxM1tahm08yHBP16MMjVUAvDaBMD38zsM9EMAUN61omwLmKlOpB/Zku5QkjZ8TZ4vn53pj+t518cH0S03RQ== - -balanced-match@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" - integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= - -base64-js@^1.0.2: - version "1.3.1" - resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.3.1.tgz#58ece8cb75dd07e71ed08c736abc5fac4dbf8df1" - integrity sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g== - -big-integer@^1.6.16: - version "1.6.48" - resolved "https://registry.yarnpkg.com/big-integer/-/big-integer-1.6.48.tgz#8fd88bd1632cba4a1c8c3e3d7159f08bb95b4b9e" - integrity sha512-j51egjPa7/i+RdiRuJbPdJ2FIUYYPhvYLjzoYbcMMm62ooO6F94fETG4MTs46zPAF9Brs04OajboA/qTGuz78w== - -big.js@^5.2.2: - version "5.2.2" - resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328" - integrity sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ== - -binary-extensions@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.1.0.tgz#30fa40c9e7fe07dbc895678cd287024dea241dd9" - integrity sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ== - -bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.4.0: - version "4.11.9" - resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.9.tgz#26d556829458f9d1e81fc48952493d0ba3507828" - integrity sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw== - -bn.js@^5.1.1: - version "5.1.3" - resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.1.3.tgz#beca005408f642ebebea80b042b4d18d2ac0ee6b" - integrity sha512-GkTiFpjFtUzU9CbMeJ5iazkCzGL3jrhzerzZIuqLABjbwRaFt33I9tUdSNryIptM+RxDet6OKm2WnLXzW51KsQ== - -body-parser@1.19.0: - version "1.19.0" - resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.19.0.tgz#96b2709e57c9c4e09a6fd66a8fd979844f69f08a" - integrity sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw== - dependencies: - bytes "3.1.0" - content-type "~1.0.4" - debug "2.6.9" - depd "~1.1.2" - http-errors "1.7.2" - iconv-lite "0.4.24" - on-finished "~2.3.0" - qs "6.7.0" - raw-body "2.4.0" - type-is "~1.6.17" - -brace-expansion@^1.1.7: - version "1.1.11" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" - integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== - dependencies: - balanced-match "^1.0.0" - concat-map "0.0.1" - -braces@^3.0.1, braces@~3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" - integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== - dependencies: - fill-range "^7.0.1" - -broadcast-channel@^3.4.1: - version "3.6.0" - resolved "https://registry.yarnpkg.com/broadcast-channel/-/broadcast-channel-3.6.0.tgz#7843ffd86529be300dd1d03668a35301626ed03f" - integrity sha512-0x87tKJULniTOfECZP/LCsqWyMEbz0Oa+4yJ4i5dosOMxWUjx6mZ6nt9QmD2ox0r3MaCPojHrTQ2dj4ASZupeA== - dependencies: - "@babel/runtime" "^7.7.2" - detect-node "^2.1.0" - js-sha3 "0.8.0" - microseconds "0.2.0" - nano-time "1.0.0" - rimraf "3.0.2" - unload "2.2.0" - -brorand@^1.0.1: - version "1.1.0" - resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" - integrity sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8= - -browserify-aes@^1.0.0, browserify-aes@^1.0.4: - version "1.2.0" - resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.2.0.tgz#326734642f403dabc3003209853bb70ad428ef48" - integrity sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA== - dependencies: - buffer-xor "^1.0.3" - cipher-base "^1.0.0" - create-hash "^1.1.0" - evp_bytestokey "^1.0.3" - inherits "^2.0.1" - safe-buffer "^5.0.1" - -browserify-cipher@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/browserify-cipher/-/browserify-cipher-1.0.1.tgz#8d6474c1b870bfdabcd3bcfcc1934a10e94f15f0" - integrity sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w== - dependencies: - browserify-aes "^1.0.4" - browserify-des "^1.0.0" - evp_bytestokey "^1.0.0" - -browserify-des@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/browserify-des/-/browserify-des-1.0.2.tgz#3af4f1f59839403572f1c66204375f7a7f703e9c" - integrity sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A== - dependencies: - cipher-base "^1.0.1" - des.js "^1.0.0" - inherits "^2.0.1" - safe-buffer "^5.1.2" - -browserify-rsa@^4.0.0, browserify-rsa@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/browserify-rsa/-/browserify-rsa-4.0.1.tgz#21e0abfaf6f2029cf2fafb133567a701d4135524" - integrity sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ= - dependencies: - bn.js "^4.1.0" - randombytes "^2.0.1" - -browserify-sign@^4.0.0: - version "4.2.1" - resolved "https://registry.yarnpkg.com/browserify-sign/-/browserify-sign-4.2.1.tgz#eaf4add46dd54be3bb3b36c0cf15abbeba7956c3" - integrity sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg== - dependencies: - bn.js "^5.1.1" - browserify-rsa "^4.0.1" - create-hash "^1.2.0" - create-hmac "^1.1.7" - elliptic "^6.5.3" - inherits "^2.0.4" - parse-asn1 "^5.1.5" - readable-stream "^3.6.0" - safe-buffer "^5.2.0" - -browserify-zlib@0.2.0, browserify-zlib@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/browserify-zlib/-/browserify-zlib-0.2.0.tgz#2869459d9aa3be245fe8fe2ca1f46e2e7f54d73f" - integrity sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA== - dependencies: - pako "~1.0.5" - -browserslist@4.16.6: - version "4.16.6" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.16.6.tgz#d7901277a5a88e554ed305b183ec9b0c08f66fa2" - integrity sha512-Wspk/PqO+4W9qp5iUTJsa1B/QrYn1keNCcEP5OvP7WBwT4KaDly0uONYmC6Xa3Z5IqnUgS0KcgLYu1l74x0ZXQ== - dependencies: - caniuse-lite "^1.0.30001219" - colorette "^1.2.2" - electron-to-chromium "^1.3.723" - escalade "^3.1.1" - node-releases "^1.1.71" - -buffer-xor@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9" - integrity sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk= - -buffer@5.6.0: - version "5.6.0" - resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.6.0.tgz#a31749dc7d81d84db08abf937b6b8c4033f62786" - integrity sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw== - dependencies: - base64-js "^1.0.2" - ieee754 "^1.1.4" - -buffer@^4.3.0: - version "4.9.2" - resolved "https://registry.yarnpkg.com/buffer/-/buffer-4.9.2.tgz#230ead344002988644841ab0244af8c44bbe3ef8" - integrity sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg== - dependencies: - base64-js "^1.0.2" - ieee754 "^1.1.4" - isarray "^1.0.0" - -builtin-status-codes@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8" - integrity sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug= - -bytes@3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.0.tgz#f6cf7933a360e0588fa9fde85651cdc7f805d1f6" - integrity sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg== - -call-bind@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.0.tgz#24127054bb3f9bdcb4b1fb82418186072f77b8ce" - integrity sha512-AEXsYIyyDY3MCzbwdhzG3Jx1R0J2wetQyUynn6dYHAO+bg8l1k7jwZtRv4ryryFs7EP+NDlikJlVe59jr0cM2w== - dependencies: - function-bind "^1.1.1" - get-intrinsic "^1.0.0" - -call-bind@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" - integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA== - dependencies: - function-bind "^1.1.1" - get-intrinsic "^1.0.2" - -callsites@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" - integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== - -camelcase@^5.0.0: - version "5.3.1" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" - integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== - -caniuse-lite@^1.0.30001202, caniuse-lite@^1.0.30001219, caniuse-lite@^1.0.30001228: - version "1.0.30001230" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001230.tgz#8135c57459854b2240b57a4a6786044bdc5a9f71" - integrity sha512-5yBd5nWCBS+jWKTcHOzXwo5xzcj4ePE/yjtkZyUV1BTUmrBaA9MRGC+e7mxnqXSA90CmCA8L3eKLaSUkt099IQ== - -ccount@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/ccount/-/ccount-1.1.0.tgz#246687debb6014735131be8abab2d93898f8d043" - integrity sha512-vlNK021QdI7PNeiUh/lKkC/mNHHfV0m/Ad5JoI0TYtlBnJAslM/JIkm/tGC88bkLIwO6OQ5uV6ztS6kVAtCDlg== - -chalk@2.4.2, chalk@^2.0.0, chalk@^2.1.0: - version "2.4.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" - integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== - dependencies: - ansi-styles "^3.2.1" - escape-string-regexp "^1.0.5" - supports-color "^5.3.0" - -chalk@4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.0.0.tgz#6e98081ed2d17faab615eb52ac66ec1fe6209e72" - integrity sha512-N9oWFcegS0sFr9oh1oz2d7Npos6vNoWW9HvtCg5N1KRFpUhaAhvTv5Y58g880fZaEYSNm3qDz8SU1UrGvp+n7A== - dependencies: - ansi-styles "^4.1.0" - supports-color "^7.1.0" - -chalk@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" - integrity sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg= - dependencies: - ansi-styles "^2.2.1" - escape-string-regexp "^1.0.2" - has-ansi "^2.0.0" - strip-ansi "^3.0.0" - supports-color "^2.0.0" - -chalk@^4.0.0, chalk@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.0.tgz#4e14870a618d9e2edd97dd8345fd9d9dc315646a" - integrity sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A== - dependencies: - ansi-styles "^4.1.0" - supports-color "^7.1.0" - -character-entities-legacy@^1.0.0: - version "1.1.4" - resolved "https://registry.yarnpkg.com/character-entities-legacy/-/character-entities-legacy-1.1.4.tgz#94bc1845dce70a5bb9d2ecc748725661293d8fc1" - integrity sha512-3Xnr+7ZFS1uxeiUDvV02wQ+QDbc55o97tIV5zHScSPJpcLm/r0DFPcoY3tYRp+VZukxuMeKgXYmsXQHO05zQeA== - -character-entities@^1.0.0: - version "1.2.4" - resolved "https://registry.yarnpkg.com/character-entities/-/character-entities-1.2.4.tgz#e12c3939b7eaf4e5b15e7ad4c5e28e1d48c5b16b" - integrity sha512-iBMyeEHxfVnIakwOuDXpVkc54HijNgCyQB2w0VfGQThle6NXn50zU6V/u+LDhxHcDUPojn6Kpga3PTAD8W1bQw== - -character-reference-invalid@^1.0.0: - version "1.1.4" - resolved "https://registry.yarnpkg.com/character-reference-invalid/-/character-reference-invalid-1.1.4.tgz#083329cda0eae272ab3dbbf37e9a382c13af1560" - integrity sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg== - -chardet@^0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" - integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA== - -chokidar@3.5.1: - version "3.5.1" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.1.tgz#ee9ce7bbebd2b79f49f304799d5468e31e14e68a" - integrity sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw== - dependencies: - anymatch "~3.1.1" - braces "~3.0.2" - glob-parent "~5.1.0" - is-binary-path "~2.1.0" - is-glob "~4.0.1" - normalize-path "~3.0.0" - readdirp "~3.5.0" - optionalDependencies: - fsevents "~2.3.1" - -chokidar@^3.3.1: - version "3.4.3" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.4.3.tgz#c1df38231448e45ca4ac588e6c79573ba6a57d5b" - integrity sha512-DtM3g7juCXQxFVSNPNByEC2+NImtBuxQQvWlHunpJIS5Ocr0lG306cC7FCi7cEA0fzmybPUIl4txBIobk1gGOQ== - dependencies: - anymatch "~3.1.1" - braces "~3.0.2" - glob-parent "~5.1.0" - is-binary-path "~2.1.0" - is-glob "~4.0.1" - normalize-path "~3.0.0" - readdirp "~3.5.0" - optionalDependencies: - fsevents "~2.1.2" - -cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de" - integrity sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q== - dependencies: - inherits "^2.0.1" - safe-buffer "^5.0.1" - -classcat@^5.0.3: - version "5.0.3" - resolved "https://registry.yarnpkg.com/classcat/-/classcat-5.0.3.tgz#38eaa0ec6eb1b10faf101bbcef2afb319c23c17b" - integrity sha512-6dK2ke4VEJZOFx2ZfdDAl5OhEL8lvkl6EHF92IfRePfHxQTqir5NlcNVUv+2idjDqCX2NDc8m8YSAI5NI975ZQ== - -classnames@2.2.6: - version "2.2.6" - resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.2.6.tgz#43935bffdd291f326dad0a205309b38d00f650ce" - integrity sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q== - -classnames@^2.2.5: - version "2.3.1" - resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.3.1.tgz#dfcfa3891e306ec1dad105d0e88f4417b8535e8e" - integrity sha512-OlQdbZ7gLfGarSqxesMesDa5uz7KFbID8Kpq/SxIoNGDqY8lSYs0D+hhtBXhcdB3rcbXArFr7vlHheLk1voeNA== - -cli-cursor@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-3.1.0.tgz#264305a7ae490d1d03bf0c9ba7c925d1753af307" - integrity sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw== - dependencies: - restore-cursor "^3.1.0" - -cli-width@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-3.0.0.tgz#a2f48437a2caa9a22436e794bf071ec9e61cedf6" - integrity sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw== - -color-convert@^1.9.0: - version "1.9.3" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" - integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== - dependencies: - color-name "1.1.3" - -color-convert@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" - integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== - dependencies: - color-name "~1.1.4" - -color-name@1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" - integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= - -color-name@~1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" - integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== - -color2k@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/color2k/-/color2k-1.1.1.tgz#f9703fab6693e2a407962211f1ab7e8e0602d5d7" - integrity sha512-pkIVqioT1tEJOwfN5O/ZNLMG55H1GhA5WlvasHR2Zj07pIDgA5JDxkqqLIz2PfZOJC8IvuJbdp1YIRbeo+MlMQ== - -colorette@^1.2.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.2.2.tgz#cbcc79d5e99caea2dbf10eb3a26fd8b3e6acfa94" - integrity sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w== - -common-tags@^1.4.0: - version "1.8.0" - resolved "https://registry.yarnpkg.com/common-tags/-/common-tags-1.8.0.tgz#8e3153e542d4a39e9b10554434afaaf98956a937" - integrity sha512-6P6g0uetGpW/sdyUy/iQQCbFF0kWVMSIVSyYz7Zgjcgh8mgw8PQzDNZeyZ5DQ2gM7LBoZPHmnjz8rUthkBG5tw== - -commondir@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" - integrity sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs= - -compute-scroll-into-view@1.0.14: - version "1.0.14" - resolved "https://registry.yarnpkg.com/compute-scroll-into-view/-/compute-scroll-into-view-1.0.14.tgz#80e3ebb25d6aa89f42e533956cb4b16a04cfe759" - integrity sha512-mKDjINe3tc6hGelUMNDzuhorIUZ7kS7BwyY0r2wQd2HOH2tRuJykiC06iSEX8y1TuhNzvz4GcJnK16mM2J1NMQ== - -concat-map@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" - integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= - -confusing-browser-globals@^1.0.9: - version "1.0.9" - resolved "https://registry.yarnpkg.com/confusing-browser-globals/-/confusing-browser-globals-1.0.9.tgz#72bc13b483c0276801681871d4898516f8f54fdd" - integrity sha512-KbS1Y0jMtyPgIxjO7ZzMAuUpAKMt1SzCL9fsrKsX6b0zJPTaT0SiSPmewwVZg9UAO83HVIlEhZF84LIjZ0lmAw== - -console-browserify@^1.1.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.2.0.tgz#67063cef57ceb6cf4993a2ab3a55840ae8c49336" - integrity sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA== - -constants-browserify@1.0.0, constants-browserify@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/constants-browserify/-/constants-browserify-1.0.0.tgz#c20b96d8c617748aaf1c16021760cd27fcb8cb75" - integrity sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U= - -contains-path@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/contains-path/-/contains-path-0.1.0.tgz#fe8cf184ff6670b6baef01a9d4861a5cbec4120a" - integrity sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo= - -content-disposition@0.5.3: - version "0.5.3" - resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.3.tgz#e130caf7e7279087c5616c2007d0485698984fbd" - integrity sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g== - dependencies: - safe-buffer "5.1.2" - -content-type@~1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" - integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA== - -convert-source-map@1.7.0, convert-source-map@^1.5.0: - version "1.7.0" - resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.7.0.tgz#17a2cb882d7f77d3490585e2ce6c524424a3a442" - integrity sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA== - dependencies: - safe-buffer "~5.1.1" - -cookie-signature@1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" - integrity sha1-4wOogrNCzD7oylE6eZmXNNqzriw= - -cookie@0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.0.tgz#beb437e7022b3b6d49019d088665303ebe9c14ba" - integrity sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg== - -copy-to-clipboard@3.3.1: - version "3.3.1" - resolved "https://registry.yarnpkg.com/copy-to-clipboard/-/copy-to-clipboard-3.3.1.tgz#115aa1a9998ffab6196f93076ad6da3b913662ae" - integrity sha512-i13qo6kIHTTpCm8/Wup+0b1mVWETvu2kIMzKoK8FpkLkFxlt0znUAHcMzox+T8sPlqtZXq3CulEjQHsYiGFJUw== - dependencies: - toggle-selection "^1.0.6" - -core-js-pure@^3.0.0: - version "3.6.5" - resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.6.5.tgz#c79e75f5e38dbc85a662d91eea52b8256d53b813" - integrity sha512-lacdXOimsiD0QyNf9BC/mxivNJ/ybBGJXQFKzRekp1WTHoVUWsUHEn+2T8GJAzzIhyOuXA+gOxCVN3l+5PLPUA== - -core-util-is@~1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" - integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= - -cosmiconfig@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-6.0.0.tgz#da4fee853c52f6b1e6935f41c1a2fc50bd4a9982" - integrity sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg== - dependencies: - "@types/parse-json" "^4.0.0" - import-fresh "^3.1.0" - parse-json "^5.0.0" - path-type "^4.0.0" - yaml "^1.7.2" - -create-ecdh@^4.0.0: - version "4.0.4" - resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.4.tgz#d6e7f4bffa66736085a0762fd3a632684dabcc4e" - integrity sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A== - dependencies: - bn.js "^4.1.0" - elliptic "^6.5.3" - -create-hash@^1.1.0, create-hash@^1.1.2, create-hash@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.2.0.tgz#889078af11a63756bcfb59bd221996be3a9ef196" - integrity sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg== - dependencies: - cipher-base "^1.0.1" - inherits "^2.0.1" - md5.js "^1.3.4" - ripemd160 "^2.0.1" - sha.js "^2.4.0" - -create-hmac@^1.1.0, create-hmac@^1.1.4, create-hmac@^1.1.7: - version "1.1.7" - resolved "https://registry.yarnpkg.com/create-hmac/-/create-hmac-1.1.7.tgz#69170c78b3ab957147b2b8b04572e47ead2243ff" - integrity sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg== - dependencies: - cipher-base "^1.0.3" - create-hash "^1.1.0" - inherits "^2.0.1" - ripemd160 "^2.0.0" - safe-buffer "^5.0.1" - sha.js "^2.4.8" - -cross-spawn@^6.0.5: - version "6.0.5" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" - integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ== - dependencies: - nice-try "^1.0.4" - path-key "^2.0.1" - semver "^5.5.0" - shebang-command "^1.2.0" - which "^1.2.9" - -cross-spawn@^7.0.1, cross-spawn@^7.0.2: - version "7.0.3" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" - integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== - dependencies: - path-key "^3.1.0" - shebang-command "^2.0.0" - which "^2.0.1" - -crypto-browserify@3.12.0, crypto-browserify@^3.11.0: - version "3.12.0" - resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.12.0.tgz#396cf9f3137f03e4b8e532c58f698254e00f80ec" - integrity sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg== - dependencies: - browserify-cipher "^1.0.0" - browserify-sign "^4.0.0" - create-ecdh "^4.0.0" - create-hash "^1.1.0" - create-hmac "^1.1.0" - diffie-hellman "^5.0.0" - inherits "^2.0.1" - pbkdf2 "^3.0.3" - public-encrypt "^4.0.0" - randombytes "^2.0.0" - randomfill "^1.0.3" - -css-box-model@1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/css-box-model/-/css-box-model-1.2.1.tgz#59951d3b81fd6b2074a62d49444415b0d2b4d7c1" - integrity sha512-a7Vr4Q/kd/aw96bnJG332W9V9LkJO69JRcaCYDUqjp6/z0w6VcZjgAcTbgFxEPfBgdnAwlh3iwu+hLopa+flJw== - dependencies: - tiny-invariant "^1.0.6" - -css.escape@1.5.1: - version "1.5.1" - resolved "https://registry.yarnpkg.com/css.escape/-/css.escape-1.5.1.tgz#42e27d4fa04ae32f931a4b4d4191fa9cddee97cb" - integrity sha1-QuJ9T6BK4y+TGktNQZH6nN3ul8s= - -cssnano-preset-simple@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/cssnano-preset-simple/-/cssnano-preset-simple-2.0.0.tgz#b55e72cb970713f425560a0e141b0335249e2f96" - integrity sha512-HkufSLkaBJbKBFx/7aj5HmCK9Ni/JedRQm0mT2qBzMG/dEuJOLnMt2lK6K1rwOOyV4j9aSY+knbW9WoS7BYpzg== - dependencies: - caniuse-lite "^1.0.30001202" - -cssnano-simple@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/cssnano-simple/-/cssnano-simple-2.0.0.tgz#930d9dcd8ba105c5a62ce719cb00854da58b5c05" - integrity sha512-0G3TXaFxlh/szPEG/o3VcmCwl0N3E60XNb9YZZijew5eIs6fLjJuOPxQd9yEBaX2p/YfJtt49i4vYi38iH6/6w== - dependencies: - cssnano-preset-simple "^2.0.0" - -csstype@^3.0.2: - version "3.0.3" - resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.0.3.tgz#2b410bbeba38ba9633353aff34b05d9755d065f8" - integrity sha512-jPl+wbWPOWJ7SXsWyqGRk3lGecbar0Cb0OvZF/r/ZU011R4YqiRehgkQ9p4eQfo9DSDLqLL3wHwfxeJiuIsNag== - -csstype@^3.0.6: - version "3.0.7" - resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.0.7.tgz#2a5fb75e1015e84dd15692f71e89a1450290950b" - integrity sha512-KxnUB0ZMlnUWCsx2Z8MUsr6qV6ja1w9ArPErJaJaF8a5SOWoHLIszeCTKGRGRgtLgYrs1E8CHkNSP1VZTTPc9g== - -"d3-color@1 - 2": - version "2.0.0" - resolved "https://registry.yarnpkg.com/d3-color/-/d3-color-2.0.0.tgz#8d625cab42ed9b8f601a1760a389f7ea9189d62e" - integrity sha512-SPXi0TSKPD4g9tw0NMZFnR95XVgUZiBH+uUTqQuDu1OsE2zomHU7ho0FISciaPvosimixwHFl3WHLGabv6dDgQ== - -"d3-dispatch@1 - 2": - version "2.0.0" - resolved "https://registry.yarnpkg.com/d3-dispatch/-/d3-dispatch-2.0.0.tgz#8a18e16f76dd3fcaef42163c97b926aa9b55e7cf" - integrity sha512-S/m2VsXI7gAti2pBoLClFFTMOO1HTtT0j99AuXLoGFKO6deHDdnv6ZGTxSTTUTgO1zVcv82fCOtDjYK4EECmWA== - -d3-drag@2: - version "2.0.0" - resolved "https://registry.yarnpkg.com/d3-drag/-/d3-drag-2.0.0.tgz#9eaf046ce9ed1c25c88661911c1d5a4d8eb7ea6d" - integrity sha512-g9y9WbMnF5uqB9qKqwIIa/921RYWzlUDv9Jl1/yONQwxbOfszAWTCm8u7HOTgJgRDXiRZN56cHT9pd24dmXs8w== - dependencies: - d3-dispatch "1 - 2" - d3-selection "2" - -"d3-ease@1 - 2": - version "2.0.0" - resolved "https://registry.yarnpkg.com/d3-ease/-/d3-ease-2.0.0.tgz#fd1762bfca00dae4bacea504b1d628ff290ac563" - integrity sha512-68/n9JWarxXkOWMshcT5IcjbB+agblQUaIsbnXmrzejn2O82n3p2A9R2zEB9HIEFWKFwPAEDDN8gR0VdSAyyAQ== - -"d3-interpolate@1 - 2": - version "2.0.1" - resolved "https://registry.yarnpkg.com/d3-interpolate/-/d3-interpolate-2.0.1.tgz#98be499cfb8a3b94d4ff616900501a64abc91163" - integrity sha512-c5UhwwTs/yybcmTpAVqwSFl6vrQ8JZJoT5F7xNFK9pymv5C0Ymcc9/LIJHtYIggg/yS9YHw8i8O8tgb9pupjeQ== - dependencies: - d3-color "1 - 2" - -d3-selection@2, d3-selection@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/d3-selection/-/d3-selection-2.0.0.tgz#94a11638ea2141b7565f883780dabc7ef6a61066" - integrity sha512-XoGGqhLUN/W14NmaqcO/bb1nqjDAw5WtSYb2X8wiuQWvSZUsUVYsOSkOybUrNvcBjaywBdYPy03eXHMXjk9nZA== - -"d3-timer@1 - 2": - version "2.0.0" - resolved "https://registry.yarnpkg.com/d3-timer/-/d3-timer-2.0.0.tgz#055edb1d170cfe31ab2da8968deee940b56623e6" - integrity sha512-TO4VLh0/420Y/9dO3+f9abDEFYeCUr2WZRlxJvbp4HPTQcSylXNiL6yZa9FIUvV1yRiFufl1bszTCLDqv9PWNA== - -d3-transition@2: - version "2.0.0" - resolved "https://registry.yarnpkg.com/d3-transition/-/d3-transition-2.0.0.tgz#366ef70c22ef88d1e34105f507516991a291c94c" - integrity sha512-42ltAGgJesfQE3u9LuuBHNbGrI/AJjNL2OAUdclE70UE6Vy239GCBEYD38uBPoLeNsOhFStGpPI0BAOV+HMxog== - dependencies: - d3-color "1 - 2" - d3-dispatch "1 - 2" - d3-ease "1 - 2" - d3-interpolate "1 - 2" - d3-timer "1 - 2" - -d3-zoom@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/d3-zoom/-/d3-zoom-2.0.0.tgz#f04d0afd05518becce879d04709c47ecd93fba54" - integrity sha512-fFg7aoaEm9/jf+qfstak0IYpnesZLiMX6GZvXtUSdv8RH2o4E2qeelgdU09eKS6wGuiGMfcnMI0nTIqWzRHGpw== - dependencies: - d3-dispatch "1 - 2" - d3-drag "2" - d3-interpolate "1 - 2" - d3-selection "2" - d3-transition "2" - -dagre@^0.8.5: - version "0.8.5" - resolved "https://registry.yarnpkg.com/dagre/-/dagre-0.8.5.tgz#ba30b0055dac12b6c1fcc247817442777d06afee" - integrity sha512-/aTqmnRta7x7MCCpExk7HQL2O4owCT2h8NT//9I1OQ9vt29Pa0BzSAkR5lwFUcQ7491yVi/3CXU9jQ5o0Mn2Sw== - dependencies: - graphlib "^2.1.8" - lodash "^4.17.15" - -damerau-levenshtein@^1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/damerau-levenshtein/-/damerau-levenshtein-1.0.6.tgz#143c1641cb3d85c60c32329e26899adea8701791" - integrity sha512-JVrozIeElnj3QzfUIt8tB8YMluBJom4Vw9qTPpjGYQ9fYlB3D/rb6OordUxf3xeFB35LKWs0xqcO5U6ySvBtug== - -data-uri-to-buffer@3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/data-uri-to-buffer/-/data-uri-to-buffer-3.0.1.tgz#594b8973938c5bc2c33046535785341abc4f3636" - integrity sha512-WboRycPNsVw3B3TL559F7kuBUM4d8CgMEvk6xEJlOp7OBPjt6G7z8WMWlD2rOFZLk6OYfFIUGsCOWzcQH9K2og== - -dayjs@^1.10.4: - version "1.10.4" - resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.10.4.tgz#8e544a9b8683f61783f570980a8a80eaf54ab1e2" - integrity sha512-RI/Hh4kqRc1UKLOAf/T5zdMMX5DQIlDxwUe3wSyMMnEbGunnpENCdbUgM+dW7kXidZqCttBrmw7BhN4TMddkCw== - -debug@2, debug@2.6.9, debug@^2.6.9: - version "2.6.9" - resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" - integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== - dependencies: - ms "2.0.0" - -debug@^4.0.0: - version "4.3.1" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.1.tgz#f0d229c505e0c6d8c49ac553d1b13dc183f6b2ee" - integrity sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ== - dependencies: - ms "2.1.2" - -debug@^4.0.1, debug@^4.1.0, debug@^4.1.1: - version "4.2.0" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.2.0.tgz#7f150f93920e94c58f5574c2fd01a3110effe7f1" - integrity sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg== - dependencies: - ms "2.1.2" - -deep-is@^0.1.3, deep-is@~0.1.3: - version "0.1.3" - resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" - integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ= - -define-properties@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" - integrity sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ== - dependencies: - object-keys "^1.0.12" - -depd@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" - integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak= - -des.js@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/des.js/-/des.js-1.0.1.tgz#5382142e1bdc53f85d86d53e5f4aa7deb91e0843" - integrity sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA== - dependencies: - inherits "^2.0.1" - minimalistic-assert "^1.0.0" - -destroy@~1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80" - integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA= - -detect-node-es@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/detect-node-es/-/detect-node-es-1.0.0.tgz#c0318b9e539a5256ca780dd9575c9345af05b8ed" - integrity sha512-S4AHriUkTX9FoFvL4G8hXDcx6t3gp2HpfCza3Q0v6S78gul2hKWifLQbeW+ZF89+hSm2ZIc/uF3J97ZgytgTRg== - -detect-node@^2.0.4, detect-node@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/detect-node/-/detect-node-2.1.0.tgz#c9c70775a49c3d03bc2c06d9a73be550f978f8b1" - integrity sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g== - -diffie-hellman@^5.0.0: - version "5.0.3" - resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.3.tgz#40e8ee98f55a2149607146921c63e1ae5f3d2875" - integrity sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg== - dependencies: - bn.js "^4.1.0" - miller-rabin "^4.0.0" - randombytes "^2.0.0" - -dir-glob@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" - integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== - dependencies: - path-type "^4.0.0" - -dlv@^1.1.0: - version "1.1.3" - resolved "https://registry.yarnpkg.com/dlv/-/dlv-1.1.3.tgz#5c198a8a11453596e751494d49874bc7732f2e79" - integrity sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA== - -doctrine@1.5.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-1.5.0.tgz#379dce730f6166f76cefa4e6707a159b02c5a6fa" - integrity sha1-N53Ocw9hZvds76TmcHoVmwLFpvo= - dependencies: - esutils "^2.0.2" - isarray "^1.0.0" - -doctrine@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d" - integrity sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw== - dependencies: - esutils "^2.0.2" - -doctrine@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" - integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w== - dependencies: - esutils "^2.0.2" - -dom-helpers@^5.0.1: - version "5.2.0" - resolved "https://registry.yarnpkg.com/dom-helpers/-/dom-helpers-5.2.0.tgz#57fd054c5f8f34c52a3eeffdb7e7e93cd357d95b" - integrity sha512-Ru5o9+V8CpunKnz5LGgWXkmrH/20cGKwcHwS4m73zIvs54CN9epEmT/HLqFJW3kXpakAFkEdzgy1hzlJe3E4OQ== - dependencies: - "@babel/runtime" "^7.8.7" - csstype "^3.0.2" - -dom-serializer@^1.0.1: - version "1.1.0" - resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-1.1.0.tgz#5f7c828f1bfc44887dc2a315ab5c45691d544b58" - integrity sha512-ox7bvGXt2n+uLWtCRLybYx60IrOlWL/aCebWJk1T0d4m3y2tzf4U3ij9wBMUb6YJZpz06HCCYuyCDveE2xXmzQ== - dependencies: - domelementtype "^2.0.1" - domhandler "^3.0.0" - entities "^2.0.0" - -domain-browser@4.19.0: - version "4.19.0" - resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-4.19.0.tgz#1093e17c0a17dbd521182fe90d49ac1370054af1" - integrity sha512-fRA+BaAWOR/yr/t7T9E9GJztHPeFjj8U35ajyAjCDtAAnTn1Rc1f6W6VGPJrO1tkQv9zWu+JRof7z6oQtiYVFQ== - -domain-browser@^1.1.1: - version "1.2.0" - resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-1.2.0.tgz#3d31f50191a6749dd1375a7f522e823d42e54eda" - integrity sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA== - -domelementtype@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.0.2.tgz#f3b6e549201e46f588b59463dd77187131fe6971" - integrity sha512-wFwTwCVebUrMgGeAwRL/NhZtHAUyT9n9yg4IMDwf10+6iCMxSkVq9MGCVEH+QZWo1nNidy8kNvwmv4zWHDTqvA== - -domhandler@^3.0.0, domhandler@^3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-3.3.0.tgz#6db7ea46e4617eb15cf875df68b2b8524ce0037a" - integrity sha512-J1C5rIANUbuYK+FuFL98650rihynUOEzRLxW+90bKZRWB6A1X1Tf82GxR1qAWLyfNPRvjqfip3Q5tdYlmAa9lA== - dependencies: - domelementtype "^2.0.1" - -domutils@^2.4.2: - version "2.4.2" - resolved "https://registry.yarnpkg.com/domutils/-/domutils-2.4.2.tgz#7ee5be261944e1ad487d9aa0616720010123922b" - integrity sha512-NKbgaM8ZJOecTZsIzW5gSuplsX2IWW2mIK7xVr8hTQF2v1CJWTmLZ1HOCh5sH+IzVPAGE5IucooOkvwBRAdowA== - dependencies: - dom-serializer "^1.0.1" - domelementtype "^2.0.1" - domhandler "^3.3.0" - -ee-first@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" - integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= - -electron-to-chromium@^1.3.723: - version "1.3.742" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.742.tgz#7223215acbbd3a5284962ebcb6df85d88b95f200" - integrity sha512-ihL14knI9FikJmH2XUIDdZFWJxvr14rPSdOhJ7PpS27xbz8qmaRwCwyg/bmFwjWKmWK9QyamiCZVCvXm5CH//Q== - -elliptic@^6.5.3: - version "6.5.3" - resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.3.tgz#cb59eb2efdaf73a0bd78ccd7015a62ad6e0f93d6" - integrity sha512-IMqzv5wNQf+E6aHeIqATs0tOLeOTwj1QKbRcS3jBbYkl5oLAserA8yJTT7/VyHUYG91PRmPyeQDObKLPpeS4dw== - dependencies: - bn.js "^4.4.0" - brorand "^1.0.1" - hash.js "^1.0.0" - hmac-drbg "^1.0.0" - inherits "^2.0.1" - minimalistic-assert "^1.0.0" - minimalistic-crypto-utils "^1.0.0" - -emoji-regex@^7.0.1: - version "7.0.3" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" - integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA== - -emoji-regex@^8.0.0: - version "8.0.0" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" - integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== - -emoji-regex@^9.0.0: - version "9.1.1" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.1.1.tgz#1d5ffce26d8191e6c3f3a9d27987b1c5bba7d20a" - integrity sha512-AaWyDiNO9rbtMIcGl7tdxMcNu8SOLaDLxmQEFT5JhgKufOJzPPkYmgN2QwqTgw4doWMZZQttC6sUWVQjb+1VdA== - -emojis-list@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-2.1.0.tgz#4daa4d9db00f9819880c79fa457ae5b09a1fd389" - integrity sha1-TapNnbAPmBmIDHn6RXrlsJof04k= - -encodeurl@~1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" - integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k= - -encoding@0.1.13: - version "0.1.13" - resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.13.tgz#56574afdd791f54a8e9b2785c0582a2d26210fa9" - integrity sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A== - dependencies: - iconv-lite "^0.6.2" - -enquirer@^2.3.5: - version "2.3.6" - resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.3.6.tgz#2a7fe5dd634a1e4125a975ec994ff5456dc3734d" - integrity sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg== - dependencies: - ansi-colors "^4.1.1" - -entities@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/entities/-/entities-2.1.0.tgz#992d3129cf7df6870b96c57858c249a120f8b8b5" - integrity sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w== - -error-ex@^1.2.0, error-ex@^1.3.1: - version "1.3.2" - resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" - integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== - dependencies: - is-arrayish "^0.2.1" - -es-abstract@^1.17.0, es-abstract@^1.17.0-next.1, es-abstract@^1.17.5: - version "1.17.7" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.17.7.tgz#a4de61b2f66989fc7421676c1cb9787573ace54c" - integrity sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g== - dependencies: - es-to-primitive "^1.2.1" - function-bind "^1.1.1" - has "^1.0.3" - has-symbols "^1.0.1" - is-callable "^1.2.2" - is-regex "^1.1.1" - object-inspect "^1.8.0" - object-keys "^1.1.1" - object.assign "^4.1.1" - string.prototype.trimend "^1.0.1" - string.prototype.trimstart "^1.0.1" - -es-abstract@^1.18.0-next.0, es-abstract@^1.18.0-next.1: - version "1.18.0-next.1" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.18.0-next.1.tgz#6e3a0a4bda717e5023ab3b8e90bec36108d22c68" - integrity sha512-I4UGspA0wpZXWENrdA0uHbnhte683t3qT/1VFH9aX2dA5PPSf6QW5HHXf5HImaqPmjXaVeVk4RGWnaylmV7uAA== - dependencies: - es-to-primitive "^1.2.1" - function-bind "^1.1.1" - has "^1.0.3" - has-symbols "^1.0.1" - is-callable "^1.2.2" - is-negative-zero "^2.0.0" - is-regex "^1.1.1" - object-inspect "^1.8.0" - object-keys "^1.1.1" - object.assign "^4.1.1" - string.prototype.trimend "^1.0.1" - string.prototype.trimstart "^1.0.1" - -es-abstract@^1.18.0-next.2: - version "1.18.0" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.18.0.tgz#ab80b359eecb7ede4c298000390bc5ac3ec7b5a4" - integrity sha512-LJzK7MrQa8TS0ja2w3YNLzUgJCGPdPOV1yVvezjNnS89D+VR08+Szt2mz3YB2Dck/+w5tfIq/RoUAFqJJGM2yw== - dependencies: - call-bind "^1.0.2" - es-to-primitive "^1.2.1" - function-bind "^1.1.1" - get-intrinsic "^1.1.1" - has "^1.0.3" - has-symbols "^1.0.2" - is-callable "^1.2.3" - is-negative-zero "^2.0.1" - is-regex "^1.1.2" - is-string "^1.0.5" - object-inspect "^1.9.0" - object-keys "^1.1.1" - object.assign "^4.1.2" - string.prototype.trimend "^1.0.4" - string.prototype.trimstart "^1.0.4" - unbox-primitive "^1.0.0" - -es-to-primitive@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" - integrity sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA== - dependencies: - is-callable "^1.1.4" - is-date-object "^1.0.1" - is-symbol "^1.0.2" - -es6-object-assign@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/es6-object-assign/-/es6-object-assign-1.1.0.tgz#c2c3582656247c39ea107cb1e6652b6f9f24523c" - integrity sha1-wsNYJlYkfDnqEHyx5mUrb58kUjw= - -escalade@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" - integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== - -escape-html@~1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" - integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg= - -escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" - integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= - -escape-string-regexp@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" - integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== - -eslint-config-prettier@^7.1.0: - version "7.1.0" - resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-7.1.0.tgz#5402eb559aa94b894effd6bddfa0b1ca051c858f" - integrity sha512-9sm5/PxaFG7qNJvJzTROMM1Bk1ozXVTKI0buKOyb0Bsr1hrwi0H/TzxF/COtf1uxikIK8SwhX7K6zg78jAzbeA== - -eslint-config-react-app@^5.2.0: - version "5.2.1" - resolved "https://registry.yarnpkg.com/eslint-config-react-app/-/eslint-config-react-app-5.2.1.tgz#698bf7aeee27f0cea0139eaef261c7bf7dd623df" - integrity sha512-pGIZ8t0mFLcV+6ZirRgYK6RVqUIKRIi9MmgzUEmrIknsn3AdO0I32asO86dJgloHq+9ZPl8UIg8mYrvgP5u2wQ== - dependencies: - confusing-browser-globals "^1.0.9" - -eslint-import-resolver-node@^0.3.4: - version "0.3.4" - resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.4.tgz#85ffa81942c25012d8231096ddf679c03042c717" - integrity sha512-ogtf+5AB/O+nM6DIeBUNr2fuT7ot9Qg/1harBfBtaP13ekEWFQEEMP94BCB7zaNW3gyY+8SHYF00rnqYwXKWOA== - dependencies: - debug "^2.6.9" - resolve "^1.13.1" - -eslint-import-resolver-typescript@^2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-2.3.0.tgz#0870988098bc6c6419c87705e6b42bee89425445" - integrity sha512-MHSXvmj5e0SGOOBhBbt7C+fWj1bJbtSYFAD85Xeg8nvUtuooTod2HQb8bfhE9f5QyyNxEfgzqOYFCvmdDIcCuw== - dependencies: - debug "^4.1.1" - glob "^7.1.6" - is-glob "^4.0.1" - resolve "^1.17.0" - tsconfig-paths "^3.9.0" - -eslint-module-utils@^2.6.0: - version "2.6.0" - resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.6.0.tgz#579ebd094f56af7797d19c9866c9c9486629bfa6" - integrity sha512-6j9xxegbqe8/kZY8cYpcp0xhbK0EgJlg3g9mib3/miLaExuuwc3n5UEfSnU6hWMbT0FAYVvDbL9RrRgpUeQIvA== - dependencies: - debug "^2.6.9" - pkg-dir "^2.0.0" - -eslint-plugin-import@^2.22.1: - version "2.22.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.22.1.tgz#0896c7e6a0cf44109a2d97b95903c2bb689d7702" - integrity sha512-8K7JjINHOpH64ozkAhpT3sd+FswIZTfMZTjdx052pnWrgRCVfp8op9tbjpAk3DdUeI/Ba4C8OjdC0r90erHEOw== - dependencies: - array-includes "^3.1.1" - array.prototype.flat "^1.2.3" - contains-path "^0.1.0" - debug "^2.6.9" - doctrine "1.5.0" - eslint-import-resolver-node "^0.3.4" - eslint-module-utils "^2.6.0" - has "^1.0.3" - minimatch "^3.0.4" - object.values "^1.1.1" - read-pkg-up "^2.0.0" - resolve "^1.17.0" - tsconfig-paths "^3.9.0" - -eslint-plugin-jest@^24.1.3: - version "24.1.3" - resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-24.1.3.tgz#fa3db864f06c5623ff43485ca6c0e8fc5fe8ba0c" - integrity sha512-dNGGjzuEzCE3d5EPZQ/QGtmlMotqnYWD/QpCZ1UuZlrMAdhG5rldh0N0haCvhGnUkSeuORS5VNROwF9Hrgn3Lg== - dependencies: - "@typescript-eslint/experimental-utils" "^4.0.1" - -eslint-plugin-json@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/eslint-plugin-json/-/eslint-plugin-json-2.1.2.tgz#5bc1c221984583c0c5ff21c488386e8263a6bbb7" - integrity sha512-isM/fsUxS4wN1+nLsWoV5T4gLgBQnsql3nMTr8u+cEls1bL8rRQO5CP5GtxJxaOfbcKqnz401styw+H/P+e78Q== - dependencies: - lodash "^4.17.19" - vscode-json-languageservice "^3.7.0" - -eslint-plugin-jsx-a11y@^6.2.3: - version "6.3.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.3.1.tgz#99ef7e97f567cc6a5b8dd5ab95a94a67058a2660" - integrity sha512-i1S+P+c3HOlBJzMFORRbC58tHa65Kbo8b52/TwCwSKLohwvpfT5rm2GjGWzOHTEuq4xxf2aRlHHTtmExDQOP+g== - dependencies: - "@babel/runtime" "^7.10.2" - aria-query "^4.2.2" - array-includes "^3.1.1" - ast-types-flow "^0.0.7" - axe-core "^3.5.4" - axobject-query "^2.1.2" - damerau-levenshtein "^1.0.6" - emoji-regex "^9.0.0" - has "^1.0.3" - jsx-ast-utils "^2.4.1" - language-tags "^1.0.5" - -eslint-plugin-prettier@^3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-3.3.0.tgz#61e295349a65688ffac0b7808ef0a8244bdd8d40" - integrity sha512-tMTwO8iUWlSRZIwS9k7/E4vrTsfvsrcM5p1eftyuqWH25nKsz/o6/54I7jwQ/3zobISyC7wMy9ZsFwgTxOcOpQ== - dependencies: - prettier-linter-helpers "^1.0.0" - -eslint-plugin-react-hooks@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.2.0.tgz#8c229c268d468956334c943bb45fc860280f5556" - integrity sha512-623WEiZJqxR7VdxFCKLI6d6LLpwJkGPYKODnkH3D7WpOG5KM8yWueBd8TLsNAetEJNF5iJmolaAKO3F8yzyVBQ== - -eslint-plugin-react@^7.22.0: - version "7.22.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.22.0.tgz#3d1c542d1d3169c45421c1215d9470e341707269" - integrity sha512-p30tuX3VS+NWv9nQot9xIGAHBXR0+xJVaZriEsHoJrASGCJZDJ8JLNM0YqKqI0AKm6Uxaa1VUHoNEibxRCMQHA== - dependencies: - array-includes "^3.1.1" - array.prototype.flatmap "^1.2.3" - doctrine "^2.1.0" - has "^1.0.3" - jsx-ast-utils "^2.4.1 || ^3.0.0" - object.entries "^1.1.2" - object.fromentries "^2.0.2" - object.values "^1.1.1" - prop-types "^15.7.2" - resolve "^1.18.1" - string.prototype.matchall "^4.0.2" - -eslint-scope@^5.0.0, eslint-scope@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" - integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== - dependencies: - esrecurse "^4.3.0" - estraverse "^4.1.1" - -eslint-utils@^1.4.3: - version "1.4.3" - resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-1.4.3.tgz#74fec7c54d0776b6f67e0251040b5806564e981f" - integrity sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q== - dependencies: - eslint-visitor-keys "^1.1.0" - -eslint-utils@^2.0.0, eslint-utils@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-2.1.0.tgz#d2de5e03424e707dc10c74068ddedae708741b27" - integrity sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg== - dependencies: - eslint-visitor-keys "^1.1.0" - -eslint-visitor-keys@^1.0.0, eslint-visitor-keys@^1.1.0, eslint-visitor-keys@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz#30ebd1ef7c2fdff01c3a4f151044af25fab0523e" - integrity sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ== - -eslint-visitor-keys@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz#21fdc8fbcd9c795cc0321f0563702095751511a8" - integrity sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ== - -eslint@^6.8.0: - version "6.8.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-6.8.0.tgz#62262d6729739f9275723824302fb227c8c93ffb" - integrity sha512-K+Iayyo2LtyYhDSYwz5D5QdWw0hCacNzyq1Y821Xna2xSJj7cijoLLYmLxTQgcgZ9mC61nryMy9S7GRbYpI5Ig== - dependencies: - "@babel/code-frame" "^7.0.0" - ajv "^6.10.0" - chalk "^2.1.0" - cross-spawn "^6.0.5" - debug "^4.0.1" - doctrine "^3.0.0" - eslint-scope "^5.0.0" - eslint-utils "^1.4.3" - eslint-visitor-keys "^1.1.0" - espree "^6.1.2" - esquery "^1.0.1" - esutils "^2.0.2" - file-entry-cache "^5.0.1" - functional-red-black-tree "^1.0.1" - glob-parent "^5.0.0" - globals "^12.1.0" - ignore "^4.0.6" - import-fresh "^3.0.0" - imurmurhash "^0.1.4" - inquirer "^7.0.0" - is-glob "^4.0.0" - js-yaml "^3.13.1" - json-stable-stringify-without-jsonify "^1.0.1" - levn "^0.3.0" - lodash "^4.17.14" - minimatch "^3.0.4" - mkdirp "^0.5.1" - natural-compare "^1.4.0" - optionator "^0.8.3" - progress "^2.0.0" - regexpp "^2.0.1" - semver "^6.1.2" - strip-ansi "^5.2.0" - strip-json-comments "^3.0.1" - table "^5.2.3" - text-table "^0.2.0" - v8-compile-cache "^2.0.3" - -eslint@^7.9.0: - version "7.17.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.17.0.tgz#4ccda5bf12572ad3bf760e6f195886f50569adb0" - integrity sha512-zJk08MiBgwuGoxes5sSQhOtibZ75pz0J35XTRlZOk9xMffhpA9BTbQZxoXZzOl5zMbleShbGwtw+1kGferfFwQ== - dependencies: - "@babel/code-frame" "^7.0.0" - "@eslint/eslintrc" "^0.2.2" - ajv "^6.10.0" - chalk "^4.0.0" - cross-spawn "^7.0.2" - debug "^4.0.1" - doctrine "^3.0.0" - enquirer "^2.3.5" - eslint-scope "^5.1.1" - eslint-utils "^2.1.0" - eslint-visitor-keys "^2.0.0" - espree "^7.3.1" - esquery "^1.2.0" - esutils "^2.0.2" - file-entry-cache "^6.0.0" - functional-red-black-tree "^1.0.1" - glob-parent "^5.0.0" - globals "^12.1.0" - ignore "^4.0.6" - import-fresh "^3.0.0" - imurmurhash "^0.1.4" - is-glob "^4.0.0" - js-yaml "^3.13.1" - json-stable-stringify-without-jsonify "^1.0.1" - levn "^0.4.1" - lodash "^4.17.19" - minimatch "^3.0.4" - natural-compare "^1.4.0" - optionator "^0.9.1" - progress "^2.0.0" - regexpp "^3.1.0" - semver "^7.2.1" - strip-ansi "^6.0.0" - strip-json-comments "^3.1.0" - table "^6.0.4" - text-table "^0.2.0" - v8-compile-cache "^2.0.3" - -espree@^6.1.2, espree@^6.2.1: - version "6.2.1" - resolved "https://registry.yarnpkg.com/espree/-/espree-6.2.1.tgz#77fc72e1fd744a2052c20f38a5b575832e82734a" - integrity sha512-ysCxRQY3WaXJz9tdbWOwuWr5Y/XrPTGX9Kiz3yoUXwW0VZ4w30HTkQLaGx/+ttFjF8i+ACbArnB4ce68a9m5hw== - dependencies: - acorn "^7.1.1" - acorn-jsx "^5.2.0" - eslint-visitor-keys "^1.1.0" - -espree@^7.3.0, espree@^7.3.1: - version "7.3.1" - resolved "https://registry.yarnpkg.com/espree/-/espree-7.3.1.tgz#f2df330b752c6f55019f8bd89b7660039c1bbbb6" - integrity sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g== - dependencies: - acorn "^7.4.0" - acorn-jsx "^5.3.1" - eslint-visitor-keys "^1.3.0" - -esprima@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" - integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== - -esquery@^1.0.1, esquery@^1.2.0: - version "1.3.1" - resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.3.1.tgz#b78b5828aa8e214e29fb74c4d5b752e1c033da57" - integrity sha512-olpvt9QG0vniUBZspVRN6lwB7hOZoTRtT+jzR+tS4ffYx2mzbw+z0XCOk44aaLYKApNX5nMm+E+P6o25ip/DHQ== - dependencies: - estraverse "^5.1.0" - -esrecurse@^4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" - integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== - dependencies: - estraverse "^5.2.0" - -estraverse@^4.1.1: - version "4.3.0" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" - integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== - -estraverse@^5.1.0, estraverse@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.2.0.tgz#307df42547e6cc7324d3cf03c155d5cdb8c53880" - integrity sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ== - -esutils@^2.0.2: - version "2.0.3" - resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" - integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== - -etag@1.8.1, etag@~1.8.1: - version "1.8.1" - resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" - integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc= - -eventemitter3@^4.0.0: - version "4.0.7" - resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f" - integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw== - -events@^3.0.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/events/-/events-3.2.0.tgz#93b87c18f8efcd4202a461aec4dfc0556b639379" - integrity sha512-/46HWwbfCX2xTawVfkKLGxMifJYQBWMwY1mjywRtb4c9x8l5NP3KoJtnIOiL1hfdRkIuYhETxQlo62IF8tcnlg== - -evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz#7fcbdb198dc71959432efe13842684e0525acb02" - integrity sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA== - dependencies: - md5.js "^1.3.4" - safe-buffer "^5.1.1" - -express@^4.17.1: - version "4.17.1" - resolved "https://registry.yarnpkg.com/express/-/express-4.17.1.tgz#4491fc38605cf51f8629d39c2b5d026f98a4c134" - integrity sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g== - dependencies: - accepts "~1.3.7" - array-flatten "1.1.1" - body-parser "1.19.0" - content-disposition "0.5.3" - content-type "~1.0.4" - cookie "0.4.0" - cookie-signature "1.0.6" - debug "2.6.9" - depd "~1.1.2" - encodeurl "~1.0.2" - escape-html "~1.0.3" - etag "~1.8.1" - finalhandler "~1.1.2" - fresh "0.5.2" - merge-descriptors "1.0.1" - methods "~1.1.2" - on-finished "~2.3.0" - parseurl "~1.3.3" - path-to-regexp "0.1.7" - proxy-addr "~2.0.5" - qs "6.7.0" - range-parser "~1.2.1" - safe-buffer "5.1.2" - send "0.17.1" - serve-static "1.14.1" - setprototypeof "1.1.1" - statuses "~1.5.0" - type-is "~1.6.18" - utils-merge "1.0.1" - vary "~1.1.2" - -extend@^3.0.0: - version "3.0.2" - resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" - integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== - -external-editor@^3.0.3: - version "3.1.0" - resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.1.0.tgz#cb03f740befae03ea4d283caed2741a83f335495" - integrity sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew== - dependencies: - chardet "^0.7.0" - iconv-lite "^0.4.24" - tmp "^0.0.33" - -fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: - version "3.1.3" - resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" - integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== - -fast-diff@^1.1.2: - version "1.2.0" - resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.2.0.tgz#73ee11982d86caaf7959828d519cfe927fac5f03" - integrity sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w== - -fast-glob@^3.1.1: - version "3.2.4" - resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.4.tgz#d20aefbf99579383e7f3cc66529158c9b98554d3" - integrity sha512-kr/Oo6PX51265qeuCYsyGypiO5uJFgBS0jksyG7FUeCyQzNwYnzrNIMR1NXfkZXsMYXYLRAHgISHBz8gQcxKHQ== - dependencies: - "@nodelib/fs.stat" "^2.0.2" - "@nodelib/fs.walk" "^1.2.3" - glob-parent "^5.1.0" - merge2 "^1.3.0" - micromatch "^4.0.2" - picomatch "^2.2.1" - -fast-json-stable-stringify@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" - integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== - -fast-levenshtein@^2.0.6, fast-levenshtein@~2.0.6: - version "2.0.6" - resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" - integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= - -fastq@^1.6.0: - version "1.10.0" - resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.10.0.tgz#74dbefccade964932cdf500473ef302719c652bb" - integrity sha512-NL2Qc5L3iQEsyYzweq7qfgy5OtXCmGzGvhElGEd/SoFWEMOEczNh5s5ocaF01HDetxz+p8ecjNPA6cZxxIHmzA== - dependencies: - reusify "^1.0.4" - -figures@^3.0.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/figures/-/figures-3.2.0.tgz#625c18bd293c604dc4a8ddb2febf0c88341746af" - integrity sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg== - dependencies: - escape-string-regexp "^1.0.5" - -file-entry-cache@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-5.0.1.tgz#ca0f6efa6dd3d561333fb14515065c2fafdf439c" - integrity sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g== - dependencies: - flat-cache "^2.0.1" - -file-entry-cache@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.0.tgz#7921a89c391c6d93efec2169ac6bf300c527ea0a" - integrity sha512-fqoO76jZ3ZnYrXLDRxBR1YvOvc0k844kcOg40bgsPrE25LAb/PDqTY+ho64Xh2c8ZXgIKldchCFHczG2UVRcWA== - dependencies: - flat-cache "^3.0.4" - -fill-range@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" - integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== - dependencies: - to-regex-range "^5.0.1" - -finalhandler@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.2.tgz#b7e7d000ffd11938d0fdb053506f6ebabe9f587d" - integrity sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA== - dependencies: - debug "2.6.9" - encodeurl "~1.0.2" - escape-html "~1.0.3" - on-finished "~2.3.0" - parseurl "~1.3.3" - statuses "~1.5.0" - unpipe "~1.0.0" - -find-cache-dir@3.3.1: - version "3.3.1" - resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-3.3.1.tgz#89b33fad4a4670daa94f855f7fbe31d6d84fe880" - integrity sha512-t2GDMt3oGC/v+BMwzmllWDuJF/xcDtE5j/fCGbqDD7OLuJkj0cfh1YSA5VKPvwMeLFLNDBkwOKZ2X85jGLVftQ== - dependencies: - commondir "^1.0.1" - make-dir "^3.0.2" - pkg-dir "^4.1.0" - -find-root@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/find-root/-/find-root-1.1.0.tgz#abcfc8ba76f708c42a97b3d685b7e9450bfb9ce4" - integrity sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng== - -find-up@^2.0.0, find-up@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" - integrity sha1-RdG35QbHF93UgndaK3eSCjwMV6c= - dependencies: - locate-path "^2.0.0" - -find-up@^4.0.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" - integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== - dependencies: - locate-path "^5.0.0" - path-exists "^4.0.0" - -flat-cache@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-2.0.1.tgz#5d296d6f04bda44a4630a301413bdbc2ec085ec0" - integrity sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA== - dependencies: - flatted "^2.0.0" - rimraf "2.6.3" - write "1.0.3" - -flat-cache@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.0.4.tgz#61b0338302b2fe9f957dcc32fc2a87f1c3048b11" - integrity sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg== - dependencies: - flatted "^3.1.0" - rimraf "^3.0.2" - -flatted@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.2.tgz#4575b21e2bcee7434aa9be662f4b7b5f9c2b5138" - integrity sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA== - -flatted@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.1.0.tgz#a5d06b4a8b01e3a63771daa5cb7a1903e2e57067" - integrity sha512-tW+UkmtNg/jv9CSofAKvgVcO7c2URjhTdW1ZTkcAritblu8tajiYy7YisnIflEwtKssCtOxpnBRoCB7iap0/TA== - -focus-lock@^0.8.1: - version "0.8.1" - resolved "https://registry.yarnpkg.com/focus-lock/-/focus-lock-0.8.1.tgz#bb36968abf77a2063fa173cb6c47b12ac8599d33" - integrity sha512-/LFZOIo82WDsyyv7h7oc0MJF9ACOvDRdx9rWPZ2pgMfNWu/z8hQDBtOchuB/0BVLmuFOZjV02YwUVzNsWx/EzA== - dependencies: - tslib "^1.9.3" - -follow-redirects@^1.0.0: - version "1.13.0" - resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.13.0.tgz#b42e8d93a2a7eea5ed88633676d6597bc8e384db" - integrity sha512-aq6gF1BEKje4a9i9+5jimNFIpq4Q1WiwBToeRK5NvZBd/TRsmW8BsJfOEGkr76TbOyPVD3OVDN910EcUNtRYEA== - -foreach@^2.0.5: - version "2.0.5" - resolved "https://registry.yarnpkg.com/foreach/-/foreach-2.0.5.tgz#0bee005018aeb260d0a3af3ae658dd0136ec1b99" - integrity sha1-C+4AUBiusmDQo6865ljdATbsG5k= - -forwarded@~0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.1.2.tgz#98c23dab1175657b8c0573e8ceccd91b0ff18c84" - integrity sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ= - -framer-motion@^4.1.17: - version "4.1.17" - resolved "https://registry.yarnpkg.com/framer-motion/-/framer-motion-4.1.17.tgz#4029469252a62ea599902e5a92b537120cc89721" - integrity sha512-thx1wvKzblzbs0XaK2X0G1JuwIdARcoNOW7VVwjO8BUltzXPyONGAElLu6CiCScsOQRI7FIk/45YTFtJw5Yozw== - dependencies: - framesync "5.3.0" - hey-listen "^1.0.8" - popmotion "9.3.6" - style-value-types "4.1.4" - tslib "^2.1.0" - optionalDependencies: - "@emotion/is-prop-valid" "^0.8.2" - -framesync@5.3.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/framesync/-/framesync-5.3.0.tgz#0ecfc955e8f5a6ddc8fdb0cc024070947e1a0d9b" - integrity sha512-oc5m68HDO/tuK2blj7ZcdEBRx3p1PjrgHazL8GYEpvULhrtGIFbQArN6cQS2QhW8mitffaB+VYzMjDqBxxQeoA== - dependencies: - tslib "^2.1.0" - -fresh@0.5.2: - version "0.5.2" - resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" - integrity sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac= - -fs.realpath@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" - integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= - -fsevents@~2.1.2: - version "2.1.3" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.1.3.tgz#fb738703ae8d2f9fe900c33836ddebee8b97f23e" - integrity sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ== - -fsevents@~2.3.1: - version "2.3.2" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" - integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== - -function-bind@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" - integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== - -functional-red-black-tree@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" - integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc= - -get-intrinsic@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.0.2.tgz#6820da226e50b24894e08859469dc68361545d49" - integrity sha512-aeX0vrFm21ILl3+JpFFRNe9aUvp6VFZb2/CTbgLb8j75kOhvoNYjt9d8KA/tJG4gSo8nzEDedRl0h7vDmBYRVg== - dependencies: - function-bind "^1.1.1" - has "^1.0.3" - has-symbols "^1.0.1" - -get-intrinsic@^1.0.2, get-intrinsic@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.1.tgz#15f59f376f855c446963948f0d24cd3637b4abc6" - integrity sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q== - dependencies: - function-bind "^1.1.1" - has "^1.0.3" - has-symbols "^1.0.1" - -get-nonce@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/get-nonce/-/get-nonce-1.0.1.tgz#fdf3f0278073820d2ce9426c18f07481b1e0cdf3" - integrity sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q== - -get-orientation@1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/get-orientation/-/get-orientation-1.1.2.tgz#20507928951814f8a91ded0a0e67b29dfab98947" - integrity sha512-/pViTfifW+gBbh/RnlFYHINvELT9Znt+SYyDKAUL6uV6By019AK/s+i9XP4jSwq7lwP38Fd8HVeTxym3+hkwmQ== - dependencies: - stream-parser "^0.3.1" - -glob-parent@^5.0.0, glob-parent@^5.1.0, glob-parent@~5.1.0: - version "5.1.1" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.1.tgz#b6c1ef417c4e5663ea498f1c45afac6916bbc229" - integrity sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ== - dependencies: - is-glob "^4.0.1" - -glob-to-regexp@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz#c75297087c851b9a578bd217dd59a92f59fe546e" - integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw== - -glob@^7.1.3, glob@^7.1.6: - version "7.1.6" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" - integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.4" - once "^1.3.0" - path-is-absolute "^1.0.0" - -globals@^11.1.0: - version "11.12.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" - integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== - -globals@^12.1.0: - version "12.4.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-12.4.0.tgz#a18813576a41b00a24a97e7f815918c2e19925f8" - integrity sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg== - dependencies: - type-fest "^0.8.1" - -globby@^11.0.1: - version "11.0.1" - resolved "https://registry.yarnpkg.com/globby/-/globby-11.0.1.tgz#9a2bf107a068f3ffeabc49ad702c79ede8cfd357" - integrity sha512-iH9RmgwCmUJHi2z5o2l3eTtGBtXek1OYlHrbcxOYugyHLmAsZrPj43OtHThd62Buh/Vv6VyCBD2bdyWcGNQqoQ== - dependencies: - array-union "^2.1.0" - dir-glob "^3.0.1" - fast-glob "^3.1.1" - ignore "^5.1.4" - merge2 "^1.3.0" - slash "^3.0.0" - -graceful-fs@^4.1.2: - version "4.2.4" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.4.tgz#2256bde14d3632958c465ebc96dc467ca07a29fb" - integrity sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw== - -graphlib@^2.1.8: - version "2.1.8" - resolved "https://registry.yarnpkg.com/graphlib/-/graphlib-2.1.8.tgz#5761d414737870084c92ec7b5dbcb0592c9d35da" - integrity sha512-jcLLfkpoVGmH7/InMC/1hIvOPSUh38oJtGhvrOFGzioE1DZ+0YW16RgmOJhHiuWTvGiJQ9Z1Ik43JvkRPRvE+A== - dependencies: - lodash "^4.17.15" - -has-ansi@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" - integrity sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE= - dependencies: - ansi-regex "^2.0.0" - -has-bigints@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.1.tgz#64fe6acb020673e3b78db035a5af69aa9d07b113" - integrity sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA== - -has-flag@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" - integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= - -has-flag@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" - integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== - -has-symbols@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.1.tgz#9f5214758a44196c406d9bd76cebf81ec2dd31e8" - integrity sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg== - -has-symbols@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.2.tgz#165d3070c00309752a1236a479331e3ac56f1423" - integrity sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw== - -has@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" - integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== - dependencies: - function-bind "^1.1.1" - -hash-base@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.1.0.tgz#55c381d9e06e1d2997a883b4a3fddfe7f0d3af33" - integrity sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA== - dependencies: - inherits "^2.0.4" - readable-stream "^3.6.0" - safe-buffer "^5.2.0" - -hash.js@^1.0.0, hash.js@^1.0.3: - version "1.1.7" - resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.7.tgz#0babca538e8d4ee4a0f8988d68866537a003cf42" - integrity sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA== - dependencies: - inherits "^2.0.3" - minimalistic-assert "^1.0.1" - -he@1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" - integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== - -hey-listen@^1.0.8: - version "1.0.8" - resolved "https://registry.yarnpkg.com/hey-listen/-/hey-listen-1.0.8.tgz#8e59561ff724908de1aa924ed6ecc84a56a9aa68" - integrity sha512-COpmrF2NOg4TBWUJ5UVyaCU2A88wEMkUPK4hNqyCkqHbxT92BbvfjoSozkAIIm6XhicGlJHhFdullInrdhwU8Q== - -hmac-drbg@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" - integrity sha1-0nRXAQJabHdabFRXk+1QL8DGSaE= - dependencies: - hash.js "^1.0.3" - minimalistic-assert "^1.0.0" - minimalistic-crypto-utils "^1.0.1" - -hoist-non-react-statics@^3.3.0, hoist-non-react-statics@^3.3.1, hoist-non-react-statics@^3.3.2: - version "3.3.2" - resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45" - integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw== - dependencies: - react-is "^16.7.0" - -hosted-git-info@^2.1.4: - version "2.8.8" - resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.8.tgz#7539bd4bc1e0e0a895815a2e0262420b12858488" - integrity sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg== - -html-to-react@^1.3.4: - version "1.4.4" - resolved "https://registry.yarnpkg.com/html-to-react/-/html-to-react-1.4.4.tgz#dd5edb76ff28ab7fc34faabd91446bece292dc38" - integrity sha512-oE4GYH8c/gvFQwfNHBhg1LpfiPsQRKj0JQmvccvUHqyyF7U1H7UzZ7Z6CyF7okv1QFukyvjH9aAApNa4kYSO9g== - dependencies: - domhandler "^3.3.0" - htmlparser2 "^5.0" - lodash.camelcase "^4.3.0" - ramda "^0.27.1" - -htmlparser2@^5.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-5.0.0.tgz#78454bc782599291d9fefd7b48ef2058dc62eb89" - integrity sha512-/Cvz5RTj9q71kCL9No1u2jhFaAdoMtxpNy0YTwjmQB3iX2TZXfCojTm7tp3rM4NxcwaX1iAzvNgo8OFectXmrQ== - dependencies: - domelementtype "^2.0.1" - domhandler "^3.3.0" - domutils "^2.4.2" - entities "^2.0.0" - -http-errors@1.7.2: - version "1.7.2" - resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.2.tgz#4f5029cf13239f31036e5b2e55292bcfbcc85c8f" - integrity sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg== - dependencies: - depd "~1.1.2" - inherits "2.0.3" - setprototypeof "1.1.1" - statuses ">= 1.5.0 < 2" - toidentifier "1.0.0" - -http-errors@1.7.3, http-errors@~1.7.2: - version "1.7.3" - resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.3.tgz#6c619e4f9c60308c38519498c14fbb10aacebb06" - integrity sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw== - dependencies: - depd "~1.1.2" - inherits "2.0.4" - setprototypeof "1.1.1" - statuses ">= 1.5.0 < 2" - toidentifier "1.0.0" - -http-proxy-middleware@0.20.0: - version "0.20.0" - resolved "https://registry.yarnpkg.com/http-proxy-middleware/-/http-proxy-middleware-0.20.0.tgz#5b128f7207985c4ea91b53fab8ad897a48c690d6" - integrity sha512-dNJAk71nEJhPiAczQH9hGvE/MT9kEs+zn2Dh+Hi94PGZe1GluQirC7mw5rdREUtWx6qGS1Gu0bZd4qEAg+REgw== - dependencies: - http-proxy "^1.17.0" - is-glob "^4.0.1" - lodash "^4.17.14" - micromatch "^4.0.2" - -http-proxy@^1.17.0: - version "1.18.1" - resolved "https://registry.yarnpkg.com/http-proxy/-/http-proxy-1.18.1.tgz#401541f0534884bbf95260334e72f88ee3976549" - integrity sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ== - dependencies: - eventemitter3 "^4.0.0" - follow-redirects "^1.0.0" - requires-port "^1.0.0" - -https-browserify@1.0.0, https-browserify@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73" - integrity sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM= - -iconv-lite@0.4.24, iconv-lite@^0.4.24: - version "0.4.24" - resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" - integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== - dependencies: - safer-buffer ">= 2.1.2 < 3" - -iconv-lite@^0.6.2: - version "0.6.2" - resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.2.tgz#ce13d1875b0c3a674bd6a04b7f76b01b1b6ded01" - integrity sha512-2y91h5OpQlolefMPmUlivelittSWy0rP+oYVpn6A7GwVHNE8AWzoYOBNmlwks3LobaJxgHCYZAnyNo2GgpNRNQ== - dependencies: - safer-buffer ">= 2.1.2 < 3.0.0" - -ieee754@^1.1.4: - version "1.1.13" - resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.13.tgz#ec168558e95aa181fd87d37f55c32bbcb6708b84" - integrity sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg== - -ignore@^4.0.6: - version "4.0.6" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" - integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== - -ignore@^5.1.4: - version "5.1.8" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.1.8.tgz#f150a8b50a34289b33e22f5889abd4d8016f0e57" - integrity sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw== - -import-fresh@^3.0.0, import-fresh@^3.1.0: - version "3.2.1" - resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.2.1.tgz#633ff618506e793af5ac91bf48b72677e15cbe66" - integrity sha512-6e1q1cnWP2RXD9/keSkxHScg508CdXqXWgWBaETNhyuBFz+kUZlKboh+ISK+bU++DmbHimVBrOz/zzPe0sZ3sQ== - dependencies: - parent-module "^1.0.0" - resolve-from "^4.0.0" - -import-fresh@^3.2.1: - version "3.3.0" - resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" - integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== - dependencies: - parent-module "^1.0.0" - resolve-from "^4.0.0" - -imurmurhash@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" - integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= - -indent-string@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" - integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== - -inflight@^1.0.4: - version "1.0.6" - resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" - integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= - dependencies: - once "^1.3.0" - wrappy "1" - -inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.1, inherits@~2.0.3, inherits@~2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" - integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== - -inherits@2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.1.tgz#b17d08d326b4423e568eff719f91b0b1cbdf69f1" - integrity sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE= - -inherits@2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" - integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= - -inquirer@^7.0.0: - version "7.3.3" - resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-7.3.3.tgz#04d176b2af04afc157a83fd7c100e98ee0aad003" - integrity sha512-JG3eIAj5V9CwcGvuOmoo6LB9kbAYT8HXffUl6memuszlwDC/qvFAJw49XJ5NROSFNPxp3iQg1GqkFhaY/CR0IA== - dependencies: - ansi-escapes "^4.2.1" - chalk "^4.1.0" - cli-cursor "^3.1.0" - cli-width "^3.0.0" - external-editor "^3.0.3" - figures "^3.0.0" - lodash "^4.17.19" - mute-stream "0.0.8" - run-async "^2.4.0" - rxjs "^6.6.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - through "^2.3.6" - -internal-slot@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.2.tgz#9c2e9fb3cd8e5e4256c6f45fe310067fcfa378a3" - integrity sha512-2cQNfwhAfJIkU4KZPkDI+Gj5yNNnbqi40W9Gge6dfnk4TocEVm00B3bdiL+JINrbGJil2TeHvM4rETGzk/f/0g== - dependencies: - es-abstract "^1.17.0-next.1" - has "^1.0.3" - side-channel "^1.0.2" - -invariant@^2.2.4: - version "2.2.4" - resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" - integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA== - dependencies: - loose-envify "^1.0.0" - -ipaddr.js@1.9.1: - version "1.9.1" - resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" - integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== - -is-alphabetical@^1.0.0: - version "1.0.4" - resolved "https://registry.yarnpkg.com/is-alphabetical/-/is-alphabetical-1.0.4.tgz#9e7d6b94916be22153745d184c298cbf986a686d" - integrity sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg== - -is-alphanumerical@^1.0.0: - version "1.0.4" - resolved "https://registry.yarnpkg.com/is-alphanumerical/-/is-alphanumerical-1.0.4.tgz#7eb9a2431f855f6b1ef1a78e326df515696c4dbf" - integrity sha512-UzoZUr+XfVz3t3v4KyGEniVL9BDRoQtY7tOyrRybkVNjDFWyo1yhXNGrrBTQxp3ib9BLAWs7k2YKBQsFRkZG9A== - dependencies: - is-alphabetical "^1.0.0" - is-decimal "^1.0.0" - -is-arguments@^1.0.4: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.1.0.tgz#62353031dfbee07ceb34656a6bde59efecae8dd9" - integrity sha512-1Ij4lOMPl/xB5kBDn7I+b2ttPMKa8szhEIrXDuXQD/oe3HJLTLhqhgGspwgyGd6MOywBUqVvYicF72lkgDnIHg== - dependencies: - call-bind "^1.0.0" - -is-arrayish@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" - integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0= - -is-bigint@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.0.1.tgz#6923051dfcbc764278540b9ce0e6b3213aa5ebc2" - integrity sha512-J0ELF4yHFxHy0cmSxZuheDOz2luOdVvqjwmEcj8H/L1JHeuEDSDbeRP+Dk9kFVk5RTFzbucJ2Kb9F7ixY2QaCg== - -is-binary-path@~2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" - integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== - dependencies: - binary-extensions "^2.0.0" - -is-boolean-object@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.1.0.tgz#e2aaad3a3a8fca34c28f6eee135b156ed2587ff0" - integrity sha512-a7Uprx8UtD+HWdyYwnD1+ExtTgqQtD2k/1yJgtXP6wnMm8byhkoTZRl+95LLThpzNZJ5aEvi46cdH+ayMFRwmA== - dependencies: - call-bind "^1.0.0" - -is-buffer@^2.0.0: - version "2.0.5" - resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.5.tgz#ebc252e400d22ff8d77fa09888821a24a658c191" - integrity sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ== - -is-callable@^1.1.4, is-callable@^1.2.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.2.tgz#c7c6715cd22d4ddb48d3e19970223aceabb080d9" - integrity sha512-dnMqspv5nU3LoewK2N/y7KLtxtakvTuaCsU9FU50/QDmdbHNy/4/JuRtMHqRU22o3q+W89YQndQEeCVwK+3qrA== - -is-callable@^1.2.3: - version "1.2.3" - resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.3.tgz#8b1e0500b73a1d76c70487636f368e519de8db8e" - integrity sha512-J1DcMe8UYTBSrKezuIUTUwjXsho29693unXM2YhJUTR2txK/eG47bvNa/wipPFmZFgr/N6f1GA66dv0mEyTIyQ== - -is-core-module@^2.1.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.2.0.tgz#97037ef3d52224d85163f5597b2b63d9afed981a" - integrity sha512-XRAfAdyyY5F5cOXn7hYQDqh2Xmii+DEfIcQGxK/uNwMHhIkPWO0g8msXcbzLe+MpGoR951MlqM/2iIlU4vKDdQ== - dependencies: - has "^1.0.3" - -is-date-object@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.2.tgz#bda736f2cd8fd06d32844e7743bfa7494c3bfd7e" - integrity sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g== - -is-decimal@^1.0.0: - version "1.0.4" - resolved "https://registry.yarnpkg.com/is-decimal/-/is-decimal-1.0.4.tgz#65a3a5958a1c5b63a706e1b333d7cd9f630d3fa5" - integrity sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw== - -is-extglob@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" - integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= - -is-fullwidth-code-point@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" - integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= - -is-fullwidth-code-point@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" - integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== - -is-generator-function@^1.0.7: - version "1.0.8" - resolved "https://registry.yarnpkg.com/is-generator-function/-/is-generator-function-1.0.8.tgz#dfb5c2b120e02b0a8d9d2c6806cd5621aa922f7b" - integrity sha512-2Omr/twNtufVZFr1GhxjOMFPAj2sjc/dKaIqBhvo4qciXfJmITGH6ZGd8eZYNHza8t1y0e01AuqRhJwfWp26WQ== - -is-glob@^4.0.0, is-glob@^4.0.1, is-glob@~4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc" - integrity sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg== - dependencies: - is-extglob "^2.1.1" - -is-hexadecimal@^1.0.0: - version "1.0.4" - resolved "https://registry.yarnpkg.com/is-hexadecimal/-/is-hexadecimal-1.0.4.tgz#cc35c97588da4bd49a8eedd6bc4082d44dcb23a7" - integrity sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw== - -is-nan@^1.2.1: - version "1.3.2" - resolved "https://registry.yarnpkg.com/is-nan/-/is-nan-1.3.2.tgz#043a54adea31748b55b6cd4e09aadafa69bd9e1d" - integrity sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w== - dependencies: - call-bind "^1.0.0" - define-properties "^1.1.3" - -is-negative-zero@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.0.tgz#9553b121b0fac28869da9ed459e20c7543788461" - integrity sha1-lVOxIbD6wohp2p7UWeIMdUN4hGE= - -is-negative-zero@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.1.tgz#3de746c18dda2319241a53675908d8f766f11c24" - integrity sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w== - -is-number-object@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.4.tgz#36ac95e741cf18b283fc1ddf5e83da798e3ec197" - integrity sha512-zohwelOAur+5uXtk8O3GPQ1eAcu4ZX3UwxQhUlfFFMNpUd83gXgjbhJh6HmB6LUNV/ieOLQuDwJO3dWJosUeMw== - -is-number@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" - integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== - -is-plain-obj@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287" - integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA== - -is-regex@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.1.tgz#c6f98aacc546f6cec5468a07b7b153ab564a57b9" - integrity sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg== - dependencies: - has-symbols "^1.0.1" - -is-regex@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.2.tgz#81c8ebde4db142f2cf1c53fc86d6a45788266251" - integrity sha512-axvdhb5pdhEVThqJzYXwMlVuZwC+FF2DpcOhTS+y/8jVq4trxyPgfcwIxIKiyeuLlSQYKkmUaPQJ8ZE4yNKXDg== - dependencies: - call-bind "^1.0.2" - has-symbols "^1.0.1" - -is-string@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.5.tgz#40493ed198ef3ff477b8c7f92f644ec82a5cd3a6" - integrity sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ== - -is-symbol@^1.0.2, is-symbol@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.3.tgz#38e1014b9e6329be0de9d24a414fd7441ec61937" - integrity sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ== - dependencies: - has-symbols "^1.0.1" - -is-typed-array@^1.1.3: - version "1.1.5" - resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.5.tgz#f32e6e096455e329eb7b423862456aa213f0eb4e" - integrity sha512-S+GRDgJlR3PyEbsX/Fobd9cqpZBuvUS+8asRqYDMLCb2qMzt1oz5m5oxQCxOgUDxiWsOVNi4yaF+/uvdlHlYug== - dependencies: - available-typed-arrays "^1.0.2" - call-bind "^1.0.2" - es-abstract "^1.18.0-next.2" - foreach "^2.0.5" - has-symbols "^1.0.1" - -isarray@^1.0.0, isarray@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" - integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= - -isexe@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" - integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= - -jest-worker@27.0.0-next.5: - version "27.0.0-next.5" - resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-27.0.0-next.5.tgz#5985ee29b12a4e191f4aae4bb73b97971d86ec28" - integrity sha512-mk0umAQ5lT+CaOJ+Qp01N6kz48sJG2kr2n1rX0koqKf6FIygQV0qLOdN9SCYID4IVeSigDOcPeGLozdMLYfb5g== - dependencies: - "@types/node" "*" - merge-stream "^2.0.0" - supports-color "^8.0.0" - -js-sha3@0.8.0: - version "0.8.0" - resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.8.0.tgz#b9b7a5da73afad7dedd0f8c463954cbde6818840" - integrity sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q== - -"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" - integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== - -js-yaml@^3.13.1: - version "3.14.0" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.0.tgz#a7a34170f26a21bb162424d8adacb4113a69e482" - integrity sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A== - dependencies: - argparse "^1.0.7" - esprima "^4.0.0" - -jsesc@^2.5.1: - version "2.5.2" - resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" - integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== - -json-parse-even-better-errors@^2.3.0: - version "2.3.1" - resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" - integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== - -json-schema-traverse@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" - integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== - -json-schema-traverse@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2" - integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== - -json-stable-stringify-without-jsonify@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" - integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE= - -json5@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.1.tgz#779fb0018604fa854eacbf6252180d83543e3dbe" - integrity sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow== - dependencies: - minimist "^1.2.0" - -jsonc-parser@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-3.0.0.tgz#abdd785701c7e7eaca8a9ec8cf070ca51a745a22" - integrity sha512-fQzRfAbIBnR0IQvftw9FJveWiHp72Fg20giDrHz6TdfB12UH/uue0D3hm57UB5KgAVuniLMCaS8P1IMj9NR7cA== - -jsx-ast-utils@^2.4.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-2.4.1.tgz#1114a4c1209481db06c690c2b4f488cc665f657e" - integrity sha512-z1xSldJ6imESSzOjd3NNkieVJKRlKYSOtMG8SFyCj2FIrvSaSuli/WjpBkEzCBoR9bYYYFgqJw61Xhu7Lcgk+w== - dependencies: - array-includes "^3.1.1" - object.assign "^4.1.0" - -"jsx-ast-utils@^2.4.1 || ^3.0.0": - version "3.1.0" - resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-3.1.0.tgz#642f1d7b88aa6d7eb9d8f2210e166478444fa891" - integrity sha512-d4/UOjg+mxAWxCiF0c5UTSwyqbchkbqCvK87aBovhnh8GtysTjWmgC63tY0cJx/HzGgm9qnA147jVBdpOiQ2RA== - dependencies: - array-includes "^3.1.1" - object.assign "^4.1.1" - -language-subtag-registry@~0.3.2: - version "0.3.20" - resolved "https://registry.yarnpkg.com/language-subtag-registry/-/language-subtag-registry-0.3.20.tgz#a00a37121894f224f763268e431c55556b0c0755" - integrity sha512-KPMwROklF4tEx283Xw0pNKtfTj1gZ4UByp4EsIFWLgBavJltF4TiYPc39k06zSTsLzxTVXXDSpbwaQXaFB4Qeg== - -language-tags@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/language-tags/-/language-tags-1.0.5.tgz#d321dbc4da30ba8bf3024e040fa5c14661f9193a" - integrity sha1-0yHbxNowuovzAk4ED6XBRmH5GTo= - dependencies: - language-subtag-registry "~0.3.2" - -levn@^0.3.0, levn@~0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" - integrity sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4= - dependencies: - prelude-ls "~1.1.2" - type-check "~0.3.2" - -levn@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" - integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ== - dependencies: - prelude-ls "^1.2.1" - type-check "~0.4.0" - -lines-and-columns@^1.1.6: - version "1.1.6" - resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.1.6.tgz#1c00c743b433cd0a4e80758f7b64a57440d9ff00" - integrity sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA= - -little-state-machine@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/little-state-machine/-/little-state-machine-4.1.0.tgz#8ca1eae22ea2408e97dc82097b4aa3fe1f96a199" - integrity sha512-JeWPyIwnhYGheF10h8DY9+OnEwJ0waRzyXP/WclB3Bqg5v1+xwruXTtDvTow/69ZBAuRlYT5Apl+I8TN+HMp9g== - -load-json-file@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-2.0.0.tgz#7947e42149af80d696cbf797bcaabcfe1fe29ca8" - integrity sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg= - dependencies: - graceful-fs "^4.1.2" - parse-json "^2.2.0" - pify "^2.0.0" - strip-bom "^3.0.0" - -loader-utils@1.2.3: - version "1.2.3" - resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.2.3.tgz#1ff5dc6911c9f0a062531a4c04b609406108c2c7" - integrity sha512-fkpz8ejdnEMG3s37wGL07iSBDg99O9D5yflE9RGNH3hRdx9SOwYfnGYdZOUIZitN8E+E2vkq3MUMYMvPYl5ZZA== - dependencies: - big.js "^5.2.2" - emojis-list "^2.0.0" - json5 "^1.0.1" - -locate-path@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" - integrity sha1-K1aLJl7slExtnA3pw9u7ygNUzY4= - dependencies: - p-locate "^2.0.0" - path-exists "^3.0.0" - -locate-path@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" - integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== - dependencies: - p-locate "^4.1.0" - -lodash.camelcase@^4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6" - integrity sha1-soqmKIorn8ZRA1x3EfZathkDMaY= - -lodash.merge@^4.6.0: - version "4.6.2" - resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" - integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== - -lodash.mergewith@4.6.2: - version "4.6.2" - resolved "https://registry.yarnpkg.com/lodash.mergewith/-/lodash.mergewith-4.6.2.tgz#617121f89ac55f59047c7aec1ccd6654c6590f55" - integrity sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ== - -lodash.sortby@^4.7.0: - version "4.7.0" - resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438" - integrity sha1-7dFMgk4sycHgsKG0K7UhBRakJDg= - -lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20: - version "4.17.20" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52" - integrity sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA== - -lodash@^4.17.21: - version "4.17.21" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" - integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== - -loglevel-colored-level-prefix@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/loglevel-colored-level-prefix/-/loglevel-colored-level-prefix-1.0.0.tgz#6a40218fdc7ae15fc76c3d0f3e676c465388603e" - integrity sha1-akAhj9x64V/HbD0PPmdsRlOIYD4= - dependencies: - chalk "^1.1.3" - loglevel "^1.4.1" - -loglevel@^1.4.1: - version "1.7.1" - resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.7.1.tgz#005fde2f5e6e47068f935ff28573e125ef72f197" - integrity sha512-Hesni4s5UkWkwCGJMQGAh71PaLUmKFM60dHvq0zi/vDhhrzuk+4GgNbTXJ12YYQJn6ZKBDNIjYcuQGKudvqrIw== - -longest-streak@^2.0.0: - version "2.0.4" - resolved "https://registry.yarnpkg.com/longest-streak/-/longest-streak-2.0.4.tgz#b8599957da5b5dab64dee3fe316fa774597d90e4" - integrity sha512-vM6rUVCVUJJt33bnmHiZEvr7wPT78ztX7rojL+LW51bHtLh6HTjx84LA5W4+oa6aKEJA7jJu5LR6vQRBpA5DVg== - -loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" - integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== - dependencies: - js-tokens "^3.0.0 || ^4.0.0" - -lru-cache@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" - integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== - dependencies: - yallist "^4.0.0" - -make-dir@^3.0.2: - version "3.1.0" - resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" - integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw== - dependencies: - semver "^6.0.0" - -markdown-table@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/markdown-table/-/markdown-table-2.0.0.tgz#194a90ced26d31fe753d8b9434430214c011865b" - integrity sha512-Ezda85ToJUBhM6WGaG6veasyym+Tbs3cMAw/ZhOPqXiYsr0jgocBV3j3nx+4lk47plLlIqjwuTm/ywVI+zjJ/A== - dependencies: - repeat-string "^1.0.0" - -match-sorter@^6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/match-sorter/-/match-sorter-6.0.2.tgz#91bbab14c28a87f4a67755b7a194c0d11dedc080" - integrity sha512-SDRLNlWof9GnAUEyhKP0O5525MMGXUGt+ep4MrrqQ2StAh3zjvICVZseiwg7Zijn3GazpJDiwuRr/mFDHd92NQ== - dependencies: - "@babel/runtime" "^7.12.5" - remove-accents "0.4.2" - -md5.js@^1.3.4: - version "1.3.5" - resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f" - integrity sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg== - dependencies: - hash-base "^3.0.0" - inherits "^2.0.1" - safe-buffer "^5.1.2" - -mdast-add-list-metadata@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/mdast-add-list-metadata/-/mdast-add-list-metadata-1.0.1.tgz#95e73640ce2fc1fa2dcb7ec443d09e2bfe7db4cf" - integrity sha512-fB/VP4MJ0LaRsog7hGPxgOrSL3gE/2uEdZyDuSEnKCv/8IkYHiDkIQSbChiJoHyxZZXZ9bzckyRk+vNxFzh8rA== - dependencies: - unist-util-visit-parents "1.1.2" - -mdast-util-find-and-replace@^1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/mdast-util-find-and-replace/-/mdast-util-find-and-replace-1.1.1.tgz#b7db1e873f96f66588c321f1363069abf607d1b5" - integrity sha512-9cKl33Y21lyckGzpSmEQnIDjEfeeWelN5s1kUW1LwdB0Fkuq2u+4GdqcGEygYxJE8GVqCl0741bYXHgamfWAZA== - dependencies: - escape-string-regexp "^4.0.0" - unist-util-is "^4.0.0" - unist-util-visit-parents "^3.0.0" - -mdast-util-from-markdown@^0.8.0: - version "0.8.4" - resolved "https://registry.yarnpkg.com/mdast-util-from-markdown/-/mdast-util-from-markdown-0.8.4.tgz#2882100c1b9fc967d3f83806802f303666682d32" - integrity sha512-jj891B5pV2r63n2kBTFh8cRI2uR9LQHsXG1zSDqfhXkIlDzrTcIlbB5+5aaYEkl8vOPIOPLf8VT7Ere1wWTMdw== - dependencies: - "@types/mdast" "^3.0.0" - mdast-util-to-string "^2.0.0" - micromark "~2.11.0" - parse-entities "^2.0.0" - unist-util-stringify-position "^2.0.0" - -mdast-util-gfm-autolink-literal@^0.1.0: - version "0.1.3" - resolved "https://registry.yarnpkg.com/mdast-util-gfm-autolink-literal/-/mdast-util-gfm-autolink-literal-0.1.3.tgz#9c4ff399c5ddd2ece40bd3b13e5447d84e385fb7" - integrity sha512-GjmLjWrXg1wqMIO9+ZsRik/s7PLwTaeCHVB7vRxUwLntZc8mzmTsLVr6HW1yLokcnhfURsn5zmSVdi3/xWWu1A== - dependencies: - ccount "^1.0.0" - mdast-util-find-and-replace "^1.1.0" - micromark "^2.11.3" - -mdast-util-gfm-strikethrough@^0.2.0: - version "0.2.3" - resolved "https://registry.yarnpkg.com/mdast-util-gfm-strikethrough/-/mdast-util-gfm-strikethrough-0.2.3.tgz#45eea337b7fff0755a291844fbea79996c322890" - integrity sha512-5OQLXpt6qdbttcDG/UxYY7Yjj3e8P7X16LzvpX8pIQPYJ/C2Z1qFGMmcw+1PZMUM3Z8wt8NRfYTvCni93mgsgA== - dependencies: - mdast-util-to-markdown "^0.6.0" - -mdast-util-gfm-table@^0.1.0: - version "0.1.6" - resolved "https://registry.yarnpkg.com/mdast-util-gfm-table/-/mdast-util-gfm-table-0.1.6.tgz#af05aeadc8e5ee004eeddfb324b2ad8c029b6ecf" - integrity sha512-j4yDxQ66AJSBwGkbpFEp9uG/LS1tZV3P33fN1gkyRB2LoRL+RR3f76m0HPHaby6F4Z5xr9Fv1URmATlRRUIpRQ== - dependencies: - markdown-table "^2.0.0" - mdast-util-to-markdown "~0.6.0" - -mdast-util-gfm-task-list-item@^0.1.0: - version "0.1.6" - resolved "https://registry.yarnpkg.com/mdast-util-gfm-task-list-item/-/mdast-util-gfm-task-list-item-0.1.6.tgz#70c885e6b9f543ddd7e6b41f9703ee55b084af10" - integrity sha512-/d51FFIfPsSmCIRNp7E6pozM9z1GYPIkSy1urQ8s/o4TC22BZ7DqfHFWiqBD23bc7J3vV1Fc9O4QIHBlfuit8A== - dependencies: - mdast-util-to-markdown "~0.6.0" - -mdast-util-gfm@^0.1.0: - version "0.1.2" - resolved "https://registry.yarnpkg.com/mdast-util-gfm/-/mdast-util-gfm-0.1.2.tgz#8ecddafe57d266540f6881f5c57ff19725bd351c" - integrity sha512-NNkhDx/qYcuOWB7xHUGWZYVXvjPFFd6afg6/e2g+SV4r9q5XUcCbV4Wfa3DLYIiD+xAEZc6K4MGaE/m0KDcPwQ== - dependencies: - mdast-util-gfm-autolink-literal "^0.1.0" - mdast-util-gfm-strikethrough "^0.2.0" - mdast-util-gfm-table "^0.1.0" - mdast-util-gfm-task-list-item "^0.1.0" - mdast-util-to-markdown "^0.6.1" - -mdast-util-to-markdown@^0.6.0, mdast-util-to-markdown@^0.6.1, mdast-util-to-markdown@~0.6.0: - version "0.6.5" - resolved "https://registry.yarnpkg.com/mdast-util-to-markdown/-/mdast-util-to-markdown-0.6.5.tgz#b33f67ca820d69e6cc527a93d4039249b504bebe" - integrity sha512-XeV9sDE7ZlOQvs45C9UKMtfTcctcaj/pGwH8YLbMHoMOXNNCn2LsqVQOqrF1+/NU8lKDAqozme9SCXWyo9oAcQ== - dependencies: - "@types/unist" "^2.0.0" - longest-streak "^2.0.0" - mdast-util-to-string "^2.0.0" - parse-entities "^2.0.0" - repeat-string "^1.0.0" - zwitch "^1.0.0" - -mdast-util-to-string@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/mdast-util-to-string/-/mdast-util-to-string-2.0.0.tgz#b8cfe6a713e1091cb5b728fc48885a4767f8b97b" - integrity sha512-AW4DRS3QbBayY/jJmD8437V1Gombjf8RSOUCMFBuo5iHi58AGEgVCKQ+ezHkZZDpAQS75hcBMpLqjpJTjtUL7w== - -media-typer@0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" - integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g= - -memoize-one@^5.0.0: - version "5.1.1" - resolved "https://registry.yarnpkg.com/memoize-one/-/memoize-one-5.1.1.tgz#047b6e3199b508eaec03504de71229b8eb1d75c0" - integrity sha512-HKeeBpWvqiVJD57ZUAsJNm71eHTykffzcLZVYWiVfQeI1rJtuEaS7hQiEpWfVVk18donPwJEcFKIkCmPJNOhHA== - -merge-descriptors@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" - integrity sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E= - -merge-stream@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" - integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== - -merge2@^1.3.0: - version "1.4.1" - resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" - integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== - -methods@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" - integrity sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4= - -micromark-extension-gfm-autolink-literal@~0.5.0: - version "0.5.7" - resolved "https://registry.yarnpkg.com/micromark-extension-gfm-autolink-literal/-/micromark-extension-gfm-autolink-literal-0.5.7.tgz#53866c1f0c7ef940ae7ca1f72c6faef8fed9f204" - integrity sha512-ePiDGH0/lhcngCe8FtH4ARFoxKTUelMp4L7Gg2pujYD5CSMb9PbblnyL+AAMud/SNMyusbS2XDSiPIRcQoNFAw== - dependencies: - micromark "~2.11.3" - -micromark-extension-gfm-strikethrough@~0.6.5: - version "0.6.5" - resolved "https://registry.yarnpkg.com/micromark-extension-gfm-strikethrough/-/micromark-extension-gfm-strikethrough-0.6.5.tgz#96cb83356ff87bf31670eefb7ad7bba73e6514d1" - integrity sha512-PpOKlgokpQRwUesRwWEp+fHjGGkZEejj83k9gU5iXCbDG+XBA92BqnRKYJdfqfkrRcZRgGuPuXb7DaK/DmxOhw== - dependencies: - micromark "~2.11.0" - -micromark-extension-gfm-table@~0.4.0: - version "0.4.3" - resolved "https://registry.yarnpkg.com/micromark-extension-gfm-table/-/micromark-extension-gfm-table-0.4.3.tgz#4d49f1ce0ca84996c853880b9446698947f1802b" - integrity sha512-hVGvESPq0fk6ALWtomcwmgLvH8ZSVpcPjzi0AjPclB9FsVRgMtGZkUcpE0zgjOCFAznKepF4z3hX8z6e3HODdA== - dependencies: - micromark "~2.11.0" - -micromark-extension-gfm-tagfilter@~0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/micromark-extension-gfm-tagfilter/-/micromark-extension-gfm-tagfilter-0.3.0.tgz#d9f26a65adee984c9ccdd7e182220493562841ad" - integrity sha512-9GU0xBatryXifL//FJH+tAZ6i240xQuFrSL7mYi8f4oZSbc+NvXjkrHemeYP0+L4ZUT+Ptz3b95zhUZnMtoi/Q== - -micromark-extension-gfm-task-list-item@~0.3.0: - version "0.3.3" - resolved "https://registry.yarnpkg.com/micromark-extension-gfm-task-list-item/-/micromark-extension-gfm-task-list-item-0.3.3.tgz#d90c755f2533ed55a718129cee11257f136283b8" - integrity sha512-0zvM5iSLKrc/NQl84pZSjGo66aTGd57C1idmlWmE87lkMcXrTxg1uXa/nXomxJytoje9trP0NDLvw4bZ/Z/XCQ== - dependencies: - micromark "~2.11.0" - -micromark-extension-gfm@^0.3.0: - version "0.3.3" - resolved "https://registry.yarnpkg.com/micromark-extension-gfm/-/micromark-extension-gfm-0.3.3.tgz#36d1a4c089ca8bdfd978c9bd2bf1a0cb24e2acfe" - integrity sha512-oVN4zv5/tAIA+l3GbMi7lWeYpJ14oQyJ3uEim20ktYFAcfX1x3LNlFGGlmrZHt7u9YlKExmyJdDGaTt6cMSR/A== - dependencies: - micromark "~2.11.0" - micromark-extension-gfm-autolink-literal "~0.5.0" - micromark-extension-gfm-strikethrough "~0.6.5" - micromark-extension-gfm-table "~0.4.0" - micromark-extension-gfm-tagfilter "~0.3.0" - micromark-extension-gfm-task-list-item "~0.3.0" - -micromark@^2.11.3, micromark@~2.11.3: - version "2.11.4" - resolved "https://registry.yarnpkg.com/micromark/-/micromark-2.11.4.tgz#d13436138eea826383e822449c9a5c50ee44665a" - integrity sha512-+WoovN/ppKolQOFIAajxi7Lu9kInbPxFuTBVEavFcL8eAfVstoc5MocPmqBeAdBOJV00uaVjegzH4+MA0DN/uA== - dependencies: - debug "^4.0.0" - parse-entities "^2.0.0" - -micromark@~2.11.0: - version "2.11.2" - resolved "https://registry.yarnpkg.com/micromark/-/micromark-2.11.2.tgz#e8b6a05f54697d2d3d27fc89600c6bc40dd05f35" - integrity sha512-IXuP76p2uj8uMg4FQc1cRE7lPCLsfAXuEfdjtdO55VRiFO1asrCSQ5g43NmPqFtRwzEnEhafRVzn2jg0UiKArQ== - dependencies: - debug "^4.0.0" - parse-entities "^2.0.0" - -micromatch@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.2.tgz#4fcb0999bf9fbc2fcbdd212f6d629b9a56c39259" - integrity sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q== - dependencies: - braces "^3.0.1" - picomatch "^2.0.5" - -microseconds@0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/microseconds/-/microseconds-0.2.0.tgz#233b25f50c62a65d861f978a4a4f8ec18797dc39" - integrity sha512-n7DHHMjR1avBbSpsTBj6fmMGh2AGrifVV4e+WYc3Q9lO+xnSZ3NyhcBND3vzzatt05LFhoKFRxrIyklmLlUtyA== - -miller-rabin@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/miller-rabin/-/miller-rabin-4.0.1.tgz#f080351c865b0dc562a8462966daa53543c78a4d" - integrity sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA== - dependencies: - bn.js "^4.0.0" - brorand "^1.0.1" - -mime-db@1.44.0: - version "1.44.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.44.0.tgz#fa11c5eb0aca1334b4233cb4d52f10c5a6272f92" - integrity sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg== - -mime-types@~2.1.24: - version "2.1.27" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.27.tgz#47949f98e279ea53119f5722e0f34e529bec009f" - integrity sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w== - dependencies: - mime-db "1.44.0" - -mime@1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" - integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== - -mimic-fn@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" - integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== - -minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" - integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== - -minimalistic-crypto-utils@^1.0.0, minimalistic-crypto-utils@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" - integrity sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo= - -minimatch@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" - integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== - dependencies: - brace-expansion "^1.1.7" - -minimist@^1.2.0, minimist@^1.2.5: - version "1.2.5" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" - integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== - -mkdirp@^0.5.1: - version "0.5.5" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def" - integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ== - dependencies: - minimist "^1.2.5" - -ms@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" - integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= - -ms@2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" - integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg== - -ms@2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" - integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== - -mute-stream@0.0.8: - version "0.0.8" - resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d" - integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA== - -nano-time@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/nano-time/-/nano-time-1.0.0.tgz#b0554f69ad89e22d0907f7a12b0993a5d96137ef" - integrity sha1-sFVPaa2J4i0JB/ehKwmTpdlhN+8= - dependencies: - big-integer "^1.6.16" - -nanoid@^3.1.22: - version "3.1.23" - resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.23.tgz#f744086ce7c2bc47ee0a8472574d5c78e4183a81" - integrity sha512-FiB0kzdP0FFVGDKlRLEQ1BgDzU87dy5NnzjeW9YZNt+/c3+q82EQDUwniSAUxp/F0gFNI1ZhKU1FqYsMuqZVnw== - -native-url@0.3.4: - version "0.3.4" - resolved "https://registry.yarnpkg.com/native-url/-/native-url-0.3.4.tgz#29c943172aed86c63cee62c8c04db7f5756661f8" - integrity sha512-6iM8R99ze45ivyH8vybJ7X0yekIcPf5GgLV5K0ENCbmRcaRIDoj37BC8iLEmaaBfqqb8enuZ5p0uhY+lVAbAcA== - dependencies: - querystring "^0.2.0" - -natural-compare@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" - integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= - -ncp@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ncp/-/ncp-2.0.0.tgz#195a21d6c46e361d2fb1281ba38b91e9df7bdbb3" - integrity sha1-GVoh1sRuNh0vsSgbo4uR6d9727M= - -negotiator@0.6.2: - version "0.6.2" - resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb" - integrity sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw== - -next@^10.2.3: - version "10.2.3" - resolved "https://registry.yarnpkg.com/next/-/next-10.2.3.tgz#5aa058a63626338cea91c198fda8f2715c058394" - integrity sha512-dkM1mIfnORtGyzw/Yme8RdqNxlCMZyi4Lqj56F01/yHbe1ZtOaJ0cyqqRB4RGiPhjGGh0319f8ddjDyO1605Ow== - dependencies: - "@babel/runtime" "7.12.5" - "@hapi/accept" "5.0.2" - "@next/env" "10.2.3" - "@next/polyfill-module" "10.2.3" - "@next/react-dev-overlay" "10.2.3" - "@next/react-refresh-utils" "10.2.3" - "@opentelemetry/api" "0.14.0" - assert "2.0.0" - ast-types "0.13.2" - browserify-zlib "0.2.0" - browserslist "4.16.6" - buffer "5.6.0" - caniuse-lite "^1.0.30001228" - chalk "2.4.2" - chokidar "3.5.1" - constants-browserify "1.0.0" - crypto-browserify "3.12.0" - cssnano-simple "2.0.0" - domain-browser "4.19.0" - encoding "0.1.13" - etag "1.8.1" - find-cache-dir "3.3.1" - get-orientation "1.1.2" - https-browserify "1.0.0" - jest-worker "27.0.0-next.5" - native-url "0.3.4" - node-fetch "2.6.1" - node-html-parser "1.4.9" - node-libs-browser "^2.2.1" - os-browserify "0.3.0" - p-limit "3.1.0" - path-browserify "1.0.1" - pnp-webpack-plugin "1.6.4" - postcss "8.2.13" - process "0.11.10" - prop-types "15.7.2" - querystring-es3 "0.2.1" - raw-body "2.4.1" - react-is "16.13.1" - react-refresh "0.8.3" - stream-browserify "3.0.0" - stream-http "3.1.1" - string_decoder "1.3.0" - styled-jsx "3.3.2" - timers-browserify "2.0.12" - tty-browserify "0.0.1" - use-subscription "1.5.1" - util "0.12.3" - vm-browserify "1.1.2" - watchpack "2.1.1" - -nice-try@^1.0.4: - version "1.0.5" - resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" - integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== - -node-fetch@2.6.1: - version "2.6.1" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052" - integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw== - -node-html-parser@1.4.9: - version "1.4.9" - resolved "https://registry.yarnpkg.com/node-html-parser/-/node-html-parser-1.4.9.tgz#3c8f6cac46479fae5800725edb532e9ae8fd816c" - integrity sha512-UVcirFD1Bn0O+TSmloHeHqZZCxHjvtIeGdVdGMhyZ8/PWlEiZaZ5iJzR189yKZr8p0FXN58BUeC7RHRkf/KYGw== - dependencies: - he "1.2.0" - -node-libs-browser@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/node-libs-browser/-/node-libs-browser-2.2.1.tgz#b64f513d18338625f90346d27b0d235e631f6425" - integrity sha512-h/zcD8H9kaDZ9ALUWwlBUDo6TKF8a7qBSCSEGfjTVIYeqsioSKaAX+BN7NgiMGp6iSIXZ3PxgCu8KS3b71YK5Q== - dependencies: - assert "^1.1.1" - browserify-zlib "^0.2.0" - buffer "^4.3.0" - console-browserify "^1.1.0" - constants-browserify "^1.0.0" - crypto-browserify "^3.11.0" - domain-browser "^1.1.1" - events "^3.0.0" - https-browserify "^1.0.0" - os-browserify "^0.3.0" - path-browserify "0.0.1" - process "^0.11.10" - punycode "^1.2.4" - querystring-es3 "^0.2.0" - readable-stream "^2.3.3" - stream-browserify "^2.0.1" - stream-http "^2.7.2" - string_decoder "^1.0.0" - timers-browserify "^2.0.4" - tty-browserify "0.0.0" - url "^0.11.0" - util "^0.11.0" - vm-browserify "^1.0.1" - -node-releases@^1.1.71: - version "1.1.72" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.72.tgz#14802ab6b1039a79a0c7d662b610a5bbd76eacbe" - integrity sha512-LLUo+PpH3dU6XizX3iVoubUNheF/owjXCZZ5yACDxNnPtgFuludV1ZL3ayK1kVep42Rmm0+R9/Y60NQbZ2bifw== - -normalize-package-data@^2.3.2: - version "2.5.0" - resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" - integrity sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA== - dependencies: - hosted-git-info "^2.1.4" - resolve "^1.10.0" - semver "2 || 3 || 4 || 5" - validate-npm-package-license "^3.0.1" - -normalize-path@^3.0.0, normalize-path@~3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" - integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== - -object-assign@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" - integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= - -object-inspect@^1.8.0: - version "1.8.0" - resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.8.0.tgz#df807e5ecf53a609cc6bfe93eac3cc7be5b3a9d0" - integrity sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA== - -object-inspect@^1.9.0: - version "1.10.2" - resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.10.2.tgz#b6385a3e2b7cae0b5eafcf90cddf85d128767f30" - integrity sha512-gz58rdPpadwztRrPjZE9DZLOABUpTGdcANUgOwBFO1C+HZZhePoP83M65WGDmbpwFYJSWqavbl4SgDn4k8RYTA== - -object-is@^1.0.1: - version "1.1.5" - resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.5.tgz#b9deeaa5fc7f1846a0faecdceec138e5778f53ac" - integrity sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" - -object-keys@^1.0.12, object-keys@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" - integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== - -object.assign@^4.1.0, object.assign@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.1.tgz#303867a666cdd41936ecdedfb1f8f3e32a478cdd" - integrity sha512-VT/cxmx5yaoHSOTSyrCygIDFco+RsibY2NM0a4RdEeY/4KgqezwFtK1yr3U67xYhqJSlASm2pKhLVzPj2lr4bA== - dependencies: - define-properties "^1.1.3" - es-abstract "^1.18.0-next.0" - has-symbols "^1.0.1" - object-keys "^1.1.1" - -object.assign@^4.1.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.2.tgz#0ed54a342eceb37b38ff76eb831a0e788cb63940" - integrity sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ== - dependencies: - call-bind "^1.0.0" - define-properties "^1.1.3" - has-symbols "^1.0.1" - object-keys "^1.1.1" - -object.entries@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/object.entries/-/object.entries-1.1.2.tgz#bc73f00acb6b6bb16c203434b10f9a7e797d3add" - integrity sha512-BQdB9qKmb/HyNdMNWVr7O3+z5MUIx3aiegEIJqjMBbBf0YT9RRxTJSim4mzFqtyr7PDAHigq0N9dO0m0tRakQA== - dependencies: - define-properties "^1.1.3" - es-abstract "^1.17.5" - has "^1.0.3" - -object.fromentries@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/object.fromentries/-/object.fromentries-2.0.2.tgz#4a09c9b9bb3843dd0f89acdb517a794d4f355ac9" - integrity sha512-r3ZiBH7MQppDJVLx6fhD618GKNG40CZYH9wgwdhKxBDDbQgjeWGGd4AtkZad84d291YxvWe7bJGuE65Anh0dxQ== - dependencies: - define-properties "^1.1.3" - es-abstract "^1.17.0-next.1" - function-bind "^1.1.1" - has "^1.0.3" - -object.values@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.1.tgz#68a99ecde356b7e9295a3c5e0ce31dc8c953de5e" - integrity sha512-WTa54g2K8iu0kmS/us18jEmdv1a4Wi//BZ/DTVYEcH0XhLM5NYdpDHja3gt57VrZLcNAO2WGA+KpWsDBaHt6eA== - dependencies: - define-properties "^1.1.3" - es-abstract "^1.17.0-next.1" - function-bind "^1.1.1" - has "^1.0.3" - -on-finished@~2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" - integrity sha1-IPEzZIGwg811M3mSoWlxqi2QaUc= - dependencies: - ee-first "1.1.1" - -once@^1.3.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" - integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= - dependencies: - wrappy "1" - -onchange@^7.1.0: - version "7.1.0" - resolved "https://registry.yarnpkg.com/onchange/-/onchange-7.1.0.tgz#a6f0f7733e4d47014b4cd70aa1ad36c2b4cf3804" - integrity sha512-ZJcqsPiWUAUpvmnJri5TPBooqJOPmC0ttN65juhN15Q8xA+Nbg3BaxBHXQ45EistKKlKElb0edmbPWnKSBkvMg== - dependencies: - "@blakeembrey/deque" "^1.0.5" - "@blakeembrey/template" "^1.0.0" - arg "^4.1.3" - chokidar "^3.3.1" - cross-spawn "^7.0.1" - ignore "^5.1.4" - tree-kill "^1.2.2" - -onetime@^5.1.0: - version "5.1.2" - resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" - integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== - dependencies: - mimic-fn "^2.1.0" - -optionator@^0.8.3: - version "0.8.3" - resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495" - integrity sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA== - dependencies: - deep-is "~0.1.3" - fast-levenshtein "~2.0.6" - levn "~0.3.0" - prelude-ls "~1.1.2" - type-check "~0.3.2" - word-wrap "~1.2.3" - -optionator@^0.9.1: - version "0.9.1" - resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.1.tgz#4f236a6373dae0566a6d43e1326674f50c291499" - integrity sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw== - dependencies: - deep-is "^0.1.3" - fast-levenshtein "^2.0.6" - levn "^0.4.1" - prelude-ls "^1.2.1" - type-check "^0.4.0" - word-wrap "^1.2.3" - -os-browserify@0.3.0, os-browserify@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.3.0.tgz#854373c7f5c2315914fc9bfc6bd8238fdda1ec27" - integrity sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc= - -os-tmpdir@~1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" - integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ= - -p-limit@3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" - integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== - dependencies: - yocto-queue "^0.1.0" - -p-limit@^1.1.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8" - integrity sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q== - dependencies: - p-try "^1.0.0" - -p-limit@^2.2.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" - integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== - dependencies: - p-try "^2.0.0" - -p-locate@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" - integrity sha1-IKAQOyIqcMj9OcwuWAaA893l7EM= - dependencies: - p-limit "^1.1.0" - -p-locate@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" - integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== - dependencies: - p-limit "^2.2.0" - -p-try@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3" - integrity sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M= - -p-try@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" - integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== - -pako@~1.0.5: - version "1.0.11" - resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.11.tgz#6c9599d340d54dfd3946380252a35705a6b992bf" - integrity sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw== - -palette-by-numbers@^0.1.5: - version "0.1.5" - resolved "https://registry.yarnpkg.com/palette-by-numbers/-/palette-by-numbers-0.1.5.tgz#90ce0a33a7245898de889aea5e7361dcb040f635" - integrity sha512-XS7Vk68rF06A3/zS4Q1LnFdsJm1so3vbiUIu3sDP+iq9g3atg74dYhdVarcLrqg+1baHlY/LtXCZOUhTVNP0Lg== - dependencies: - color2k "^1.1.1" - -parent-module@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" - integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== - dependencies: - callsites "^3.0.0" - -parse-asn1@^5.0.0, parse-asn1@^5.1.5: - version "5.1.6" - resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.6.tgz#385080a3ec13cb62a62d39409cb3e88844cdaed4" - integrity sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw== - dependencies: - asn1.js "^5.2.0" - browserify-aes "^1.0.0" - evp_bytestokey "^1.0.0" - pbkdf2 "^3.0.3" - safe-buffer "^5.1.1" - -parse-entities@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/parse-entities/-/parse-entities-2.0.0.tgz#53c6eb5b9314a1f4ec99fa0fdf7ce01ecda0cbe8" - integrity sha512-kkywGpCcRYhqQIchaWqZ875wzpS/bMKhz5HnN3p7wveJTkTtyAB/AlnS0f8DFSqYW1T82t6yEAkEcB+A1I3MbQ== - dependencies: - character-entities "^1.0.0" - character-entities-legacy "^1.0.0" - character-reference-invalid "^1.0.0" - is-alphanumerical "^1.0.0" - is-decimal "^1.0.0" - is-hexadecimal "^1.0.0" - -parse-json@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9" - integrity sha1-9ID0BDTvgHQfhGkJn43qGPVaTck= - dependencies: - error-ex "^1.2.0" - -parse-json@^5.0.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.1.0.tgz#f96088cdf24a8faa9aea9a009f2d9d942c999646" - integrity sha512-+mi/lmVVNKFNVyLXV31ERiy2CY5E1/F6QtJFEzoChPRwwngMNXRDQ9GJ5WdE2Z2P4AujsOi0/+2qHID68KwfIQ== - dependencies: - "@babel/code-frame" "^7.0.0" - error-ex "^1.3.1" - json-parse-even-better-errors "^2.3.0" - lines-and-columns "^1.1.6" - -parseurl@~1.3.3: - version "1.3.3" - resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" - integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== - -path-browserify@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-0.0.1.tgz#e6c4ddd7ed3aa27c68a20cc4e50e1a4ee83bbc4a" - integrity sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ== - -path-browserify@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-1.0.1.tgz#d98454a9c3753d5790860f16f68867b9e46be1fd" - integrity sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g== - -path-exists@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" - integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU= - -path-exists@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" - integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== - -path-is-absolute@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" - integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= - -path-key@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" - integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A= - -path-key@^3.1.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" - integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== - -path-parse@^1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c" - integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw== - -path-to-regexp@0.1.7: - version "0.1.7" - resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" - integrity sha1-32BBeABfUi8V60SQ5yR6G/qmf4w= - -path-type@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/path-type/-/path-type-2.0.0.tgz#f012ccb8415b7096fc2daa1054c3d72389594c73" - integrity sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM= - dependencies: - pify "^2.0.0" - -path-type@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" - integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== - -pbkdf2@^3.0.3: - version "3.1.1" - resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.1.1.tgz#cb8724b0fada984596856d1a6ebafd3584654b94" - integrity sha512-4Ejy1OPxi9f2tt1rRV7Go7zmfDQ+ZectEQz3VGUQhgq62HtIRPDyG/JtnwIxs6x3uNMwo2V7q1fMvKjb+Tnpqg== - dependencies: - create-hash "^1.1.2" - create-hmac "^1.1.4" - ripemd160 "^2.0.1" - safe-buffer "^5.0.1" - sha.js "^2.4.8" - -picomatch@^2.0.4, picomatch@^2.0.5, picomatch@^2.2.1: - version "2.2.2" - resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.2.tgz#21f333e9b6b8eaff02468f5146ea406d345f4dad" - integrity sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg== - -pify@^2.0.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" - integrity sha1-7RQaasBDqEnqWISY59yosVMw6Qw= - -pkg-dir@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-2.0.0.tgz#f6d5d1109e19d63edf428e0bd57e12777615334b" - integrity sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s= - dependencies: - find-up "^2.1.0" - -pkg-dir@^4.1.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" - integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== - dependencies: - find-up "^4.0.0" - -platform@1.3.6: - version "1.3.6" - resolved "https://registry.yarnpkg.com/platform/-/platform-1.3.6.tgz#48b4ce983164b209c2d45a107adb31f473a6e7a7" - integrity sha512-fnWVljUchTro6RiCFvCXBbNhJc2NijN7oIQxbwsyL0buWJPG85v81ehlHI9fXrJsMNgTofEoWIQeClKpgxFLrg== - -pnp-webpack-plugin@1.6.4: - version "1.6.4" - resolved "https://registry.yarnpkg.com/pnp-webpack-plugin/-/pnp-webpack-plugin-1.6.4.tgz#c9711ac4dc48a685dabafc86f8b6dd9f8df84149" - integrity sha512-7Wjy+9E3WwLOEL30D+m8TSTF7qJJUJLONBnwQp0518siuMxUQUbgZwssaFX+QKlZkjHZcw/IpZCt/H0srrntSg== - dependencies: - ts-pnp "^1.1.6" - -popmotion@9.3.6: - version "9.3.6" - resolved "https://registry.yarnpkg.com/popmotion/-/popmotion-9.3.6.tgz#b5236fa28f242aff3871b9e23721f093133248d1" - integrity sha512-ZTbXiu6zIggXzIliMi8LGxXBF5ST+wkpXGEjeTUDUOCdSQ356hij/xjeUdv0F8zCQNeqB1+PR5/BB+gC+QLAPw== - dependencies: - framesync "5.3.0" - hey-listen "^1.0.8" - style-value-types "4.1.4" - tslib "^2.1.0" - -postcss@8.2.13: - version "8.2.13" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.2.13.tgz#dbe043e26e3c068e45113b1ed6375d2d37e2129f" - integrity sha512-FCE5xLH+hjbzRdpbRb1IMCvPv9yZx2QnDarBEYSN0N0HYk+TcXsEhwdFcFb+SRWOKzKGErhIEbBK2ogyLdTtfQ== - dependencies: - colorette "^1.2.2" - nanoid "^3.1.22" - source-map "^0.6.1" - -prelude-ls@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" - integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== - -prelude-ls@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" - integrity sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ= - -prettier-eslint@^12.0.0: - version "12.0.0" - resolved "https://registry.yarnpkg.com/prettier-eslint/-/prettier-eslint-12.0.0.tgz#b4dab5111aad1c0dca062eb7f92a69d5fb1ac1d3" - integrity sha512-N8SGGQwAosISXTNl1E57sBbtnqUGlyRWjcfIUxyD3HF4ynehA9GZ8IfJgiep/OfYvCof/JEpy9ZqSl250Wia7A== - dependencies: - "@typescript-eslint/parser" "^3.0.0" - common-tags "^1.4.0" - dlv "^1.1.0" - eslint "^7.9.0" - indent-string "^4.0.0" - lodash.merge "^4.6.0" - loglevel-colored-level-prefix "^1.0.0" - prettier "^2.0.0" - pretty-format "^23.0.1" - require-relative "^0.8.7" - typescript "^3.9.3" - vue-eslint-parser "~7.1.0" - -prettier-linter-helpers@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz#d23d41fe1375646de2d0104d3454a3008802cf7b" - integrity sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w== - dependencies: - fast-diff "^1.1.2" - -prettier@^1.x.x: - version "1.19.1" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.19.1.tgz#f7d7f5ff8a9cd872a7be4ca142095956a60797cb" - integrity sha512-s7PoyDv/II1ObgQunCbB9PdLmUcBZcnWOcxDh7O0N/UwDEsHyqkW+Qh28jW+mVuCdx7gLB0BotYI1Y6uI9iyew== - -prettier@^2.0.0, prettier@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.2.1.tgz#795a1a78dd52f073da0cd42b21f9c91381923ff5" - integrity sha512-PqyhM2yCjg/oKkFPtTGUojv7gnZAoG80ttl45O6x2Ug/rMJw4wcc9k6aaf2hibP7BGVCCM33gZoGjyvt9mm16Q== - -pretty-format@^23.0.1: - version "23.6.0" - resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-23.6.0.tgz#5eaac8eeb6b33b987b7fe6097ea6a8a146ab5760" - integrity sha512-zf9NV1NSlDLDjycnwm6hpFATCGl/K1lt0R/GdkAK2O5LN/rwJoB+Mh93gGJjut4YbmecbfgLWVGSTCr0Ewvvbw== - dependencies: - ansi-regex "^3.0.0" - ansi-styles "^3.2.0" - -process-nextick-args@~2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" - integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== - -process@0.11.10, process@^0.11.10: - version "0.11.10" - resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" - integrity sha1-czIwDoQBYb2j5podHZGn1LwW8YI= - -progress@^2.0.0: - version "2.0.3" - resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" - integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== - -prop-types@15.7.2, prop-types@^15.5.8, prop-types@^15.6.0, prop-types@^15.6.2, prop-types@^15.7.2: - version "15.7.2" - resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5" - integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ== - dependencies: - loose-envify "^1.4.0" - object-assign "^4.1.1" - react-is "^16.8.1" - -proxy-addr@~2.0.5: - version "2.0.6" - resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.6.tgz#fdc2336505447d3f2f2c638ed272caf614bbb2bf" - integrity sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw== - dependencies: - forwarded "~0.1.2" - ipaddr.js "1.9.1" - -public-encrypt@^4.0.0: - version "4.0.3" - resolved "https://registry.yarnpkg.com/public-encrypt/-/public-encrypt-4.0.3.tgz#4fcc9d77a07e48ba7527e7cbe0de33d0701331e0" - integrity sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q== - dependencies: - bn.js "^4.1.0" - browserify-rsa "^4.0.0" - create-hash "^1.1.0" - parse-asn1 "^5.0.0" - randombytes "^2.0.1" - safe-buffer "^5.1.2" - -punycode@1.3.2: - version "1.3.2" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d" - integrity sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0= - -punycode@^1.2.4: - version "1.4.1" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" - integrity sha1-wNWmOycYgArY4esPpSachN1BhF4= - -punycode@^2.1.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" - integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== - -qs@6.7.0: - version "6.7.0" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.7.0.tgz#41dc1a015e3d581f1621776be31afb2876a9b1bc" - integrity sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ== - -querystring-es3@0.2.1, querystring-es3@^0.2.0: - version "0.2.1" - resolved "https://registry.yarnpkg.com/querystring-es3/-/querystring-es3-0.2.1.tgz#9ec61f79049875707d69414596fd907a4d711e73" - integrity sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM= - -querystring@0.2.0, querystring@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620" - integrity sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA= - -ramda@^0.27.1: - version "0.27.1" - resolved "https://registry.yarnpkg.com/ramda/-/ramda-0.27.1.tgz#66fc2df3ef873874ffc2da6aa8984658abacf5c9" - integrity sha512-PgIdVpn5y5Yns8vqb8FzBUEYn98V3xcPgawAkkgj0YJ0qDsnHCiNmZYfOGMgOvoB0eWFLpYbhxUR3mxfDIMvpw== - -randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5: - version "2.1.0" - resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" - integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== - dependencies: - safe-buffer "^5.1.0" - -randomfill@^1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/randomfill/-/randomfill-1.0.4.tgz#c92196fc86ab42be983f1bf31778224931d61458" - integrity sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw== - dependencies: - randombytes "^2.0.5" - safe-buffer "^5.1.0" - -range-parser@~1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" - integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== - -raw-body@2.4.0: - version "2.4.0" - resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.4.0.tgz#a1ce6fb9c9bc356ca52e89256ab59059e13d0332" - integrity sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q== - dependencies: - bytes "3.1.0" - http-errors "1.7.2" - iconv-lite "0.4.24" - unpipe "1.0.0" - -raw-body@2.4.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.4.1.tgz#30ac82f98bb5ae8c152e67149dac8d55153b168c" - integrity sha512-9WmIKF6mkvA0SLmA2Knm9+qj89e+j1zqgyn8aXGd7+nAduPoqgI9lO57SAZNn/Byzo5P7JhXTyg9PzaJbH73bA== - dependencies: - bytes "3.1.0" - http-errors "1.7.3" - iconv-lite "0.4.24" - unpipe "1.0.0" - -react-clientside-effect@^1.2.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/react-clientside-effect/-/react-clientside-effect-1.2.2.tgz#6212fb0e07b204e714581dd51992603d1accc837" - integrity sha512-nRmoyxeok5PBO6ytPvSjKp9xwXg9xagoTK1mMjwnQxqM9Hd7MNPl+LS1bOSOe+CV2+4fnEquc7H/S8QD3q697A== - dependencies: - "@babel/runtime" "^7.0.0" - -react-countdown@^2.2.1: - version "2.3.0" - resolved "https://registry.yarnpkg.com/react-countdown/-/react-countdown-2.3.0.tgz#fb07ab3d834f123961a3521298b281cf6328b9b3" - integrity sha512-uiwEIBPbGKyT/bOLv/RI1Q8FtmlefUREKeJMtJ91IKBWfTOinfPFZcxCXVHBazr3+i/DvOMk6A323Fv+ysZLKw== - dependencies: - prop-types "^15.7.2" - -react-device-detect@^1.15.0: - version "1.15.0" - resolved "https://registry.yarnpkg.com/react-device-detect/-/react-device-detect-1.15.0.tgz#5321f94ae3c4d51ef399b0502a6c739e32d0f315" - integrity sha512-ywjtWW04U7vaJK87IAFHhKozZhTPeDVWsfYx5CxQSQCjU5+fnMMxWZt9HnVWaNTqBEn6g8wCNWyqav7sXJrURg== - dependencies: - ua-parser-js "^0.7.23" - -react-dom@^17.0.2: - version "17.0.2" - resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-17.0.2.tgz#ecffb6845e3ad8dbfcdc498f0d0a939736502c23" - integrity sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA== - dependencies: - loose-envify "^1.1.0" - object-assign "^4.1.1" - scheduler "^0.20.2" - -react-draggable@^4.4.3: - version "4.4.3" - resolved "https://registry.yarnpkg.com/react-draggable/-/react-draggable-4.4.3.tgz#0727f2cae5813e36b0e4962bf11b2f9ef2b406f3" - integrity sha512-jV4TE59MBuWm7gb6Ns3Q1mxX8Azffb7oTtDtBgFkxRvhDp38YAARmRplrj0+XGkhOJB5XziArX+4HUUABtyZ0w== - dependencies: - classnames "^2.2.5" - prop-types "^15.6.0" - -react-fast-compare@3.2.0, react-fast-compare@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-3.2.0.tgz#641a9da81b6a6320f270e89724fb45a0b39e43bb" - integrity sha512-rtGImPZ0YyLrscKI9xTpV8psd6I8VAtjKCzQDlzyDvqJA8XOW78TXYQwNRNd8g8JZnDu8q9Fu/1v4HPAVwVdHA== - -react-flow-renderer@^9.6.0: - version "9.6.0" - resolved "https://registry.yarnpkg.com/react-flow-renderer/-/react-flow-renderer-9.6.0.tgz#b056cbb11ac429d3e19082e3d28aeef6d0323d31" - integrity sha512-uV0uVxaBJl++B0VGKVMr5dKaPfiRpq1IpicwTPY4xZYFrmKTipdGAoCM/SlH02UDcI886SSypdvrh4UXQA4xnQ== - dependencies: - "@babel/runtime" "^7.14.0" - "@types/d3" "^6.7.0" - "@types/react-redux" "^7.1.16" - classcat "^5.0.3" - d3-selection "^2.0.0" - d3-zoom "^2.0.0" - fast-deep-equal "^3.1.3" - react-draggable "^4.4.3" - react-redux "^7.2.4" - redux "^4.1.0" - -react-focus-lock@2.5.0: - version "2.5.0" - resolved "https://registry.yarnpkg.com/react-focus-lock/-/react-focus-lock-2.5.0.tgz#12e3a3940e897c26e2c2a0408cd25ea3c99b3709" - integrity sha512-XLxj6uTXgz0US8TmqNU2jMfnXwZG0mH2r/afQqvPEaX6nyEll5LHVcEXk2XDUQ34RVeLPkO/xK5x6c/qiuSq/A== - dependencies: - "@babel/runtime" "^7.0.0" - focus-lock "^0.8.1" - prop-types "^15.6.2" - react-clientside-effect "^1.2.2" - use-callback-ref "^1.2.1" - use-sidecar "^1.0.1" - -react-ga@^3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/react-ga/-/react-ga-3.3.0.tgz#c91f407198adcb3b49e2bc5c12b3fe460039b3ca" - integrity sha512-o8RScHj6Lb8cwy3GMrVH6NJvL+y0zpJvKtc0+wmH7Bt23rszJmnqEQxRbyrqUzk9DTJIHoP42bfO5rswC9SWBQ== - -react-hook-form@^7.7.0: - version "7.7.0" - resolved "https://registry.yarnpkg.com/react-hook-form/-/react-hook-form-7.7.0.tgz#11072091fde39775ad834321d9f18f160d47e997" - integrity sha512-WhTl6lbQrV942yzmDL+Eq9AGwG0gARHBH198wuxYIoxtvrsBt5EskdTcRjAYXvJv9N5ojd3t+QoT4QXgDi5l0g== - -react-input-autosize@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/react-input-autosize/-/react-input-autosize-3.0.0.tgz#6b5898c790d4478d69420b55441fcc31d5c50a85" - integrity sha512-nL9uS7jEs/zu8sqwFE5MAPx6pPkNAriACQ2rGLlqmKr2sPGtN7TXTyDdQt4lbNXVx7Uzadb40x8qotIuru6Rhg== - dependencies: - prop-types "^15.5.8" - -react-is@16.13.1, react-is@^16.13.1, react-is@^16.7.0, react-is@^16.8.1, react-is@^16.8.6: - version "16.13.1" - resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" - integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== - -react-markdown@^5.0.3: - version "5.0.3" - resolved "https://registry.yarnpkg.com/react-markdown/-/react-markdown-5.0.3.tgz#41040ea7a9324b564b328fb81dd6c04f2a5373ac" - integrity sha512-jDWOc1AvWn0WahpjW6NK64mtx6cwjM4iSsLHJPNBqoAgGOVoIdJMqaKX4++plhOtdd4JksdqzlDibgPx6B/M2w== - dependencies: - "@types/mdast" "^3.0.3" - "@types/unist" "^2.0.3" - html-to-react "^1.3.4" - mdast-add-list-metadata "1.0.1" - prop-types "^15.7.2" - react-is "^16.8.6" - remark-parse "^9.0.0" - unified "^9.0.0" - unist-util-visit "^2.0.0" - xtend "^4.0.1" - -react-query@^3.16.0: - version "3.16.0" - resolved "https://registry.yarnpkg.com/react-query/-/react-query-3.16.0.tgz#8de1556aabb3d200d0f8eeb74ce2b0b3dd0a0a51" - integrity sha512-YOvI8mO9WG+r4XsyJinjlDMiV5IewUWUcTv2J7z6bIP3KOFvgT6k6HM8vQouz4hPnme7Ktq9j5e7LarUqgJXFQ== - dependencies: - "@babel/runtime" "^7.5.5" - broadcast-channel "^3.4.1" - match-sorter "^6.0.2" - -react-redux@^7.2.4: - version "7.2.4" - resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-7.2.4.tgz#1ebb474032b72d806de2e0519cd07761e222e225" - integrity sha512-hOQ5eOSkEJEXdpIKbnRyl04LhaWabkDPV+Ix97wqQX3T3d2NQ8DUblNXXtNMavc7DpswyQM6xfaN4HQDKNY2JA== - dependencies: - "@babel/runtime" "^7.12.1" - "@types/react-redux" "^7.1.16" - hoist-non-react-statics "^3.3.2" - loose-envify "^1.4.0" - prop-types "^15.7.2" - react-is "^16.13.1" - -react-refresh@0.8.3: - version "0.8.3" - resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.8.3.tgz#721d4657672d400c5e3c75d063c4a85fb2d5d68f" - integrity sha512-X8jZHc7nCMjaCqoU+V2I0cOhNW+QMBwSUkeXnTi8IPe6zaRWfn60ZzvFDZqWPfmSJfjub7dDW1SP0jaHWLu/hg== - -react-remove-scroll-bar@^2.1.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/react-remove-scroll-bar/-/react-remove-scroll-bar-2.1.1.tgz#5876428dfd546f2f63a4d277aea2197925505c1e" - integrity sha512-IZbfQPSozIr8ylHE9MFcQeb2TTzj4abfE7OBXjmtUeXQ5h6ColGKDNo5h7OmzrJRilAx3YIKBf3jb0yrb31BJQ== - dependencies: - react-style-singleton "^2.1.0" - tslib "^1.0.0" - -react-remove-scroll@2.4.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/react-remove-scroll/-/react-remove-scroll-2.4.1.tgz#e0af6126621083a5064591d367291a81b2d107f5" - integrity sha512-K7XZySEzOHMTq7dDwcHsZA6Y7/1uX5RsWhRXVYv8rdh+y9Qz2nMwl9RX/Mwnj/j7JstCGmxyfyC0zbVGXYh3mA== - dependencies: - react-remove-scroll-bar "^2.1.0" - react-style-singleton "^2.1.0" - tslib "^1.0.0" - use-callback-ref "^1.2.3" - use-sidecar "^1.0.1" - -react-select@^4.3.1: - version "4.3.1" - resolved "https://registry.yarnpkg.com/react-select/-/react-select-4.3.1.tgz#389fc07c9bc7cf7d3c377b7a05ea18cd7399cb81" - integrity sha512-HBBd0dYwkF5aZk1zP81Wx5UsLIIT2lSvAY2JiJo199LjoLHoivjn9//KsmvQMEFGNhe58xyuOITjfxKCcGc62Q== - dependencies: - "@babel/runtime" "^7.12.0" - "@emotion/cache" "^11.4.0" - "@emotion/react" "^11.1.1" - memoize-one "^5.0.0" - prop-types "^15.6.0" - react-input-autosize "^3.0.0" - react-transition-group "^4.3.0" - -react-simple-animate@^3.3.12: - version "3.3.12" - resolved "https://registry.yarnpkg.com/react-simple-animate/-/react-simple-animate-3.3.12.tgz#ddea0f230feb3c1f069fbdb0a26e735e0b233265" - integrity sha512-lFXjxD6ficcpOMsHfcDs1jqdkCve6jNlJnubOCzVOLswFDRANsaLN4KwpezDuliEFz8Q1zyj4J7Tmj3KMRnPcg== - -react-style-singleton@^2.1.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/react-style-singleton/-/react-style-singleton-2.1.1.tgz#ce7f90b67618be2b6b94902a30aaea152ce52e66" - integrity sha512-jNRp07Jza6CBqdRKNgGhT3u9umWvils1xsuMOjZlghBDH2MU0PL2WZor4PGYjXpnRCa9DQSlHMs/xnABWOwYbA== - dependencies: - get-nonce "^1.0.0" - invariant "^2.2.4" - tslib "^1.0.0" - -react-table@^7.7.0: - version "7.7.0" - resolved "https://registry.yarnpkg.com/react-table/-/react-table-7.7.0.tgz#e2ce14d7fe3a559f7444e9ecfe8231ea8373f912" - integrity sha512-jBlj70iBwOTvvImsU9t01LjFjy4sXEtclBovl3mTiqjz23Reu0DKnRza4zlLtOPACx6j2/7MrQIthIK1Wi+LIA== - -react-transition-group@^4.3.0: - version "4.4.1" - resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-4.4.1.tgz#63868f9325a38ea5ee9535d828327f85773345c9" - integrity sha512-Djqr7OQ2aPUiYurhPalTrVy9ddmFCCzwhqQmtN+J3+3DzLO209Fdr70QrN8Z3DsglWql6iY1lDWAfpFiBtuKGw== - dependencies: - "@babel/runtime" "^7.5.5" - dom-helpers "^5.0.1" - loose-envify "^1.4.0" - prop-types "^15.6.2" - -react@^17.0.2: - version "17.0.2" - resolved "https://registry.yarnpkg.com/react/-/react-17.0.2.tgz#d0b5cc516d29eb3eee383f75b62864cfb6800037" - integrity sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA== - dependencies: - loose-envify "^1.1.0" - object-assign "^4.1.1" - -read-pkg-up@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-2.0.0.tgz#6b72a8048984e0c41e79510fd5e9fa99b3b549be" - integrity sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4= - dependencies: - find-up "^2.0.0" - read-pkg "^2.0.0" - -read-pkg@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-2.0.0.tgz#8ef1c0623c6a6db0dc6713c4bfac46332b2368f8" - integrity sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg= - dependencies: - load-json-file "^2.0.0" - normalize-package-data "^2.3.2" - path-type "^2.0.0" - -readable-stream@^2.0.2, readable-stream@^2.3.3, readable-stream@^2.3.6: - version "2.3.7" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" - integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.3" - isarray "~1.0.0" - process-nextick-args "~2.0.0" - safe-buffer "~5.1.1" - string_decoder "~1.1.1" - util-deprecate "~1.0.1" - -readable-stream@^3.5.0, readable-stream@^3.6.0: - version "3.6.0" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" - integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== - dependencies: - inherits "^2.0.3" - string_decoder "^1.1.1" - util-deprecate "^1.0.1" - -readdirp@~3.5.0: - version "3.5.0" - resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.5.0.tgz#9ba74c019b15d365278d2e91bb8c48d7b4d42c9e" - integrity sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ== - dependencies: - picomatch "^2.2.1" - -redux-devtools-extension@2.13.8: - version "2.13.8" - resolved "https://registry.yarnpkg.com/redux-devtools-extension/-/redux-devtools-extension-2.13.8.tgz#37b982688626e5e4993ff87220c9bbb7cd2d96e1" - integrity sha512-8qlpooP2QqPtZHQZRhx3x3OP5skEV1py/zUdMY28WNAocbafxdG2tRD1MWE7sp8obGMNYuLWanhhQ7EQvT1FBg== - -redux@4.0.5: - version "4.0.5" - resolved "https://registry.yarnpkg.com/redux/-/redux-4.0.5.tgz#4db5de5816e17891de8a80c424232d06f051d93f" - integrity sha512-VSz1uMAH24DM6MF72vcojpYPtrTUu3ByVWfPL1nPfVRb5mZVTve5GnNCUV53QM/BZ66xfWrm0CTWoM+Xlz8V1w== - dependencies: - loose-envify "^1.4.0" - symbol-observable "^1.2.0" - -redux@^4.0.0, redux@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/redux/-/redux-4.1.0.tgz#eb049679f2f523c379f1aff345c8612f294c88d4" - integrity sha512-uI2dQN43zqLWCt6B/BMGRMY6db7TTY4qeHHfGeKb3EOhmOKjU3KdWvNLJyqaHRksv/ErdNH7cFZWg9jXtewy4g== - dependencies: - "@babel/runtime" "^7.9.2" - -regenerator-runtime@^0.13.4: - version "0.13.7" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz#cac2dacc8a1ea675feaabaeb8ae833898ae46f55" - integrity sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew== - -regexp.prototype.flags@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.3.0.tgz#7aba89b3c13a64509dabcf3ca8d9fbb9bdf5cb75" - integrity sha512-2+Q0C5g951OlYlJz6yu5/M33IcsESLlLfsyIaLJaG4FA2r4yP8MvVMJUUP/fVBkSpbbbZlS5gynbEWLipiiXiQ== - dependencies: - define-properties "^1.1.3" - es-abstract "^1.17.0-next.1" - -regexpp@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-2.0.1.tgz#8d19d31cf632482b589049f8281f93dbcba4d07f" - integrity sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw== - -regexpp@^3.0.0, regexpp@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.1.0.tgz#206d0ad0a5648cffbdb8ae46438f3dc51c9f78e2" - integrity sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q== - -remark-gfm@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/remark-gfm/-/remark-gfm-1.0.0.tgz#9213643001be3f277da6256464d56fd28c3b3c0d" - integrity sha512-KfexHJCiqvrdBZVbQ6RopMZGwaXz6wFJEfByIuEwGf0arvITHjiKKZ1dpXujjH9KZdm1//XJQwgfnJ3lmXaDPA== - dependencies: - mdast-util-gfm "^0.1.0" - micromark-extension-gfm "^0.3.0" - -remark-parse@^9.0.0: - version "9.0.0" - resolved "https://registry.yarnpkg.com/remark-parse/-/remark-parse-9.0.0.tgz#4d20a299665880e4f4af5d90b7c7b8a935853640" - integrity sha512-geKatMwSzEXKHuzBNU1z676sGcDcFoChMK38TgdHJNAYfFtsfHDQG7MoJAjs6sgYMqyLduCYWDIWZIxiPeafEw== - dependencies: - mdast-util-from-markdown "^0.8.0" - -remove-accents@0.4.2: - version "0.4.2" - resolved "https://registry.yarnpkg.com/remove-accents/-/remove-accents-0.4.2.tgz#0a43d3aaae1e80db919e07ae254b285d9e1c7bb5" - integrity sha1-CkPTqq4egNuRngeuJUsoXZ4ce7U= - -repeat-string@^1.0.0: - version "1.6.1" - resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" - integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc= - -require-from-string@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" - integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== - -require-relative@^0.8.7: - version "0.8.7" - resolved "https://registry.yarnpkg.com/require-relative/-/require-relative-0.8.7.tgz#7999539fc9e047a37928fa196f8e1563dabd36de" - integrity sha1-eZlTn8ngR6N5KPoZb44VY9q9Nt4= - -requires-port@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" - integrity sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8= - -resolve-from@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" - integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== - -resolve@^1.10.0, resolve@^1.13.1, resolve@^1.18.1: - version "1.19.0" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.19.0.tgz#1af5bf630409734a067cae29318aac7fa29a267c" - integrity sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg== - dependencies: - is-core-module "^2.1.0" - path-parse "^1.0.6" - -resolve@^1.12.0, resolve@^1.17.0: - version "1.17.0" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.17.0.tgz#b25941b54968231cc2d1bb76a79cb7f2c0bf8444" - integrity sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w== - dependencies: - path-parse "^1.0.6" - -restore-cursor@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-3.1.0.tgz#39f67c54b3a7a58cea5236d95cf0034239631f7e" - integrity sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA== - dependencies: - onetime "^5.1.0" - signal-exit "^3.0.2" - -reusify@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" - integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== - -rimraf@2.6.3: - version "2.6.3" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" - integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA== - dependencies: - glob "^7.1.3" - -rimraf@3.0.2, rimraf@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" - integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== - dependencies: - glob "^7.1.3" - -ripemd160@^2.0.0, ripemd160@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c" - integrity sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA== - dependencies: - hash-base "^3.0.0" - inherits "^2.0.1" - -run-async@^2.4.0: - version "2.4.1" - resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.4.1.tgz#8440eccf99ea3e70bd409d49aab88e10c189a455" - integrity sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ== - -run-parallel@^1.1.9: - version "1.1.10" - resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.1.10.tgz#60a51b2ae836636c81377df16cb107351bcd13ef" - integrity sha512-zb/1OuZ6flOlH6tQyMPUrE3x3Ulxjlo9WIVXR4yVYi4H9UXQaeIsPbLn2R3O3vQCnDKkAl2qHiuocKKX4Tz/Sw== - -rxjs@^6.6.0: - version "6.6.3" - resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.6.3.tgz#8ca84635c4daa900c0d3967a6ee7ac60271ee552" - integrity sha512-trsQc+xYYXZ3urjOiJOuCOa5N3jAZ3eiSpQB5hIT8zGlL2QfnHLJ2r7GMkBGuIausdJN1OneaI6gQlsqNHHmZQ== - dependencies: - tslib "^1.9.0" - -safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: - version "5.1.2" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" - integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== - -safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@~5.2.0: - version "5.2.1" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" - integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== - -"safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0", safer-buffer@^2.1.0: - version "2.1.2" - resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" - integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== - -scheduler@^0.20.2: - version "0.20.2" - resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.20.2.tgz#4baee39436e34aa93b4874bddcbf0fe8b8b50e91" - integrity sha512-2eWfGgAqqWFGqtdMmcL5zCMK1U8KlXv8SQFGglL3CEtd0aDVDWgeF/YoCmvln55m5zSk3J/20hTaSBeSObsQDQ== - dependencies: - loose-envify "^1.1.0" - object-assign "^4.1.1" - -"semver@2 || 3 || 4 || 5", semver@^5.5.0: - version "5.7.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" - integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== - -semver@^6.0.0, semver@^6.1.2: - version "6.3.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" - integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== - -semver@^7.2.1: - version "7.3.4" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.4.tgz#27aaa7d2e4ca76452f98d3add093a72c943edc97" - integrity sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw== - dependencies: - lru-cache "^6.0.0" - -semver@^7.3.2: - version "7.3.2" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.2.tgz#604962b052b81ed0786aae84389ffba70ffd3938" - integrity sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ== - -send@0.17.1: - version "0.17.1" - resolved "https://registry.yarnpkg.com/send/-/send-0.17.1.tgz#c1d8b059f7900f7466dd4938bdc44e11ddb376c8" - integrity sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg== - dependencies: - debug "2.6.9" - depd "~1.1.2" - destroy "~1.0.4" - encodeurl "~1.0.2" - escape-html "~1.0.3" - etag "~1.8.1" - fresh "0.5.2" - http-errors "~1.7.2" - mime "1.6.0" - ms "2.1.1" - on-finished "~2.3.0" - range-parser "~1.2.1" - statuses "~1.5.0" - -serve-static@1.14.1: - version "1.14.1" - resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.14.1.tgz#666e636dc4f010f7ef29970a88a674320898b2f9" - integrity sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg== - dependencies: - encodeurl "~1.0.2" - escape-html "~1.0.3" - parseurl "~1.3.3" - send "0.17.1" - -setimmediate@^1.0.4: - version "1.0.5" - resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" - integrity sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU= - -setprototypeof@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.1.tgz#7e95acb24aa92f5885e0abef5ba131330d4ae683" - integrity sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw== - -sha.js@^2.4.0, sha.js@^2.4.8: - version "2.4.11" - resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7" - integrity sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ== - dependencies: - inherits "^2.0.1" - safe-buffer "^5.0.1" - -shebang-command@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" - integrity sha1-RKrGW2lbAzmJaMOfNj/uXer98eo= - dependencies: - shebang-regex "^1.0.0" - -shebang-command@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" - integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== - dependencies: - shebang-regex "^3.0.0" - -shebang-regex@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" - integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM= - -shebang-regex@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" - integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== - -shell-quote@1.7.2: - version "1.7.2" - resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.7.2.tgz#67a7d02c76c9da24f99d20808fcaded0e0e04be2" - integrity sha512-mRz/m/JVscCrkMyPqHc/bczi3OQHkLTqXHEFu0zDhK/qfv3UcOA4SVmRCLmos4bhjr9ekVQubj/R7waKapmiQg== - -side-channel@^1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.3.tgz#cdc46b057550bbab63706210838df5d4c19519c3" - integrity sha512-A6+ByhlLkksFoUepsGxfj5x1gTSrs+OydsRptUxeNCabQpCFUvcwIczgOigI8vhY/OJCnPnyE9rGiwgvr9cS1g== - dependencies: - es-abstract "^1.18.0-next.0" - object-inspect "^1.8.0" - -signal-exit@^3.0.2: - version "3.0.3" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.3.tgz#a1410c2edd8f077b08b4e253c8eacfcaf057461c" - integrity sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA== - -slash@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" - integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== - -slice-ansi@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-2.1.0.tgz#cacd7693461a637a5788d92a7dd4fba068e81636" - integrity sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ== - dependencies: - ansi-styles "^3.2.0" - astral-regex "^1.0.0" - is-fullwidth-code-point "^2.0.0" - -slice-ansi@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-4.0.0.tgz#500e8dd0fd55b05815086255b3195adf2a45fe6b" - integrity sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ== - dependencies: - ansi-styles "^4.0.0" - astral-regex "^2.0.0" - is-fullwidth-code-point "^3.0.0" - -source-map@0.7.3: - version "0.7.3" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.3.tgz#5302f8169031735226544092e64981f751750383" - integrity sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ== - -source-map@0.8.0-beta.0: - version "0.8.0-beta.0" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.8.0-beta.0.tgz#d4c1bb42c3f7ee925f005927ba10709e0d1d1f11" - integrity sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA== - dependencies: - whatwg-url "^7.0.0" - -source-map@^0.5.0, source-map@^0.5.7: - version "0.5.7" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" - integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= - -source-map@^0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" - integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== - -spdx-correct@^3.0.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.1.tgz#dece81ac9c1e6713e5f7d1b6f17d468fa53d89a9" - integrity sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w== - dependencies: - spdx-expression-parse "^3.0.0" - spdx-license-ids "^3.0.0" - -spdx-exceptions@^2.1.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz#3f28ce1a77a00372683eade4a433183527a2163d" - integrity sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A== - -spdx-expression-parse@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz#cf70f50482eefdc98e3ce0a6833e4a53ceeba679" - integrity sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q== - dependencies: - spdx-exceptions "^2.1.0" - spdx-license-ids "^3.0.0" - -spdx-license-ids@^3.0.0: - version "3.0.7" - resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.7.tgz#e9c18a410e5ed7e12442a549fbd8afa767038d65" - integrity sha512-U+MTEOO0AiDzxwFvoa4JVnMV6mZlJKk2sBLt90s7G0Gd0Mlknc7kxEn3nuDPNZRta7O2uy8oLcZLVT+4sqNZHQ== - -sprintf-js@~1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" - integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= - -stacktrace-parser@0.1.10: - version "0.1.10" - resolved "https://registry.yarnpkg.com/stacktrace-parser/-/stacktrace-parser-0.1.10.tgz#29fb0cae4e0d0b85155879402857a1639eb6051a" - integrity sha512-KJP1OCML99+8fhOHxwwzyWrlUuVX5GQ0ZpJTd1DFXhdkrvg1szxfHhawXUZ3g9TkXORQd4/WG68jMlQZ2p8wlg== - dependencies: - type-fest "^0.7.1" - -"statuses@>= 1.5.0 < 2", statuses@~1.5.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" - integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow= - -stream-browserify@3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-3.0.0.tgz#22b0a2850cdf6503e73085da1fc7b7d0c2122f2f" - integrity sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA== - dependencies: - inherits "~2.0.4" - readable-stream "^3.5.0" - -stream-browserify@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-2.0.2.tgz#87521d38a44aa7ee91ce1cd2a47df0cb49dd660b" - integrity sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg== - dependencies: - inherits "~2.0.1" - readable-stream "^2.0.2" - -stream-http@3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/stream-http/-/stream-http-3.1.1.tgz#0370a8017cf8d050b9a8554afe608f043eaff564" - integrity sha512-S7OqaYu0EkFpgeGFb/NPOoPLxFko7TPqtEeFg5DXPB4v/KETHG0Ln6fRFrNezoelpaDKmycEmmZ81cC9DAwgYg== - dependencies: - builtin-status-codes "^3.0.0" - inherits "^2.0.4" - readable-stream "^3.6.0" - xtend "^4.0.2" - -stream-http@^2.7.2: - version "2.8.3" - resolved "https://registry.yarnpkg.com/stream-http/-/stream-http-2.8.3.tgz#b2d242469288a5a27ec4fe8933acf623de6514fc" - integrity sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw== - dependencies: - builtin-status-codes "^3.0.0" - inherits "^2.0.1" - readable-stream "^2.3.6" - to-arraybuffer "^1.0.0" - xtend "^4.0.0" - -stream-parser@^0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/stream-parser/-/stream-parser-0.3.1.tgz#1618548694420021a1182ff0af1911c129761773" - integrity sha1-FhhUhpRCACGhGC/wrxkRwSl2F3M= - dependencies: - debug "2" - -string-format@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/string-format/-/string-format-2.0.0.tgz#f2df2e7097440d3b65de31b6d40d54c96eaffb9b" - integrity sha512-bbEs3scLeYNXLecRRuk6uJxdXUSj6le/8rNPHChIJTn2V79aXVTR1EH2OH5zLKKoz0V02fOUKZZcw01pLUShZA== - -string-hash@1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/string-hash/-/string-hash-1.1.3.tgz#e8aafc0ac1855b4666929ed7dd1275df5d6c811b" - integrity sha1-6Kr8CsGFW0Zmkp7X3RJ1311sgRs= - -string-width@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961" - integrity sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w== - dependencies: - emoji-regex "^7.0.1" - is-fullwidth-code-point "^2.0.0" - strip-ansi "^5.1.0" - -string-width@^4.1.0, string-width@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.0.tgz#952182c46cc7b2c313d1596e623992bd163b72b5" - integrity sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.0" - -string.prototype.matchall@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/string.prototype.matchall/-/string.prototype.matchall-4.0.2.tgz#48bb510326fb9fdeb6a33ceaa81a6ea04ef7648e" - integrity sha512-N/jp6O5fMf9os0JU3E72Qhf590RSRZU/ungsL/qJUYVTNv7hTG0P/dbPjxINVN9jpscu3nzYwKESU3P3RY5tOg== - dependencies: - define-properties "^1.1.3" - es-abstract "^1.17.0" - has-symbols "^1.0.1" - internal-slot "^1.0.2" - regexp.prototype.flags "^1.3.0" - side-channel "^1.0.2" - -string.prototype.trimend@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz#85812a6b847ac002270f5808146064c995fb6913" - integrity sha512-LRPxFUaTtpqYsTeNKaFOw3R4bxIzWOnbQ837QfBylo8jIxtcbK/A/sMV7Q+OAV/vWo+7s25pOE10KYSjaSO06g== - dependencies: - define-properties "^1.1.3" - es-abstract "^1.17.5" - -string.prototype.trimend@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz#e75ae90c2942c63504686c18b287b4a0b1a45f80" - integrity sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" - -string.prototype.trimstart@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz#14af6d9f34b053f7cfc89b72f8f2ee14b9039a54" - integrity sha512-XxZn+QpvrBI1FOcg6dIpxUPgWCPuNXvMD72aaRaUQv1eD4e/Qy8i/hFTe0BUmD60p/QA6bh1avmuPTfNjqVWRw== - dependencies: - define-properties "^1.1.3" - es-abstract "^1.17.5" - -string.prototype.trimstart@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz#b36399af4ab2999b4c9c648bd7a3fb2bb26feeed" - integrity sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" - -string_decoder@1.3.0, string_decoder@^1.0.0, string_decoder@^1.1.1: - version "1.3.0" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" - integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== - dependencies: - safe-buffer "~5.2.0" - -string_decoder@~1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" - integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== - dependencies: - safe-buffer "~5.1.0" - -strip-ansi@6.0.0, strip-ansi@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.0.tgz#0b1571dd7669ccd4f3e06e14ef1eed26225ae532" - integrity sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w== - dependencies: - ansi-regex "^5.0.0" - -strip-ansi@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" - integrity sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8= - dependencies: - ansi-regex "^2.0.0" - -strip-ansi@^5.1.0, strip-ansi@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae" - integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA== - dependencies: - ansi-regex "^4.1.0" - -strip-bom@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" - integrity sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM= - -strip-json-comments@^3.0.1, strip-json-comments@^3.1.0, strip-json-comments@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" - integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== - -style-value-types@4.1.4: - version "4.1.4" - resolved "https://registry.yarnpkg.com/style-value-types/-/style-value-types-4.1.4.tgz#80f37cb4fb024d6394087403dfb275e8bb627e75" - integrity sha512-LCJL6tB+vPSUoxgUBt9juXIlNJHtBMy8jkXzUJSBzeHWdBu6lhzHqCvLVkXFGsFIlNa2ln1sQHya/gzaFmB2Lg== - dependencies: - hey-listen "^1.0.8" - tslib "^2.1.0" - -styled-jsx@3.3.2: - version "3.3.2" - resolved "https://registry.yarnpkg.com/styled-jsx/-/styled-jsx-3.3.2.tgz#2474601a26670a6049fb4d3f94bd91695b3ce018" - integrity sha512-daAkGd5mqhbBhLd6jYAjYBa9LpxYCzsgo/f6qzPdFxVB8yoGbhxvzQgkC0pfmCVvW3JuAEBn0UzFLBfkHVZG1g== - dependencies: - "@babel/types" "7.8.3" - babel-plugin-syntax-jsx "6.18.0" - convert-source-map "1.7.0" - loader-utils "1.2.3" - source-map "0.7.3" - string-hash "1.1.3" - stylis "3.5.4" - stylis-rule-sheet "0.0.10" - -stylis-rule-sheet@0.0.10: - version "0.0.10" - resolved "https://registry.yarnpkg.com/stylis-rule-sheet/-/stylis-rule-sheet-0.0.10.tgz#44e64a2b076643f4b52e5ff71efc04d8c3c4a430" - integrity sha512-nTbZoaqoBnmK+ptANthb10ZRZOGC+EmTLLUxeYIuHNkEKcmKgXX1XWKkUBT2Ac4es3NybooPe0SmvKdhKJZAuw== - -stylis@3.5.4: - version "3.5.4" - resolved "https://registry.yarnpkg.com/stylis/-/stylis-3.5.4.tgz#f665f25f5e299cf3d64654ab949a57c768b73fbe" - integrity sha512-8/3pSmthWM7lsPBKv7NXkzn2Uc9W7NotcwGNpJaa3k7WMM1XDCA4MgT5k/8BIexd5ydZdboXtU90XH9Ec4Bv/Q== - -stylis@^4.0.3: - version "4.0.3" - resolved "https://registry.yarnpkg.com/stylis/-/stylis-4.0.3.tgz#0d714765f3f694a685550f0c45411ebf90a9bded" - integrity sha512-iAxdFyR9cHKp4H5M2dJlDnvcb/3TvPprzlKjvYVbH7Sh+y8hjY/mUu/ssdcvVz6Z4lKI3vsoS0jAkMYmX7ozfA== - -supports-color@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" - integrity sha1-U10EXOa2Nj+kARcIRimZXp3zJMc= - -supports-color@^5.3.0: - version "5.5.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" - integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== - dependencies: - has-flag "^3.0.0" - -supports-color@^7.1.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" - integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== - dependencies: - has-flag "^4.0.0" - -supports-color@^8.0.0: - version "8.1.1" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" - integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== - dependencies: - has-flag "^4.0.0" - -symbol-observable@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.2.0.tgz#c22688aed4eab3cdc2dfeacbb561660560a00804" - integrity sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ== - -table@^5.2.3: - version "5.4.6" - resolved "https://registry.yarnpkg.com/table/-/table-5.4.6.tgz#1292d19500ce3f86053b05f0e8e7e4a3bb21079e" - integrity sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug== - dependencies: - ajv "^6.10.2" - lodash "^4.17.14" - slice-ansi "^2.1.0" - string-width "^3.0.0" - -table@^6.0.4: - version "6.0.6" - resolved "https://registry.yarnpkg.com/table/-/table-6.0.6.tgz#e9223f1e851213e2e43ab584b0fec33fb09a8e7a" - integrity sha512-OInCtPmDNieVBkVFi6C8RwU2S2H0h8mF3e3TQK4nreaUNCpooQUkI+A/KuEkm5FawfhWIfNqG+qfelVVR+V00g== - dependencies: - ajv "^7.0.2" - lodash "^4.17.20" - slice-ansi "^4.0.0" - string-width "^4.2.0" - -text-table@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" - integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= - -through@^2.3.6: - version "2.3.8" - resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" - integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= - -timers-browserify@2.0.12: - version "2.0.12" - resolved "https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-2.0.12.tgz#44a45c11fbf407f34f97bccd1577c652361b00ee" - integrity sha512-9phl76Cqm6FhSX9Xe1ZUAMLtm1BLkKj2Qd5ApyWkXzsMRaA7dgr81kf4wJmQf/hAvg8EEyJxDo3du/0KlhPiKQ== - dependencies: - setimmediate "^1.0.4" - -timers-browserify@^2.0.4: - version "2.0.11" - resolved "https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-2.0.11.tgz#800b1f3eee272e5bc53ee465a04d0e804c31211f" - integrity sha512-60aV6sgJ5YEbzUdn9c8kYGIqOubPoUdqQCul3SBAsRCZ40s6Y5cMcrW4dt3/k/EsbLVJNl9n6Vz3fTc+k2GeKQ== - dependencies: - setimmediate "^1.0.4" - -tiny-invariant@^1.0.6: - version "1.1.0" - resolved "https://registry.yarnpkg.com/tiny-invariant/-/tiny-invariant-1.1.0.tgz#634c5f8efdc27714b7f386c35e6760991d230875" - integrity sha512-ytxQvrb1cPc9WBEI/HSeYYoGD0kWnGEOR8RY6KomWLBVhqz0RgTwVO9dLrGz7dC+nN9llyI7OKAgRq8Vq4ZBSw== - -tinycolor2@1.4.2: - version "1.4.2" - resolved "https://registry.yarnpkg.com/tinycolor2/-/tinycolor2-1.4.2.tgz#3f6a4d1071ad07676d7fa472e1fac40a719d8803" - integrity sha512-vJhccZPs965sV/L2sU4oRQVAos0pQXwsvTLkWYdqJ+a8Q5kPFzJTuOFwy7UniPli44NKQGAglksjvOcpo95aZA== - -tmp@^0.0.33: - version "0.0.33" - resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" - integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw== - dependencies: - os-tmpdir "~1.0.2" - -to-arraybuffer@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz#7d229b1fcc637e466ca081180836a7aabff83f43" - integrity sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M= - -to-fast-properties@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" - integrity sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4= - -to-regex-range@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" - integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== - dependencies: - is-number "^7.0.0" - -toggle-selection@^1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/toggle-selection/-/toggle-selection-1.0.6.tgz#6e45b1263f2017fa0acc7d89d78b15b8bf77da32" - integrity sha1-bkWxJj8gF/oKzH2J14sVuL932jI= - -toidentifier@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553" - integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw== - -tr46@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/tr46/-/tr46-1.0.1.tgz#a8b13fd6bfd2489519674ccde55ba3693b706d09" - integrity sha1-qLE/1r/SSJUZZ0zN5VujaTtwbQk= - dependencies: - punycode "^2.1.0" - -tree-kill@^1.2.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/tree-kill/-/tree-kill-1.2.2.tgz#4ca09a9092c88b73a7cdc5e8a01b507b0790a0cc" - integrity sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A== - -trough@^1.0.0: - version "1.0.5" - resolved "https://registry.yarnpkg.com/trough/-/trough-1.0.5.tgz#b8b639cefad7d0bb2abd37d433ff8293efa5f406" - integrity sha512-rvuRbTarPXmMb79SmzEp8aqXNKcK+y0XaB298IXueQ8I2PsrATcPBCSPyK/dDNa2iWOhKlfNnOjdAOTBU/nkFA== - -ts-pnp@^1.1.6: - version "1.2.0" - resolved "https://registry.yarnpkg.com/ts-pnp/-/ts-pnp-1.2.0.tgz#a500ad084b0798f1c3071af391e65912c86bca92" - integrity sha512-csd+vJOb/gkzvcCHgTGSChYpy5f1/XKNsmvBGO4JXS+z1v2HobugDz4s1IeFXM3wZB44uczs+eazB5Q/ccdhQw== - -tsconfig-paths@^3.9.0: - version "3.9.0" - resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.9.0.tgz#098547a6c4448807e8fcb8eae081064ee9a3c90b" - integrity sha512-dRcuzokWhajtZWkQsDVKbWyY+jgcLC5sqJhg2PSgf4ZkH2aHPvaOY8YWGhmjb68b5qqTfasSsDO9k7RUiEmZAw== - dependencies: - "@types/json5" "^0.0.29" - json5 "^1.0.1" - minimist "^1.2.0" - strip-bom "^3.0.0" - -tslib@^1.0.0, tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.3: - version "1.14.1" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" - integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== - -tslib@^2.1.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.2.0.tgz#fb2c475977e35e241311ede2693cee1ec6698f5c" - integrity sha512-gS9GVHRU+RGn5KQM2rllAlR3dU6m7AcpJKdtH8gFvQiC4Otgk98XnmMU+nZenHt/+VhnBPWwgrJsyrdcw6i23w== - -tsutils@^3.17.1: - version "3.17.1" - resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.17.1.tgz#ed719917f11ca0dee586272b2ac49e015a2dd759" - integrity sha512-kzeQ5B8H3w60nFY2g8cJIuH7JDpsALXySGtwGJ0p2LSjLgay3NdIpqq5SoOBe46bKDW2iq25irHCr8wjomUS2g== - dependencies: - tslib "^1.8.1" - -tty-browserify@0.0.0: - version "0.0.0" - resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.0.tgz#a157ba402da24e9bf957f9aa69d524eed42901a6" - integrity sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY= - -tty-browserify@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.1.tgz#3f05251ee17904dfd0677546670db9651682b811" - integrity sha512-C3TaO7K81YvjCgQH9Q1S3R3P3BtN3RIM8n+OvX4il1K1zgE8ZhI0op7kClgkxtutIE8hQrcrHBXvIheqKUUCxw== - -type-check@^0.4.0, type-check@~0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" - integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew== - dependencies: - prelude-ls "^1.2.1" - -type-check@~0.3.2: - version "0.3.2" - resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" - integrity sha1-WITKtRLPHTVeP7eE8wgEsrUg23I= - dependencies: - prelude-ls "~1.1.2" - -type-fest@^0.11.0: - version "0.11.0" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.11.0.tgz#97abf0872310fed88a5c466b25681576145e33f1" - integrity sha512-OdjXJxnCN1AvyLSzeKIgXTXxV+99ZuXl3Hpo9XpJAv9MBcHrrJOQ5kV7ypXOuQie+AmWG25hLbiKdwYTifzcfQ== - -type-fest@^0.7.1: - version "0.7.1" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.7.1.tgz#8dda65feaf03ed78f0a3f9678f1869147f7c5c48" - integrity sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg== - -type-fest@^0.8.1: - version "0.8.1" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" - integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== - -type-is@~1.6.17, type-is@~1.6.18: - version "1.6.18" - resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" - integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g== - dependencies: - media-typer "0.3.0" - mime-types "~2.1.24" - -typescript@^3.9.3: - version "3.9.7" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.7.tgz#98d600a5ebdc38f40cb277522f12dc800e9e25fa" - integrity sha512-BLbiRkiBzAwsjut4x/dsibSTB6yWpwT5qWmC2OfuCg3GgVQCSgMs4vEctYPhsaGtd0AeuuHMkjZ2h2WG8MSzRw== - -typescript@^4.3.2: - version "4.3.2" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.3.2.tgz#399ab18aac45802d6f2498de5054fcbbe716a805" - integrity sha512-zZ4hShnmnoVnAHpVHWpTcxdv7dWP60S2FsydQLV8V5PbS3FifjWFFRiHSWpDJahly88PRyV5teTSLoq4eG7mKw== - -ua-parser-js@^0.7.23: - version "0.7.23" - resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.23.tgz#704d67f951e13195fbcd3d78818577f5bc1d547b" - integrity sha512-m4hvMLxgGHXG3O3fQVAyyAQpZzDOvwnhOTjYz5Xmr7r/+LpkNy3vJXdVRWgd1TkAb7NGROZuSy96CrlNVjA7KA== - -unbox-primitive@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.1.tgz#085e215625ec3162574dc8859abee78a59b14471" - integrity sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw== - dependencies: - function-bind "^1.1.1" - has-bigints "^1.0.1" - has-symbols "^1.0.2" - which-boxed-primitive "^1.0.2" - -unified@^9.0.0: - version "9.2.0" - resolved "https://registry.yarnpkg.com/unified/-/unified-9.2.0.tgz#67a62c627c40589edebbf60f53edfd4d822027f8" - integrity sha512-vx2Z0vY+a3YoTj8+pttM3tiJHCwY5UFbYdiWrwBEbHmK8pvsPj2rtAX2BFfgXen8T39CJWblWRDT4L5WGXtDdg== - dependencies: - bail "^1.0.0" - extend "^3.0.0" - is-buffer "^2.0.0" - is-plain-obj "^2.0.0" - trough "^1.0.0" - vfile "^4.0.0" - -unist-util-is@^4.0.0: - version "4.0.4" - resolved "https://registry.yarnpkg.com/unist-util-is/-/unist-util-is-4.0.4.tgz#3e9e8de6af2eb0039a59f50c9b3e99698a924f50" - integrity sha512-3dF39j/u423v4BBQrk1AQ2Ve1FxY5W3JKwXxVFzBODQ6WEvccguhgp802qQLKSnxPODE6WuRZtV+ohlUg4meBA== - -unist-util-stringify-position@^2.0.0: - version "2.0.3" - resolved "https://registry.yarnpkg.com/unist-util-stringify-position/-/unist-util-stringify-position-2.0.3.tgz#cce3bfa1cdf85ba7375d1d5b17bdc4cada9bd9da" - integrity sha512-3faScn5I+hy9VleOq/qNbAd6pAx7iH5jYBMS9I1HgQVijz/4mv5Bvw5iw1sC/90CODiKo81G/ps8AJrISn687g== - dependencies: - "@types/unist" "^2.0.2" - -unist-util-visit-parents@1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/unist-util-visit-parents/-/unist-util-visit-parents-1.1.2.tgz#f6e3afee8bdbf961c0e6f028ea3c0480028c3d06" - integrity sha512-yvo+MMLjEwdc3RhhPYSximset7rwjMrdt9E41Smmvg25UQIenzrN83cRnF1JMzoMi9zZOQeYXHSDf7p+IQkW3Q== - -unist-util-visit-parents@^3.0.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/unist-util-visit-parents/-/unist-util-visit-parents-3.1.1.tgz#65a6ce698f78a6b0f56aa0e88f13801886cdaef6" - integrity sha512-1KROIZWo6bcMrZEwiH2UrXDyalAa0uqzWCxCJj6lPOvTve2WkfgCytoDTPaMnodXh1WrXOq0haVYHj99ynJlsg== - dependencies: - "@types/unist" "^2.0.0" - unist-util-is "^4.0.0" - -unist-util-visit@^2.0.0: - version "2.0.3" - resolved "https://registry.yarnpkg.com/unist-util-visit/-/unist-util-visit-2.0.3.tgz#c3703893146df47203bb8a9795af47d7b971208c" - integrity sha512-iJ4/RczbJMkD0712mGktuGpm/U4By4FfDonL7N/9tATGIF4imikjOuagyMY53tnZq3NP6BcmlrHhEKAfGWjh7Q== - dependencies: - "@types/unist" "^2.0.0" - unist-util-is "^4.0.0" - unist-util-visit-parents "^3.0.0" - -unload@2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/unload/-/unload-2.2.0.tgz#ccc88fdcad345faa06a92039ec0f80b488880ef7" - integrity sha512-B60uB5TNBLtN6/LsgAf3udH9saB5p7gqJwcFfbOEZ8BcBHnGwCf6G/TGiEqkRAxX7zAFIUtzdrXQSdL3Q/wqNA== - dependencies: - "@babel/runtime" "^7.6.2" - detect-node "^2.0.4" - -unpipe@1.0.0, unpipe@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" - integrity sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw= - -uri-js@^4.2.2: - version "4.4.0" - resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.0.tgz#aa714261de793e8a82347a7bcc9ce74e86f28602" - integrity sha512-B0yRTzYdUCCn9n+F4+Gh4yIDtMQcaJsmYBDsTSG8g/OejKBodLQ2IHfN3bM7jUsRXndopT7OIXWdYqc1fjmV6g== - dependencies: - punycode "^2.1.0" - -url@^0.11.0: - version "0.11.0" - resolved "https://registry.yarnpkg.com/url/-/url-0.11.0.tgz#3838e97cfc60521eb73c525a8e55bfdd9e2e28f1" - integrity sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE= - dependencies: - punycode "1.3.2" - querystring "0.2.0" - -use-callback-ref@^1.2.1, use-callback-ref@^1.2.3: - version "1.2.4" - resolved "https://registry.yarnpkg.com/use-callback-ref/-/use-callback-ref-1.2.4.tgz#d86d1577bfd0b955b6e04aaf5971025f406bea3c" - integrity sha512-rXpsyvOnqdScyied4Uglsp14qzag1JIemLeTWGKbwpotWht57hbP78aNT+Q4wdFKQfQibbUX4fb6Qb4y11aVOQ== - -use-sidecar@^1.0.1: - version "1.0.3" - resolved "https://registry.yarnpkg.com/use-sidecar/-/use-sidecar-1.0.3.tgz#17a4e567d4830c0c0ee100040e85a7fe68611e0f" - integrity sha512-ygJwGUBeQfWgDls7uTrlEDzJUUR67L8Rm14v/KfFtYCdHhtjHZx1Krb3DIQl3/Q5dJGfXLEQ02RY8BdNBv87SQ== - dependencies: - detect-node-es "^1.0.0" - tslib "^1.9.3" - -use-subscription@1.5.1: - version "1.5.1" - resolved "https://registry.yarnpkg.com/use-subscription/-/use-subscription-1.5.1.tgz#73501107f02fad84c6dd57965beb0b75c68c42d1" - integrity sha512-Xv2a1P/yReAjAbhylMfFplFKj9GssgTwN7RlcTxBujFQcloStWNDQdc4g4NRWH9xS4i/FDk04vQBptAXoF3VcA== - dependencies: - object-assign "^4.1.1" - -util-deprecate@^1.0.1, util-deprecate@~1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" - integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= - -util@0.10.3: - version "0.10.3" - resolved "https://registry.yarnpkg.com/util/-/util-0.10.3.tgz#7afb1afe50805246489e3db7fe0ed379336ac0f9" - integrity sha1-evsa/lCAUkZInj23/g7TeTNqwPk= - dependencies: - inherits "2.0.1" - -util@0.12.3, util@^0.12.0: - version "0.12.3" - resolved "https://registry.yarnpkg.com/util/-/util-0.12.3.tgz#971bb0292d2cc0c892dab7c6a5d37c2bec707888" - integrity sha512-I8XkoQwE+fPQEhy9v012V+TSdH2kp9ts29i20TaaDUXsg7x/onePbhFJUExBfv/2ay1ZOp/Vsm3nDlmnFGSAog== - dependencies: - inherits "^2.0.3" - is-arguments "^1.0.4" - is-generator-function "^1.0.7" - is-typed-array "^1.1.3" - safe-buffer "^5.1.2" - which-typed-array "^1.1.2" - -util@^0.11.0: - version "0.11.1" - resolved "https://registry.yarnpkg.com/util/-/util-0.11.1.tgz#3236733720ec64bb27f6e26f421aaa2e1b588d61" - integrity sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ== - dependencies: - inherits "2.0.3" - -utils-merge@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" - integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM= - -v8-compile-cache@^2.0.3: - version "2.1.1" - resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.1.1.tgz#54bc3cdd43317bca91e35dcaf305b1a7237de745" - integrity sha512-8OQ9CL+VWyt3JStj7HX7/ciTL2V3Rl1Wf5OL+SNTm0yK1KvtReVulksyeRnCANHHuUxHlQig+JJDlUhBt1NQDQ== - -validate-npm-package-license@^3.0.1: - version "3.0.4" - resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a" - integrity sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew== - dependencies: - spdx-correct "^3.0.0" - spdx-expression-parse "^3.0.0" - -vary@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" - integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw= - -vest@^3.2.3: - version "3.2.3" - resolved "https://registry.yarnpkg.com/vest/-/vest-3.2.3.tgz#834781cbbba5f8529513660e81f540f927f468bc" - integrity sha512-fB05C57gmmwQ4/ZPUE8jMgcGty1ra44zua5ph3hYrkhOgk3q995BrzSJU7m5oa4y8eyaVzBAqj0yHXHGrsFP8Q== - -vfile-message@^2.0.0: - version "2.0.4" - resolved "https://registry.yarnpkg.com/vfile-message/-/vfile-message-2.0.4.tgz#5b43b88171d409eae58477d13f23dd41d52c371a" - integrity sha512-DjssxRGkMvifUOJre00juHoP9DPWuzjxKuMDrhNbk2TdaYYBNMStsNhEOt3idrtI12VQYM/1+iM0KOzXi4pxwQ== - dependencies: - "@types/unist" "^2.0.0" - unist-util-stringify-position "^2.0.0" - -vfile@^4.0.0: - version "4.2.1" - resolved "https://registry.yarnpkg.com/vfile/-/vfile-4.2.1.tgz#03f1dce28fc625c625bc6514350fbdb00fa9e624" - integrity sha512-O6AE4OskCG5S1emQ/4gl8zK586RqA3srz3nfK/Viy0UPToBc5Trp9BVFb1u0CjsKrAWwnpr4ifM/KBXPWwJbCA== - dependencies: - "@types/unist" "^2.0.0" - is-buffer "^2.0.0" - unist-util-stringify-position "^2.0.0" - vfile-message "^2.0.0" - -vm-browserify@1.1.2, vm-browserify@^1.0.1: - version "1.1.2" - resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-1.1.2.tgz#78641c488b8e6ca91a75f511e7a3b32a86e5dda0" - integrity sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ== - -vscode-json-languageservice@^3.7.0: - version "3.11.0" - resolved "https://registry.yarnpkg.com/vscode-json-languageservice/-/vscode-json-languageservice-3.11.0.tgz#ad574b36c4346bd7830f1d34b5a5213d3af8d232" - integrity sha512-QxI+qV97uD7HHOCjh3MrM1TfbdwmTXrMckri5Tus1/FQiG3baDZb2C9Y0y8QThs7PwHYBIQXcAc59ZveCRZKPA== - dependencies: - jsonc-parser "^3.0.0" - vscode-languageserver-textdocument "^1.0.1" - vscode-languageserver-types "3.16.0-next.2" - vscode-nls "^5.0.0" - vscode-uri "^2.1.2" - -vscode-languageserver-textdocument@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.1.tgz#178168e87efad6171b372add1dea34f53e5d330f" - integrity sha512-UIcJDjX7IFkck7cSkNNyzIz5FyvpQfY7sdzVy+wkKN/BLaD4DQ0ppXQrKePomCxTS7RrolK1I0pey0bG9eh8dA== - -vscode-languageserver-types@3.16.0-next.2: - version "3.16.0-next.2" - resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.16.0-next.2.tgz#940bd15c992295a65eae8ab6b8568a1e8daa3083" - integrity sha512-QjXB7CKIfFzKbiCJC4OWC8xUncLsxo19FzGVp/ADFvvi87PlmBSCAtZI5xwGjF5qE0xkLf0jjKUn3DzmpDP52Q== - -vscode-nls@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-5.0.0.tgz#99f0da0bd9ea7cda44e565a74c54b1f2bc257840" - integrity sha512-u0Lw+IYlgbEJFF6/qAqG2d1jQmJl0eyAGJHoAJqr2HT4M2BNuQYSEiSE75f52pXHSJm8AlTjnLLbBFPrdz2hpA== - -vscode-uri@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/vscode-uri/-/vscode-uri-2.1.2.tgz#c8d40de93eb57af31f3c715dd650e2ca2c096f1c" - integrity sha512-8TEXQxlldWAuIODdukIb+TR5s+9Ds40eSJrw+1iDDA9IFORPjMELarNQE3myz5XIkWWpdprmJjm1/SxMlWOC8A== - -vue-eslint-parser@~7.1.0: - version "7.1.1" - resolved "https://registry.yarnpkg.com/vue-eslint-parser/-/vue-eslint-parser-7.1.1.tgz#c43c1c715ff50778b9a7e9a4e16921185f3425d3" - integrity sha512-8FdXi0gieEwh1IprIBafpiJWcApwrU+l2FEj8c1HtHFdNXMd0+2jUSjBVmcQYohf/E72irwAXEXLga6TQcB3FA== - dependencies: - debug "^4.1.1" - eslint-scope "^5.0.0" - eslint-visitor-keys "^1.1.0" - espree "^6.2.1" - esquery "^1.0.1" - lodash "^4.17.15" - -warning@^4.0.3: - version "4.0.3" - resolved "https://registry.yarnpkg.com/warning/-/warning-4.0.3.tgz#16e9e077eb8a86d6af7d64aa1e05fd85b4678ca3" - integrity sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w== - dependencies: - loose-envify "^1.0.0" - -watchpack@2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.1.1.tgz#e99630550fca07df9f90a06056987baa40a689c7" - integrity sha512-Oo7LXCmc1eE1AjyuSBmtC3+Wy4HcV8PxWh2kP6fOl8yTlNS7r0K9l1ao2lrrUza7V39Y3D/BbJgY8VeSlc5JKw== - dependencies: - glob-to-regexp "^0.4.1" - graceful-fs "^4.1.2" - -webidl-conversions@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad" - integrity sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg== - -whatwg-url@^7.0.0: - version "7.1.0" - resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-7.1.0.tgz#c2c492f1eca612988efd3d2266be1b9fc6170d06" - integrity sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg== - dependencies: - lodash.sortby "^4.7.0" - tr46 "^1.0.1" - webidl-conversions "^4.0.2" - -which-boxed-primitive@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6" - integrity sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg== - dependencies: - is-bigint "^1.0.1" - is-boolean-object "^1.1.0" - is-number-object "^1.0.4" - is-string "^1.0.5" - is-symbol "^1.0.3" - -which-typed-array@^1.1.2: - version "1.1.4" - resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.4.tgz#8fcb7d3ee5adf2d771066fba7cf37e32fe8711ff" - integrity sha512-49E0SpUe90cjpoc7BOJwyPHRqSAd12c10Qm2amdEZrJPCY2NDxaW01zHITrem+rnETY3dwrbH3UUrUwagfCYDA== - dependencies: - available-typed-arrays "^1.0.2" - call-bind "^1.0.0" - es-abstract "^1.18.0-next.1" - foreach "^2.0.5" - function-bind "^1.1.1" - has-symbols "^1.0.1" - is-typed-array "^1.1.3" - -which@^1.2.9: - version "1.3.1" - resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" - integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== - dependencies: - isexe "^2.0.0" - -which@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" - integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== - dependencies: - isexe "^2.0.0" - -word-wrap@^1.2.3, word-wrap@~1.2.3: - version "1.2.3" - resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" - integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== - -wrappy@1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" - integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= - -write@1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/write/-/write-1.0.3.tgz#0800e14523b923a387e415123c865616aae0f5c3" - integrity sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig== - dependencies: - mkdirp "^0.5.1" - -xtend@^4.0.0, xtend@^4.0.1, xtend@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" - integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== - -yallist@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" - integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== - -yaml@^1.7.2: - version "1.10.0" - resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.0.tgz#3b593add944876077d4d683fee01081bd9fff31e" - integrity sha512-yr2icI4glYaNG+KWONODapy2/jDdMSDnrONSjblABjD9B4Z5LgiircSt8m8sRZFNi08kG9Sm0uSHtEmP3zaEGg== - -yocto-queue@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" - integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== - -zwitch@^1.0.0: - version "1.0.5" - resolved "https://registry.yarnpkg.com/zwitch/-/zwitch-1.0.5.tgz#d11d7381ffed16b742f6af7b3f223d5cd9fe9920" - integrity sha512-V50KMwwzqJV0NpZIZFwfOD5/lyny3WlSzRiXgA0G7VUnRlqttta1L6UQIHzd6EuBY/cHGfwTIck7w1yH6Q5zUw== diff --git a/hyperglass/util/__init__.py b/hyperglass/util/__init__.py deleted file mode 100644 index cde1100..0000000 --- a/hyperglass/util/__init__.py +++ /dev/null @@ -1,318 +0,0 @@ -"""Utility functions.""" - -# Standard Library -import os -import sys -import json -import platform -from queue import Queue -from typing import Dict, Union, Optional, Generator -from asyncio import iscoroutine -from pathlib import Path -from ipaddress import IPv4Address, IPv6Address, ip_address - -# Third Party -from loguru._logger import Logger as LoguruLogger -from netmiko.ssh_dispatcher import CLASS_MAPPER - -# Project -from hyperglass.log import log -from hyperglass.constants import DRIVER_MAP - -ALL_NOS = {*DRIVER_MAP.keys(), *CLASS_MAPPER.keys()} -ALL_DRIVERS = {*DRIVER_MAP.values(), "netmiko"} - - -def cpu_count(multiplier: int = 0) -> int: - """Get server's CPU core count. - - Used to determine the number of web server workers. - """ - # Standard Library - import multiprocessing - - return multiprocessing.cpu_count() * multiplier - - -def check_python() -> str: - """Verify Python Version.""" - # Project - from hyperglass.constants import MIN_PYTHON_VERSION - - pretty_version = ".".join(tuple(str(v) for v in MIN_PYTHON_VERSION)) - if sys.version_info < MIN_PYTHON_VERSION: - raise RuntimeError(f"Python {pretty_version}+ is required.") - return platform.python_version() - - -async def write_env(variables: Dict) -> str: - """Write environment variables to temporary JSON file.""" - env_file = Path("/tmp/hyperglass.env.json") # noqa: S108 - env_vars = json.dumps(variables) - - try: - with env_file.open("w+") as ef: - ef.write(env_vars) - except Exception as e: - raise RuntimeError(str(e)) - - return f"Wrote {env_vars} to {str(env_file)}" - - -async def clear_redis_cache(db: int, config: Dict) -> bool: - """Clear the Redis cache.""" - # Third Party - import aredis - - try: - redis_instance = aredis.StrictRedis(db=db, **config) - await redis_instance.flushdb() - except Exception as e: - raise RuntimeError(f"Error clearing cache: {str(e)}") from None - return True - - -def sync_clear_redis_cache() -> None: - """Clear the Redis cache.""" - # Project - from hyperglass.cache import SyncCache - from hyperglass.configuration import REDIS_CONFIG, params - - try: - cache = SyncCache(db=params.cache.database, **REDIS_CONFIG) - cache.clear() - except BaseException as err: - raise RuntimeError from err - - -def set_app_path(required: bool = False) -> Path: - """Find app directory and set value to environment variable.""" - - # Standard Library - from getpass import getuser - - matched_path = None - - config_paths = (Path.home() / "hyperglass", Path("/etc/hyperglass/")) - - # Ensure only one app directory exists to reduce confusion. - if all((p.exists() for p in config_paths)): - raise RuntimeError( - "Both '{}' and '{}' exist. ".format(*(p.as_posix() for p in config_paths)) - + "Please choose only one configuration directory and delete the other." - ) - - for path in config_paths: - try: - if path.exists(): - tmp = path / "test.tmp" - tmp.touch() - if tmp.exists(): - matched_path = path - tmp.unlink() - break - except Exception: - matched_path = None - - if required and matched_path is None: - # Only raise an error if required is True - raise RuntimeError( - """ -No configuration directories were determined to both exist and be readable -by hyperglass. hyperglass is running as user '{un}' (UID '{uid}'), and tried -to access the following directories: -{dir}""".format( - un=getuser(), - uid=os.getuid(), - dir="\n".join(["\t - " + str(p) for p in config_paths]), - ) - ) - - os.environ["hyperglass_directory"] = str(matched_path) - return matched_path - - -def format_listen_address(listen_address: Union[IPv4Address, IPv6Address, str]) -> str: - """Format a listen_address. Wraps IPv6 address in brackets.""" - fmt = str(listen_address) - - if isinstance(listen_address, str): - try: - listen_address = ip_address(listen_address) - except ValueError as err: - log.error(err) - pass - - if ( - isinstance(listen_address, (IPv4Address, IPv6Address)) - and listen_address.version == 6 - ): - fmt = f"[{str(listen_address)}]" - - return fmt - - -def split_on_uppercase(s): - """Split characters by uppercase letters. - - From: https://stackoverflow.com/a/40382663 - """ - string_length = len(s) - is_lower_around = ( - lambda: s[i - 1].islower() or string_length > (i + 1) and s[i + 1].islower() - ) - - start = 0 - parts = [] - for i in range(1, string_length): - if s[i].isupper() and is_lower_around(): - parts.append(s[start:i]) - start = i - parts.append(s[start:]) - - return parts - - -def parse_exception(exc): - """Parse an exception and its direct cause.""" - - if not isinstance(exc, BaseException): - raise TypeError(f"'{repr(exc)}' is not an exception.") - - def get_exc_name(exc): - return " ".join(split_on_uppercase(exc.__class__.__name__)) - - def get_doc_summary(doc): - return doc.strip().split("\n")[0].strip(".") - - name = get_exc_name(exc) - parsed = [] - if exc.__doc__: - detail = get_doc_summary(exc.__doc__) - parsed.append(f"{name} ({detail})") - else: - parsed.append(name) - - if exc.__cause__: - cause = get_exc_name(exc.__cause__) - if exc.__cause__.__doc__: - cause_detail = get_doc_summary(exc.__cause__.__doc__) - parsed.append(f"{cause} ({cause_detail})") - else: - parsed.append(cause) - return ", caused by ".join(parsed) - - -def set_cache_env(host, port, db): - """Set basic cache config parameters to environment variables. - - Functions using Redis to access the pickled config need to be able - to access Redis without reading the config. - """ - - os.environ["HYPERGLASS_CACHE_HOST"] = str(host) - os.environ["HYPERGLASS_CACHE_PORT"] = str(port) - os.environ["HYPERGLASS_CACHE_DB"] = str(db) - return True - - -def get_cache_env(): - """Get basic cache config from environment variables.""" - - host = os.environ.get("HYPERGLASS_CACHE_HOST") - port = os.environ.get("HYPERGLASS_CACHE_PORT") - db = os.environ.get("HYPERGLASS_CACHE_DB") - for i in (host, port, db): - if i is None: - raise LookupError( - "Unable to find cache configuration in environment variables" - ) - return host, port, db - - -def make_repr(_class): - """Create a user-friendly represention of an object.""" - - def _process_attrs(_dir): - for attr in _dir: - if not attr.startswith("_"): - attr_val = getattr(_class, attr) - - if callable(attr_val): - yield f'{attr}=' - - elif iscoroutine(attr_val): - yield f'{attr}=' - - elif isinstance(attr_val, str): - yield f'{attr}="{attr_val}"' - - else: - yield f"{attr}={str(attr_val)}" - - return f'{_class.__name__}({", ".join(_process_attrs(dir(_class)))})' - - -def validate_nos(nos): - """Validate device NOS is supported.""" - - result = (False, None) - - if nos in ALL_NOS: - result = (True, DRIVER_MAP.get(nos, "netmiko")) - - return result - - -def get_driver(nos: str, driver: Optional[str]) -> str: - """Determine the appropriate driver for a device.""" - - if driver is None: - # If no driver is set, use the driver map with netmiko as - # fallback. - return DRIVER_MAP.get(nos, "netmiko") - elif driver in ALL_DRIVERS: - # If a driver is set and it is valid, allow it. - return driver - else: - # Otherwise, fail validation. - raise ValueError("{} is not a supported driver.".format(driver)) - - -def current_log_level(logger: LoguruLogger) -> str: - """Get the current log level of a logger instance.""" - - try: - handler = list(logger._core.handlers.values())[0] - levels = {v.no: k for k, v in logger._core.levels.items()} - current_level = levels[handler.levelno].lower() - - except Exception as err: - logger.error(err) - current_level = "info" - - return current_level - - -def resolve_hostname(hostname: str) -> Generator: - """Resolve a hostname via DNS/hostfile.""" - # Standard Library - from socket import gaierror, getaddrinfo - - log.debug("Ensuring '{}' is resolvable...", hostname) - - ip4 = None - ip6 = None - try: - res = getaddrinfo(hostname, None) - for sock in res: - if sock[0].value == 2 and ip4 is None: - ip4 = ip_address(sock[4][0]) - elif sock[0].value in (10, 30) and ip6 is None: - ip6 = ip_address(sock[4][0]) - except (gaierror, ValueError, IndexError) as err: - log.debug(str(err)) - pass - - yield ip4 - yield ip6 diff --git a/hyperglass/util/files.py b/hyperglass/util/files.py deleted file mode 100644 index 6356157..0000000 --- a/hyperglass/util/files.py +++ /dev/null @@ -1,163 +0,0 @@ -"""Utilities for working with files.""" - -# Standard Library -import shutil -from queue import Queue -from typing import List, Tuple, Union, Iterable, Optional, Generator -from pathlib import Path -from threading import Thread - -# Project -from hyperglass.log import log - - -async def move_files( # noqa: C901 - src: Path, dst: Path, files: Iterable[Path] -) -> Tuple[str]: - """Move iterable of files from source to destination. - - Arguments: - src {Path} -- Current directory of files - dst {Path} -- Target destination directory - files {Iterable} -- Iterable of files - """ - - def error(*args, **kwargs): - msg = ", ".join(args) - kwargs = {k: str(v) for k, v in kwargs.items()} - error_msg = msg.format(**kwargs) - log.error(error_msg) - return RuntimeError(error_msg) - - if not isinstance(src, Path): - try: - src = Path(src) - except TypeError: - raise error("{p} is not a valid path", p=src) - - if not isinstance(dst, Path): - try: - dst = Path(dst) - except TypeError: - raise error("{p} is not a valid path", p=dst) - - if not isinstance(files, (List, Tuple, Generator)): - raise error( - "{fa} must be an iterable (list, tuple, or generator). Received {f}", - fa="Files argument", - f=files, - ) - - for path in (src, dst): - if not path.exists(): - raise error("{p} does not exist", p=path) - - migrated = () - - for file in files: - dst_file = dst / file.name - - if not file.exists(): - raise error("{f} does not exist", f=file) - - try: - if not dst_file.exists(): - shutil.copyfile(file, dst_file) - migrated += (str(dst_file),) - except Exception as e: - raise error("Failed to migrate {f}: {e}", f=dst_file, e=e) - - return migrated - - -class FileCopy(Thread): - """Custom thread for copyfiles() function.""" - - def __init__(self, src: Path, dst: Path, queue: Queue): - """Initialize custom thread.""" - super().__init__() - - if not src.exists(): - raise ValueError("{} does not exist", str(src)) - - self.src = src - self.dst = dst - self.queue = queue - - def run(self): - """Put one object into the queue for each file.""" - try: - try: - shutil.copy(self.src, self.dst) - except IOError as err: - self.queue.put(err) - else: - self.queue.put(self.src) - finally: - pass - - -def copyfiles(src_files: Iterable[Path], dst_files: Iterable[Path]): - """Copy iterable of files from source to destination with threading.""" - queue = Queue() - threads = () - src_files_len = len(src_files) - dst_files_len = len(dst_files) - - if src_files_len != dst_files_len: - raise ValueError( - "The number of source files " - + "({}) must match the number of destination files ({}).".format( - src_files_len, dst_files_len - ) - ) - - for i, file in enumerate(src_files): - file_thread = FileCopy(src=file, dst=dst_files[i], queue=queue) - threads += (file_thread,) - - for thread in threads: - thread.start() - - for _file in src_files: - copied = queue.get() - log.debug("Copied {}", str(copied)) - - for thread in threads: - thread.join() - - for i, file in enumerate(dst_files): - if not file.exists(): - raise RuntimeError("{} was not copied to {}", str(src_files[i]), str(file)) - - return True - - -def check_path( - path: Union[Path, str], mode: str = "r", create: bool = False -) -> Optional[Path]: - """Verify if a path exists and is accessible.""" - - result = None - - try: - if not isinstance(path, Path): - path = Path(path) - - if not path.exists(): - if create: - if path.is_file(): - path.parent.mkdir(parents=True) - else: - path.mkdir(parents=True) - else: - raise FileNotFoundError(f"{str(path)} does not exist.") - - if path.exists(): - with path.open(mode): - result = path - - except Exception: # noqa: S110 - pass - - return result diff --git a/hyperglass/util/frontend.py b/hyperglass/util/frontend.py deleted file mode 100644 index 1d2480a..0000000 --- a/hyperglass/util/frontend.py +++ /dev/null @@ -1,404 +0,0 @@ -"""Utility functions for frontend-related tasks.""" - -# Standard Library -import os -import json -import math -import shutil -import asyncio -import subprocess -from typing import Dict, Tuple, Optional -from pathlib import Path - -# Project -from hyperglass.log import log - -# Local -from .files import copyfiles, check_path - - -def get_node_version() -> Tuple[int, int, int]: - """Get the system's NodeJS version.""" - node_path = shutil.which("node") - - raw_version = subprocess.check_output( # noqa: S603 - [node_path, "--version"] - ).decode() - - # Node returns the version as 'v14.5.0', for example. Remove the v. - version = raw_version.replace("v", "") - # Parse the version parts. - return tuple((int(v) for v in version.split("."))) - - -def get_ui_build_timeout() -> Optional[int]: - """Read the UI build timeout from environment variables or set a default.""" - timeout = None - - if "HYPERGLASS_UI_BUILD_TIMEOUT" in os.environ: - timeout = int(os.environ["HYPERGLASS_UI_BUILD_TIMEOUT"]) - log.info("Found UI build timeout environment variable: {}", timeout) - - elif "POETRY_HYPERGLASS_UI_BUILD_TIMEOUT" in os.environ: - timeout = int(os.environ["POETRY_HYPERGLASS_UI_BUILD_TIMEOUT"]) - log.info("Found UI build timeout environment variable: {}", timeout) - - return timeout - - -async def check_node_modules() -> bool: - """Check if node_modules exists and has contents.""" - - ui_path = Path(__file__).parent.parent / "ui" - node_modules = ui_path / "node_modules" - - exists = node_modules.exists() - valid = exists - - if exists and not tuple(node_modules.iterdir()): - valid = False - - return valid - - -async def read_package_json() -> Dict: - """Import package.json as a python dict.""" - - package_json_file = Path(__file__).parent.parent / "ui" / "package.json" - - try: - - with package_json_file.open("r") as file: - package_json = json.load(file) - - except Exception as e: - raise RuntimeError(f"Error reading package.json: {str(e)}") - - log.debug("package.json:\n{p}", p=package_json) - - return package_json - - -async def node_initial(timeout: int = 180, dev_mode: bool = False) -> str: - """Initialize node_modules.""" - - ui_path = Path(__file__).parent.parent / "ui" - - env_timeout = get_ui_build_timeout() - - if env_timeout is not None and env_timeout > timeout: - timeout = env_timeout - - all_messages = () - - try: - proc = await asyncio.create_subprocess_shell( - cmd="yarn --silent --emoji false", - stdout=asyncio.subprocess.PIPE, - stderr=asyncio.subprocess.PIPE, - cwd=ui_path, - ) - - stdout, stderr = await asyncio.wait_for(proc.communicate(), timeout=timeout) - messages = stdout.decode("utf-8").strip() - errors = stderr.decode("utf-8").strip() - - if proc.returncode != 0: - raise RuntimeError(f"\nMessages:\n{messages}\nErrors:\n{errors}") - - await proc.wait() - all_messages += (messages,) - - except Exception as e: - raise RuntimeError(str(e)) - - return "\n".join(all_messages) - - -async def build_ui(app_path): - """Execute `next build` & `next export` from UI directory. - - Raises: - RuntimeError: Raised if exit code is not 0. - RuntimeError: Raised when any other error occurs. - """ - timeout = get_ui_build_timeout() - - ui_dir = Path(__file__).parent.parent / "ui" - build_dir = app_path / "static" / "ui" - - build_command = "node_modules/.bin/next build" - export_command = "node_modules/.bin/next export -o {f}".format(f=build_dir) - - all_messages = [] - for command in (build_command, export_command): - try: - proc = await asyncio.create_subprocess_shell( - cmd=command, - stdout=asyncio.subprocess.PIPE, - stderr=asyncio.subprocess.PIPE, - cwd=ui_dir, - ) - - stdout, stderr = await asyncio.wait_for(proc.communicate(), timeout=timeout) - messages = stdout.decode("utf-8").strip() - errors = stderr.decode("utf-8").strip() - - if proc.returncode != 0: - raise RuntimeError(f"\nMessages:\n{messages}\nErrors:\n{errors}") - - await proc.wait() - all_messages.append(messages) - - except asyncio.TimeoutError: - raise RuntimeError(f"{timeout} second timeout exceeded while building UI") - - except Exception as err: - log.error(err) - raise RuntimeError(str(err)) - - return "\n".join(all_messages) - - -def generate_opengraph( - image_path: Path, - max_width: int, - max_height: int, - target_path: Path, - background_color: str, -): - """Generate an OpenGraph compliant image.""" - # Third Party - from PIL import Image - - def center_point(background: Image, foreground: Image): - """Generate a tuple of center points for PIL.""" - bg_x, bg_y = background.size[0:2] - fg_x, fg_y = foreground.size[0:2] - x1 = math.floor((bg_x / 2) - (fg_x / 2)) - y1 = math.floor((bg_y / 2) - (fg_y / 2)) - x2 = math.floor((bg_x / 2) + (fg_x / 2)) - y2 = math.floor((bg_y / 2) + (fg_y / 2)) - return (x1, y1, x2, y2) - - # Convert image to JPEG format with static name "opengraph.jpg" - dst_path = target_path / "opengraph.jpg" - - # Copy the original image to the target path - copied = shutil.copy2(image_path, target_path) - log.debug("Copied {} to {}", str(image_path), str(target_path)) - - with Image.open(copied) as src: - - # Only resize the image if it needs to be resized - if src.size[0] != max_width or src.size[1] != max_height: - - # Resize image while maintaining aspect ratio - log.debug("Opengraph image is not 1200x630, resizing...") - src.thumbnail((max_width, max_height)) - - # Only impose a background image if the original image has - # alpha/transparency channels - if src.mode in ("RGBA", "LA"): - log.debug("Opengraph image has transparency, converting...") - background = Image.new("RGB", (max_width, max_height), background_color) - background.paste(src, box=center_point(background, src)) - dst = background - else: - dst = src - - # Save new image to derived target path - dst.save(dst_path) - - # Delete the copied image - Path(copied).unlink() - - if not dst_path.exists(): - raise RuntimeError(f"Unable to save resized image to {str(dst_path)}") - - log.debug("Opengraph image ready at {}", str(dst_path)) - - return True - - -def migrate_images(app_path: Path, params: dict): - """Migrate images from source code to install directory.""" - images_dir = app_path / "static" / "images" - favicon_dir = images_dir / "favicons" - check_path(favicon_dir, create=True) - src_files = () - dst_files = () - - for image in ("light", "dark", "favicon"): - src = Path(params["web"]["logo"][image]) - dst = images_dir / f"{image + src.suffix}" - src_files += (src,) - dst_files += (dst,) - return copyfiles(src_files, dst_files) - - -async def build_frontend( # noqa: C901 - dev_mode: bool, - dev_url: str, - prod_url: str, - params: Dict, - app_path: Path, - force: bool = False, - timeout: int = 180, -) -> bool: - """Perform full frontend UI build process. - - Securely creates temporary file, writes frontend configuration - parameters to file as JSON. Then writes the name of the temporary - file to /tmp/hyperglass.env.json as {"configFile": }. - - Webpack reads /tmp/hyperglass.env.json, loads the temporary file, - and sets its contents to Node environment variables during the build - process. - - After the build is successful, the temporary file is automatically - closed during garbage collection. - - Arguments: - dev_mode {bool} -- Development Mode - dev_url {str} -- Development Mode URL - prod_url {str} -- Production Mode URL - params {dict} -- Frontend Config paramters - - Raises: - RuntimeError: Raised if errors occur during build process. - - Returns: - {bool} -- True if successful - """ - # Standard Library - import hashlib - import tempfile - - # Third Party - from favicons import Favicons - - # Project - from hyperglass.constants import __version__ - - env_file = Path("/tmp/hyperglass.env.json") # noqa: S108 - - package_json = await read_package_json() - - env_vars = { - "_HYPERGLASS_CONFIG_": params, - "_HYPERGLASS_VERSION_": __version__, - "_HYPERGLASS_PACKAGE_JSON_": package_json, - "_HYPERGLASS_APP_PATH_": str(app_path), - } - - # Set NextJS production/development mode and base URL based on - # developer_mode setting. - if dev_mode: - env_vars.update({"NODE_ENV": "development", "_HYPERGLASS_URL_": dev_url}) - - else: - env_vars.update({"NODE_ENV": "production", "_HYPERGLASS_URL_": prod_url}) - - # Check if hyperglass/ui/node_modules has been initialized. If not, - # initialize it. - initialized = await check_node_modules() - - if initialized: - log.debug("node_modules is already initialized") - - elif not initialized: - log.debug("node_modules has not been initialized. Starting initialization...") - - node_setup = await node_initial(timeout, dev_mode) - - if node_setup == "": - log.debug("Re-initialized node_modules") - - images_dir = app_path / "static" / "images" - favicon_dir = images_dir / "favicons" - - try: - if not favicon_dir.exists(): - favicon_dir.mkdir() - async with Favicons( - source=params["web"]["logo"]["favicon"], - output_directory=favicon_dir, - base_url="/images/favicons/", - ) as favicons: - await favicons.generate() - log.debug("Generated {} favicons", favicons.completed) - env_vars.update({"_HYPERGLASS_FAVICONS_": favicons.formats()}) - - env_json = json.dumps(env_vars, default=str) - - # Create SHA256 hash from all parameters passed to UI, use as - # build identifier. - build_id = hashlib.sha256(env_json.encode()).hexdigest() - - # Read hard-coded environment file from last build. If build ID - # matches this build's ID, don't run a new build. - if env_file.exists() and not force: - - with env_file.open("r") as ef: - ef_id = json.load(ef).get("buildId", "empty") - - log.debug("Previous Build ID: {id}", id=ef_id) - - if ef_id == build_id: - - log.debug( - "UI parameters unchanged since last build, skipping UI build..." - ) - - return True - - # Create temporary file. json file extension is added for easy - # webpack JSON parsing. - temp_file = tempfile.NamedTemporaryFile( - mode="w+", prefix="hyperglass_", suffix=".json", delete=not dev_mode - ) - - log.info("Starting UI build...") - log.debug( - f"Created temporary UI config file: '{temp_file.name}' for build {build_id}" - ) - - with Path(temp_file.name).open("w+") as temp: - temp.write(env_json) - - # Write "permanent" file (hard-coded named) for Node to read. - env_file.write_text( - json.dumps({"configFile": temp_file.name, "buildId": build_id}) - ) - - # While temporary file is still open, initiate UI build process. - if not dev_mode or force: - initialize_result = await node_initial(timeout, dev_mode) - build_result = await build_ui(app_path=app_path) - - if initialize_result: - log.debug(initialize_result) - elif initialize_result == "": - log.debug("Re-initialized node_modules") - - if build_result: - log.success("Completed UI build") - elif dev_mode and not force: - log.debug("Running in developer mode, did not build new UI files") - - migrate_images(app_path, params) - - generate_opengraph( - Path(params["web"]["opengraph"]["image"]), - 1200, - 630, - images_dir, - params["web"]["theme"]["colors"]["black"], - ) - - except Exception as err: - log.error(err) - raise RuntimeError(str(err)) from None - - return True diff --git a/hyperglass/util/system_info.py b/hyperglass/util/system_info.py deleted file mode 100644 index 10994b6..0000000 --- a/hyperglass/util/system_info.py +++ /dev/null @@ -1,68 +0,0 @@ -"""Utility functions for gathering system information.""" - -# Standard Library -import os -import platform -from typing import Dict, Tuple, Union - -# Third Party -import psutil as _psutil -from cpuinfo import get_cpu_info as _get_cpu_info - -# Project -from hyperglass.constants import __version__ - -# Local -from .frontend import get_node_version - -SystemData = Dict[str, Tuple[Union[str, int], str]] - - -def _cpu() -> SystemData: - """Construct CPU Information.""" - cpu_info = _get_cpu_info() - brand = cpu_info.get("brand_raw", "") - cores_logical = _psutil.cpu_count() - cores_raw = _psutil.cpu_count(logical=False) - cpu_ghz = _psutil.cpu_freq().current / 1000 - return (brand, cores_logical, cores_raw, cpu_ghz) - - -def _memory() -> SystemData: - """Construct RAM Information.""" - mem_info = _psutil.virtual_memory() - total_gb = round(mem_info.total / 1e9, 2) - usage_percent = mem_info.percent - return (total_gb, usage_percent) - - -def _disk() -> SystemData: - """Construct Disk Information.""" - disk_info = _psutil.disk_usage("/") - total_gb = round(disk_info.total / 1e9, 2) - usage_percent = disk_info.percent - return (total_gb, usage_percent) - - -def get_system_info() -> SystemData: - """Get system info.""" - - cpu_info, cpu_logical, cpu_physical, cpu_speed = _cpu() - mem_total, mem_usage = _memory() - disk_total, disk_usage = _disk() - - return { - "hyperglass Version": (__version__, "text"), - "hyperglass Path": (os.environ["hyperglass_directory"], "code"), - "Python Version": (platform.python_version(), "code"), - "Node Version": (".".join(str(v) for v in get_node_version()), "code"), - "Platform Info": (platform.platform(), "code"), - "CPU Info": (cpu_info, "text"), - "Logical Cores": (cpu_logical, "code"), - "Physical Cores": (cpu_physical, "code"), - "Processor Speed": (f"{cpu_speed}GHz", "code"), - "Total Memory": (f"{mem_total} GB", "text"), - "Memory Utilization": (f"{mem_usage}%", "text"), - "Total Disk Space": (f"{disk_total} GB", "text"), - "Disk Utilization": (f"{disk_usage}%", "text"), - } diff --git a/install.sh b/install.sh deleted file mode 100755 index 6de2057..0000000 --- a/install.sh +++ /dev/null @@ -1,541 +0,0 @@ -#!/usr/bin/env bash - -set -e - -# HYPERGLASS_VERSION="1.0.0b42" - -MIN_PYTHON_MAJOR="3" -MIN_PYTHON_MINOR="6" -MIN_NODE_MAJOR="14" -MIN_YARN_MAJOR="1" -MIN_REDIS_MAJOR="4" - -APT_INSTALL="apt-get install -y" -APT_UPDATE="apt update" -YUM_INSTALL="yum install -y" -YUM_UPDATE="yum update" -BREW_INSTALL="brew install" -BREW_UPDATE="brew update" - -INSTALL_MAP=(["apt"]="$APT_INSTALL" ["yum"]="$YUM_INSTALL" ["brew"]="$BREW_INSTALL") -UPDATE_MAP=(["apt"]="$APT_UPDATE" ["yum"]="$YUM_UPDATE" ["brew"]="$BREW_UPDATE") - -INSTALLER="" -NEEDS_UPDATE="0" -NEEDS_PYTHON="1" -NEEDS_NODE="1" -NEEDS_YARN="1" -NEEDS_REDIS="1" - -has_cmd() { - which $1 >/dev/null - - if [[ $? == 0 ]]; then - echo "0" - else - echo "1" - fi -} - -clean_temp() { - echo "Cleaning up temporary files..." - rm -rf /tmp/yarnkey.gpg - rm -rf /tmp/nodesetup.sh -} - -catch_interrupt() { - echo "Stopping..." - exit 1 -} - -semver() { - local ver_raw=$(echo "$1" | egrep -o '[0-9]+\.[0-9]+\.[0-9]+') - local ver_digits=(${ver_raw//./ }) - echo ${ver_digits[@]} -} - -parse_redis_version() { - local one=$(echo "$@" | egrep -o 'v=[0-9]+\.[0-9]+\.[0-9]+') - local two=$(echo $one | egrep -o '[0-9]+\.[0-9]+\.[0-9]+') - echo $two -} - -python3_version() { - local ver_digits=($(semver "$(python3 --version)")) - local major="${ver_digits[0]}" - local minor="${ver_digits[1]}" - - if [[ $major != $MIN_PYTHON_MAJOR ]]; then - echo "1" - return 1 - elif [[ $major == $MIN_PYTHON_MAJOR && $minor -lt $MIN_PYTHON_MINOR ]]; then - echo "1" - return 1 - elif [[ $major == $MIN_PYTHON_MAJOR && $minor -ge $MIN_PYTHON_MINOR ]]; then - echo "0" - return 0 - else - echo "1" - return 1 - fi -} - -node_version() { - local ver_digits=($(semver "$(node --version)")) - local major="${ver_digits[0]}" - - if [[ $major < $MIN_NODE_MAJOR ]]; then - echo "1" - elif [[ $major -ge $MIN_NODE_MAJOR ]]; then - echo "0" - else - echo "1" - fi -} - -needs_python() { - local has_python3=$(has_cmd "python3") - if [[ $has_python3 == 1 ]]; then - NEEDS_PYTHON="1" - elif [[ $has_python3 == 0 ]]; then - local needs_upgrade=$(python3_version) - if [[ $needs_upgrade == 1 ]]; then - NEEDS_PYTHON="1" - elif [[ $needs_upgrade == 0 ]]; then - NEEDS_PYTHON="0" - else - NEEDS_PYTHON="1" - fi - else - NEEDS_PYTHON="1" - fi -} - -needs_node() { - local has_node=$(has_cmd node) - if [[ $has_node == 1 ]]; then - NEEDS_NODE="1" - elif [[ $has_node == 0 ]]; then - local needs_upgrade=$(node_version) - if [[ $needs_upgrade == 1 ]]; then - NEEDS_NODE="1" - elif [[ $needs_upgrade == 0 ]]; then - NEEDS_NODE="0" - else - NEEDS_NODE="1" - fi - else - NEEDS_NODE="1" - fi -} - -needs_yarn() { - local has_yarn=$(has_cmd yarn) - if [[ $has_yarn == 1 ]]; then - NEEDS_YARN="1" - elif [[ $has_yarn == 0 ]]; then - NEEDS_YARN="0" - else - NEEDS_YARN="1" - fi -} - -needs_redis() { - local has_redis=$(has_cmd redis-server) - if [[ $has_redis == 1 ]]; then - NEEDS_REDIS="1" - elif [[ $has_redis == 0 ]]; then - NEEDS_REDIS="0" - else - NEEDS_REDIS="1" - fi -} - -get_platform() { - local use_apt=$(has_cmd apt-get) - local use_yum=$(has_cmd yum) - local use_brew=$(has_cmd brew) - - if [[ $use_apt == 0 ]]; then - INSTALLER="apt" - elif [[ $use_yum == 0 ]]; then - INSTALLER="yum" - elif [[ $use_brew == 0 ]]; then - INSTALLER="brew" - else - echo "[ERROR] Unable to identify this system's package manager" - exit 1 - fi -} - -python_post() { - if [[ $1 == 0 ]]; then - local successful=$(needs_python) - if [[ $successful == 0 ]]; then - echo "[SUCCESS] Installed $(python --version)" - else - echo "[ERROR] Tried to install Python 3, but post-install check failed." - fi - else - echo '[ERROR] Tried to install Python 3, but encountered an error. Consult the Python 3 installation instructions for your system.' - fi -} - -node_post() { - if [[ $1 == 0 ]]; then - local successful=$(needs_node) - if [[ $successful == 0 ]]; then - echo "[SUCCESS] Installed NodeJS $(node --version | egrep -o '\d+\.\d+\.\d+')" - else - echo "[ERROR] Tried to install NodeJS, but post-install check failed." - fi - else - echo '[ERROR] Tried to install NodeJS, but encountered an error.' - fi -} - -yarn_post() { - if [[ $1 == 0 ]]; then - local successful=$(needs_yarn) - if [[ $successful == 0 ]]; then - echo "[SUCCESS] Installed Yarn $(yarn --version | egrep -o '\d+\.\d+\.\d+')" - else - echo "[ERROR] Tried to install Yarn, but post-install check failed." - fi - else - echo '[ERROR] Tried to install Yarn, but encountered an error.' - fi -} - -redis_post() { - if [[ $1 == 0 ]]; then - local successful=$(needs_redis) - if [[ $successful == 0 ]]; then - echo "[SUCCESS] Installed Redis $(parse_redis_version $(redis-server --version))" - else - echo "[ERROR] Tried to install Redis, but post-install check failed." - fi - else - echo '[ERROR] Tried to install Redis, but encountered an error.' - fi -} - -node_apt_prepare() { - curl -sL https://deb.nodesource.com/setup_$MIN_NODE_MAJOR.x -o /tmp/nodesetup.sh - sleep 1 - bash /tmp/nodesetup.sh - NEEDS_UPDATE="1" -} - -yarn_apt_prepare() { - curl -sL https://dl.yarnpkg.com/debian/pubkey.gpg -o /tmp/yarnkey.gpg - sleep 1 - apt-key add /tmp/yarnkey.gpg - echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list - NEEDS_UPDATE="1" -} - -node_yum_prepare() { - curl -sL https://rpm.nodesource.com/setup_$MIN_NODE_MAJOR.x -o /tmp/nodesetup.sh - bash /tmp/nodesetup.sh - sleep 1 - NEEDS_UPDATE="1" -} - -yarn_yum_prepare() { - curl -sL https://dl.yarnpkg.com/rpm/yarn.repo -o /etc/yum.repos.d/yarn.repo - sleep 1 - NEEDS_UPDATE="1" -} - -node_apt() { - apt-get install -y nodejs - sleep 1 - node_post $? -} - -node_yum() { - yum -y install gcc-c++ make nodejs - sleep 1 - node_post $? -} - -node_brew() { - brew install node - sleep 1 - node_post $? -} - -yarn_apt() { - apt-get install -y yarn - sleep 1 - yarn_post $? -} - -yarn_yum() { - yum -y install gcc-c++ make yarn - sleep 1 - yarn_post $? -} - -yarn_brew() { - brew install yarn - sleep 1 - yarn_post $? -} - -python_apt() { - apt-get install -y python3-dev python3-pip >/dev/null - sleep 1 - python_post $? -} - -python_yum() { - yum install centos-release-scl - yum install rh-python36 - yum install python3-devel - scl enable rh-python36 - sleep 1 - python_post $? -} - -python_brew() { - brew install python3 - sleep 1 - python_post $? -} - -redis_apt() { - apt-get install -y redis-server - sleep 1 - redis_post $? -} - -redis_yum() { - yum -y install redis - sleep 1 - redis_post $? -} - -redis_brew() { - brew install redis - sleep 1 - redis_post $? -} - -update_repo() { - if [[ $INSTALLER == "apt" ]]; then - apt-get update - elif [[ $INSTALLER == "yum" ]]; then - yum update - elif [[ $INSTALLER == "brew" ]]; then - brew update - fi -} - -install_python() { - if [[ $NEEDS_PYTHON == "1" ]]; then - echo "[INFO] Installing Python..." - - if [[ $INSTALLER == "apt" ]]; then - python_apt - elif [[ $INSTALLER == "yum" ]]; then - python_yum - elif [[ $INSTALLER == "brew" ]]; then - python_brew - fi - - elif [[ $NEEDS_PYTHON == "0" ]]; then - echo "[INFO] Your system is running $(python3 --version) (Minimum is $MIN_PYTHON_MAJOR.$MIN_PYTHON_MINOR+)." - - else - echo "[ERROR] Unable to determine if your system needs Python." - exit 1 - fi -} - -install_node() { - if [[ $NEEDS_NODE == "1" ]]; then - echo "[INFO] Installing NodeJS..." - - if [[ $INSTALLER == "apt" ]]; then - node_apt - elif [[ $INSTALLER == "yum" ]]; then - node_yum - elif [[ $INSTALLER == "brew" ]]; then - node_brew - fi - - elif [[ $NEEDS_NODE == "0" ]]; then - echo "[INFO] Your system is running NodeJS $(node --version) (Minimum is $MIN_NODE_MAJOR+)." - - else - echo "[ERROR] Unable to determine if your system needs NodeJS." - exit 1 - fi -} - -install_yarn() { - if [[ $NEEDS_YARN == "1" ]]; then - echo "[INFO] Installing Yarn..." - - if [[ $INSTALLER == "apt" ]]; then - yarn_apt - elif [[ $INSTALLER == "yum" ]]; then - yarn_yum - elif [[ $INSTALLER == "brew" ]]; then - yarn_brew - fi - - elif [[ $NEEDS_YARN == "0" ]]; then - echo "[INFO] Your system is running Yarn $(yarn --version) (Minimum is $MIN_YARN_MAJOR+)." - - else - echo "[ERROR] Unable to determine if your system needs Yarn." - exit 1 - fi -} - -install_redis() { - if [[ $NEEDS_REDIS == "1" ]]; then - echo "[INFO] Installing Redis..." - - if [[ $INSTALLER == "apt" ]]; then - redis_apt - elif [[ $INSTALLER == "yum" ]]; then - redis_yum - elif [[ $INSTALLER == "brew" ]]; then - redis_brew - fi - - elif [[ $NEEDS_REDIS == "0" ]]; then - echo "[INFO] Your system is running Redis $(parse_redis_version $(redis-server --version)) (Minimum is $MIN_REDIS_MAJOR+)." - - else - echo "[ERROR] Unable to determine if your system needs Redis." - exit 1 - fi -} - -# The below script installs locally instead of from PyPI -# -install_app() { - echo "[INFO] Installing hyperglass..." - - curl -sSL https://raw.githubusercontent.com/python-poetry/poetry/master/get-poetry.py -o /tmp/get-poetry.py - python3 /tmp/get-poetry.py -f -y >/dev/null - sleep 1 - source $HOME/.profile - - [ -d "/tmp/hyperglass" ] && rm -rf /tmp/hyperglass - [ -d "/tmp/build" ] && rm -rf /tmp/build - - git clone --branch v1.0.0 --depth 1 https://github.com/thatmattlove/hyperglass.git /tmp/hyperglass - cd /tmp/hyperglass - poetry build - mkdir /tmp/build - - # local build_tarball="/tmp/hyperglass/dist/hyperglass-build.tar.gz" - local build_tarballs=(/tmp/hyperglass/dist/*.tar.gz) - local build_tarball=${build_tarballs[-1]} - local build_dir=$(basename $build_tarball .tar.gz) - - tar -xvf /tmp/hyperglass/dist/$build_dir.tar.gz -C /tmp/build - cd /tmp/build/$build_dir - pip3 install . >/dev/null - - if [[ ! $? == 0 ]]; then - echo "[ERROR] An error occurred while trying to install hyperglass." - exit 1 - else - source $HOME/.profile - export LC_ALL=C.UTF-8 - export LANG=C.UTF-8 - local successful=$(has_cmd "hyperglass") - if [[ $successful == 0 ]]; then - echo "[SUCCESS] Installed hyperglass." - else - echo "[ERROR] hyperglass installation succeeded, but the hyperglass command was not found." - exit 1 - fi - fi - rm -rf /tmp/build -} - -# The below script installs from PyPI, which requires a package matching $HYPERGLASS_VERSION to exist on -# PyPI, which is not ideal for CI testing, since you don't really want to push code that potentially doesn't work. -# -# install_app () { -# echo "[INFO] Installing hyperglass..." - -# pip3 install "hyperglass==$HYPERGLASS_VERSION" > /dev/null - -# if [[ ! $? == 0 ]]; then -# echo "[ERROR] An error occurred while trying to install hyperglass." -# exit 1 -# else -# source $HOME/.profile -# export LC_ALL=C.UTF-8 -# export LANG=C.UTF-8 -# local successful=$(has_cmd "hyperglass") -# if [[ $successful == 0 ]]; then -# echo "[SUCCESS] Installed hyperglass." -# else -# echo "[ERROR] hyperglass installation succeeded, but the hyperglass command was not found." -# exit 1 -# fi -# fi -# } - -trap catch_interrupt SIGINT - -while true; do - PID=$! - - if (($EUID != 0)); then - echo 'hyperglass installer must be run with root privileges. Try running with `sudo`' - exit 1 - fi - - get_platform - - needs_python - needs_node - needs_yarn - needs_redis - - if [[ $NEEDS_YARN == "1" && $INSTALLER == "apt" ]]; then - yarn_apt_prepare - elif [[ $NEEDS_YARN == "1" && $INSTALLER == "yum" ]]; then - yarn_yum_prepare - fi - - if [[ $NEEDS_NODE == "1" && $INSTALLER == "apt" ]]; then - node_apt_prepare - elif [[ $NEEDS_NODE == "1" && $INSTALLER == "yum" ]]; then - node_yum_prepare - fi - - if [[ $NEEDS_UPDATE == "1" ]]; then - update_repo - fi - - install_python - install_node - install_yarn - install_redis - - if [[ $? == 0 ]]; then - clean_temp - echo "[SUCCESS] Finished installed dependencies." - else - clean_temp - echo "[ERROR] An error occurred while attempting to install dependencies." - exit 1 - fi - - install_app - - echo 'hyperglass installation was successful! You can now run `hyperglass --help` to see available commands.' - exit 0 -done diff --git a/main.go b/main.go new file mode 100644 index 0000000..6e2cfde --- /dev/null +++ b/main.go @@ -0,0 +1,7 @@ +package main + +import "github.com/thatmattlove/hyperglass/cmd" + +func main() { + cmd.Main() +} diff --git a/pyproject.toml b/pyproject.toml deleted file mode 100644 index 3c6e706..0000000 --- a/pyproject.toml +++ /dev/null @@ -1,84 +0,0 @@ -[build-system] -build-backend = "poetry.masonry.api" -requires = ["poetry>=0.12"] - -[tool.poetry] -authors = ["Matt Love "] -classifiers = [ - "Development Status :: 5 - Production/Stable", - "Intended Audience :: Information Technology", - "Operating System :: POSIX :: Linux", - "Programming Language :: JavaScript", - "Programming Language :: Python :: 3.6", - "Programming Language :: Python :: 3.7", - "Programming Language :: Python :: 3.8", - "Topic :: Internet", - "Topic :: System :: Networking", -] -description = "hyperglass is the modern network looking glass that tries to make the internet better." -documentation = "https://hyperglass.dev" -homepage = "https://hyperglass.dev" -keywords = ["looking glass", "network automation", "isp", "bgp", "routing"] -license = "BSD-3-Clause-Clear" -name = "hyperglass" -readme = "README.md" -repository = "https://github.com/thatmattlove/hyperglass" -version = "1.0.4" - -[tool.poetry.scripts] -hyperglass = "hyperglass.console:CLI" - -[tool.poetry.dependencies] -Pillow = "^7.2" -PyJWT = "^2.0.1" -PyYAML = "^5.4.1" -aiofiles = "^0.6.0" -aredis = "^1.1.8" -click = "^7.1.2" -cryptography = "3.0.0" -distro = "^1.5.0" -fastapi = "^0.63.0" -favicons = "^0.0.9" -gunicorn = "^20.1.0" -httpx = "^0.17.1" -inquirer = "^2.6.3" -loguru = "^0.5.3" -netmiko = "^3.4.0" -paramiko = "^2.7.2" -psutil = "^5.7.2" -py-cpuinfo = "^7.0.0" -pydantic = "^1.8.1" -python = ">=3.6.1,<4.0" -redis = "^3.5.3" -scrapli = {extras = ["asyncssh"], version = "^2021.1.30"} -uvicorn = {extras = ["standard"], version = "^0.13.4"} -uvloop = "^0.14.0" -xmltodict = "^0.12.0" - -[tool.poetry.dev-dependencies] -bandit = "^1.6.2" -black = "^19.10b0" -flake8 = "^3.8" -flake8-bandit = "^2.1.2" -flake8-black = "^0.1.1" -flake8-breakpoint = "^1.1.0" -flake8-bugbear = "^20.1.0" -flake8-builtins = "^1.4.2" -flake8-comprehensions = "^3.1.4" -flake8-deprecated = "^1.3" -flake8-docstrings = "^1.5.0" -flake8-eradicate = "^0.2.4" -flake8-if-expr = "^1.0.0" -flake8-isort = "^4.0.0" -flake8-pie = "^0.4.2" -flake8-plugin-utils = "^1.3.1" -flake8-polyfill = "^1.0.2" -flake8-print = "^3.1.4" -isort = "^5.5.3" -mccabe = "^0.6.1" -pep8-naming = "^0.9.1" -pre-commit = "^1.21.0" -stackprinter = "^0.2.3" - -[tool.black] -line-length = 88 diff --git a/tools.go b/tools.go new file mode 100644 index 0000000..2b2e2b7 --- /dev/null +++ b/tools.go @@ -0,0 +1,8 @@ +//go:build tools + +package main + +import ( + _ "github.com/twitchtv/twirp/protoc-gen-twirp" + _ "google.golang.org/protobuf/cmd/protoc-gen-go" +) diff --git a/validate_examples.py b/validate_examples.py deleted file mode 100644 index 4a08214..0000000 --- a/validate_examples.py +++ /dev/null @@ -1,115 +0,0 @@ -"""Validate example files.""" - -# Standard Library -import re -import sys -from pathlib import Path - -# Third Party -import yaml - -# Project -from hyperglass.util import set_app_path - -EXAMPLES = Path(__file__).parent.parent / "hyperglass" / "examples" - -DEVICES = EXAMPLES / "devices.yaml" -COMMANDS = EXAMPLES / "commands.yaml" -MAIN = EXAMPLES / "hyperglass.yaml" - - -def _uncomment_files(): - """Uncomment out files.""" - for file in (MAIN, COMMANDS): - output = [] - with file.open("r") as f: - for line in f.readlines(): - commented = re.compile(r"^(#\s*#?\s?).*$") - if re.match(commented, line): - output.append(re.sub(r"^#\s*#?\s?$", "", line)) - else: - output.append(line) - with file.open("w") as f: - f.write("".join(output)) - return True - - -def _comment_optional_files(): - """Comment out files.""" - for file in (MAIN, COMMANDS): - output = [] - with file.open("r") as f: - for line in f.readlines(): - if not re.match(r"^(#\s*#?\s?).*$|(^\-{3})", line): - output.append("# " + line) - else: - output.append(line) - with file.open("w") as f: - f.write("".join(output)) - return True - - -def _validate_devices(): - # Project - from hyperglass.models.config.devices import Devices - - with DEVICES.open() as raw: - devices_dict = yaml.safe_load(raw.read()) or {} - try: - Devices(devices_dict.get("routers", [])) - except Exception as e: - raise ValueError(str(e)) - return True - - -def _validate_commands(): - # Project - from hyperglass.models.commands import Commands - - with COMMANDS.open() as raw: - commands_dict = yaml.safe_load(raw.read()) or {} - try: - Commands.import_params(**commands_dict) - except Exception as e: - raise ValueError(str(e)) - return True - - -def _validate_main(): - # Project - from hyperglass.models.config.params import Params - - with MAIN.open() as raw: - main_dict = yaml.safe_load(raw.read()) or {} - try: - Params(**main_dict) - except Exception as e: - raise - raise ValueError(str(e)) - return True - - -def validate_all(): - """Validate all example configs against configuration models.""" - _uncomment_files() - for validator in (_validate_main, _validate_commands, _validate_devices): - try: - validator() - except ValueError as e: - raise RuntimeError(str(e)) - return True - - -if __name__ == "__main__": - set_app_path(required=True) - try: - all_passed = validate_all() - message = "All tests passed" - status = 0 - except RuntimeError as e: - message = str(e) - status = 1 - if status == 0: - _comment_optional_files() - print(message) - sys.exit(status)