diff --git a/.github/OWNERS b/.github/OWNERS index 594352be83251..9bf8a2486491f 100644 --- a/.github/OWNERS +++ b/.github/OWNERS @@ -1,7 +1,7 @@ # See the OWNERS docs at https://go.k8s.io/owners reviewers: -- sig-docs-en-reviews # Defined in OWNERS_ALIASES +- sig-docs-website-owners # Defined in OWNERS_ALIASES approvers: -- sig-docs-en-owners # Defined in OWNERS_ALIASES +- sig-docs-website-owners # Defined in OWNERS_ALIASES diff --git a/.well-known/security.txt b/.well-known/security.txt new file mode 100644 index 0000000000000..40371f929208b --- /dev/null +++ b/.well-known/security.txt @@ -0,0 +1,5 @@ +Contact: mailto:security@kubernetes.io +Expires: 2031-01-11T06:30:00.000Z +Preferred-Languages: en +Canonical: https://kubernetes.io/.well-known/security.txt +Policy: https://github.com/kubernetes/website/blob/main/SECURITY.md diff --git a/OWNERS b/OWNERS index 1b2d0babb793b..09d4e7c257928 100644 --- a/OWNERS +++ b/OWNERS @@ -1,10 +1,10 @@ # See the OWNERS docs at https://go.k8s.io/owners reviewers: -- sig-docs-en-reviews # Defined in OWNERS_ALIASES +- sig-docs-website-owners # Defined in OWNERS_ALIASES approvers: -- sig-docs-en-owners # Defined in OWNERS_ALIASES +- sig-docs-website-owners # Defined in OWNERS_ALIASES emeritus_approvers: # - chenopis, commented out to disable PR assignments diff --git a/OWNERS_ALIASES b/OWNERS_ALIASES index da427e1bca210..613797246b41b 100644 --- a/OWNERS_ALIASES +++ b/OWNERS_ALIASES @@ -2,19 +2,34 @@ aliases: sig-docs-blog-owners: # Approvers for blog content - mrbobbytables - nate-double-u - - onlydole - sftim sig-docs-blog-reviewers: # Reviewers for blog content - Gauravpadam - mrbobbytables - nate-double-u - - onlydole - sftim + sig-docs-website-owners: # Admins for overall website + - divya-mohan0209 + - natalisucks + - reylejano + - sftim + - tengqm + - drewhagen # RT 1.30 Docs Lead + - katcosgrove # RT 1.30 Lead sig-docs-localization-owners: # Admins for localization content - a-mccarthy - divya-mohan0209 - natalisucks - - onlydole + - nate-double-u + - reylejano + - sftim + - seokho-son + - tengqm + sig-docs-localization-reviewers: # PR reviews for localization changes + - a-mccarthy + - divya-mohan0209 + - natalisucks + - nate-double-u - reylejano - sftim - seokho-son @@ -27,25 +42,22 @@ aliases: - rlenferink sig-docs-en-owners: # Admins for English content - celestehorgan + - dipesh-rawat - divya-mohan0209 - - drewhagen # RT 1.30 Docs Lead - - katcosgrove # RT 1.30 Lead - natalisucks - nate-double-u - - onlydole - reylejano - sftim - tengqm sig-docs-en-reviews: # PR reviews for English content - - bradtopol + - celestehorgan - dipesh-rawat - divya-mohan0209 - kbhawkey - - mehabhalodiya - mengjiao-liu + - mickeyboxell - natalisucks - nate-double-u - - onlydole - reylejano - sftim - shannonxtreme @@ -53,14 +65,15 @@ aliases: - windsonsea sig-docs-es-owners: # Admins for Spanish content - 92nqb - - krol3 - electrocucaracha + - krol3 - raelga - ramrodo sig-docs-es-reviews: # PR reviews for Spanish content - 92nqb - - krol3 - electrocucaracha + - jossemarGT + - krol3 - raelga - ramrodo sig-docs-fr-owners: # Admins for French content @@ -126,7 +139,6 @@ aliases: sig-docs-leads: # Website chairs and tech leads - divya-mohan0209 - natalisucks - - onlydole - reylejano - sftim - tengqm @@ -181,9 +193,11 @@ aliases: - truongnh1992 sig-docs-ru-owners: # Admins for Russian content - Arhell + - kirkonru - shurup sig-docs-ru-reviews: # PR reviews for Russian content - Arhell + - kirkonru - shurup sig-docs-pl-owners: # Admins for Polish content - mfilocha @@ -231,7 +245,7 @@ aliases: - jimangel # Release Manager Associate - jrsapi # Release Manager Associate - salaxander # Release Manager Associate -# authoritative source: https://github.com/kubernetes/committee-security-response/blob/main/OWNERS_ALIASES + # authoritative source: https://github.com/kubernetes/committee-security-response/blob/main/OWNERS_ALIASES committee-security-response: - cjcullen - cji @@ -241,7 +255,7 @@ aliases: - ritazh - SaranBalaji90 - tabbysable -# authoritative source: https://github.com/kubernetes/sig-security/blob/main/OWNERS_ALIASES + # authoritative source: https://github.com/kubernetes/sig-security/blob/main/OWNERS_ALIASES sig-security-leads: - IanColdwater - tabbysable diff --git a/README-es.md b/README-es.md index 3f007461259c7..2668eff76a9ed 100644 --- a/README-es.md +++ b/README-es.md @@ -1,6 +1,6 @@ # La documentación de Kubernetes -[![Build Status](https://api.travis-ci.org/kubernetes/website.svg?branch=master)](https://travis-ci.org/kubernetes/website) +[![Netlify Status](https://api.netlify.com/api/v1/badges/be93b718-a6df-402a-b4a4-855ba186c97d/deploy-status)](https://app.netlify.com/sites/kubernetes-io-main-staging/deploys) [![GitHub release](https://img.shields.io/github/release/kubernetes/website.svg)](https://github.com/kubernetes/website/releases/latest) Bienvenido! diff --git a/README-hi.md b/README-hi.md index 958a44ead119c..06be4397f3c93 100644 --- a/README-hi.md +++ b/README-hi.md @@ -1,6 +1,6 @@ # कुबरनेट्स प्रलेखन -[![Build Status](https://api.travis-ci.org/kubernetes/website.svg?branch=master)](https://travis-ci.org/kubernetes/website) +[![Netlify Status](https://api.netlify.com/api/v1/badges/be93b718-a6df-402a-b4a4-855ba186c97d/deploy-status)](https://app.netlify.com/sites/kubernetes-io-main-staging/deploys) [![GitHub release](https://img.shields.io/github/release/kubernetes/website.svg)](https://github.com/kubernetes/website/releases/latest) स्वागत है! इस रिपॉजिटरी में [कुबरनेट्स वेबसाइट और दस्तावेज](https://kubernetes.io/) बनाने के लिए आवश्यक सभी संपत्तियाँ हैं। हम बहुत खुश हैं कि आप योगदान करना चाहते हैं! diff --git a/README-it.md b/README-it.md index dea728cba51d4..b983218e5c5b8 100644 --- a/README-it.md +++ b/README-it.md @@ -1,6 +1,6 @@ # La documentazione di Kubernetes -[![Build Status](https://api.travis-ci.org/kubernetes/website.svg?branch=master)](https://travis-ci.org/kubernetes/website) +[![Netlify Status](https://api.netlify.com/api/v1/badges/be93b718-a6df-402a-b4a4-855ba186c97d/deploy-status)](https://app.netlify.com/sites/kubernetes-io-main-staging/deploys) [![GitHub release](https://img.shields.io/github/release/kubernetes/website.svg)](https://github.com/kubernetes/website/releases/latest) Benvenuto! Questo repository contiene tutte le informazioni necessarie per creare la [documentazione e il sito web di Kubernetes](https://kubernetes.io/). Siamo onorati che tu voglia contribuire! diff --git a/README-vi.md b/README-vi.md index 8f8d9cecefe80..16c86f277b9ae 100644 --- a/README-vi.md +++ b/README-vi.md @@ -1,71 +1,217 @@ # Tài liệu Kubernetes -[![Netlify Status](https://api.netlify.com/api/v1/badges/be93b718-a6df-402a-b4a4-855ba186c97d/deploy-status)](https://app.netlify.com/sites/kubernetes-io-main-staging/deploys) [![GitHub release](https://img.shields.io/github/release/kubernetes/website.svg)](https://github.com/kubernetes/website/releases/latest) +[![Trạng thái Netlify](https://api.netlify.com/api/v1/badges/be93b718-a6df-402a-b4a4-855ba186c97d/deploy-status)](https://app.netlify.com/sites/kubernetes-io-main-staging/deploys) [![Phiên bản GitHub](https://img.shields.io/github/release/kubernetes/website.svg)](https://github.com/kubernetes/website/releases/latest) -Chào mừng! Kho lưu trữ này chứa tất cả các tài nguyên cần thiết để xây dựng [trang web của Kubernetes và các tài liệu](https://kubernetes.io/). Chúng tôi rất vui vì bạn muốn đóng góp. +Kho lưu trữ này chứa các tài sản cần thiết để xây dựng [trang web và tài liệu Kubernetes](https://kubernetes.io/). Chúng tôi rất vui mừng khi bạn muốn đóng góp! -## Đóng góp cho tài liệu +- [Đóng góp vào tài liệu](#đóng-góp-vào-tài-liệu) +- [READMEs đa ngôn ngữ](#các-tệp-readme-đa-ngôn-ngữ) -Bạn có thể click vào nút **Fork** ở góc trên bên phải màn hình để tạo bản sao của kho lưu trữ này trong tài khoản GitHub của bạn. Bản sao này được gọi là một bản *fork*. Thực hiện bất kì thay đổi nào mà bạn muốn trong bản fork của bạn và khi bạn sẵn sang gửi những thay đổi đó cho chúng tôi, hãy đến bản fork của bạn và tạo một Pull Request mới để cho chúng tôi biết về nó. +## Sử dụng kho lưu trữ này -Một khi Pull Request của bạn được tạo, reviewer sẽ chịu trách nhiệm cung cấp các phản hồi rõ ràng, có thể thực hiện được. Là chủ sở hữu của pull request, **bạn có trách nhiệm sửa đổi Pull Request của mình để giải quyết các phản hồi bởi reviewer.** Ngoài ra, lưu ý rằng bạn có thể có nhiều hơn một reviewer cung cấp cho bạn các phản hồi hoặc bạn có thể nhận được phản hồi từ reviewer khác với reviewer ban đầu được chỉ định. Hơn nữa, trong một số trường hợp, một trong những reviewer của bạn có thể yêu cầu đánh giá kỹ thuật từ [Kubernetes tech reviewer](https://github.com/kubernetes/website/wiki/Tech-reviewers) khi cần. Các reviewers sẽ cố gắng hết sức để cung cấp phản hồi một cách kịp thời nhưng thời gian phản hồi có thể thay đổi tùy theo hoàn cảnh. +Bạn có thể chạy trang web này ở chế độ local bằng cách sử dụng [Hugo (Phiên bản mở rộng)](https://gohugo.io/), hoặc bạn có thể chạy nó trong một container runtime. Chúng tôi khuyến nghị sử dụng container runtime, vì nó mang lại tính nhất quán trong triển khai so với trang web thực tế. -Để biết thêm thông tin về việc đóng góp cho tài liệu Kubernetes, hãy xem: +## Chuẩn bị để sử dụng -* [Bắt đầu đóng góp](https://kubernetes.io/docs/contribute/start/) -* [Các giai đoạn thay đổi tài liệu](http://kubernetes.io/docs/contribute/intermediate#view-your-changes-locally) -* [Sử dụng các trang templates](https://kubernetes.io/docs/contribute/style/page-content-types/) -* [Hướng dẫn biểu mẫu tài liệu](http://kubernetes.io/docs/contribute/style/style-guide/) -* [Địa phương hóa tài liệu Kubernetes](https://kubernetes.io/docs/contribute/localization/) +Để sử dụng kho lưu trữ này, bạn cần cài đặt các phần mềm sau trên máy tính của bạn: +- [npm](https://www.npmjs.com/) +- [Go](https://go.dev/) +- [Hugo (Phiên bản mở rộng)](https://gohugo.io/) +- Một container runtime, như [Docker](https://www.docker.com/). -## Chạy website cục bộ dùng Docker +> [!Chú ý] +Hãy chắc chắn rằng bạn mở rộng của Hugo bạn cài đặt trùng với phiên bản được chỉ định thông qua biến môi trường `HUGO_VERSION` trong tệp [`netlify.toml`](netlify.toml#L11). -Cách được đề xuất để chạy trang web Kubernetes cục bộ là dùng [Docker](https://docker.com) image chứa trình tạo web tĩnh [Hugo](https://gohugo.io). +Trước khi bắt đầu, hãy cài đặt các phụ thuộc. Sao chép kho lưu trữ và di chuyển đến thư mục: -> Nếu bạn làm việc trên môi trường Windows, bạn sẽ cần thêm môt vài công cụ mà bạn có thể cài đặt với [Chocolatey](https://chocolatey.org). `choco install make` +```bash +git clone https://github.com/kubernetes/website.git +cd website +``` -> Nếu bạn không muốn dùng Docker để chạy trang web cục bộ, hãy xem [Chạy website cục bộ dùng Hugo](#chạy-website-cục-bộ-dùng-hugo) dưới đây. +Trang web Kubernetes sử dụng [Docsy Hugo](https://github.com/google/docsy#readme). Ngay cả khi bạn dự định chạy trang web trong một vùng chứa, chúng tôi thực sự khuyên bạn nên kéo mô-đun con và các phần phụ thuộc phát triển khác bằng cách chạy như sau: -Nếu bạn có Docker đang [up và running](https://www.docker.com/get-started), build `kubernetes-hugo` Docker image cục bộ: +### Windows + +```powershell +# fetch submodule dependencies +git submodule update --init --recursive --depth 1 +``` + +### Linux / other Unix ```bash -make container-image +# fetch submodule dependencies +make module-init ``` -Khi image đã được built, bạn có thể chạy website cục bộ: +## Chạy trang web bằng container + +Để xây dựng trang web trong một container, chạy lệnh sau: ```bash +# Bạn có thể đặt biến $CONTAINER_ENGINE thành tên của bất kỳ công cụ container giống Docker nào make container-serve ``` -Mở trình duyệt và đến địa chỉ http://localhost:1313 để xem website. Khi bạn thay đổi các file nguồn, Hugo cập nhật website và buộc làm mới trình duyệt. +Nếu bạn thấy lỗi, điều đó có thể có nghĩa là container Hugo không có đủ tài nguyên. Để giải quyết nó, hãy tăng số lượng CPU và bộ nhớ được phép sử dụng cho Docker trên máy của bạn ([macOS](https://docs.docker.com/desktop/setings/mac/) và [windows](https://docs.docker.com/desktop/settings/windows/)). + +Mở trình duyệt của bạn, truy cập để xem trang web. Khi bạn thay đổi các tệp nguồn, Hugo sẽ cập nhật và tự động làm mới lại trang web. + +## Chạy trang web trực tiếp bằng cách sử dụng Hugo + +Đảm bảo cài đặt phiên bản mở rộng Hugo được chỉ định bởi biến môi trường `HUGO_VERSION` trong tệp [`netlify.toml`](netlify.toml#l11). + +Để cài đặt các phụ thuộc, triển khai và kiểm tra trang web cục bộ, chạy: + +- Đối với MacOS và Linux + + ```bash + npm ci + make serve + ``` + +- Đối với Windows (PowerShell) + + ```powershell + npm ci + hugo.exe server --buildFuture --environment development + ``` + +Máy chủ Hugo cục bộ sẽ được khởi động trên cổng 1313. Mở trình duyệt của bạn, truy cập để xem trang web. Khi bạn thay đổi các tệp nguồn, Hugo sẽ cập nhật và tự động làm mới lại trang web. + +## Xây dựng các trang tài liệu tham khảo API + +Các trang tài liệu tham khảo API nằm trong thư mục `content/en/docs/reference/kubernetes-api` được xây dựng từ Swagger specification, còn được gọi là OpenAPI specification, sử dụng . + +Để cập nhật các trang tài liệu tham khảo cho một phiên bản Kubernetes mới, làm theo các bước sau: + +1. Kéo về submodule `api-ref-generator`: + + ```bash + git submodule update --init --recursive --depth 1 + ``` + +2. Cập nhật Swagger specification: + + ```bash + curl 'https://raw.githubusercontent.com/kubernetes/kubernetes/master/api/openapi-spec/swagger.json' > api-ref-assets/api/swagger.json + ``` + +3. Trong `api-ref-assets/config/`, điều chỉnh các tệp `toc.yaml` và `fields.yaml` để phản ánh các thay đổi của phiên bản mới. + +4. Tiếp theo, xây dựng các trang: + + ```bash + make api-reference + ``` + + Bạn có thể kiểm tra kết quả bằng cách xây dựng và chạy trang web từ một container: + + ```bash + make container-serve + ``` -## Chạy website cục bộ dùng Hugo + Trong trình duyệt web, truy cập vào để xem tài liệu tham khảo API. -Hãy xem [tài liệu chính thức của Hugo](https://gohugo.io/getting-started/installing/) cho việc hướng dẫn cài đặt Hugo. Đảm bảo cài đặt phiên bản mở rộng của Hugo được xác định bởi biến môi trường `HUGO_VERSION` trong file [`netlify.toml`](netlify.toml#L9) +5. Khi tất cả các thay đổi được phản ánh vào các tệp cấu hình `toc.yaml` và `fields.yaml`, tạo một Pull Request với các trang tài liệu tham khảo API mới được tạo ra. -Để chạy website cục bộ khi Hugo được cài đặt: +## Khắc phục sự cố + +### error: failed to transform resource: TOCSS: failed to transform "scss/main.scss" (text/x-scss): this feature is not available in your current Hugo version + +Hugo được cung cấp dưới dạng hai phiên bản (cơ bản và bản mở rộng - extended) vì lý do kỹ thuật. Trang web hiện tại chỉ chạy với phiên bản **Hugo Extended**. Trong [trang phát hành của Hugo](https://github.com/gohugoio/hugo/releases), tìm kiếm các +phiên bản có chứa từ khóa `extended` trong tên. Để xác nhận, chạy `hugo version` và tìm từ khóa `extended`. + +### Khắc phục sự cố trên macOS với quá nhiều tệp mở + +Nếu bạn chạy `make serve` trên macOS và nhận được lỗi sau đây: ```bash -make serve +ERROR 2020/08/01 19:09:18 Error: listen tcp 127.0.0.1:1313: socket: too many open files +make: *** [serve] Error 1 +``` + +Hãy kiểm tra giới hạn hiện tại cho số tệp mở: + +`launchctl limit maxfiles` + +Sau đó, chạy các lệnh sau (được lấy từ ): + +```shell +#!/bin/sh + +# These are the original gist links, linking to my gists now. +# curl -O https://gist.githubusercontent.com/a2ikm/761c2ab02b7b3935679e55af5d81786a/raw/ab644cb92f216c019a2f032bbf25e258b01d87f9/limit.maxfiles.plist +# curl -O https://gist.githubusercontent.com/a2ikm/761c2ab02b7b3935679e55af5d81786a/raw/ab644cb92f216c019a2f032bbf25e258b01d87f9/limit.maxproc.plist + +curl -O https://gist.githubusercontent.com/tombigel/d503800a282fcadbee14b537735d202c/raw/ed73cacf82906fdde59976a0c8248cce8b44f906/limit.maxfiles.plist +curl -O https://gist.githubusercontent.com/tombigel/d503800a282fcadbee14b537735d202c/raw/ed73cacf82906fdde59976a0c8248cce8b44f906/limit.maxproc.plist + +sudo mv limit.maxfiles.plist /Library/LaunchDaemons +sudo mv limit.maxproc.plist /Library/LaunchDaemons + +sudo chown root:wheel /Library/LaunchDaemons/limit.maxfiles.plist +sudo chown root:wheel /Library/LaunchDaemons/limit.maxproc.plist + +sudo launchctl load -w /Library/LaunchDaemons/limit.maxfiles.plist ``` -Câu lệnh trên sẽ khởi động server Hugo cục bộ trên cổng 1313. Mở trình duyệt và đến địa chỉ http://localhost:1313 để xem website. Khi bạn thay đổi các file nguồn, Hugo cập nhật website và buộc làm mới trình duyệt. +Các lệnh trên hoạt động trên cả macOS Catalina và Mojave. -## Cộng đồng, thảo luận, đóng góp và hỗ trợ +## Tham gia với SIG Docs -Tìm hiểu cách tham gia với cộng đồng Kubernetes trên [trang cộng đồng](http://kubernetes.io/community/). +Tìm hiểu thêm về cộng đồng SIG Docs Kubernetes và cuộc họp trên [trang cộng đồng](https://github.com/kubernetes/community/tree/master/sig-docs#meetings). -Bạn có thể tiếp cận những maintainers của dự án này tại: +Bạn cũng có thể liên hệ với những người duy trì dự án này tại: - [Slack](https://kubernetes.slack.com/messages/sig-docs) +- [Nhận lời mời tham gia Slack này](https://slack.k8s.io/) - [Mailing List](https://groups.google.com/forum/#!forum/kubernetes-sig-docs) -### Quy tắc ứng xử +## Đóng góp vào tài liệu + +Bạn có thể nhấp vào nút **Fork** ở phía trên bên phải của màn hình để tạo một bản sao của kho lưu trữ này trong tài khoản GitHub của bạn. Bản sao này được gọi là _fork_. Thực hiện bất kỳ thay đổi nào bạn muốn trong fork của bạn, và khi bạn sẵn sàng gửi những thay đổi đó cho chúng tôi, hãy vào fork của bạn và tạo một pull request mới để thông báo cho chúng tôi biết về nó. + +Sau khi pull request của bạn được tạo, một người xem Kubernetes sẽ chịu trách nhiệm cung cấp phản hồi rõ ràng, có thể thực hiện được. Là chủ sở hữu của pull request, **bạn có trách nhiệm sửa đổi pull request của mình để giải quyết phản hồi đã được cung cấp cho bạn bởi người đánh giá tài liệu Kubernetes.** + +Lưu ý rằng bạn có thể nhận được phản hồi từ nhiều người đánh giá Kubernetes hoặc bạn có thể nhận được phản hồi từ một người đánh giá Kubernetes khác với người được chỉ định ban đầu để cung cấp phản hồi. + +Hơn nữa, trong một số trường hợp, một trong những người đánh giá của bạn có thể yêu cầu một đánh giá kỹ thuật từ một người đánh giá kỹ thuật Kubernetes khi cần thiết. Người đánh giá sẽ cố gắng cung cấp phản hồi một cách kịp thời, nhưng thời gian phản hồi có thể thay đổi tùy thuộc vào các tình huống. + +Để biết thêm thông tin về việc đóng góp vào tài liệu Kubernetes, hãy xem: + +- [Đóng góp vào tài liệu Kubernetes](https://kubernetes.io/docs/contribute/) +- [Loại nội dung trang](https://kubernetes.io/docs/contribute/style/page-content-types/) +- [Hướng dẫn về phong cách tài liệu](https://kubernetes.io/docs/contribute/style/style-guide/) +- [Dịch tài liệu Kubernetes](https://kubernetes.io/docs/contribute/localization/) +- [Giới thiệu về tài liệu Kubernetes](https://www.youtube.com/watch?v=pprMgmNzDcw) + +### Đại sứ đóng góp mới + +Nếu bạn cần trợ giúp bất kỳ lúc nào khi đóng góp, [Đại sứ đóng góp mới](https://kubernetes.io/docs/contribute/advanced/#serve-as-a-new-contributor-ambassador) là điểm liên lạc tốt. Đây là những người phê duyệt SIG Docs có trách nhiệm hướng dẫn các đóng góp viên mới và giúp họ qua những pull request đầu tiên. Nơi tốt nhất để liên hệ với Đại sứ đóng góp mới là trên [Kubernetes Slack](https://slack.k8s.io/). Đại sứ đóng góp mới hiện tại cho SIG Docs: + +| Name | Slack | GitHub | +| -------------------------- | -------------------------- | -------------------------- | +| Arsh Sharma | @arsh | @RinkiyaKeDad | + +## Các tệp README đa ngôn ngữ + +| Language | Language | +| -------------------------- | -------------------------- | +| [Chinese](README-zh.md) | [Korean](README-ko.md) | +| [French](README-fr.md) | [Polish](README-pl.md) | +| [German](README-de.md) | [Portuguese](README-pt.md) | +| [Hindi](README-hi.md) | [Russian](README-ru.md) | +| [Indonesian](README-id.md) | [Spanish](README-es.md) | +| [Italian](README-it.md) | [Ukrainian](README-uk.md) | +| [Japanese](README-ja.md) | [Vietnamese](README-vi.md) | + +## Quy tắc ứng xử -Sự tham gia vào cộng đồng Kubernetes được điểu chỉnh bởi [Kubernetes Code of Conduct](code-of-conduct.md). +Sự tham gia vào cộng đồng Kubernetes được điều chỉnh bởi [Quy tắc ứng xử của CNCF](https://github.com/cncf/foundation/blob/main/code-of-conduct.md). -## Cảm ơn! +## Cảm ơn bạn -Kubernetes phát triển mạnh mẽ về sự tham gia của cộng đồng và chúng tôi đánh giá cao những đóng góp của bạn cho trang web và tài liệu của chúng tôi! +Kubernetes phát triển dựa trên sự tham gia của cộng đồng, và chúng tôi đánh giá cao những đóng góp của bạn cho trang web và tài liệu của chúng tôi! diff --git a/README.md b/README.md index a47bdd6b44d5f..6e05028efde82 100644 --- a/README.md +++ b/README.md @@ -20,6 +20,9 @@ To use this repository, you need the following installed locally: - [Hugo (Extended version)](https://gohugo.io/) - A container runtime, like [Docker](https://www.docker.com/). +> [!NOTE] +Make sure to install the Hugo extended version specified by the `HUGO_VERSION` environment variable in the [`netlify.toml`](netlify.toml#L11) file. + Before you start, install the dependencies. Clone the repository and navigate to the directory: ```bash @@ -56,8 +59,6 @@ Open up your browser to to view the website. As you make ## Running the website locally using Hugo -Make sure to install the Hugo extended version specified by the `HUGO_VERSION` environment variable in the [`netlify.toml`](netlify.toml#L11) file. - To install dependencies, deploy and test the site locally, run: - For macOS and Linux @@ -99,10 +100,9 @@ To update the reference pages for a new Kubernetes release follow these steps: make api-reference ``` - You can test the results locally by making and serving the site from a container image: + You can test the results locally by building and serving the site from a container: ```bash - make container-image make container-serve ``` diff --git a/assets/OWNERS b/assets/OWNERS new file mode 100644 index 0000000000000..1f542bedeaa52 --- /dev/null +++ b/assets/OWNERS @@ -0,0 +1,9 @@ +# Label certain changes as web development + +filters: + "\\.js": + labels: + - area/web-development + "\\.scss$": + labels: + - area/web-development diff --git a/assets/images/OWNERS b/assets/images/OWNERS new file mode 100644 index 0000000000000..8f58bed7aa634 --- /dev/null +++ b/assets/images/OWNERS @@ -0,0 +1,22 @@ +# See the OWNERS docs at https://go.k8s.io/owners + +# This is the directory for common images. Allow English localization +# reviewers to review and approve. +# Teams and members are visible at https://github.com/orgs/kubernetes/teams. + +reviewers: +- sig-docs-en-reviews + +approvers: +- sig-docs-en-owners + +filters: + "\\.svg": + labels: + - area/web-development + "\\.png$": + labels: + - area/web-development + "\\.jpe?g$": + labels: + - area/web-development diff --git a/assets/scss/_custom.scss b/assets/scss/_custom.scss index a3b740028dfc5..287e073ec89c2 100644 --- a/assets/scss/_custom.scss +++ b/assets/scss/_custom.scss @@ -239,6 +239,31 @@ body.td-404 main .error-details { } } +.search-item.nav-item { + input, input::placeholder { + color: black; + } +} + +.flip-nav .search-item { + .td-search-input, .search-bar { + background-color: $medium-grey; + } + input, input::placeholder, .search-icon { + color: white; + } + textarea:focus, input:focus { + color: white; + } +} + +@media only screen and (max-width: 1500px) { + header nav .search-item { + display: none; + } +} + + /* FOOTER */ footer { background-color: #303030; @@ -559,23 +584,230 @@ body.td-home #deprecation-warning { #caseStudies body > #deprecation-warning, body.cid-casestudies > #deprecation-warning { padding-top: 32px; } -body.cid-partners > #deprecation-warning { - padding: 0; - margin-right: 0; - margin-left: 0; - margin-top: 0; - width: 100vw; -} -body.cid-partners > #deprecation-warning > .content { - width: 100%; - max-width: initial; - margin-right: 0; - margin-left: 0; - margin-top: 0; - padding-left: 5vw; - padding-right: 5vw; - padding-top: 2rem; - padding-bottom: 2rem; +body.cid-partners { + > #deprecation-warning { + padding: 0; + margin-right: 0; + margin-left: 0; + margin-top: 0; + width: 100vw; + > .content { + width: 100%; + max-width: initial; + margin-right: 0; + margin-left: 0; + margin-top: 0; + padding-left: 5vw; + padding-right: 5vw; + padding-top: 2rem; + padding-bottom: 2rem; + } + } + /* SECTIONS */ + .section { + clear: both; + padding: 0px; + margin-bottom: 2em; + } + + section#users { + text-align: center; + } + + .kcsp_section { + clear: both; + padding: 0px; + margin-bottom: 2em; + } + + /* COLUMN SETUP */ + .col { + display: block; + float:left; + margin: 1% 0 1% 1.6%; + background-color: #f9f9f9; + } + .col:first-child { margin-left: 0; } + + + /* GROUPING */ + .group:before, + .group:after { + content:""; + display:table; + } + .group:after { + clear:both; + } + .group { + zoom:1; /* For IE 6/7 */ + } + + /* GRID OF THREE */ + .span_3_of_3 { + width: 35%; + background-color: #f9f9f9; + padding: 20px; + } + .span_2_of_3 { + width: 35%; + background-color: #f9f9f9; + padding: 20px; + } + .span_1_of_3 { + width: 35%; + background-color: #f9f9f9; + padding: 20px; + } + + .col-container { + display: table; /* Make the container element behave like a table */ + width: 100%; /* Set full-width to expand the whole page */ + padding-bottom: 30px; + } + + .col-nav { + display: table-cell; /* Make elements inside the container behave like table cells */ + width: 18%; + background-color: #f9f9f9; + padding: 20px; + border: 5px solid white; + } + + /* GO FULL WIDTH AT LESS THAN 480 PIXELS */ + + @media only screen and (max-width: 480px) { + .col { margin: 1% 0 1% 0%;} + .span_3_of_3, .span_2_of_3, .span_1_of_3 { width: 100%; } + } + + @media only screen and (max-width: 650px) { + .col-nav { + display: block; + width: 100%; + } + } + + .button{ + max-width: 100%; + box-sizing: border-box; + margin: 0; + display: inline-block; + border-radius: 6px; + padding: 0 20px; + line-height: 40px; + color: #ffffff; + font-size: 16px; + background-color: #3371e3; + text-decoration: none; + } + + h5 { + font-size: 16px; + line-height: 1.5em; + margin-bottom: 2em; + } + + #usersGrid a { + display: inline-block; + background-color: #f9f9f9; + } + + #ktpContainer, #distContainer, #kcspContainer, #isvContainer, #servContainer { + position: relative; + width: 100%; + display: flex; + justify-content: space-between; + flex-wrap: wrap; + } + + #isvContainer { + margin-bottom: 80px; + } + + #kcspContainer { + margin-bottom: 80px; + } + + #distContainer { + margin-bottom: 80px; + } + + #ktpContainer { + margin-bottom: 80px; + } + + .partner-box { + position: relative; + width: 47%; + max-width: 48%; + min-width: 48%; + margin-bottom: 20px; + padding: 20px; + flex: 1; + display: flex; + justify-content: left; + align-items: flex-start; + } + + .partner-box img { + background-color: #f9f9f9; + } + + .partner-box > div { + margin-left: 30px; + } + + .partner-box a { + color: #3576E3; + } + + @media screen and (max-width: 1024px) { + .partner-box { + flex-direction: column; + justify-content: flex-start; + } + + .partner-box > div { + margin: 20px 0 0; + } + } + + @media screen and (max-width: 568px) { + #ktpContainer, #distContainter, #kcspContainer, #isvContainer, #servContainer { + justify-content: center; + } + + .partner-box { + flex-direction: column; + justify-content: flex-start; + width: 100%; + max-width: 100%; + min-width: 100%; + } + + .partner-box > div { + margin: 20px 0 0; + } + } + + @media screen and (max-width: 568px) { + #ktpContainer, #distContainer, #kcspContainer, #isvContainer, #servContainer { + justify-content: center; + } + + .partner-box { + flex-direction: column; + justify-content: flex-start; + width: 100%; + max-width: 100%; + min-width: 100%; + } + + .partner-box > div { + margin: 20px 0 0; + } + } } body.cid-community > #deprecation-warning > .deprecation-warning { margin-left: 20px; @@ -680,6 +912,11 @@ main.content { } } +.td-blog .header-hero h1, .td-blog .header-hero h2 { + font-size: 2.25rem; // match rest of site, even if it is actually h2 + margin-bottom: 20px; +} + /* CASE-STUDIES */ // Many of the case studies have small variations in markup and styles; @@ -727,6 +964,8 @@ body.td-documentation { } } +/* Announcements */ + #announcement { > * { color: inherit; @@ -748,10 +987,21 @@ body.td-documentation { padding-top: 40px; } +// Don't show announcements when javascript is not available + +html.no-js body div#announcement { + display: none; +} + +#announcement.display-announcement{ + display: block; // apply this class to display the announcement +} + #announcement { // default background is blue; overrides are possible color: #fff; - + display: none; // When javascript is available, Let javascript handle the state of the announcement + .announcement-main { margin-left: auto; margin-right: auto; @@ -819,7 +1069,8 @@ body.td-documentation { } } -#announcement + .header-hero.filler { +/* don't display the hero header for some pages when there is a banner active */ +#announcement + .header-hero.filler, .td-page.td-blog #announcement + .header-hero { display: none; } @@ -1031,4 +1282,4 @@ div.alert > em.javascript-required { border: none; outline: none; padding: .5em 0 .5em 0; -} \ No newline at end of file +} diff --git a/content/OWNERS b/content/OWNERS new file mode 100644 index 0000000000000..07352032a81c8 --- /dev/null +++ b/content/OWNERS @@ -0,0 +1,11 @@ +# See the OWNERS docs at https://go.k8s.io/owners + +# This is the directory for all source content. +# Teams and members are visible at https://github.com/orgs/kubernetes/teams. + +reviewers: +- sig-docs-localization-reviewers + +approvers: +- sig-docs-localization-owners +- sig-docs-website-owners diff --git a/content/de/OWNERS b/content/de/OWNERS index 7f2f2fb5a6429..d460d57fc0a89 100644 --- a/content/de/OWNERS +++ b/content/de/OWNERS @@ -8,6 +8,14 @@ reviewers: approvers: - sig-docs-de-owners +- sig-docs-website-owners # important due to no_parent_owners option labels: +- area/localization - language/de + +# Disable inheritance so that the localization team don't end up as approvers for all +# languages. +# https://github.com/kubernetes/community/blob/master/communication/website-guidelines.md +options: + no_parent_owners: true diff --git a/content/de/docs/concepts/containers/_index.md b/content/de/docs/concepts/containers/_index.md index 764c891d01196..0424ac7ca83c0 100644 --- a/content/de/docs/concepts/containers/_index.md +++ b/content/de/docs/concepts/containers/_index.md @@ -2,6 +2,6 @@ title: "Container" weight: 40 description: > - Methoden, um Anwendungen und ihre Abhängigkeiten zu zusammenzufassen. + Methoden, um Anwendungen und ihre Abhängigkeiten zusammenzufassen. --- diff --git a/content/de/docs/reference/glossary/cadvisor.md b/content/de/docs/reference/glossary/cadvisor.md new file mode 100644 index 0000000000000..f04a5c8370688 --- /dev/null +++ b/content/de/docs/reference/glossary/cadvisor.md @@ -0,0 +1,16 @@ +--- +title: cAdvisor +id: cadvisor +date: 2021-12-09 +full_link: https://github.com/google/cadvisor/ +short_description: > + Werkzeug, um Ressourcenverbrauch und Performance Charakteristiken von Container besser zu verstehen +aka: +tags: +- tool +--- +cAdvisor (Container Advisor) ermöglicht Benutzer von Container ein besseres Verständnis des Ressourcenverbrauchs und der Performance Charakteristiken ihrer laufenden {{< glossary_tooltip text="Container" term_id="container" >}}. + + + +Es ist ein laufender Daemon, der Informationen über laufende Container sammelt, aggregiert, verarbeitet, und exportiert. Genauer gesagt, speichert es für jeden Container die Ressourcenisolationsparameter, den historischen Ressourcenverbrauch, die Histogramme des kompletten historischen Ressourcenverbrauchs und die Netzwerkstatistiken. Diese Daten werden pro Container und maschinenweit exportiert. diff --git a/content/de/docs/reference/glossary/certificate.md b/content/de/docs/reference/glossary/certificate.md new file mode 100644 index 0000000000000..e9eea0db659a4 --- /dev/null +++ b/content/de/docs/reference/glossary/certificate.md @@ -0,0 +1,18 @@ +--- +title: Zertifikat +id: certificate +date: 2018-04-12 +full_link: /docs/tasks/tls/managing-tls-in-a-cluster/ +short_description: > + Eine kryptographisch sichere Datei, die verwendet wird um den Zugriff auf das Kubernetes Cluster zu validieren. + +aka: +tags: +- security +--- + Eine kryptographisch sichere Datei, die verwendet wird um den Zugriff auf das Kubernetes Cluster zu bestätigen. + + + +Zertfikate ermöglichen es Anwendungen in einem Kubernetes Cluster sicher auf die Kubernetes API zuzugreifen. Zertfikate bestätigen, dass Clients die Erlaubnis haben auf die API zuzugreifen. + diff --git a/content/de/docs/reference/glossary/cidr.md b/content/de/docs/reference/glossary/cidr.md new file mode 100644 index 0000000000000..245ccd9b19d0c --- /dev/null +++ b/content/de/docs/reference/glossary/cidr.md @@ -0,0 +1,18 @@ +--- +title: CIDR +id: cidr +date: 2019-11-12 +full_link: +short_description: > + CIDR ist eine Notation, um Blöcke von IP Adressen zu beschreiben und wird viel verwendet in verschiedenen Netzwerkkonfigurationen. + +aka: +tags: +- networking +--- +CIDR (Classless Inter-Domain Routing) ist eine Notation, um Blöcke von IP Adressen zu beschreiben und wird viel verwendet in verschiedenen Netzwerkkonfigurationen. + + + +Im Kubernetes Kontext, erhält jeder {{< glossary_tooltip text="Knoten" term_id="node" >}} eine Reihe von IP Adressen durch die Startadresse und eine Subnetzmaske unter Verwendung von CIDR. Dies erlaubt Knoten jedem {{< glossary_tooltip text="Pod" term_id="pod" >}} eine eigene IP Adresse zuzuweisen. Obwohl es ursprünglich ein Konzept für IPv4 ist, wurde CIDR erweitert um auch IPv6 einzubinden. + diff --git a/content/de/docs/reference/glossary/cla.md b/content/de/docs/reference/glossary/cla.md new file mode 100644 index 0000000000000..b6163a995cc30 --- /dev/null +++ b/content/de/docs/reference/glossary/cla.md @@ -0,0 +1,18 @@ +--- +title: CLA (Contributor License Agreement) +id: cla +date: 2018-04-12 +full_link: https://github.com/kubernetes/community/blob/master/CLA.md +short_description: > + Bedingungen unter denen ein Mitwirkender eine Lizenz an ein Open Source Projekt erteilt für seine Mitwirkungen. + +aka: +tags: +- community +--- + Bedingungen unter denen ein {{< glossary_tooltip text="Mitwirkender" term_id="contributor" >}} eine Lizenz an ein Open Source Projekt erteilt für seine Mitwirkungen. + + + +CLAs helfen dabei rechtliche Streitigkeiten rund um Mitwirkungen und geistigem Eigentum (IP) zu lösen. + diff --git a/content/de/docs/tasks/tools/included/verify-kubectl.md b/content/de/docs/tasks/tools/included/verify-kubectl.md index 3fcea4b223d35..0e200d02db8d7 100644 --- a/content/de/docs/tasks/tools/included/verify-kubectl.md +++ b/content/de/docs/tasks/tools/included/verify-kubectl.md @@ -29,9 +29,9 @@ Falls eine Nachricht ähnlich wie die Folgende zu sehen ist, ist kubectl nicht k The connection to the server was refused - did you specify the right host or port? ``` -Wenn zum Beispiel versucht wird ein Kubernetes Cluster lokal auf dem Laptop zu starten, muss ein Tool wie zum Beispiel Minikube zuerst installiert werden. Danach können die oben erwähnten Befehle erneut ausgeführt werden. +Wenn zum Beispiel versucht wird ein Kubernetes Cluster lokal auf dem Laptop zu starten, muss ein Tool wie zum Beispiel [Minikube](https://minikube.sigs.k8s.io/docs/start/) zuerst installiert werden. Danach können die oben erwähnten Befehle erneut ausgeführt werden. -Falls kubectl cluster-info eine URL zurück gibt, aber nicht auf das Cluster zugreifen kann, prüfe ob kubectl korrekt konfiguriert wurde: +Falls `kubectl cluster-info` eine URL zurück gibt, aber nicht auf das Cluster zugreifen kann, prüfe ob kubectl korrekt konfiguriert wurde: ```shell kubectl cluster-info dump diff --git a/content/de/docs/tutorials/kubernetes-basics/_index.html b/content/de/docs/tutorials/kubernetes-basics/_index.html index 1a1b7cbfff500..71dd175efcabc 100644 --- a/content/de/docs/tutorials/kubernetes-basics/_index.html +++ b/content/de/docs/tutorials/kubernetes-basics/_index.html @@ -50,25 +50,25 @@

Kubernetes Grundlagen Module

@@ -78,25 +78,25 @@

Kubernetes Grundlagen Module

@@ -107,7 +107,7 @@

Kubernetes Grundlagen Module

diff --git a/content/en/blog/_index.md b/content/en/blog/_index.md index a16a4ffe499eb..f6128329316ca 100644 --- a/content/en/blog/_index.md +++ b/content/en/blog/_index.md @@ -4,9 +4,7 @@ linkTitle: Blog menu: main: title: "Blog" - weight: 40 - post: > -

Read the latest news for Kubernetes and the containers space in general, and get technical how-tos hot off the presses.

+ weight: 20 --- {{< comment >}} diff --git a/content/en/blog/_posts/2020-08-03-kubernetes-1-18-release-interview.md b/content/en/blog/_posts/2020-08-03-kubernetes-1-18-release-interview.md index a8e4e717367fc..f2057895c5fb5 100644 --- a/content/en/blog/_posts/2020-08-03-kubernetes-1-18-release-interview.md +++ b/content/en/blog/_posts/2020-08-03-kubernetes-1-18-release-interview.md @@ -62,7 +62,7 @@ It was actually just making— again, startup, small company, small team, so rea **ADAM GLICK: What time frame was this?** -JORGE ALARCÓN: Three, four years ago, so definitely not 1.13. That's the best guesstimate that I can give at this point. But I wasn't able to find any good examples, any tutorials. The only book that I was able to get my hands on was the one written by Joe Beda, Kelsey Hightower, and I forget the other author. But what is it? "[Kubernetes— Up and Running](](http://shop.oreilly.com/product/0636920223788.do))"? +JORGE ALARCÓN: Three, four years ago, so definitely not 1.13. That's the best guesstimate that I can give at this point. But I wasn't able to find any good examples, any tutorials. The only book that I was able to get my hands on was the one written by Joe Beda, Kelsey Hightower, and I forget the other author. But what is it? "[Kubernetes— Up and Running](http://shop.oreilly.com/product/0636920223788.do)"? And in general, right now I use it as reference— it's really good. But as a beginner, I still was lost. They give all these amazing examples, they provide the applications, but I had no idea why someone might need a Pod, why someone might need a Deployment. So my last resort was to try and find someone who actually knew Kubernetes. diff --git a/content/en/blog/_posts/2021-11-12-are-you-ready-for-dockershim-removal/index.md b/content/en/blog/_posts/2021-11-12-are-you-ready-for-dockershim-removal/index.md index e55f26cb4515f..3af43024e262a 100644 --- a/content/en/blog/_posts/2021-11-12-are-you-ready-for-dockershim-removal/index.md +++ b/content/en/blog/_posts/2021-11-12-are-you-ready-for-dockershim-removal/index.md @@ -64,7 +64,7 @@ time to review the [dockershim migration documentation](/docs/tasks/administer-c and consult your Kubernetes hosting vendor (if you have one) what container runtime options are available for you. Read up [container runtime documentation with instructions on how to use containerd and CRI-O](/docs/setup/production-environment/container-runtimes/#container-runtimes) to help prepare you when you're ready to upgrade to 1.24. CRI-O, containerd, and -Docker with [Mirantis cri-dockerd](https://github.com/Mirantis/cri-dockerd) are +Docker with [Mirantis cri-dockerd](https://mirantis.github.io/cri-dockerd/) are not the only container runtime options, we encourage you to explore the [CNCF landscape on container runtimes](https://landscape.cncf.io/?group=projects-and-products&view-mode=card#runtime--container-runtime) in case another suits you better. diff --git a/content/en/blog/_posts/2022-02-17-updated-dockershim-faq.md b/content/en/blog/_posts/2022-02-17-updated-dockershim-faq.md index 36bc567047ce3..4bda4184ae9e9 100644 --- a/content/en/blog/_posts/2022-02-17-updated-dockershim-faq.md +++ b/content/en/blog/_posts/2022-02-17-updated-dockershim-faq.md @@ -109,7 +109,7 @@ Kubernetes clusters. Containers make this kind of interoperability possible. Mirantis and Docker have [committed][mirantis] to maintaining a replacement adapter for Docker Engine, and to maintain that adapter even after the in-tree dockershim is removed -from Kubernetes. The replacement adapter is named [`cri-dockerd`](https://github.com/Mirantis/cri-dockerd). +from Kubernetes. The replacement adapter is named [`cri-dockerd`](https://mirantis.github.io/cri-dockerd/). You can install `cri-dockerd` and use it to connect the kubelet to Docker Engine. Read [Migrate Docker Engine nodes from dockershim to cri-dockerd](/docs/tasks/administer-cluster/migrating-from-dockershim/migrate-dockershim-dockerd/) to learn more. diff --git a/content/en/blog/_posts/2022-11-04-live-and-let-live-with-kluctl-and-ssa.md b/content/en/blog/_posts/2022-11-04-live-and-let-live-with-kluctl-and-ssa.md index b9a6e56d869b2..28a214dc1d307 100644 --- a/content/en/blog/_posts/2022-11-04-live-and-let-live-with-kluctl-and-ssa.md +++ b/content/en/blog/_posts/2022-11-04-live-and-let-live-with-kluctl-and-ssa.md @@ -22,12 +22,12 @@ large Kubernetes deployments, composed of multiple smaller parts To get a basic understanding of Kluctl, I suggest to visit the [kluctl.io](https://kluctl.io) website and read through the documentation and tutorials, for example the -[microservices demo tutorial](https://kluctl.io/docs/guides/tutorials/microservices-demo/). +[microservices demo tutorial](https://kluctl.io/docs/tutorials/microservices-demo/1-basic-project-setup/). As an alternative, you can watch [Hands-on Introduction to kluctl](https://www.youtube.com/watch?v=9LoYLjDjOdg) from the Rawkode Academy YouTube channel which shows a hands-on demo session. -There is also a [Kluctl delivery scenario](https://github.com/codablock/podtato-head/tree/kluctl/delivery/kluctl) -available in my fork of the [podtato-head](https://github.com/codablock/podtato-head) demo project. +There is also a [Kluctl delivery scenario](https://github.com/podtato-head/podtato-head-delivery/tree/main/kluctl) +for the [podtato-head](https://github.com/podtato-head/podtato-head) demo project. ## Live and let live @@ -144,8 +144,8 @@ If the field manager is not known by Kluctl, it will check if force-applying is requested for that field. Force-applying can be requested in different ways: 1. By passing `--force-apply` to Kluctl. This will cause ALL fields to be force-applied on conflicts. -2. By adding the [`kluctl.io/force-apply=true`](https://kluctl.io/docs/reference/deployments/annotations/all-resources/#kluctlioforce-apply) annotation to the object in question. This will cause all fields of that object to be force-applied on conflicts. -3. By adding the [`kluctl.io/force-apply-field=my.json.path`](https://kluctl.io/docs/reference/deployments/annotations/all-resources/#kluctlioforce-apply-field) annotation to the object in question. This causes only fields matching the JSON path to be force-applied on conflicts. +2. By adding the [`kluctl.io/force-apply=true`](https://kluctl.io/docs/kluctl/deployments/annotations/all-resources/#kluctlioforce-apply) annotation to the object in question. This will cause all fields of that object to be force-applied on conflicts. +3. By adding the [`kluctl.io/force-apply-field=my.json.path`](https://kluctl.io/docs/kluctl/deployments/annotations/all-resources/#kluctlioforce-apply-field) annotation to the object in question. This causes only fields matching the JSON path to be force-applied on conflicts. Marking a field to be force-applied is required whenever some other actor is known to erroneously claim fields (the ECK operator does this to the nodeSets diff --git a/content/en/blog/_posts/2023-08-15-pkgs-k8s-io-introduction.md b/content/en/blog/_posts/2023-08-15-pkgs-k8s-io-introduction.md index 755b4ce04ddf7..974bac1930cb0 100644 --- a/content/en/blog/_posts/2023-08-15-pkgs-k8s-io-introduction.md +++ b/content/en/blog/_posts/2023-08-15-pkgs-k8s-io-introduction.md @@ -18,41 +18,52 @@ This blog post contains information about these new package repositories, what does it mean to you as an end user, and how to migrate to the new repositories. -**ℹ️ Update (January 12, 2024):** the _**legacy Google-hosted repositories are going -away in January 2024.**_ +**ℹ️ Update (March 26, 2024): _the legacy Google-hosted repositories went +away on March 4, 2024. It's not possible to install Kubernetes packages from +the legacy Google-hosted package repositories any longer._** Check out [the deprecation announcement](/blog/2023/08/31/legacy-package-repository-deprecation/) for more details about this change. + ## What you need to know about the new package repositories? -_(updated on January 12, 2024)_ +_(updated on January 12, 2024 and March 26, 2024)_ - This is an **opt-in change**; you're required to manually migrate from the Google-hosted repository to the Kubernetes community-owned repositories. See [how to migrate](#how-to-migrate) later in this announcement for migration information and instructions. -- **The legacy Google-hosted package repositories are going away in January 2024.** These repositories - have been **deprecated as of August 31, 2023**, and **frozen as of September 13, 2023**. +- **The legacy Google-hosted package repositories went away on March 4, 2024. It's not possible + to install Kubernetes packages from the legacy Google-hosted package repositories any longer.** + These repositories have been **deprecated as of August 31, 2023**, and **frozen as of September 13, 2023**. Check out the [deprecation announcement](/blog/2023/08/31/legacy-package-repository-deprecation/) for more details about this change. +- ~~**The legacy Google-hosted package repositories are going away in January 2024.** These repositories + have been **deprecated as of August 31, 2023**, and **frozen as of September 13, 2023**. + Check out the [deprecation announcement](/blog/2023/08/31/legacy-package-repository-deprecation/) + for more details about this change.~~ - ~~The existing packages in the legacy repositories will be available for the foreseeable future. However, the Kubernetes project can't provide any guarantees on how long is that going to be. The deprecated legacy repositories, and their contents, might be removed at any time in the future - and without a further notice period.~~ **The legacy package repositories are going away in - January 2024.** + and without a further notice period. **The legacy package repositories are going away in + January 2024.**~~ **The legacy Google-hosted package repositories went away on March 4, 2024.** - Given that no new releases will be published to the legacy repositories after the September 13, 2023 cut-off point, you will not be able to upgrade to any patch or minor release made from that date onwards if you don't migrate to the new Kubernetes package repositories. - That said, we recommend migrating to the new Kubernetes package repositories **as soon as possible**. -- The new Kubernetes package repositories contain packages beginning with those + ~~That said, we recommend migrating to the new Kubernetes package repositories **as soon as possible**.~~ + Migrating to the new Kubernetes package repositories is required to consume the official Kubernetes + packages. +- **The new Kubernetes package repositories contain packages beginning with those Kubernetes versions that were still under support when the community took over the package builds. This means that the new package repositories have Linux packages for all - Kubernetes releases starting with v1.24.0. + Kubernetes releases starting with v1.24.0.** - Kubernetes does not have official Linux packages available for earlier releases of Kubernetes; however, your Linux distribution may provide its own packages. - There's a dedicated package repository for each Kubernetes minor version. When upgrading to a different minor release, you must bear in mind that - the package repository details also change. + the package repository details also change. Check out + [Changing The Kubernetes Package Repository](/docs/tasks/administer-cluster/kubeadm/change-package-repository/) + guide for information about steps that you need to take upon upgrading the Kubernetes minor version. ## Why are we introducing new package repositories? @@ -144,13 +155,20 @@ There are three significant differences that you should be aware of: ## Does this in any way affect existing Google-hosted repositories? -The Google-hosted repository and all packages published to it will continue +_(updated on March 26, 2024)_ + +**The legacy Google-hosted repositories went away on March 4, 2024. It's not possible to +install Kubernetes packages from the legacy Google-hosted package repositories any longer.** +Check out [the deprecation announcement](/blog/2023/08/31/legacy-package-repository-deprecation/) +for more details about this change. + +~~The Google-hosted repository and all packages published to it will continue working in the same way as before. There are no changes in how we build and publish packages to the Google-hosted repository, all newly-introduced changes -are only affecting packages publish to the community-owned repositories. +are only affecting packages publish to the community-owned repositories.~~ -However, as mentioned at the beginning of this blog post, we plan to stop -publishing packages to the Google-hosted repository in the future. +~~However, as mentioned at the beginning of this blog post, we plan to stop +publishing packages to the Google-hosted repository in the future.~~ ## How to migrate to the Kubernetes community-owned repositories? {#how-to-migrate} @@ -173,6 +191,8 @@ publishing packages to the Google-hosted repository in the future. curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.28/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg ``` + _Update: In releases older than Debian 12 and Ubuntu 22.04, the folder `/etc/apt/keyrings` does not exist by default, and it should be created before the curl command._ + 3. Update the `apt` package index: ```shell @@ -198,11 +218,28 @@ publishing packages to the Google-hosted repository in the future. EOF ``` +## Where can I get packages for Kubernetes versions prior to v1.24.0? + +_(updated on March 26, 2024)_ + +For Kubernetes v1.24 and onwards, Linux packages of Kubernetes components are available for +download via the official Kubernetes package repositories. Kubernetes does not publish any +software packages for releases of Kubernetes older than v1.24.0; however, your Linux +distribution may provide its own packages. Alternatively, you can directly download binaries +instead of using packages. As an example, see `Without a package manager` instructions in +["Installing kubeadm"](/docs/setup/production-environment/tools/kubeadm/install-kubeadm) +document. + ## Can I rollback to the Google-hosted repository after migrating to the Kubernetes repositories? -In general, yes. Just do the same steps as when migrating, but use parameters +_(updated on March 26, 2024)_ + +**The legacy Google-hosted repositories went away on March 4, 2024 and therefore it's not possible +to rollback to the legacy Google-hosted repositories any longer.** + +~~In general, yes. Just do the same steps as when migrating, but use parameters for the Google-hosted repository. You can find those parameters in a document -like ["Installing kubeadm"](/docs/setup/production-environment/tools/kubeadm/install-kubeadm). +like ["Installing kubeadm"](/docs/setup/production-environment/tools/kubeadm/install-kubeadm).~~ ## Why isn’t there a stable list of domains/IPs? Why can’t I restrict package downloads? diff --git a/content/en/blog/_posts/2023-08-31-legacy-package-repository-deprecation/index.md b/content/en/blog/_posts/2023-08-31-legacy-package-repository-deprecation/index.md index b186585263339..6d609aeca089a 100644 --- a/content/en/blog/_posts/2023-08-31-legacy-package-repository-deprecation/index.md +++ b/content/en/blog/_posts/2023-08-31-legacy-package-repository-deprecation/index.md @@ -24,6 +24,10 @@ the repositories as of **September 13, 2023**. Please continue reading in order to learn what does this mean for you as an user or distributor, and what steps you may need to take. +**ℹ️ Update (March 26, 2024): _the legacy Google-hosted repositories went +away on March 4, 2024. It's not possible to install Kubernetes packages from +the legacy Google-hosted package repositories any longer._** + ## How does this affect me as a Kubernetes end user? This change affects users **directly installing upstream versions of Kubernetes**, @@ -72,6 +76,8 @@ possible and inform your users about this change and what steps they need to tak +_(updated on March 26, 2024)_ + - **15th August 2023:** Kubernetes announces a new, community-managed source for Linux software packages of Kubernetes components - **31st August 2023:** @@ -81,6 +87,11 @@ possible and inform your users about this change and what steps they need to tak Kubernetes will freeze the legacy package repositories, (`apt.kubernetes.io` and `yum.kubernetes.io`). The freeze will happen immediately following the patch releases that are scheduled for September, 2023. +- **12th January 2024:** + Kubernetes announced intentions to remove the legacy package repositories in January 2024 +- **4th March 2024:** + The legacy package repositories have been removed. It's not possible to install Kubernetes packages from + the legacy package repositories any longer The Kubernetes patch releases scheduled for September 2023 (v1.28.2, v1.27.6, v1.26.9, v1.25.14) will have packages published **both** to the community-owned and @@ -107,15 +118,20 @@ distribution may provide its own packages. ## Can I continue to use the legacy package repositories? +_(updated on March 26, 2024)_ + +**The legacy Google-hosted repositories went away on March 4, 2024. It's not possible +to install Kubernetes packages from the legacy Google-hosted package repositories any +longer.** + ~~The existing packages in the legacy repositories will be available for the foreseeable future. However, the Kubernetes project can't provide _any_ guarantees on how long is that going to be. The deprecated legacy repositories, and their contents, might be removed at any time in the future and without a further notice period.~~ -**UPDATE**: The legacy packages are expected to go away in January 2024. - -The Kubernetes project **strongly recommends** migrating to the new community-owned -repositories **as soon as possible**. +~~The Kubernetes project **strongly recommends** migrating to the new community-owned +repositories **as soon as possible**.~~ Migrating to the new package repositories is +required to consume the official Kubernetes packages. Given that no new releases will be published to the legacy repositories **after the September 13, 2023** cut-off point, **you will not be able to upgrade to any patch or minor release made from that date onwards.** diff --git a/content/en/blog/_posts/2024-01-15-SIG-Release-Spotlight/index.md b/content/en/blog/_posts/2024-01-15-SIG-Release-Spotlight/index.md index 460dd27fff976..a86701ddf9b66 100644 --- a/content/en/blog/_posts/2024-01-15-SIG-Release-Spotlight/index.md +++ b/content/en/blog/_posts/2024-01-15-SIG-Release-Spotlight/index.md @@ -4,10 +4,10 @@ title: "Spotlight on SIG Release (Release Team Subproject)" date: 2024-01-15 slug: sig-release-spotlight-2023 canonicalUrl: https://www.kubernetes.dev/blog/2024/01/15/sig-release-spotlight-2023/ +author: > + Nitish Kumar --- -**Author:** Nitish Kumar - The Release Special Interest Group (SIG Release), where Kubernetes sharpens its blade with cutting-edge features and bug fixes every 4 months. Have you ever considered how such a big project like Kubernetes manages its timeline so efficiently to release its new version, or how diff --git a/content/en/blog/_posts/2024-01-23-image-filesystem.md b/content/en/blog/_posts/2024-01-23-image-filesystem.md index 19c80f00cbb18..39a3328971523 100644 --- a/content/en/blog/_posts/2024-01-23-image-filesystem.md +++ b/content/en/blog/_posts/2024-01-23-image-filesystem.md @@ -3,10 +3,10 @@ layout: blog title: 'Image Filesystem: Configuring Kubernetes to store containers on a separate filesystem' date: 2024-01-23 slug: kubernetes-separate-image-filesystem +author: > + Kevin Hannon (Red Hat) --- -**Author:** Kevin Hannon (Red Hat) - A common issue in running/operating Kubernetes clusters is running out of disk space. When the node is provisioned, you should aim to have a good amount of storage space for your container images and running containers. The [container runtime](/docs/setup/production-environment/container-runtimes/) usually writes to `/var`. diff --git a/content/en/blog/_posts/2024-02-21-prevent-unauthorized-volume-mode-conversion-ga.md b/content/en/blog/_posts/2024-02-21-prevent-unauthorized-volume-mode-conversion-ga.md new file mode 100644 index 0000000000000..464060283fdb6 --- /dev/null +++ b/content/en/blog/_posts/2024-02-21-prevent-unauthorized-volume-mode-conversion-ga.md @@ -0,0 +1,115 @@ +--- +layout: blog +title: "Kubernetes 1.30: Preventing unauthorized volume mode conversion moves to GA" +date: 2024-04-30 +slug: prevent-unauthorized-volume-mode-conversion-ga +author: > + Raunak Pradip Shah (Mirantis) +--- + +With the release of Kubernetes 1.30, the feature to prevent the modification of the volume mode +of a [PersistentVolumeClaim](/docs/concepts/storage/persistent-volumes/) that was created from +an existing VolumeSnapshot in a Kubernetes cluster, has moved to GA! + + +## The problem + +The [Volume Mode](/docs/concepts/storage/persistent-volumes/#volume-mode) of a PersistentVolumeClaim +refers to whether the underlying volume on the storage device is formatted into a filesystem or +presented as a raw block device to the Pod that uses it. + +Users can leverage the VolumeSnapshot feature, which has been stable since Kubernetes v1.20, +to create a PersistentVolumeClaim (shortened as PVC) from an existing VolumeSnapshot in +the Kubernetes cluster. The PVC spec includes a dataSource field, which can point to an +existing VolumeSnapshot instance. +Visit [Create a PersistentVolumeClaim from a Volume Snapshot](/docs/concepts/storage/persistent-volumes/#create-persistent-volume-claim-from-volume-snapshot) +for more details on how to create a PVC from an existing VolumeSnapshot in a Kubernetes cluster. + +When leveraging the above capability, there is no logic that validates whether the mode of the +original volume, whose snapshot was taken, matches the mode of the newly created volume. + +This presents a security gap that allows malicious users to potentially exploit an +as-yet-unknown vulnerability in the host operating system. + +There is a valid use case to allow some users to perform such conversions. Typically, storage backup +vendors convert the volume mode during the course of a backup operation, to retrieve changed blocks +for greater efficiency of operations. This prevents Kubernetes from blocking the operation completely +and presents a challenge in distinguishing trusted users from malicious ones. + +## Preventing unauthorized users from converting the volume mode + +In this context, an authorized user is one who has access rights to perform **update** +or **patch** operations on VolumeSnapshotContents, which is a cluster-level resource. +It is up to the cluster administrator to provide these rights only to trusted users +or applications, like backup vendors. +Users apart from such authorized ones will never be allowed to modify the volume mode +of a PVC when it is being created from a VolumeSnapshot. + +To convert the volume mode, an authorized user must do the following: + +1. Identify the VolumeSnapshot that is to be used as the data source for a newly + created PVC in the given namespace. +2. Identify the VolumeSnapshotContent bound to the above VolumeSnapshot. + + ```shell + kubectl describe volumesnapshot -n + ``` + +3. Add the annotation [`snapshot.storage.kubernetes.io/allow-volume-mode-change: "true"`](/docs/reference/labels-annotations-taints/#snapshot-storage-kubernetes-io-allowvolumemodechange) + to the above VolumeSnapshotContent. The VolumeSnapshotContent annotations must include one similar to the following manifest fragment: + + ```yaml + kind: VolumeSnapshotContent + metadata: + annotations: + - snapshot.storage.kubernetes.io/allow-volume-mode-change: "true" + ... + ``` + +**Note**: For pre-provisioned VolumeSnapshotContents, you must take an extra +step of setting `spec.sourceVolumeMode` field to either `Filesystem` or `Block`, +depending on the mode of the volume from which this snapshot was taken. + +An example is shown below: + + ```yaml + apiVersion: snapshot.storage.k8s.io/v1 + kind: VolumeSnapshotContent + metadata: + annotations: + - snapshot.storage.kubernetes.io/allow-volume-mode-change: "true" + name: + spec: + deletionPolicy: Delete + driver: hostpath.csi.k8s.io + source: + snapshotHandle: + sourceVolumeMode: Filesystem + volumeSnapshotRef: + name: + namespace: + ``` + +Repeat steps 1 to 3 for all VolumeSnapshotContents whose volume mode needs to be +converted during a backup or restore operation. This can be done either via software +with credentials of an authorized user or manually by the authorized user(s). + +If the annotation shown above is present on a VolumeSnapshotContent object, +Kubernetes will not prevent the volume mode from being converted. +Users should keep this in mind before they attempt to add the annotation +to any VolumeSnapshotContent. + +## Action required + +The `prevent-volume-mode-conversion` feature flag is enabled by default in the +external-provisioner `v4.0.0` and external-snapshotter `v7.0.0`. Volume mode change +will be rejected when creating a PVC from a VolumeSnapshot unless the steps +described above have been performed. + +## What's next + +To determine which CSI external sidecar versions support this feature, please head +over to the [CSI docs page](https://kubernetes-csi.github.io/docs/). +For any queries or issues, join [Kubernetes on Slack](https://slack.k8s.io/) and +create a thread in the #csi or #sig-storage channel. Alternately, create an issue in the +CSI external-snapshotter [repository](https://github.com/kubernetes-csi/external-snapshotter). \ No newline at end of file diff --git a/content/en/blog/_posts/2024-02-22-k8s-book-club/csantana_k8s_book_club.jpg b/content/en/blog/_posts/2024-02-22-k8s-book-club/csantana_k8s_book_club.jpg new file mode 100644 index 0000000000000..989ba7228df01 Binary files /dev/null and b/content/en/blog/_posts/2024-02-22-k8s-book-club/csantana_k8s_book_club.jpg differ diff --git a/content/en/blog/_posts/2024-02-22-k8s-book-club/index.md b/content/en/blog/_posts/2024-02-22-k8s-book-club/index.md new file mode 100644 index 0000000000000..74e2c4f70ab24 --- /dev/null +++ b/content/en/blog/_posts/2024-02-22-k8s-book-club/index.md @@ -0,0 +1,126 @@ +------ +layout: blog +title: "A look into the Kubernetes Book Club" +slug: k8s-book-club +date: 2024-02-22 +canonicalUrl: https://www.k8s.dev/blog/2024/02/22/k8s-book-club/ +author: > + Frederico Muñoz (SAS Institute) +--- + +Learning Kubernetes and the entire ecosystem of technologies around it is not without its +challenges. In this interview, we will talk with [Carlos Santana +(AWS)](https://www.linkedin.com/in/csantanapr/) to learn a bit more about how he created the +[Kubernetes Book Club](https://community.cncf.io/kubernetes-virtual-book-club/), how it works, and +how anyone can join in to take advantage of a community-based learning experience. + +![Carlos Santana speaking at KubeCon NA 2023](csantana_k8s_book_club.jpg) + +**Frederico Muñoz (FSM)**: Hello Carlos, thank you so much for your availability. To start with, +could you tell us a bit about yourself? + +**Carlos Santana (CS)**: Of course. My experience in deploying Kubernetes in production six +years ago opened the door for me to join [Knative](https://knative.dev/) and then contribute to +Kubernetes through the Release Team. Working on upstream Kubernetes has been one of the best +experiences I've had in open-source. Over the past two years, in my role as a Senior Specialist +Solutions Architect at AWS, I have been assisting large enterprises build their internal developer +platforms (IDP) on top of Kubernetes. Going forward, my open source contributions are directed +towards [CNOE](https://cnoe.io/) and CNCF projects like [Argo](https://github.com/argoproj), +[Crossplane](https://www.crossplane.io/), and [Backstage](https://www.cncf.io/projects/backstage/). + +## Creating the Book Club + +**FSM**: So your path led you to Kubernetes, and at that point what was the motivating factor for +starting the Book Club? + +**CS**: The idea for the Kubernetes Book Club sprang from a casual suggestion during a +[TGIK](https://github.com/vmware-archive/tgik) livestream. For me, it was more than just about +reading a book; it was about creating a learning community. This platform has not only been a source +of knowledge but also a support system, especially during the challenging times of the +pandemic. It's gratifying to see how this initiative has helped members cope and grow. The first +book [Production +Kubernetes](https://www.oreilly.com/library/view/production-kubernetes/9781492092292/) took 36 +weeks, when we started on March 5th 2021. Currently don't take that long to cover a book, one or two +chapters per week. + +**FSM**: Could you describe the way the Kubernetes Book Club works? How do you select the books and how +do you go through them? + +**CS**: We collectively choose books based on the interests and needs of the group. This practical +approach helps members, especially beginners, grasp complex concepts more easily. We have two weekly +series, one for the EMEA timezone, and I organize the US one. Each organizer works with their co-host +and picks a book on Slack, then sets up a lineup of hosts for a couple of weeks to discuss each +chapter. + +**FSM**: If I’m not mistaken, the Kubernetes Book Club is in its 17th book, which is significant: is +there any secret recipe for keeping things active? + +**CS**: The secret to keeping the club active and engaging lies in a couple of key factors. + +Firstly, consistency has been crucial. We strive to maintain a regular schedule, only cancelling +meetups for major events like holidays or KubeCon. This regularity helps members stay engaged and +builds a reliable community. + +Secondly, making the sessions interesting and interactive has been vital. For instance, I often +introduce pop-up quizzes during the meetups, which not only tests members' understanding but also +adds an element of fun. This approach keeps the content relatable and helps members understand how +theoretical concepts are applied in real-world scenarios. + +## Topics covered in the Book Club + +**FSM**: The main topics of the books have been Kubernetes, GitOps, Security, SRE, and +Observability: is this a reflection of the cloud native landscape, especially in terms of +popularity? + +**CS**: Our journey began with 'Production Kubernetes', setting the tone for our focus on practical, +production-ready solutions. Since then, we've delved into various aspects of the CNCF landscape, +aligning our books with a different theme. Each theme, whether it be Security, Observability, or +Service Mesh, is chosen based on its relevance and demand within the community. For instance, in our +recent themes on Kubernetes Certifications, we brought the book authors into our fold as active +hosts, enriching our discussions with their expertise. + +**FSM**: I know that the project had recent changes, namely being integrated into the CNCF as a +[Cloud Native Community Group](https://community.cncf.io/). Could you talk a bit about this change? + +**CS**: The CNCF graciously accepted the book club as a Cloud Native Community Group. This is a +significant development that has streamlined our operations and expanded our reach. This alignment +has been instrumental in enhancing our administrative capabilities, similar to those used by +Kubernetes Community Days (KCD) meetups. Now, we have a more robust structure for memberships, event +scheduling, mailing lists, hosting web conferences, and recording sessions. + +**FSM**: How has your involvement with the CNCF impacted the growth and engagement of the Kubernetes +Book Club over the past six months? + + +**CS**: Since becoming part of the CNCF community six months ago, we've witnessed significant +quantitative changes within the Kubernetes Book Club. Our membership has surged to over 600 members, +and we've successfully organized and conducted more than 40 events during this period. What's even +more promising is the consistent turnout, with an average of 30 attendees per event. This growth and +engagement are clear indicators of the positive influence of our CNCF affiliation on the Kubernetes +Book Club's reach and impact in the community. + + +## Joining the Book Club + +**FSM**: For anyone wanting to join, what should they do? + +**CS**: There are three steps to join: + +- First, join the [Kubernetes Book Club + Community](https://community.cncf.io/kubernetes-virtual-book-club/) +- Then RSVP to the + [events](https://community.cncf.io/kubernetes-virtual-book-club/) + on the community page +- Lastly, join the CNCF Slack channel + [#kubernetes-book-club](https://cloud-native.slack.com/archives/C05EYA14P37). + +**FSM**: Excellent, thank you! Any final comments you would like to share? + +**CS**: The Kubernetes Book Club is more than just a group of professionals discussing books; it's a +vibrant community and amazing volunteers that help organize and host [Neependra +Khare](https://www.linkedin.com/in/neependra/), [Eric +Smalling](https://www.linkedin.com/in/ericsmalling/), [Sevi +Karakulak](https://www.linkedin.com/in/sevikarakulak/), [Chad +M. Crowell](https://www.linkedin.com/in/chadmcrowell/), and [Walid (CNJ) +Shaari](https://www.linkedin.com/in/walidshaari/). Look us up at KubeCon and get your Kubernetes +Book Club sticker! diff --git a/content/en/blog/_posts/2024-03-01-sig-cloud-provider-spotlight.md b/content/en/blog/_posts/2024-03-01-sig-cloud-provider-spotlight.md new file mode 100644 index 0000000000000..d4e533822d3f7 --- /dev/null +++ b/content/en/blog/_posts/2024-03-01-sig-cloud-provider-spotlight.md @@ -0,0 +1,148 @@ +--- +layout: blog +title: "Spotlight on SIG Cloud Provider" +slug: sig-cloud-provider-spotlight-2024 +date: 2024-03-01 +canonicalUrl: https://www.k8s.dev/blog/2024/03/01/sig-cloud-provider-spotlight-2024/ +author: > + Arujjwal Negi +--- + +One of the most popular ways developers use Kubernetes-related services is via cloud providers, but +have you ever wondered how cloud providers can do that? How does this whole process of integration +of Kubernetes to various cloud providers happen? To answer that, let's put the spotlight on [SIG +Cloud Provider](https://github.com/kubernetes/community/blob/master/sig-cloud-provider/README.md). + +SIG Cloud Provider works to create seamless integrations between Kubernetes and various cloud +providers. Their mission? Keeping the Kubernetes ecosystem fair and open for all. By setting clear +standards and requirements, they ensure every cloud provider plays nicely with Kubernetes. It is +their responsibility to configure cluster components to enable cloud provider integrations. + +In this blog of the SIG Spotlight series, [Arujjwal Negi](https://twitter.com/arujjval) interviews +[Michael McCune](https://github.com/elmiko) (Red Hat), also known as _elmiko_, co-chair of SIG Cloud +Provider, to give us an insight into the workings of this group. + +## Introduction + +**Arujjwal**: Let's start by getting to know you. Can you give us a small intro about yourself and +how you got into Kubernetes? + +**Michael**: Hi, I’m Michael McCune, most people around the community call me by my handle, +_elmiko_. I’ve been a software developer for a long time now (Windows 3.1 was popular when I +started!), and I’ve been involved with open-source software for most of my career. I first got +involved with Kubernetes as a developer of machine learning and data science applications; the team +I was on at the time was creating tutorials and examples to demonstrate the use of technologies like +Apache Spark on Kubernetes. That said, I’ve been interested in distributed systems for many years +and when an opportunity arose to join a team working directly on Kubernetes, I jumped at it! + +## Functioning and working + +**Arujjwal**: Can you give us an insight into what SIG Cloud Provider does and how it functions? + +**Michael**: SIG Cloud Provider was formed to help ensure that Kubernetes provides a neutral +integration point for all infrastructure providers. Our largest task to date has been the extraction +and migration of in-tree cloud controllers to out-of-tree components. The SIG meets regularly to +discuss progress and upcoming tasks and also to answer questions and bugs that +arise. Additionally, we act as a coordination point for cloud provider subprojects such as the cloud +provider framework, specific cloud controller implementations, and the [Konnectivity proxy +project](https://kubernetes.io/docs/tasks/extend-kubernetes/setup-konnectivity/). + + +**Arujjwal:** After going through the project +[README](https://github.com/kubernetes/community/blob/master/sig-cloud-provider/README.md), I +learned that SIG Cloud Provider works with the integration of Kubernetes with cloud providers. How +does this whole process go? + +**Michael:** One of the most common ways to run Kubernetes is by deploying it to a cloud environment +(AWS, Azure, GCP, etc). Frequently, the cloud infrastructures have features that enhance the +performance of Kubernetes, for example, by providing elastic load balancing for Service objects. To +ensure that cloud-specific services can be consistently consumed by Kubernetes, the Kubernetes +community has created cloud controllers to address these integration points. Cloud providers can +create their own controllers either by using the framework maintained by the SIG or by following +the API guides defined in the Kubernetes code and documentation. One thing I would like to point out +is that SIG Cloud Provider does not deal with the lifecycle of nodes in a Kubernetes cluster; +for those types of topics, SIG Cluster Lifecycle and the Cluster API project are more appropriate +venues. + +## Important subprojects + +**Arujjwal:** There are a lot of subprojects within this SIG. Can you highlight some of the most +important ones and what job they do? + +**Michael:** I think the two most important subprojects today are the [cloud provider +framework](https://github.com/kubernetes/community/blob/master/sig-cloud-provider/README.md#kubernetes-cloud-provider) +and the [extraction/migration +project](https://github.com/kubernetes/community/blob/master/sig-cloud-provider/README.md#cloud-provider-extraction-migration). The +cloud provider framework is a common library to help infrastructure integrators build a cloud +controller for their infrastructure. This project is most frequently the starting point for new +people coming to the SIG. The extraction and migration project is the other big subproject and a +large part of why the framework exists. A little history might help explain further: for a long +time, Kubernetes needed some integration with the underlying infrastructure, not +necessarily to add features but to be aware of cloud events like instance termination. The cloud +provider integrations were built into the Kubernetes code tree, and thus the term "in-tree" was +created (check out this [article on the topic](https://kaslin.rocks/out-of-tree/) for more +info). The activity of maintaining provider-specific code in the main Kubernetes source tree was +considered undesirable by the community. The community’s decision inspired the creation of the +extraction and migration project to remove the "in-tree" cloud controllers in favor of +"out-of-tree" components. + + +**Arujjwal:** What makes [the cloud provider framework] a good place to start? Does it have consistent good beginner work? What +kind? + +**Michael:** I feel that the cloud provider framework is a good place to start as it encodes the +community’s preferred practices for cloud controller managers and, as such, will give a newcomer a +strong understanding of how and what the managers do. Unfortunately, there is not a consistent +stream of beginner work on this component; this is due in part to the mature nature of the framework +and that of the individual providers as well. For folks who are interested in getting more involved, +having some [Go language](https://go.dev/) knowledge is good and also having an understanding of +how at least one cloud API (e.g., AWS, Azure, GCP) works is also beneficial. In my personal opinion, +being a newcomer to SIG Cloud Provider can be challenging as most of the code around this project +deals directly with specific cloud provider interactions. My best advice to people wanting to do +more work on cloud providers is to grow your familiarity with one or two cloud APIs, then look +for open issues on the controller managers for those clouds, and always communicate with the other +contributors as much as possible. + +## Accomplishments + +**Arujjwal:** Can you share about an accomplishment(s) of the SIG that you are proud of? + +**Michael:** Since I joined the SIG, more than a year ago, we have made great progress in advancing +the extraction and migration subproject. We have moved from an alpha status on the defining +[KEP](https://github.com/kubernetes/enhancements/blob/master/keps/README.md) to a beta status and +are inching ever closer to removing the old provider code from the Kubernetes source tree. I've been +really proud to see the active engagement from our community members and to see the progress we have +made towards extraction. I have a feeling that, within the next few releases, we will see the final +removal of the in-tree cloud controllers and the completion of the subproject. + +## Advice for new contributors + +**Arujjwal:** Is there any suggestion or advice for new contributors on how they can start at SIG +Cloud Provider? + +**Michael:** This is a tricky question in my opinion. SIG Cloud Provider is focused on the code +pieces that integrate between Kubernetes and an underlying infrastructure. It is very common, but +not necessary, for members of the SIG to be representing a cloud provider in an official capacity. I +recommend that anyone interested in this part of Kubernetes should come to an SIG meeting to see how +we operate and also to study the cloud provider framework project. We have some interesting ideas +for future work, such as a common testing framework, that will cut across all cloud providers and +will be a great opportunity for anyone looking to expand their Kubernetes involvement. + +**Arujjwal:** Are there any specific skills you're looking for that we should highlight? To give you +an example from our own [SIG ContribEx] +(https://github.com/kubernetes/community/blob/master/sig-contributor-experience/README.md): +if you're an expert in [Hugo](https://gohugo.io/), we can always use some help with k8s.dev! + +**Michael:** The SIG is currently working through the final phases of our extraction and migration +process, but we are looking toward the future and starting to plan what will come next. One of the +big topics that the SIG has discussed is testing. Currently, we do not have a generic common set of +tests that can be exercised by each cloud provider to confirm the behaviour of their controller +manager. If you are an expert in Ginkgo and the Kubetest framework, we could probably use your help +in designing and implementing the new tests. + +--- + +This is where the conversation ends. I hope this gave you some insights about SIG Cloud Provider's +aim and working. This is just the tip of the iceberg. To know more and get involved with SIG Cloud +Provider, try attending their meetings +[here](https://github.com/kubernetes/community/blob/master/sig-cloud-provider/README.md#meetings). diff --git a/content/en/blog/_posts/2024-03-07-cri-o-seccomp-oci-artifacts.md b/content/en/blog/_posts/2024-03-07-cri-o-seccomp-oci-artifacts.md new file mode 100644 index 0000000000000..6f6e4083fa7e1 --- /dev/null +++ b/content/en/blog/_posts/2024-03-07-cri-o-seccomp-oci-artifacts.md @@ -0,0 +1,476 @@ +--- +layout: blog +title: "CRI-O: Applying seccomp profiles from OCI registries" +date: 2024-03-07 +slug: cri-o-seccomp-oci-artifacts +author: > + Sascha Grunert +--- + +Seccomp stands for secure computing mode and has been a feature of the Linux +kernel since version 2.6.12. It can be used to sandbox the privileges of a +process, restricting the calls it is able to make from userspace into the +kernel. Kubernetes lets you automatically apply seccomp profiles loaded onto a +node to your Pods and containers. + +But distributing those seccomp profiles is a major challenge in Kubernetes, +because the JSON files have to be available on all nodes where a workload can +possibly run. Projects like the [Security Profiles +Operator](https://sigs.k8s.io/security-profiles-operator) solve that problem by +running as a daemon within the cluster, which makes me wonder which part of that +distribution could be done by the [container +runtime](/docs/setup/production-environment/container-runtimes). + +Runtimes usually apply the profiles from a local path, for example: + +```yaml +apiVersion: v1 +kind: Pod +metadata: + name: pod +spec: + containers: + - name: container + image: nginx:1.25.3 + securityContext: + seccompProfile: + type: Localhost + localhostProfile: nginx-1.25.3.json +``` + +The profile `nginx-1.25.3.json` has to be available in the root directory of the +kubelet, appended by the `seccomp` directory. This means the default location +for the profile on-disk would be `/var/lib/kubelet/seccomp/nginx-1.25.3.json`. +If the profile is not available, then runtimes will fail on container creation +like this: + +```shell +kubectl get pods +``` + +```console +NAME READY STATUS RESTARTS AGE +pod 0/1 CreateContainerError 0 38s +``` + +```shell +kubectl describe pod/pod | tail +``` + +```console +Tolerations: node.kubernetes.io/not-ready:NoExecute op=Exists for 300s + node.kubernetes.io/unreachable:NoExecute op=Exists for 300s +Events: + Type Reason Age From Message + ---- ------ ---- ---- ------- + Normal Scheduled 117s default-scheduler Successfully assigned default/pod to 127.0.0.1 + Normal Pulling 117s kubelet Pulling image "nginx:1.25.3" + Normal Pulled 111s kubelet Successfully pulled image "nginx:1.25.3" in 5.948s (5.948s including waiting) + Warning Failed 7s (x10 over 111s) kubelet Error: setup seccomp: unable to load local profile "/var/lib/kubelet/seccomp/nginx-1.25.3.json": open /var/lib/kubelet/seccomp/nginx-1.25.3.json: no such file or directory + Normal Pulled 7s (x9 over 111s) kubelet Container image "nginx:1.25.3" already present on machine +``` + +The major obstacle of having to manually distribute the `Localhost` profiles +will lead many end-users to fall back to `RuntimeDefault` or even running their +workloads as `Unconfined` (with disabled seccomp). + +## CRI-O to the rescue + +The Kubernetes container runtime [CRI-O](https://github.com/cri-o/cri-o) +provides various features using custom annotations. The v1.30 release +[adds](https://github.com/cri-o/cri-o/pull/7719) support for a new set of +annotations called `seccomp-profile.kubernetes.cri-o.io/POD` and +`seccomp-profile.kubernetes.cri-o.io/`. Those annotations allow you +to specify: + +- a seccomp profile for a specific container, when used as: + `seccomp-profile.kubernetes.cri-o.io/` (example: + `seccomp-profile.kubernetes.cri-o.io/webserver: +'registry.example/example/webserver:v1'`) +- a seccomp profile for every container within a pod, when used without the + container name suffix but the reserved name `POD`: + `seccomp-profile.kubernetes.cri-o.io/POD` +- a seccomp profile for a whole container image, if the image itself contains + the annotation `seccomp-profile.kubernetes.cri-o.io/POD` or + `seccomp-profile.kubernetes.cri-o.io/`. + +CRI-O will only respect the annotation if the runtime is configured to allow it, +as well as for workloads running as `Unconfined`. All other workloads will still +use the value from the `securityContext` with a higher priority. + +The annotations alone will not help much with the distribution of the profiles, +but the way they can be referenced will! For example, you can now specify +seccomp profiles like regular container images by using OCI artifacts: + +```yaml +apiVersion: v1 +kind: Pod +metadata: + name: pod + annotations: + seccomp-profile.kubernetes.cri-o.io/POD: quay.io/crio/seccomp:v2 +spec: … +``` + +The image `quay.io/crio/seccomp:v2` contains a `seccomp.json` file, which +contains the actual profile content. Tools like [ORAS](https://oras.land) or +[Skopeo](https://github.com/containers/skopeo) can be used to inspect the +contents of the image: + +```shell +oras pull quay.io/crio/seccomp:v2 +``` + +```console +Downloading 92d8ebfa89aa seccomp.json +Downloaded 92d8ebfa89aa seccomp.json +Pulled [registry] quay.io/crio/seccomp:v2 +Digest: sha256:f0205dac8a24394d9ddf4e48c7ac201ca7dcfea4c554f7ca27777a7f8c43ec1b +``` + +```shell +jq . seccomp.json | head +``` + +```yaml +{ + "defaultAction": "SCMP_ACT_ERRNO", + "defaultErrnoRet": 38, + "defaultErrno": "ENOSYS", + "archMap": [ + { + "architecture": "SCMP_ARCH_X86_64", + "subArchitectures": [ + "SCMP_ARCH_X86", + "SCMP_ARCH_X32" +``` + +```shell +# Inspect the plain manifest of the image +skopeo inspect --raw docker://quay.io/crio/seccomp:v2 | jq . +``` + +```yaml +{ + "schemaVersion": 2, + "mediaType": "application/vnd.oci.image.manifest.v1+json", + "config": + { + "mediaType": "application/vnd.cncf.seccomp-profile.config.v1+json", + "digest": "sha256:ca3d163bab055381827226140568f3bef7eaac187cebd76878e0b63e9e442356", + "size": 3, + }, + "layers": + [ + { + "mediaType": "application/vnd.oci.image.layer.v1.tar", + "digest": "sha256:92d8ebfa89aa6dd752c6443c27e412df1b568d62b4af129494d7364802b2d476", + "size": 18853, + "annotations": { "org.opencontainers.image.title": "seccomp.json" }, + }, + ], + "annotations": { "org.opencontainers.image.created": "2024-02-26T09:03:30Z" }, +} +``` + +The image manifest contains a reference to a specific required config media type +(`application/vnd.cncf.seccomp-profile.config.v1+json`) and a single layer +(`application/vnd.oci.image.layer.v1.tar`) pointing to the `seccomp.json` file. +But now, let's give that new feature a try! + +### Using the annotation for a specific container or whole pod + +CRI-O needs to be configured adequately before it can utilize the annotation. To +do this, add the annotation to the `allowed_annotations` array for the runtime. +This can be done by using a drop-in configuration +`/etc/crio/crio.conf.d/10-crun.conf` like this: + +```toml +[crio.runtime] +default_runtime = "crun" + +[crio.runtime.runtimes.crun] +allowed_annotations = [ + "seccomp-profile.kubernetes.cri-o.io", +] +``` + +Now, let's run CRI-O from the latest `main` commit. This can be done by either +building it from source, using the [static binary bundles](https://github.com/cri-o/packaging?tab=readme-ov-file#using-the-static-binary-bundles-directly) +or [the prerelease packages](https://github.com/cri-o/packaging?tab=readme-ov-file#usage). + +To demonstrate this, I ran the `crio` binary from my command line using a single +node Kubernetes cluster via [`local-up-cluster.sh`](https://github.com/cri-o/cri-o?tab=readme-ov-file#running-kubernetes-with-cri-o). +Now that the cluster is up and running, let's try a pod without the annotation +running as seccomp `Unconfined`: + +```shell +cat pod.yaml +``` + +```yaml +apiVersion: v1 +kind: Pod +metadata: + name: pod +spec: + containers: + - name: container + image: nginx:1.25.3 + securityContext: + seccompProfile: + type: Unconfined +``` + +```shell +kubectl apply -f pod.yaml +``` + +The workload is up and running: + +```shell +kubectl get pods +``` + +```console +NAME READY STATUS RESTARTS AGE +pod 1/1 Running 0 15s +``` + +And no seccomp profile got applied if I inspect the container using +[`crictl`](https://sigs.k8s.io/cri-tools): + +```shell +export CONTAINER_ID=$(sudo crictl ps --name container -q) +sudo crictl inspect $CONTAINER_ID | jq .info.runtimeSpec.linux.seccomp +``` + +```console +null +``` + +Now, let's modify the pod to apply the profile `quay.io/crio/seccomp:v2` to the +container: + +```yaml +apiVersion: v1 +kind: Pod +metadata: + name: pod + annotations: + seccomp-profile.kubernetes.cri-o.io/container: quay.io/crio/seccomp:v2 +spec: + containers: + - name: container + image: nginx:1.25.3 +``` + +I have to delete and recreate the Pod, because only recreation will apply a new +seccomp profile: + +```shell +kubectl delete pod/pod +``` + +```console +pod "pod" deleted +``` + +```shell +kubectl apply -f pod.yaml +``` + +```console +pod/pod created +``` + +The CRI-O logs will now indicate that the runtime pulled the artifact: + +```console +WARN[…] Allowed annotations are specified for workload [seccomp-profile.kubernetes.cri-o.io] +INFO[…] Found container specific seccomp profile annotation: seccomp-profile.kubernetes.cri-o.io/container=quay.io/crio/seccomp:v2 id=26ddcbe6-6efe-414a-88fd-b1ca91979e93 name=/runtime.v1.RuntimeService/CreateContainer +INFO[…] Pulling OCI artifact from ref: quay.io/crio/seccomp:v2 id=26ddcbe6-6efe-414a-88fd-b1ca91979e93 name=/runtime.v1.RuntimeService/CreateContainer +INFO[…] Retrieved OCI artifact seccomp profile of len: 18853 id=26ddcbe6-6efe-414a-88fd-b1ca91979e93 name=/runtime.v1.RuntimeService/CreateContainer +``` + +And the container is finally using the profile: + +```shell +export CONTAINER_ID=$(sudo crictl ps --name container -q) +sudo crictl inspect $CONTAINER_ID | jq .info.runtimeSpec.linux.seccomp | head +``` + +```yaml +{ + "defaultAction": "SCMP_ACT_ERRNO", + "defaultErrnoRet": 38, + "architectures": [ + "SCMP_ARCH_X86_64", + "SCMP_ARCH_X86", + "SCMP_ARCH_X32" + ], + "syscalls": [ + { +``` + +The same would work for every container in the pod, if users replace the +`/container` suffix with the reserved name `/POD`, for example: + +```yaml +apiVersion: v1 +kind: Pod +metadata: + name: pod + annotations: + seccomp-profile.kubernetes.cri-o.io/POD: quay.io/crio/seccomp:v2 +spec: + containers: + - name: container + image: nginx:1.25.3 +``` + +### Using the annotation for a container image + +While specifying seccomp profiles as OCI artifacts on certain workloads is a +cool feature, the majority of end users would like to link seccomp profiles to +published container images. This can be done by using a container image +annotation; instead of being applied to a Kubernetes Pod, the annotation is some +metadata applied at the container image itself. For example, +[Podman](https://podman.io) can be used to add the image annotation directly +during image build: + +```shell +podman build \ + --annotation seccomp-profile.kubernetes.cri-o.io=quay.io/crio/seccomp:v2 \ + -t quay.io/crio/nginx-seccomp:v2 . +``` + +The pushed image then contains the annotation: + +```shell +skopeo inspect --raw docker://quay.io/crio/nginx-seccomp:v2 | + jq '.annotations."seccomp-profile.kubernetes.cri-o.io"' +``` + +```console +"quay.io/crio/seccomp:v2" +``` + +If I now use that image in an CRI-O test pod definition: + +```yaml +apiVersion: v1 +kind: Pod +metadata: + name: pod + # no Pod annotations set +spec: + containers: + - name: container + image: quay.io/crio/nginx-seccomp:v2 +``` + +Then the CRI-O logs will indicate that the image annotation got evaluated and +the profile got applied: + +```shell +kubectl delete pod/pod +``` + +```console +pod "pod" deleted +``` + +```shell +kubectl apply -f pod.yaml +``` + +```console +pod/pod created +``` + +```console +INFO[…] Found image specific seccomp profile annotation: seccomp-profile.kubernetes.cri-o.io=quay.io/crio/seccomp:v2 id=c1f22c59-e30e-4046-931d-a0c0fdc2c8b7 name=/runtime.v1.RuntimeService/CreateContainer +INFO[…] Pulling OCI artifact from ref: quay.io/crio/seccomp:v2 id=c1f22c59-e30e-4046-931d-a0c0fdc2c8b7 name=/runtime.v1.RuntimeService/CreateContainer +INFO[…] Retrieved OCI artifact seccomp profile of len: 18853 id=c1f22c59-e30e-4046-931d-a0c0fdc2c8b7 name=/runtime.v1.RuntimeService/CreateContainer +INFO[…] Created container 116a316cd9a11fe861dd04c43b94f45046d1ff37e2ed05a4e4194fcaab29ee63: default/pod/container id=c1f22c59-e30e-4046-931d-a0c0fdc2c8b7 name=/runtime.v1.RuntimeService/CreateContainer +``` + +```shell +export CONTAINER_ID=$(sudo crictl ps --name container -q) +sudo crictl inspect $CONTAINER_ID | jq .info.runtimeSpec.linux.seccomp | head +``` + +```yaml +{ + "defaultAction": "SCMP_ACT_ERRNO", + "defaultErrnoRet": 38, + "architectures": [ + "SCMP_ARCH_X86_64", + "SCMP_ARCH_X86", + "SCMP_ARCH_X32" + ], + "syscalls": [ + { +``` + +For container images, the annotation `seccomp-profile.kubernetes.cri-o.io` will +be treated in the same way as `seccomp-profile.kubernetes.cri-o.io/POD` and +applies to the whole pod. In addition to that, the whole feature also works when +using the container specific annotation on an image, for example if a container +is named `container1`: + +```shell +skopeo inspect --raw docker://quay.io/crio/nginx-seccomp:v2-container | + jq '.annotations."seccomp-profile.kubernetes.cri-o.io/container1"' +``` + +```console +"quay.io/crio/seccomp:v2" +``` + +The cool thing about this whole feature is that users can now create seccomp +profiles for specific container images and store them side by side in the same +registry. Linking the images to the profiles provides a great flexibility to +maintain them over the whole application's life cycle. + +### Pushing profiles using ORAS + +The actual creation of the OCI object that contains a seccomp profile requires a +bit more work when using ORAS. I have the hope that tools like Podman will +simplify the overall process in the future. Right now, the container registry +needs to be [OCI compatible](https://oras.land/docs/compatible_oci_registries/#registries-supporting-oci-artifacts), +which is also the case for [Quay.io](https://quay.io). CRI-O expects the seccomp +profile object to have a container image media type +(`application/vnd.cncf.seccomp-profile.config.v1+json`), while ORAS uses +`application/vnd.oci.empty.v1+json` per default. To achieve all of that, the +following commands can be executed: + +```shell +echo "{}" > config.json +oras push \ + --config config.json:application/vnd.cncf.seccomp-profile.config.v1+json \ + quay.io/crio/seccomp:v2 seccomp.json +``` + +The resulting image contains the `mediaType` that CRI-O expects. ORAS pushes a +single layer `seccomp.json` to the registry. The name of the profile does not +matter much. CRI-O will pick the first layer and check if that can act as a +seccomp profile. + +## Future work + +CRI-O internally manages the OCI artifacts like regular files. This provides the +benefit of moving them around, removing them if not used any more or having any +other data available than seccomp profiles. This enables future enhancements in +CRI-O on top of OCI artifacts, but also allows thinking about stacking seccomp +profiles as part of having multiple layers in an OCI artifact. The limitation +that it only works for `Unconfined` workloads for v1.30.x releases is something +different CRI-O would like to address in the future. Simplifying the overall +user experience by not compromising security seems to be the key for a +successful future of seccomp in container workloads. + +The CRI-O maintainers will be happy to listen to any feedback or suggestions on +the new feature! Thank you for reading this blog post, feel free to reach out +to the maintainers via the Kubernetes [Slack channel #crio](https://kubernetes.slack.com/messages/CAZH62UR1) +or create an issue in the [GitHub repository](https://github.com/cri-o/cri-o). diff --git a/content/en/blog/_posts/2024-03-12-mid-cycle-1.30.md b/content/en/blog/_posts/2024-03-12-mid-cycle-1.30.md new file mode 100644 index 0000000000000..3280bb569a1a8 --- /dev/null +++ b/content/en/blog/_posts/2024-03-12-mid-cycle-1.30.md @@ -0,0 +1,130 @@ +--- +layout: blog +title: 'A Peek at Kubernetes v1.30' +date: 2024-03-12 +slug: kubernetes-1-30-upcoming-changes +author: > + Amit Dsouza, + Frederick Kautz, + Kristin Martin, + Abigail McCarthy, + Natali Vlatko +--- + +## A quick look: exciting changes in Kubernetes v1.30 + +It's a new year and a new Kubernetes release. We're halfway through the release cycle and +have quite a few interesting and exciting enhancements coming in v1.30. From brand new features +in alpha, to established features graduating to stable, to long-awaited improvements, this release +has something for everyone to pay attention to! + +To tide you over until the official release, here's a sneak peek of the enhancements we're most +excited about in this cycle! + +## Major changes for Kubernetes v1.30 + +### Structured parameters for dynamic resource allocation ([KEP-4381](https://kep.k8s.io/4381)) + +[Dynamic resource allocation](/docs/concepts/scheduling-eviction/dynamic-resource-allocation/) was +added to Kubernetes as an alpha feature in v1.26. It defines an alternative to the traditional +device-plugin API for requesting access to third-party resources. By design, dynamic resource +allocation uses parameters for resources that are completely opaque to core Kubernetes. This +approach poses a problem for the Cluster Autoscaler (CA) or any higher-level controller that +needs to make decisions for a group of pods (e.g. a job scheduler). It cannot simulate the effect of +allocating or deallocating claims over time. Only the third-party DRA drivers have the information +available to do this. + +​​Structured Parameters for dynamic resource allocation is an extension to the original +implementation that addresses this problem by building a framework to support making these claim +parameters less opaque. Instead of handling the semantics of all claim parameters themselves, +drivers could manage resources and describe them using a specific "structured model" pre-defined by +Kubernetes. This would allow components aware of this "structured model" to make decisions about +these resources without outsourcing them to some third-party controller. For example, the scheduler +could allocate claims rapidly without back-and-forth communication with dynamic resource +allocation drivers. Work done for this release centers on defining the framework necessary to enable +different "structured models" and to implement the "named resources" model. This model allows +listing individual resource instances and, compared to the traditional device plugin API, adds the +ability to select those instances individually via attributes. + +### Node memory swap support ([KEP-2400](https://kep.k8s.io/2400)) + +In Kubernetes v1.30, memory swap support on Linux nodes gets a big change to how it works - with a +strong emphasis on improving system stability. In previous Kubernetes versions, the `NodeSwap` +feature gate was disabled by default, and when enabled, it used `UnlimitedSwap` behavior as the +default behavior. To achieve better stability, `UnlimitedSwap` behavior (which might compromise node +stability) will be removed in v1.30. + +The updated, still-beta support for swap on Linux nodes will be available by default. However, the +default behavior will be to run the node set to `NoSwap` (not `UnlimitedSwap`) mode. In `NoSwap` +mode, the kubelet supports running on a node where swap space is active, but Pods don't use any of +the page file. You'll still need to set `--fail-swap-on=false` for the kubelet to run on that node. +However, the big change is the other mode: `LimitedSwap`. In this mode, the kubelet actually uses +the page file on that node and allows Pods to have some of their virtual memory paged out. +Containers (and their parent pods) do not have access to swap beyond their memory limit, but the +system can still use the swap space if available. + +Kubernetes' Node special interest group (SIG Node) will also update the documentation to help you +understand how to use the revised implementation, based on feedback from end users, contributors, +and the wider Kubernetes community. + +Read the previous [blog post](/blog/2023/08/24/swap-linux-beta/) or the [node swap +documentation](/docs/concepts/architecture/nodes/#swap-memory) for more details on +Linux node swap support in Kubernetes. + +### Support user namespaces in pods ([KEP-127](https://kep.k8s.io/127)) + +[User namespaces](/docs/concepts/workloads/pods/user-namespaces) is a Linux-only feature that better +isolates pods to prevent or mitigate several CVEs rated high/critical, including +[CVE-2024-21626](https://github.com/opencontainers/runc/security/advisories/GHSA-xr7r-f8xq-vfvv), +published in January 2024. In Kubernetes 1.30, support for user namespaces is migrating to beta and +now supports pods with and without volumes, custom UID/GID ranges, and more! + +### Structured authorization configuration ([KEP-3221](https://kep.k8s.io/3221)) + +Support for [structured authorization +configuration](/docs/reference/access-authn-authz/authorization/#configuring-the-api-server-using-an-authorization-config-file) +is moving to beta and will be enabled by default. This feature enables the creation of +authorization chains with multiple webhooks with well-defined parameters that validate requests in a +particular order and allows fine-grained control – such as explicit Deny on failures. The +configuration file approach even allows you to specify [CEL](/docs/reference/using-api/cel/) rules +to pre-filter requests before they are dispatched to webhooks, helping you to prevent unnecessary +invocations. The API server also automatically reloads the authorizer chain when the configuration +file is modified. + +You must specify the path to that authorization configuration using the `--authorization-config` +command line argument. If you want to keep using command line flags instead of a +configuration file, those will continue to work as-is. To gain access to new authorization webhook +capabilities like multiple webhooks, failure policy, and pre-filter rules, switch to putting options +in an `--authorization-config` file. From Kubernetes 1.30, the configuration file format is +beta-level, and only requires specifying `--authorization-config` since the feature gate is enabled by +default. An example configuration with all possible values is provided in the [Authorization +docs](/docs/reference/access-authn-authz/authorization/#configuring-the-api-server-using-an-authorization-config-file). +For more details, read the [Authorization +docs](/docs/reference/access-authn-authz/authorization/#configuring-the-api-server-using-an-authorization-config-file). + +### Container resource based pod autoscaling ([KEP-1610](https://kep.k8s.io/1610)) + +Horizontal pod autoscaling based on `ContainerResource` metrics will graduate to stable in v1.30. +This new behavior for HorizontalPodAutoscaler allows you to configure automatic scaling based on the +resource usage for individual containers, rather than the aggregate resource use over a Pod. See our +[previous article](/blog/2023/05/02/hpa-container-resource-metric/) for further details, or read +[container resource metrics](/docs/tasks/run-application/horizontal-pod-autoscale/#container-resource-metrics). + +### CEL for admission control ([KEP-3488](https://kep.k8s.io/3488)) + +Integrating Common Expression Language (CEL) for admission control in Kubernetes introduces a more +dynamic and expressive way of evaluating admission requests. This feature allows complex, +fine-grained policies to be defined and enforced directly through the Kubernetes API, enhancing +security and governance capabilities without compromising performance or flexibility. + +CEL's addition to Kubernetes admission control empowers cluster administrators to craft intricate +rules that can evaluate the content of API requests against the desired state and policies of the +cluster without resorting to Webhook-based access controllers. This level of control is crucial for +maintaining the integrity, security, and efficiency of cluster operations, making Kubernetes +environments more robust and adaptable to various use cases and requirements. For more information +on using CEL for admission control, see the [API +documentation](/docs/reference/access-authn-authz/validating-admission-policy/) for +ValidatingAdmissionPolicy. + +We hope you're as excited for this release as we are. Keep an eye out for the official release +blog in a few weeks for more highlights! diff --git a/content/en/blog/_posts/2024-04-03-windows-ops-readiness.md b/content/en/blog/_posts/2024-04-03-windows-ops-readiness.md new file mode 100644 index 0000000000000..2ba0848198f91 --- /dev/null +++ b/content/en/blog/_posts/2024-04-03-windows-ops-readiness.md @@ -0,0 +1,157 @@ +--- +layout: blog +title: "Introducing the Windows Operational Readiness Specification" +date: 2024-04-03 +slug: intro-windows-ops-readiness +author: > + Jay Vyas (Tesla), + Amim Knabben (Broadcom), + Tatenda Zifudzi (AWS) +--- + +Since Windows support [graduated to stable](/blog/2019/03/25/kubernetes-1-14-release-announcement/) +with Kubernetes 1.14 in 2019, the capability to run Windows workloads has been much +appreciated by the end user community. The level of and availability of Windows workload +support has consistently been a major differentiator for Kubernetes distributions used by +large enterprises. However, with more Windows workloads being migrated to Kubernetes +and new Windows features being continuously released, it became challenging to test +Windows worker nodes in an effective and standardized way. + +The Kubernetes project values the ability to certify conformance without requiring a +closed-source license for a certified distribution or service that has no intention +of offering Windows. + +Some notable examples brought to the attention of SIG Windows were: + +- An issue with load balancer source address ranges functionality not operating correctly on + Windows nodes, detailed in a GitHub issue: + [kubernetes/kubernetes#120033](https://github.com/kubernetes/kubernetes/issues/120033). +- Reports of functionality issues with Windows features, such as + “[GMSA](https://learn.microsoft.com/en-us/windows-server/security/group-managed-service-accounts/group-managed-service-accounts-overview) not working with containerd, + discussed in [microsoft/Windows-Containers#44](https://github.com/microsoft/Windows-Containers/issues/44). +- Challenges developing networking policy tests that could objectively evaluate + Container Network Interface (CNI) plugins across different operating system configurations, + as discussed in [kubernetes/kubernetes#97751](https://github.com/kubernetes/kubernetes/issues/97751). + +SIG Windows therefore recognized the need for a tailored solution to ensure Windows +nodes' operational readiness *before* their deployment into production environments. +Thus, the idea to develop a [Windows Operational Readiness Specification](https://kep.k8s.io/2578) +was born. + +## Can’t we just run the official Conformance tests? + +The Kubernetes project contains a set of [conformance tests](https://www.cncf.io/training/certification/software-conformance/#how), +which are standardized tests designed to ensure that a Kubernetes cluster meets +the required Kubernetes specifications. + +However, these tests were originally defined at a time when Linux was the *only* +operating system compatible with Kubernetes, and thus, they were not easily +extendable for use with Windows. Given that Windows workloads, despite their +importance, account for a smaller portion of the Kubernetes community, it was +important to ensure that the primary conformance suite relied upon by many +Kubernetes distributions to certify Linux conformance, didn't become encumbered +with Windows specific features or enhancements such as GMSA or multi-operating +system kube-proxy behavior. + +Therefore, since there was a specialized need for Windows conformance testing, +SIG Windows went down the path of offering Windows specific conformance tests +through the Windows Operational Readiness Specification. + +## Can’t we just run the Kubernetes end-to-end test suite? + +In the Linux world, tools such as [Sonobuoy](https://sonobuoy.io/) simplify execution of the +conformance suite, relieving users from needing to be aware of Kubernetes' +compilation paths or the semantics of [Ginkgo](https://onsi.github.io/ginkgo) tags. + +Regarding needing to compile the Kubernetes tests, we realized that Windows +users might similarly find the process of compiling and running the Kubernetes +e2e suite from scratch similarly undesirable, hence, there was a clear need to +provide a user-friendly, "push-button" solution that is ready to go. Moreover, +regarding Ginkgo tags, applying conformance tests to Windows nodes through a set +of [Ginkgo](https://onsi.github.io/ginkgo/) tags would also be burdensome for +any user, including Linux enthusiasts or experienced Windows system admins alike. + +To bridge the gap and give users a straightforward way to confirm their clusters +support a variety of features, the Kubernetes SIG for Windows found it necessary to +therefore create the Windows Operational Readiness application. This application +written in Go, simplifies the process to run the necessary Windows specific tests +while delivering results in a clear, accessible format. + +This initiative has been a collaborative effort, with contributions from different +cloud providers and platforms, including Amazon, Microsoft, SUSE, and Broadcom. + +## A closer look at the Windows Operational Readiness Specification {#specification} + +The Windows Operational Readiness specification specifically targets and executes +tests found within the Kubernetes repository in a more user-friendly way than +simply targeting [Ginkgo](https://onsi.github.io/ginkgo/) tags. It introduces a +structured test suite that is split into sets of core and extended tests, with +each set of tests containing categories directed at testing a specific area of +testing, such as networking. Core tests target fundamental and critical +functionalities that Windows nodes should support as defined by the Kubernetes +specification. On the other hand, extended tests cover more complex features, +more aligned with diving deeper into Windows-specific capabilities such as +integrations with Active Directory. These goal of these tests is to be extensive, +covering a wide array of Windows-specific capabilities to ensure compatibility +with a diverse set of workloads and configurations, extending beyond basic +requirements. Below is the current list of categories. + +| Category Name | Category Description | +|--------------------------|-------------------------------------------------------------------------------------------------------------------------------------| +| `Core.Network` | Tests minimal networking functionality (ability to access pod-by-pod IP.) | +| `Core.Storage` | Tests minimal storage functionality, (ability to mount a hostPath storage volume.) | +| `Core.Scheduling` | Tests minimal scheduling functionality, (ability to schedule a pod with CPU limits.) | +| `Core.Concurrent` | Tests minimal concurrent functionality, (the ability of a node to handle traffic to multiple pods concurrently.) | +| `Extend.HostProcess` | Tests features related to Windows HostProcess pod functionality. | +| `Extend.ActiveDirectory` | Tests features related to Active Directory functionality. | +| `Extend.NetworkPolicy` | Tests features related to Network Policy functionality. | +| `Extend.Network` | Tests advanced networking functionality, (ability to support IPv6) | +| `Extend.Worker` | Tests features related to Windows worker node functionality, (ability for nodes to access TCP and UDP services in the same cluster) | + +## How to conduct operational readiness tests for Windows nodes + +To run the Windows Operational Readiness test suite, refer to the test suite's +[`README`](https://github.com/kubernetes-sigs/windows-operational-readiness/blob/main/README.md), which explains how to set it up and run it. The test suite offers +flexibility in how you can execute tests, either using a compiled binary or a +Sonobuoy plugin. You also have the choice to run the tests against the entire +test suite or by specifying a list of categories. Cloud providers have the +choice of uploading their conformance results, enhancing transparency and reliability. + +Once you have checked out that code, you can run a test. For example, this sample +command runs the tests from the `Core.Concurrent` category: + +```shell +./op-readiness --kubeconfig $KUBE_CONFIG --category Core.Concurrent +``` + +As a contributor to Kubernetes, if you want to test your changes against a specific pull +request using the Windows Operational Readiness Specification, use the following bot +command in the new pull request. + +```shell +/test operational-tests-capz-windows-2019 +``` + +## Looking ahead + +We’re looking to improve our curated list of Windows-specific tests by adding +new tests to the Kubernetes repository and also identifying existing test cases +that can be targetted. The long term goal for the specification is to continually +enhance test coverage for Windows worker nodes and improve the robustness of +Windows support, facilitating a seamless experience across diverse cloud +environments. We also have plans to integrate the Windows Operational Readiness +tests into the official Kubernetes conformance suite. + +If you are interested in helping us out, please reach out to us! We welcome help +in any form, from giving once-off feedback to making a code contribution, +to having long-term owners to help us drive changes. The Windows Operational +Readiness specification is owned by the SIG Windows team. You can reach out +to the team on the [Kubernetes Slack workspace](https://slack.k8s.io/) **#sig-windows** +channel. You can also explore the [Windows Operational Readiness test suite](https://github.com/kubernetes-sigs/windows-operational-readiness/#readme) +and make contributions directly to the GitHub repository. + +Special thanks to Kulwant Singh (AWS), Pramita Gautam Rana (VMWare), Xinqi Li +(Google) and Marcio Morales (AWS) for their help in making notable contributions to the specification. Additionally, +appreciation goes to James Sturtevant (Microsoft), Mark Rossetti (Microsoft), +Claudiu Belu (Cloudbase Solutions) and Aravindh Puthiyaparambil +(Softdrive Technologies Group Inc.) from the SIG Windows team for their guidance and support. \ No newline at end of file diff --git a/content/en/blog/_posts/2024-04-05-diy-create-your-own-cloud-with-kubernetes-part-1/asciicast.svg b/content/en/blog/_posts/2024-04-05-diy-create-your-own-cloud-with-kubernetes-part-1/asciicast.svg new file mode 100644 index 0000000000000..b129b1c102129 --- /dev/null +++ b/content/en/blog/_posts/2024-04-05-diy-create-your-own-cloud-with-kubernetes-part-1/asciicast.svg @@ -0,0 +1,497 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +talos-bootstrap + + +Installing...(portisopenat192.168.100.112) + + + + + + + + + + + + + + + + + +20% + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/content/en/blog/_posts/2024-04-05-diy-create-your-own-cloud-with-kubernetes-part-1/baremetal.svg b/content/en/blog/_posts/2024-04-05-diy-create-your-own-cloud-with-kubernetes-part-1/baremetal.svg new file mode 100644 index 0000000000000..08f964fe93e9a --- /dev/null +++ b/content/en/blog/_posts/2024-04-05-diy-create-your-own-cloud-with-kubernetes-part-1/baremetal.svg @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/content/en/blog/_posts/2024-04-05-diy-create-your-own-cloud-with-kubernetes-part-1/cloud.svg b/content/en/blog/_posts/2024-04-05-diy-create-your-own-cloud-with-kubernetes-part-1/cloud.svg new file mode 100644 index 0000000000000..1605c38061ffc --- /dev/null +++ b/content/en/blog/_posts/2024-04-05-diy-create-your-own-cloud-with-kubernetes-part-1/cloud.svg @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/content/en/blog/_posts/2024-04-05-diy-create-your-own-cloud-with-kubernetes-part-1/index.md b/content/en/blog/_posts/2024-04-05-diy-create-your-own-cloud-with-kubernetes-part-1/index.md new file mode 100644 index 0000000000000..dd4945eca4e82 --- /dev/null +++ b/content/en/blog/_posts/2024-04-05-diy-create-your-own-cloud-with-kubernetes-part-1/index.md @@ -0,0 +1,251 @@ +--- +layout: blog +title: "DIY: Create Your Own Cloud with Kubernetes (Part 1)" +slug: diy-create-your-own-cloud-with-kubernetes-part-1 +date: 2024-04-05T07:30:00+00:00 +author: > + Andrei Kvapil (Ænix) +--- + +At Ænix, we have a deep affection for Kubernetes and dream that all modern technologies will soon +start utilizing its remarkable patterns. + +Have you ever thought about building your own cloud? I bet you have. But is it possible to do this +using only modern technologies and approaches, without leaving the cozy Kubernetes ecosystem? +Our experience in developing Cozystack required us to delve deeply into it. + +You might argue that Kubernetes is not intended for this purpose and why not simply use OpenStack +for bare metal servers and run Kubernetes inside it as intended. But by doing so, you would simply + shift the responsibility from your hands to the hands of OpenStack administrators. + This would add at least one more huge and complex system to your ecosystem. + +Why complicate things? - after all, Kubernetes already has everything needed to run tenant +Kubernetes clusters at this point. + +I want to share with you our experience in developing a cloud platform based on Kubernetes, +highlighting the open-source projects that we use ourselves and believe deserve your attention. + +In this series of articles, I will tell you our story about how we prepare managed Kubernetes +from bare metal using only open-source technologies. Starting from the basic level of data +center preparation, running virtual machines, isolating networks, setting up fault-tolerant +storage to provisioning full-featured Kubernetes clusters with dynamic volume provisioning, +load balancers, and autoscaling. + +With this article, I start a series consisting of several parts: + +- **Part 1**: Preparing the groundwork for your cloud. Challenges faced during the preparation +and operation of Kubernetes on bare metal and a ready-made recipe for provisioning infrastructure. +- **Part 2**: Networking, storage, and virtualization. How to turn Kubernetes into a tool for +launching virtual machines and what is needed for this. +- **Part 3**: Cluster API and how to start provisioning Kubernetes clusters at the push of a +button. How autoscaling works, dynamic provisioning of volumes, and load balancers. + +I will try to describe various technologies as independently as possible, but at the same time, +I will share our experience and why we came to one solution or another. + +To begin with, let's understand the main advantage of Kubernetes and how it has changed the +approach to using cloud resources. + +It is important to understand that the use of Kubernetes in the cloud and on bare metal differs. + +## Kubernetes in the cloud + +When you operate Kubernetes in the cloud, you don't worry about persistent volumes, +cloud load balancers, or the process of provisioning nodes. All of this is handled by your cloud +provider, who accepts your requests in the form of Kubernetes objects. In other words, the server +side is completely hidden from you, and you don't really want to know how exactly the cloud +provider implements as it's not in your area of responsibility. + +{{< figure src="cloud.svg" alt="A diagram showing cloud Kubernetes, with load balancing and storage done outside the cluster" caption="A diagram showing cloud Kubernetes, with load balancing and storage done outside the cluster" >}} + +Kubernetes offers convenient abstractions that work the same everywhere, allowing you to deploy +your application on any Kubernetes in any cloud. + +In the cloud, you very commonly have several separate entities: the Kubernetes control plane, +virtual machines, persistent volumes, and load balancers as distinct entities. Using these entities, you can create highly dynamic environments. + +Thanks to Kubernetes, virtual machines are now only seen as a utility entity for utilizing +cloud resources. You no longer store data inside virtual machines. You can delete all your virtual +machines at any moment and recreate them without breaking your application. The Kubernetes control +plane will continue to hold information about what should run in your cluster. The load balancer +will keep sending traffic to your workload, simply changing the endpoint to send traffic to a new +node. And your data will be safely stored in external persistent volumes provided by cloud. + +This approach is fundamental when using Kubernetes in clouds. The reason for it is quite obvious: +the simpler the system, the more stable it is, and for this simplicity you go buying Kubernetes +in the cloud. + +## Kubernetes on bare metal + +Using Kubernetes in the clouds is really simple and convenient, which cannot be said about bare +metal installations. In the bare metal world, Kubernetes, on the contrary, becomes unbearably +complex. Firstly, because the entire network, backend storage, cloud balancers, etc. are usually +run not outside, but inside your cluster. As result such a system is much more difficult to +update and maintain. + +{{< figure src="baremetal.svg" alt="A diagram showing bare metal Kubernetes, with load balancing and storage done inside the cluster" caption="A diagram showing bare metal Kubernetes, with load balancing and storage done inside the cluster" >}} + + +Judge for yourself: in the cloud, to update a node, you typically delete the virtual machine +(or even use `kubectl delete node`) and you let your node management tooling create a new +one, based on an immutable image. The new node will join the cluster and ”just work” as a node; +following a very simple and commonly used pattern in the Kubernetes world. +Many clusters order new virtual machines every few minutes, simply because they can use +cheaper spot instances. However, when you have a physical server, you can't just delete and +recreate it, firstly because it often runs some cluster services, stores data, and its update process +is significantly more complicated. + +There are different approaches to solving this problem, ranging from in-place updates, as done by +kubeadm, kubespray, and k3s, to full automation of provisioning physical nodes through Cluster API +and Metal3. + +I like the hybrid approach offered by Talos Linux, where your entire system is described in a +single configuration file. Most parameters of this file can be applied without rebooting or +recreating the node, including the version of Kubernetes control-plane components. However, it +still keeps the maximum declarative nature of Kubernetes. +This approach minimizes unnecessary impact on cluster services when updating bare metal nodes. +In most cases, you won't need to migrate your virtual machines and rebuild the cluster filesystem +on minor updates. + +## Preparing a base for your future cloud + +So, suppose you've decided to build your own cloud. To start somewhere, you need a base layer. +You need to think not only about how you will install Kubernetes on your servers but also about how +you will update and maintain it. Consider the fact that you will have to think about things like +updating the kernel, installing necessary modules, as well packages and security patches. +Now you have to think much more that you don't have to worry about when using a ready-made +Kubernetes in the cloud. + +Of course you can use standard distributions like Ubuntu or Debian, or you can consider specialized +ones like Flatcar Container Linux, Fedora Core, and Talos Linux. Each has its advantages and +disadvantages. + +What about us? At Ænix, we use quite a few specific kernel modules like ZFS, DRBD, and OpenvSwitch, +so we decided to go the route of forming a system image with all the necessary modules in advance. +In this case, Talos Linux turned out to be the most convenient for us. +For example, such a config is enough to build a system image with all the necessary kernel modules: + +```yaml +arch: amd64 +platform: metal +secureboot: false +version: v1.6.4 +input: + kernel: + path: /usr/install/amd64/vmlinuz + initramfs: + path: /usr/install/amd64/initramfs.xz + baseInstaller: + imageRef: ghcr.io/siderolabs/installer:v1.6.4 + systemExtensions: + - imageRef: ghcr.io/siderolabs/amd-ucode:20240115 + - imageRef: ghcr.io/siderolabs/amdgpu-firmware:20240115 + - imageRef: ghcr.io/siderolabs/bnx2-bnx2x:20240115 + - imageRef: ghcr.io/siderolabs/i915-ucode:20240115 + - imageRef: ghcr.io/siderolabs/intel-ice-firmware:20240115 + - imageRef: ghcr.io/siderolabs/intel-ucode:20231114 + - imageRef: ghcr.io/siderolabs/qlogic-firmware:20240115 + - imageRef: ghcr.io/siderolabs/drbd:9.2.6-v1.6.4 + - imageRef: ghcr.io/siderolabs/zfs:2.1.14-v1.6.4 +output: + kind: installer + outFormat: raw +``` + +Then we use the `docker` command line tool to build an OS image: + +``` +cat config.yaml | docker run --rm -i -v /dev:/dev --privileged "ghcr.io/siderolabs/imager:v1.6.4" - +``` + +And as a result, we get a Docker container image with everything we need, which we can use to +install Talos Linux on our servers. You can do the same; this image will contain all the necessary +firmware and kernel modules. + +But the question arises, how do you deliver the freshly formed image to your nodes? + +I have been contemplating the idea of PXE booting for quite some time. For example, the +**Kubefarm** project that I wrote an +[article](/blog/2021/12/22/kubernetes-in-kubernetes-and-pxe-bootable-server-farm/) about +two years ago was entirely built using this approach. But unfortunately, it does help you to +deploy your very first parent cluster that will hold the others. So now you have prepared a +solution that will help you do this the same using PXE approach. + +Essentially, all you need to do is [run temporary](https://cozystack.io/docs/get-started/) +**DHCP** and **PXE** servers inside containers. Then your nodes will boot from your +image, and you can use a simple Debian-flavored script to help you bootstrap your nodes. + +[![asciicast](asciicast.svg)](https://asciinema.org/a/627123) + +The [source](https://github.com/aenix-io/talos-bootstrap/) for that `talos-bootstrap` script is +available on GitHub. + +This script allows you to deploy Kubernetes on bare metal in five minutes and obtain a kubeconfig +for accessing it. However, many unresolved issues still lie ahead. + +## Delivering system components + +At this stage, you already have a Kubernetes cluster capable of running various workloads. However, +it is not fully functional yet. In other words, you need to set up networking and storage, as well +as install necessary cluster extensions, like KubeVirt to run virtual machines, as well the +monitoring stack and other system-wide components. + +Traditionally, this is solved by installing **Helm charts** into your cluster. You can do this by +running `helm install` commands locally, but this approach becomes inconvenient when you want to +track updates, and if you have multiple clusters and you want to keep them uniform. In fact, there +are plenty of ways to do this declaratively. To solve this, I recommend using best GitOps practices. +I mean tools like ArgoCD and FluxCD. + +While ArgoCD is more convenient for dev purposes with its graphical interface and a central control +plane, FluxCD, on the other hand, is better suited for creating Kubernetes distributions. With FluxCD, +you can specify which charts with what parameters should be launched and describe dependencies. Then, +FluxCD will take care of everything for you. + +It is suggested to perform a one-time installation of FluxCD in your newly created cluster and +provide it with the configuration. This will install everything necessary, bringing the cluster +to the expected state. + +By carrying out a single installation of FluxCD in your newly minted cluster and configuring it +accordingly, you enable it to automatically deploy all the essentials. This will allow your cluster +to upgrade itself into the desired state. For example, after installing our platform you'll see the +next pre-configured Helm charts with system components: + +``` +NAMESPACE NAME AGE READY STATUS +cozy-cert-manager cert-manager 4m1s True Release reconciliation succeeded +cozy-cert-manager cert-manager-issuers 4m1s True Release reconciliation succeeded +cozy-cilium cilium 4m1s True Release reconciliation succeeded +cozy-cluster-api capi-operator 4m1s True Release reconciliation succeeded +cozy-cluster-api capi-providers 4m1s True Release reconciliation succeeded +cozy-dashboard dashboard 4m1s True Release reconciliation succeeded +cozy-fluxcd cozy-fluxcd 4m1s True Release reconciliation succeeded +cozy-grafana-operator grafana-operator 4m1s True Release reconciliation succeeded +cozy-kamaji kamaji 4m1s True Release reconciliation succeeded +cozy-kubeovn kubeovn 4m1s True Release reconciliation succeeded +cozy-kubevirt-cdi kubevirt-cdi 4m1s True Release reconciliation succeeded +cozy-kubevirt-cdi kubevirt-cdi-operator 4m1s True Release reconciliation succeeded +cozy-kubevirt kubevirt 4m1s True Release reconciliation succeeded +cozy-kubevirt kubevirt-operator 4m1s True Release reconciliation succeeded +cozy-linstor linstor 4m1s True Release reconciliation succeeded +cozy-linstor piraeus-operator 4m1s True Release reconciliation succeeded +cozy-mariadb-operator mariadb-operator 4m1s True Release reconciliation succeeded +cozy-metallb metallb 4m1s True Release reconciliation succeeded +cozy-monitoring monitoring 4m1s True Release reconciliation succeeded +cozy-postgres-operator postgres-operator 4m1s True Release reconciliation succeeded +cozy-rabbitmq-operator rabbitmq-operator 4m1s True Release reconciliation succeeded +cozy-redis-operator redis-operator 4m1s True Release reconciliation succeeded +cozy-telepresence telepresence 4m1s True Release reconciliation succeeded +cozy-victoria-metrics-operator victoria-metrics-operator 4m1s True Release reconciliation succeeded +``` + +## Conclusion + +As a result, you achieve a highly repeatable environment that you can provide to anyone, knowing +that it operates exactly as intended. +This is actually what the [Cozystack](https://github.com/aenix-io/cozystack) project does, which +you can try out for yourself absolutely free. + +In the following articles, I will discuss +[how to prepare Kubernetes for running virtual machines](/blog/2024/04/05/diy-create-your-own-cloud-with-kubernetes-part-2/) +and [how to run Kubernetes clusters with the click of a button](/blog/2024/04/05/diy-create-your-own-cloud-with-kubernetes-part-3/). +Stay tuned, it'll be fun! diff --git a/content/en/blog/_posts/2024-04-05-diy-create-your-own-cloud-with-kubernetes-part-2/index.md b/content/en/blog/_posts/2024-04-05-diy-create-your-own-cloud-with-kubernetes-part-2/index.md new file mode 100644 index 0000000000000..2126f0e255ad1 --- /dev/null +++ b/content/en/blog/_posts/2024-04-05-diy-create-your-own-cloud-with-kubernetes-part-2/index.md @@ -0,0 +1,260 @@ +--- +layout: blog +title: "DIY: Create Your Own Cloud with Kubernetes (Part 2)" +slug: diy-create-your-own-cloud-with-kubernetes-part-2 +date: 2024-04-05T07:35:00+00:00 +author: > + Andrei Kvapil (Ænix) +--- + +Continuing our series of posts on how to build your own cloud using just the Kubernetes ecosystem. +In the [previous article](/blog/2024/04/05/diy-create-your-own-cloud-with-kubernetes-part-1/), we +explained how we prepare a basic Kubernetes distribution based on Talos Linux and Flux CD. +In this article, we'll show you a few various virtualization technologies in Kubernetes and prepare +everything need to run virtual machines in Kubernetes, primarily storage and networking. + +We will talk about technologies such as KubeVirt, LINSTOR, and Kube-OVN. + +But first, let's explain what virtual machines are needed for, and why can't you just use docker +containers for building cloud? +The reason is that containers do not provide a sufficient level of isolation. +Although the situation improves year by year, we often encounter vulnerabilities that allow +escaping the container sandbox and elevating privileges in the system. + +On the other hand, Kubernetes was not originally designed to be a multi-tenant system, meaning +the basic usage pattern involves creating a separate Kubernetes cluster for every independent +project and development team. + +Virtual machines are the primary means of isolating tenants from each other in a cloud environment. +In virtual machines, users can execute code and programs with administrative privilege, but this +doesn't affect other tenants or the environment itself. In other words, virtual machines allow to +achieve [hard multi-tenancy isolation](/docs/concepts/security/multi-tenancy/#isolation), and run +in environments where tenants do not trust each other. + +## Virtualization technologies in Kubernetes + +There are several different technologies that bring virtualization into the Kubernetes world: +[KubeVirt](https://kubevirt.io/) and [Kata Containers](https://katacontainers.io/) +are the most popular ones. But you should know that they work differently. + +**Kata Containers** implements the CRI (Container Runtime Interface) and provides an additional +level of isolation for standard containers by running them in virtual machines. +But they work in a same single Kubernetes-cluster. + +{{< figure src="kata-containers.svg" caption="A diagram showing how container isolation is ensured by running containers in virtual machines with Kata Containers" alt="A diagram showing how container isolation is ensured by running containers in virtual machines with Kata Containers" >}} + +**KubeVirt** allows running traditional virtual machines using the Kubernetes API. KubeVirt virtual +machines are run as regular linux processes in containers. In other words, in KubeVirt, a container +is used as a sandbox for running virtual machine (QEMU) processes. +This can be clearly seen in the figure below, by looking at how live migration of virtual machines +is implemented in KubeVirt. When migration is needed, the virtual machine moves from one container +to another. + +{{< figure src="kubevirt-migration.svg" caption="A diagram showing live migration of a virtual machine from one container to another in KubeVirt" alt="A diagram showing live migration of a virtual machine from one container to another in KubeVirt" >}} + +There is also an alternative project - [Virtink](https://github.com/smartxworks/virtink), which +implements lightweight virtualization using +[Cloud-Hypervisor](https://github.com/cloud-hypervisor/cloud-hypervisor) and is initially focused +on running virtual Kubernetes clusters using the Cluster API. + +Considering our goals, we decided to use KubeVirt as the most popular project in this area. +Besides we have extensive expertise and already made a lot of contributions to KubeVirt. + +KubeVirt is [easy to install](https://kubevirt.io/user-guide/operations/installation/) and allows +you to run virtual machines out-of-the-box using +[containerDisk](https://kubevirt.io/user-guide/virtual_machines/disks_and_volumes/#containerdisk) +feature - this allows you to store and distribute VM images directly as OCI images from container +image registry. +Virtual machines with containerDisk are well suited for creating Kubernetes worker nodes and other +VMs that do not require state persistence. + +For managing persistent data, KubeVirt offers a separate tool, Containerized Data Importer (CDI). +It allows for cloning PVCs and populating them with data from base images. The CDI is necessary +if you want to automatically provision persistent volumes for your virtual machines, and it is + also required for the KubeVirt CSI Driver, which is used to handle persistent volumes claims + from tenant Kubernetes clusters. + +But at first, you have to decide where and how you will store these data. + +## Storage for Kubernetes VMs + +With the introduction of the CSI (Container Storage Interface), a wide range of technologies that +integrate with Kubernetes has become available. +In fact, KubeVirt fully utilizes the CSI interface, aligning the choice of storage for +virtualization closely with the choice of storage for Kubernetes itself. +However, there are nuances, which you need to consider. Unlike containers, which typically use a +standard filesystem, block devices are more efficient for virtual machine. + +Although the CSI interface in Kubernetes allows the request of both types of volumes: filesystems +and block devices, it's important to verify that your storage backend supports this. + +Using block devices for virtual machines eliminates the need for an additional abstraction layer, +such as a filesystem, that makes it more performant and in most cases enables the use of the +_ReadWriteMany_ mode. This mode allows concurrent access to the volume from multiple nodes, which +is a critical feature for enabling the live migration of virtual machines in KubeVirt. + +The storage system can be external or internal (in the case of hyper-converged infrastructure). +Using external storage in many cases makes the whole system more stable, as your data is stored +separately from compute nodes. + +{{< figure src="storage-external.svg" caption="A diagram showing external data storage communication with the compute nodes" alt="A diagram showing external data storage communication with the compute nodes" >}} + +External storage solutions are often popular in enterprise systems because such storage is +frequently provided by an external vendor, that takes care of its operations. The integration with +Kubernetes involves only a small component installed in the cluster - the CSI driver. This driver +is responsible for provisioning volumes in this storage and attaching them to pods run by Kubernetes. +However, such storage solutions can also be implemented using purely open-source technologies. +One of the popular solutions is [TrueNAS](https://www.truenas.com/) powered by +[democratic-csi](https://github.com/democratic-csi/democratic-csi) driver. + +{{< figure src="storage-local.svg" caption="A diagram showing local data storage running on the compute nodes" alt="A diagram showing local data storage running on the compute nodes" >}} + +On the other hand, hyper-converged systems are often implemented using local storage (when you do +not need replication) and with software-defined storages, often installed directly in Kubernetes, +such as [Rook/Ceph](https://rook.io/), [OpenEBS](https://openebs.io/), +[Longhorn](https://longhorn.io/), [LINSTOR](https://linbit.com/linstor/), and others. + +{{< figure src="storage-clustered.svg" caption="A diagram showing clustered data storage running on the compute nodes" alt="A diagram showing clustered data storage running on the compute nodes" >}} + +A hyper-converged system has its advantages. For example, data locality: when your data is stored +locally, access to such data is faster. But there are disadvantages as such a system is usually +more difficult to manage and maintain. + +At Ænix, we wanted to provide a ready-to-use solution that could be used without the need to +purchase and setup an additional external storage, and that was optimal in terms of speed and +resource utilization. LINSTOR became that solution. +The time-tested and industry-popular technologies such as LVM and ZFS as backend gives confidence +that data is securely stored. DRBD-based replication is incredible fast and consumes a small amount +of computing resources. + +For installing LINSTOR in Kubernetes, there is the Piraeus project, which already provides a +ready-made block storage to use with KubeVirt. + +{{< note >}} +In case you are using Talos Linux, as we described in the +[previous article](/blog/2024/04/05/diy-create-your-own-cloud-with-kubernetes-part-1/), you will +need to enable the necessary kernel modules in advance, and configure piraeus as described in the +[instruction](https://github.com/piraeusdatastore/piraeus-operator/blob/v2/docs/how-to/talos.md). +{{< /note >}} + +## Networking for Kubernetes VMs + +Despite having the similar interface - CNI, The network architecture in Kubernetes is actually more +complex and typically consists of many independent components that are not directly connected to +each other. In fact, you can split Kubernetes networking into four layers, which are described below. + +### Node Network (Data Center Network) + +The network through which nodes are interconnected with each other. This network is usually not +managed by Kubernetes, but it is an important one because, without it, nothing would work. +In practice, the bare metal infrastructure usually has more than one of such networks e.g. +one for node-to-node communication, second for storage replication, third for external access, etc. + +{{< figure src="net-nodes.svg" caption="A diagram showing the role of the node network (data center network) on the Kubernetes networking scheme" alt="A diagram showing the role of the node network (data center network) on the Kubernetes networking scheme" >}} + +Configuring the physical network interaction between nodes goes beyond the scope of this article, +as in most situations, Kubernetes utilizes already existing network infrastructure. + +### Pod Network + +This is the network provided by your CNI plugin. The task of the CNI plugin is to ensure transparent +connectivity between all containers and nodes in the cluster. Most CNI plugins implement a flat +network from which separate blocks of IP addresses are allocated for use on each node. + +{{< figure src="net-pods.svg" caption="A diagram showing the role of the pod network (CNI-plugin) on the Kubernetes network scheme" alt="A diagram showing the role of the pod network (CNI-plugin) on the Kubernetes network scheme" >}} + +In practice, your cluster can have several CNI plugins managed by +[Multus](https://github.com/k8snetworkplumbingwg/multus-cni). This approach is often used in +virtualization solutions based on KubeVirt - [Rancher](https://www.rancher.com/) and +[OpenShift](https://www.redhat.com/en/technologies/cloud-computing/openshift/virtualization). +The primary CNI plugin is used for integration with Kubernetes services, while additional CNI +plugins are used to implement private networks (VPC) and integration with the physical networks +of your data center. + +The [default CNI-plugins](https://github.com/containernetworking/plugins/tree/main/plugins) can +be used to connect bridges or physical interfaces. Additionally, there are specialized plugins +such as [macvtap-cni](https://github.com/kubevirt/macvtap-cni) which are designed to provide +more performance. + +One additional aspect to keep in mind when running virtual machines in Kubernetes is the need for +IPAM (IP Address Management), especially for secondary interfaces provided by Multus. This is +commonly managed by a DHCP server operating within your infrastructure. Additionally, the allocation +of MAC addresses for virtual machines can be managed by +[Kubemacpool](https://github.com/k8snetworkplumbingwg/kubemacpool). + +Although in our platform, we decided to go another way and fully rely on +[Kube-OVN](https://www.kube-ovn.io/). This CNI plugin is based on OVN (Open Virtual Network) which +was originally developed for OpenStack and it provides a complete network solution for virtual +machines in Kubernetes, features Custom Resources for managing IPs and MAC addresses, supports +live migration with preserving IP addresses between the nodes, and enables the creation of VPCs +for physical network separation between tenants. + +In Kube-OVN you can assign separate subnets to an entire namespace or connect them as additional +network interfaces using Multus. + +### Services Network + +In addition to the CNI plugin, Kubernetes also has a services network, which is primarily needed +for service discovery. +Contrary to traditional virtual machines, Kubernetes is originally designed to run pods with a +random address. +And the services network provides a convenient abstraction (stable IP addresses and DNS names) +that will always direct traffic to the correct pod. +The same approach is also commonly used with virtual machines in clouds despite the fact that +their IPs are usually static. + +{{< figure src="net-services.svg" caption="A diagram showing the role of the services network (services network plugin) on the Kubernetes network scheme" alt="A diagram showing the role of the services network (services network plugin) on the Kubernetes network scheme" >}} + + +The implementation of the services network in Kubernetes is handled by the services network plugin, +The standard implementation is called **kube-proxy** and is used in most clusters. +But nowadays, this functionality might be provided as part of the CNI plugin. The most advanced +implementation is offered by the [Cilium](https://cilium.io/) project, which can be run in kube-proxy replacement mode. + +Cilium is based on the eBPF technology, which allows for efficient offloading of the Linux +networking stack, thereby improving performance and security compared to traditional methods based +on iptables. + +In practice, Cilium and Kube-OVN can be easily +[integrated](https://kube-ovn.readthedocs.io/zh-cn/stable/en/advance/with-cilium/) to provide a +unified solution that offers seamless, multi-tenant networking for virtual machines, as well as +advanced network policies and combined services network functionality. + +### External Traffic Load Balancer + +At this stage, you already have everything needed to run virtual machines in Kubernetes. +But there is actually one more thing. +You still need to access your services from outside your cluster, and an external load balancer +will help you with organizing this. + +For bare metal Kubernetes clusters, there are several load balancers available: +[MetalLB](https://metallb.universe.tf/), [kube-vip](https://kube-vip.io/), +[LoxiLB](https://www.loxilb.io/), also [Cilium](https://docs.cilium.io/en/latest/network/lb-ipam/) and +[Kube-OVN](https://kube-ovn.readthedocs.io/zh-cn/latest/en/guide/loadbalancer-service/) +provides built-in implementation. + +The role of a external load balancer is to provide a stable address available externally and direct +external traffic to the services network. +The services network plugin will direct it to your pods and virtual machines as usual. + +{{< figure src="net-loadbalancer.svg" caption="A diagram showing the role of the external load balancer on the Kubernetes network scheme" alt="The role of the external load balancer on the Kubernetes network scheme" >}} + +In most cases, setting up a load balancer on bare metal is achieved by creating floating IP address +on the nodes within the cluster, and announce it externally using ARP/NDP or BGP protocols. + +After exploring various options, we decided that MetalLB is the simplest and most reliable solution, +although we do not strictly enforce the use of only it. + +Another benefit is that in L2 mode, MetalLB speakers continuously check their neighbour's state by +sending preforming liveness checks using a memberlist protocol. +This enables failover that works independently of Kubernetes control-plane. + +## Conclusion + +This concludes our overview of virtualization, storage, and networking in Kubernetes. +The technologies mentioned here are available and already pre-configured on the +[Cozystack](https://github.com/aenix-io/cozystack) platform, where you can try them with no limitations. + +In the [next article](/blog/2024/04/05/diy-create-your-own-cloud-with-kubernetes-part-3/), +I'll detail how, on top of this, you can implement the provisioning of fully functional Kubernetes +clusters with just the click of a button. diff --git a/content/en/blog/_posts/2024-04-05-diy-create-your-own-cloud-with-kubernetes-part-2/kata-containers.svg b/content/en/blog/_posts/2024-04-05-diy-create-your-own-cloud-with-kubernetes-part-2/kata-containers.svg new file mode 100644 index 0000000000000..724cd4fadda3a --- /dev/null +++ b/content/en/blog/_posts/2024-04-05-diy-create-your-own-cloud-with-kubernetes-part-2/kata-containers.svg @@ -0,0 +1,281 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/content/en/blog/_posts/2024-04-05-diy-create-your-own-cloud-with-kubernetes-part-2/kubevirt-migration.svg b/content/en/blog/_posts/2024-04-05-diy-create-your-own-cloud-with-kubernetes-part-2/kubevirt-migration.svg new file mode 100644 index 0000000000000..06850aee09298 --- /dev/null +++ b/content/en/blog/_posts/2024-04-05-diy-create-your-own-cloud-with-kubernetes-part-2/kubevirt-migration.svg @@ -0,0 +1,172 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/content/en/blog/_posts/2024-04-05-diy-create-your-own-cloud-with-kubernetes-part-2/net-loadbalancer.svg b/content/en/blog/_posts/2024-04-05-diy-create-your-own-cloud-with-kubernetes-part-2/net-loadbalancer.svg new file mode 100644 index 0000000000000..05b2ff17d26e0 --- /dev/null +++ b/content/en/blog/_posts/2024-04-05-diy-create-your-own-cloud-with-kubernetes-part-2/net-loadbalancer.svg @@ -0,0 +1,136 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/content/en/blog/_posts/2024-04-05-diy-create-your-own-cloud-with-kubernetes-part-2/net-nodes.svg b/content/en/blog/_posts/2024-04-05-diy-create-your-own-cloud-with-kubernetes-part-2/net-nodes.svg new file mode 100644 index 0000000000000..6fefe611496e3 --- /dev/null +++ b/content/en/blog/_posts/2024-04-05-diy-create-your-own-cloud-with-kubernetes-part-2/net-nodes.svg @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/content/en/blog/_posts/2024-04-05-diy-create-your-own-cloud-with-kubernetes-part-2/net-pods.svg b/content/en/blog/_posts/2024-04-05-diy-create-your-own-cloud-with-kubernetes-part-2/net-pods.svg new file mode 100644 index 0000000000000..25c0bbf538fca --- /dev/null +++ b/content/en/blog/_posts/2024-04-05-diy-create-your-own-cloud-with-kubernetes-part-2/net-pods.svg @@ -0,0 +1,131 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/content/en/blog/_posts/2024-04-05-diy-create-your-own-cloud-with-kubernetes-part-2/net-services.svg b/content/en/blog/_posts/2024-04-05-diy-create-your-own-cloud-with-kubernetes-part-2/net-services.svg new file mode 100644 index 0000000000000..528cfe6d79868 --- /dev/null +++ b/content/en/blog/_posts/2024-04-05-diy-create-your-own-cloud-with-kubernetes-part-2/net-services.svg @@ -0,0 +1,133 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/content/en/blog/_posts/2024-04-05-diy-create-your-own-cloud-with-kubernetes-part-2/storage-clustered.svg b/content/en/blog/_posts/2024-04-05-diy-create-your-own-cloud-with-kubernetes-part-2/storage-clustered.svg new file mode 100644 index 0000000000000..1115e28197180 --- /dev/null +++ b/content/en/blog/_posts/2024-04-05-diy-create-your-own-cloud-with-kubernetes-part-2/storage-clustered.svg @@ -0,0 +1,213 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/content/en/blog/_posts/2024-04-05-diy-create-your-own-cloud-with-kubernetes-part-2/storage-external.svg b/content/en/blog/_posts/2024-04-05-diy-create-your-own-cloud-with-kubernetes-part-2/storage-external.svg new file mode 100644 index 0000000000000..5c97e8f01d5b7 --- /dev/null +++ b/content/en/blog/_posts/2024-04-05-diy-create-your-own-cloud-with-kubernetes-part-2/storage-external.svg @@ -0,0 +1,219 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/content/en/blog/_posts/2024-04-05-diy-create-your-own-cloud-with-kubernetes-part-2/storage-local.svg b/content/en/blog/_posts/2024-04-05-diy-create-your-own-cloud-with-kubernetes-part-2/storage-local.svg new file mode 100644 index 0000000000000..9fbbd13562f40 --- /dev/null +++ b/content/en/blog/_posts/2024-04-05-diy-create-your-own-cloud-with-kubernetes-part-2/storage-local.svg @@ -0,0 +1,309 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/content/en/blog/_posts/2024-04-05-diy-create-your-own-cloud-with-kubernetes-part-3/clusterapi1.svg b/content/en/blog/_posts/2024-04-05-diy-create-your-own-cloud-with-kubernetes-part-3/clusterapi1.svg new file mode 100644 index 0000000000000..7c5b792e18abc --- /dev/null +++ b/content/en/blog/_posts/2024-04-05-diy-create-your-own-cloud-with-kubernetes-part-3/clusterapi1.svg @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/content/en/blog/_posts/2024-04-05-diy-create-your-own-cloud-with-kubernetes-part-3/clusterapi2.svg b/content/en/blog/_posts/2024-04-05-diy-create-your-own-cloud-with-kubernetes-part-3/clusterapi2.svg new file mode 100644 index 0000000000000..51788885eb93b --- /dev/null +++ b/content/en/blog/_posts/2024-04-05-diy-create-your-own-cloud-with-kubernetes-part-3/clusterapi2.svg @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/content/en/blog/_posts/2024-04-05-diy-create-your-own-cloud-with-kubernetes-part-3/clusterapi3.svg b/content/en/blog/_posts/2024-04-05-diy-create-your-own-cloud-with-kubernetes-part-3/clusterapi3.svg new file mode 100644 index 0000000000000..87e99ec4ee933 --- /dev/null +++ b/content/en/blog/_posts/2024-04-05-diy-create-your-own-cloud-with-kubernetes-part-3/clusterapi3.svg @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/content/en/blog/_posts/2024-04-05-diy-create-your-own-cloud-with-kubernetes-part-3/components1.svg b/content/en/blog/_posts/2024-04-05-diy-create-your-own-cloud-with-kubernetes-part-3/components1.svg new file mode 100644 index 0000000000000..00715d84dd073 --- /dev/null +++ b/content/en/blog/_posts/2024-04-05-diy-create-your-own-cloud-with-kubernetes-part-3/components1.svg @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/content/en/blog/_posts/2024-04-05-diy-create-your-own-cloud-with-kubernetes-part-3/components2.svg b/content/en/blog/_posts/2024-04-05-diy-create-your-own-cloud-with-kubernetes-part-3/components2.svg new file mode 100644 index 0000000000000..3601d61a8192b --- /dev/null +++ b/content/en/blog/_posts/2024-04-05-diy-create-your-own-cloud-with-kubernetes-part-3/components2.svg @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/content/en/blog/_posts/2024-04-05-diy-create-your-own-cloud-with-kubernetes-part-3/components3.svg b/content/en/blog/_posts/2024-04-05-diy-create-your-own-cloud-with-kubernetes-part-3/components3.svg new file mode 100644 index 0000000000000..74a85975064ae --- /dev/null +++ b/content/en/blog/_posts/2024-04-05-diy-create-your-own-cloud-with-kubernetes-part-3/components3.svg @@ -0,0 +1,97 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/content/en/blog/_posts/2024-04-05-diy-create-your-own-cloud-with-kubernetes-part-3/components4.svg b/content/en/blog/_posts/2024-04-05-diy-create-your-own-cloud-with-kubernetes-part-3/components4.svg new file mode 100644 index 0000000000000..d19f79408f428 --- /dev/null +++ b/content/en/blog/_posts/2024-04-05-diy-create-your-own-cloud-with-kubernetes-part-3/components4.svg @@ -0,0 +1,66 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/content/en/blog/_posts/2024-04-05-diy-create-your-own-cloud-with-kubernetes-part-3/fluxcd.svg b/content/en/blog/_posts/2024-04-05-diy-create-your-own-cloud-with-kubernetes-part-3/fluxcd.svg new file mode 100644 index 0000000000000..039b1e9cb0839 --- /dev/null +++ b/content/en/blog/_posts/2024-04-05-diy-create-your-own-cloud-with-kubernetes-part-3/fluxcd.svg @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/content/en/blog/_posts/2024-04-05-diy-create-your-own-cloud-with-kubernetes-part-3/index.md b/content/en/blog/_posts/2024-04-05-diy-create-your-own-cloud-with-kubernetes-part-3/index.md new file mode 100644 index 0000000000000..4426557299728 --- /dev/null +++ b/content/en/blog/_posts/2024-04-05-diy-create-your-own-cloud-with-kubernetes-part-3/index.md @@ -0,0 +1,267 @@ +--- +layout: blog +title: "DIY: Create Your Own Cloud with Kubernetes (Part 3)" +slug: diy-create-your-own-cloud-with-kubernetes-part-3 +date: 2024-04-05T07:40:00+00:00 +author: > + Andrei Kvapil (Ænix) +--- + +Approaching the most interesting phase, this article delves into running Kubernetes within +Kubernetes. Technologies such as Kamaji and Cluster API are highlighted, along with their +integration with KubeVirt. + +Previous discussions have covered +[preparing Kubernetes on bare metal](/blog/2024/04/05/diy-create-your-own-cloud-with-kubernetes-part-1/) +and +[how to turn Kubernetes into virtual machines management system](/blog/2024/04/05/diy-create-your-own-cloud-with-kubernetes-part-2). +This article concludes the series by explaining how, using all of the above, you can build a +full-fledged managed Kubernetes and run virtual Kubernetes clusters with just a click. + +First up, let's dive into the Cluster API. + +## Cluster API + +Cluster API is an extension for Kubernetes that allows the management of Kubernetes clusters as +custom resources within another Kubernetes cluster. + +The main goal of the Cluster API is to provide a unified interface for describing the basic +entities of a Kubernetes cluster and managing their lifecycle. This enables the automation of +processes for creating, updating, and deleting clusters, simplifying scaling, and infrastructure +management. + +Within the context of Cluster API, there are two terms: **management cluster** and +**tenant clusters**. + +- **Management cluster** is a Kubernetes cluster used to deploy and manage other clusters. +This cluster contains all the necessary Cluster API components and is responsible for describing, +creating, and updating tenant clusters. It is often used just for this purpose. +- **Tenant clusters** are the user clusters or clusters deployed using the Cluster API. They are +created by describing the relevant resources in the management cluster. They are then used for +deploying applications and services by end-users. + +It's important to understand that physically, tenant clusters do not necessarily have to run on +the same infrastructure with the management cluster; more often, they are running elsewhere. + +{{< figure src="clusterapi1.svg" caption="A diagram showing interaction of management Kubernetes cluster and tenant Kubernetes clusters using Cluster API" alt="A diagram showing interaction of management Kubernetes cluster and tenant Kubernetes clusters using Cluster API" >}} + +For its operation, Cluster API utilizes the concept of _providers_ which are separate controllers +responsible for specific components of the cluster being created. Within Cluster API, there are +several types of providers. The major ones are: + + - **Infrastructure Provider**, which is responsible for providing the computing infrastructure, such as virtual machines or physical servers. + - **Control Plane Provider**, which provides the Kubernetes control plane, namely the components kube-apiserver, kube-scheduler, and kube-controller-manager. + - **Bootstrap Provider**, which is used for generating cloud-init configuration for the virtual machines and servers being created. + +To get started, you will need to install the Cluster API itself and one provider of each type. +You can find a complete list of supported providers in the project's +[documentation](https://cluster-api.sigs.k8s.io/reference/providers.html). + +For installation, you can use the `clusterctl` utility, or +[Cluster API Operator](https://github.com/kubernetes-sigs/cluster-api-operator) +as the more declarative method. + +## Choosing providers + +### Infrastructure provider + +To run Kubernetes clusters using KubeVirt, the +[KubeVirt Infrastructure Provider](https://github.com/kubernetes-sigs/cluster-api-provider-kubevirt) +must be installed. +It enables the deployment of virtual machines for worker nodes in the same management cluster, where +the Cluster API operates. + +### Control plane provider + +The [Kamaji](https://github.com/clastix/kamaji) project offers a ready solution for running the +Kubernetes control plane for tenant clusters as containers within the management cluster. +This approach has several significant advantages: + +- **Cost-effectiveness**: Running the control plane in containers avoids the use of separate control +plane nodes for each cluster, thereby significantly reducing infrastructure costs. +- **Stability**: Simplifying architecture by eliminating complex multi-layered deployment schemes. +Instead of sequentially launching a virtual machine and then installing etcd and Kubernetes components +inside it, there's a simple control plane that is deployed and run as a regular application inside +Kubernetes and managed by an operator. +- **Security**: The cluster's control plane is hidden from the end user, reducing the possibility +of its components being compromised, and also eliminates user access to the cluster's certificate +store. This approach to organizing a control plane invisible to the user is often used by cloud providers. + +### Bootstrap provider + +[Kubeadm](https://github.com/kubernetes-sigs/cluster-api/tree/main/bootstrap) as the Bootstrap +Provider - as the standard method for preparing clusters in Cluster API. This provider is developed +as part of the Cluster API itself. It requires only a prepared system image with kubelet and kubeadm +installed and allows generating configs in the cloud-init and ignition formats. + +It's worth noting that Talos Linux also supports provisioning via the Cluster API and +[has](https://github.com/siderolabs/cluster-api-bootstrap-provider-talos) +[providers](https://github.com/siderolabs/cluster-api-bootstrap-provider-talos) for this. +Although [previous articles](/blog/2024/04/05/diy-create-your-own-cloud-with-kubernetes-part-1/) +discussed using Talos Linux to set up a management cluster on bare-metal nodes, to provision tenant +clusters the Kamaji+Kubeadm approach has more advantages. +It facilitates the deployment of Kubernetes control planes in containers, thus removing the need for +separate virtual machines for control plane instances. This simplifies the management and reduces costs. + +## How it works + +The primary object in Cluster API is the Cluster resource, which acts as the parent for all the others. +Typically, this resource references two others: a resource describing the **control plane** and a +resource describing the **infrastructure**, each managed by a separate provider. + +Unlike the Cluster, these two resources are not standardized, and their kind depends on the specific +provider you are using: + +{{< figure src="clusterapi2.svg" caption="A diagram showing the relationship of a Cluster resource and the resources it links to in Cluster API" alt="A diagram showing the relationship of a Cluster resource and the resources it links to in Cluster API" >}} + +Within Cluster API, there is also a resource named MachineDeployment, which describes a group of nodes, +whether they are physical servers or virtual machines. This resource functions similarly to standard +Kubernetes resources such as Deployment, ReplicaSet, and Pod, providing a mechanism for the +declarative description of a group of nodes and automatic scaling. + +In other words, the MachineDeployment resource allows you to declaratively describe nodes for your +cluster, automating their creation, deletion, and updating according to specified parameters and +the requested number of replicas. + +{{< figure src="machinedeploymentres.svg" caption="A diagram showing the relationship of a MachineDeployment resource and its children in Cluster API" alt="A diagram showing the relationship of a Cluster resource and its children in Cluster API" >}} + +To create machines, MachineDeployment refers to a template for generating the machine itself and a +template for generating its cloud-init config: + +{{< figure src="clusterapi3.svg" caption="A diagram showing the relationship of a MachineDeployment resource and the resources it links to in Cluster API" alt="A diagram showing the relationship of a Cluster resource and the resources it links to in Cluster API" >}} + +To deploy a new Kubernetes cluster using Cluster API, you will need to prepare the following set of resources: + +- A general Cluster resource +- A KamajiControlPlane resource, responsible for the control plane operated by Kamaji +- A KubevirtCluster resource, describing the cluster configuration in KubeVirt +- A KubevirtMachineTemplate resource, responsible for the virtual machine template +- A KubeadmConfigTemplate resource, responsible for generating tokens and cloud-init +- At least one MachineDeployment to create some workers + +## Polishing the cluster + +In most cases, this is sufficient, but depending on the providers used, you may need other resources +as well. You can find examples of the resources created for each type of provider in the +[Kamaji project documentation](https://github.com/clastix/cluster-api-control-plane-provider-kamaji?tab=readme-ov-file#-supported-capi-infrastructure-providers). + +At this stage, you already have a ready tenant Kubernetes cluster, but so far, it contains nothing +but API workers and a few core plugins that are standardly included in the installation of any +Kubernetes cluster: **kube-proxy** and **CoreDNS**. For full integration, you will need to install +several more components: + +To install additional components, you can use a separate +[Cluster API Add-on Provider for Helm](https://github.com/kubernetes-sigs/cluster-api-addon-provider-helm), +or the same [FluxCD](https://fluxcd.io/) discussed in +[previous articles](/blog/2024/04/05/diy-create-your-own-cloud-with-kubernetes-part-1/). + +When creating resources in FluxCD, it's possible to specify the target cluster by referring to the +kubeconfig generated by Cluster API. Then, the installation will be performed directly into it. +Thus, FluxCD becomes a universal tool for managing resources both in the management cluster and +in the user tenant clusters. + +{{< figure src="fluxcd.svg" caption="A diagram showing the interaction scheme of fluxcd, which can install components in both management and tenant Kubernetes clusters" alt="A diagram showing the interaction scheme of fluxcd, which can install components in both management and tenant Kubernetes clusters" >}} + +What components are being discussed here? Generally, the set includes the following: + +### CNI Plugin + +To ensure communication between pods in a tenant Kubernetes cluster, it's necessary to deploy a +CNI plugin. This plugin creates a virtual network that allows pods to interact with each other +and is traditionally deployed as a Daemonset on the cluster's worker nodes. You can choose and +install any CNI plugin that you find suitable. + +{{< figure src="components1.svg" caption="A diagram showing a CNI plugin installed inside the tenant Kubernetes cluster on a scheme of nested Kubernetes clusters" alt="A diagram showing a CNI plugin installed inside the tenant Kubernetes cluster on a scheme of nested Kubernetes clusters" >}} + +### Cloud Controller Manager + +The main task of the Cloud Controller Manager (CCM) is to integrate Kubernetes with the cloud +infrastructure provider's environment (in your case, it is the management Kubernetes cluster +in which all worksers of tenant Kubernetes are provisioned). Here are some tasks it performs: + +1. When a service of type LoadBalancer is created, the CCM initiates the process of creating a cloud load balancer, which directs traffic to your Kubernetes cluster. +1. If a node is removed from the cloud infrastructure, the CCM ensures its removal from your cluster as well, maintaining the cluster's current state. +1. When using the CCM, nodes are added to the cluster with a special taint, `node.cloudprovider.kubernetes.io/uninitialized`, + which allows for the processing of additional business logic if necessary. After successful initialization, this taint is removed from the node. + +Depending on the cloud provider, the CCM can operate both inside and outside the tenant cluster. + +[The KubeVirt Cloud Provider](https://github.com/kubevirt/cloud-provider-kubevirt) is designed +to be installed in the external parent management cluster. Thus, creating services of type +LoadBalancer in the tenant cluster initiates the creation of LoadBalancer services in the parent +cluster, which direct traffic into the tenant cluster. + +{{< figure src="components2.svg" caption="A diagram showing a Cloud Controller Manager installed outside of a tenant Kubernetes cluster on a scheme of nested Kubernetes clusters and the mapping of services it manages from the parent to the child Kubernetes cluster" alt="A diagram showing a Cloud Controller Manager installed outside of a tenant Kubernetes cluster on a scheme of nested Kubernetes clusters and the mapping of services it manages from the parent to the child Kubernetes cluster" >}} + +### CSI Driver + +The Container Storage Interface (CSI) is divided into two main parts for interacting with storage +in Kubernetes: + +- **csi-controller**: This component is responsible for interacting with the cloud provider's API +to create, delete, attach, detach, and resize volumes. +- **csi-node**: This component runs on each node and facilitates the mounting of volumes to pods +as requested by kubelet. + +In the context of using the [KubeVirt CSI Driver](https://github.com/kubevirt/csi-driver), a unique +opportunity arises. Since virtual machines in KubeVirt runs within the management Kubernetes cluster, +where a full-fledged Kubernetes API is available, this opens the path for running the csi-controller +outside of the user's tenant cluster. This approach is popular in the KubeVirt community and offers +several key advantages: + +- **Security**: This method hides the internal cloud API from the end-user, providing access to +resources exclusively through the Kubernetes interface. Thus, it reduces the risk of direct access +to the management cluster from user clusters. +- **Simplicity and Convenience**: Users don't need to manage additional controllers in their clusters, +simplifying the architecture and reducing the management burden. + +However, the CSI-node must necessarily run inside the tenant cluster, as it directly interacts with +kubelet on each node. This component is responsible for the mounting and unmounting of volumes into pods, +requiring close integration with processes occurring directly on the cluster nodes. + +The KubeVirt CSI Driver acts as a proxy for ordering volumes. When a PVC is created inside the tenant +cluster, a PVC is created in the management cluster, and then the created PV is connected to the +virtual machine. + +{{< figure src="components3.svg" caption="A diagram showing a CSI plugin components installed on both inside and outside of a tenant Kubernetes cluster on a scheme of nested Kubernetes clusters and the mapping of persistent volumes it manages from the parent to the child Kubernetes cluster" alt="A diagram showing a CSI plugin components installed on both inside and outside of a tenant Kubernetes cluster on a scheme of nested Kubernetes clusters and the mapping of persistent volumes it manages from the parent to the child Kubernetes cluster" >}} + +### Cluster Autoscaler + +The [Cluster Autoscaler](https://github.com/kubernetes/autoscaler) is a versatile component that +can work with various cloud APIs, and its integration with Cluster-API is just one of the available +functions. For proper configuration, it requires access to two clusters: the tenant cluster, to +track pods and determine the need for adding new nodes, and the managing Kubernetes cluster +(management kubernetes cluster), where it interacts with the MachineDeployment resource and adjusts +the number of replicas. + +Although Cluster Autoscaler usually runs inside the tenant Kubernetes cluster, in this situation, +it is suggested to install it outside for the same reasons described before. This approach is +simpler to maintain and more secure as it prevents users of tenant clusters from accessing the +management API of the management cluster. + +{{< figure src="components4.svg" caption="A diagram showing a Cluster Autoscaler installed outside of a tenant Kubernetes cluster on a scheme of nested Kubernetes clusters" alt="A diagram showing a Cloud Controller Manager installed outside of a tenant Kubernetes cluster on a scheme of nested Kubernetes clusters" >}} + +### Konnectivity + +There's another additional component I'd like to mention - +[Konnectivity](https://kubernetes.io/docs/tasks/extend-kubernetes/setup-konnectivity/). +You will likely need it later on to get webhooks and the API aggregation layer working in your +tenant Kubernetes cluster. This topic is covered in detail in one of my +[previous article](/blog/2021/12/22/kubernetes-in-kubernetes-and-pxe-bootable-server-farm/#webhooks-and-api-aggregation-layer). + +Unlike the components presented above, Kamaji allows you to easily enable Konnectivity and manage +it as one of the core components of your tenant cluster, alongside kube-proxy and CoreDNS. + +## Conclusion + +Now you have a fully functional Kubernetes cluster with the capability for dynamic scaling, automatic +provisioning of volumes, and load balancers. + +Going forward, you might consider metrics and logs collection from your tenant clusters, but that +goes beyond the scope of this article. + +Of course, all the components necessary for deploying a Kubernetes cluster can be packaged into a +single Helm chart and deployed as a unified application. This is precisely how we organize the +deployment of managed Kubernetes clusters with the click of a button on our open PaaS platform, +[Cozystack](https://cozystack.io/), where you can try all the technologies described in the article +for free. diff --git a/content/en/blog/_posts/2024-04-05-diy-create-your-own-cloud-with-kubernetes-part-3/machinedeploymentres.svg b/content/en/blog/_posts/2024-04-05-diy-create-your-own-cloud-with-kubernetes-part-3/machinedeploymentres.svg new file mode 100644 index 0000000000000..8adeee6e1a444 --- /dev/null +++ b/content/en/blog/_posts/2024-04-05-diy-create-your-own-cloud-with-kubernetes-part-3/machinedeploymentres.svg @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/content/en/blog/_posts/2024-04-11-SIG-Architecture-Code-Organization-Spotlight.md b/content/en/blog/_posts/2024-04-11-SIG-Architecture-Code-Organization-Spotlight.md new file mode 100644 index 0000000000000..8f9a9ca16d3c3 --- /dev/null +++ b/content/en/blog/_posts/2024-04-11-SIG-Architecture-Code-Organization-Spotlight.md @@ -0,0 +1,140 @@ +--- +layout: blog +title: "Spotlight on SIG Architecture: Code Organization" +slug: sig-architecture-code-spotlight-2024 +canonicalUrl: https://www.kubernetes.dev/blog/2024/04/11/sig-architecture-code-spotlight-2024 +date: 2024-04-11 +author: > + Frederico Muñoz (SAS Institute) +--- + +_This is the third interview of a SIG Architecture Spotlight series that will cover the different +subprojects. We will cover [SIG Architecture: Code Organization](https://github.com/kubernetes/community/blob/e44c2c9d0d3023e7111d8b01ac93d54c8624ee91/sig-architecture/README.md#code-organization)._ + +In this SIG Architecture spotlight I talked with [Madhav Jivrajani](https://github.com/MadhavJivrajani) +(VMware), a member of the Code Organization subproject. + +## Introducing the Code Organization subproject + +**Frederico (FSM)**: Hello Madhav, thank you for your availability. Could you start by telling us a +bit about yourself, your role and how you got involved in Kubernetes? + +**Madhav Jivrajani (MJ)**: Hello! My name is Madhav Jivrajani, I serve as a technical lead for SIG +Contributor Experience and a GitHub Admin for the Kubernetes project. Apart from that I also +contribute to SIG API Machinery and SIG Etcd, but more recently, I’ve been helping out with the work +that is needed to help Kubernetes [stay on supported versions of +Go](https://github.com/kubernetes/enhancements/tree/cf6ee34e37f00d838872d368ec66d7a0b40ee4e6/keps/sig-release/3744-stay-on-supported-go-versions), +and it is through this that I am involved with the Code Organization subproject of SIG Architecture. + +**FSM**: A project the size of Kubernetes must have unique challenges in terms of code organization +-- is this a fair assumption? If so, what would you pick as some of the main challenges that are +specific to Kubernetes? + +**MJ**: That’s a fair assumption! The first interesting challenge comes from the sheer size of the +Kubernetes codebase. We have ≅2.2 million lines of Go code (which is steadily decreasing thanks to +[dims](https://github.com/dims) and other folks in this sub-project!), and a little over 240 +dependencies that we rely on either directly or indirectly, which is why having a sub-project +dedicated to helping out with dependency management is crucial: we need to know what dependencies +we’re pulling in, what versions these dependencies are at, and tooling to help make sure we are +managing these dependencies across different parts of the codebase in a consistent manner. + +Another interesting challenge with Kubernetes is that we publish a lot of Go modules as part of the +Kubernetes release cycles, one example of this is +[`client-go`](https://github.com/kubernetes/client-go).However, we as a project would also like the +benefits of having everything in one repository to get the advantages of using a monorepo, like +atomic commits... so, because of this, code organization works with other SIGs (like SIG Release) to +automate the process of publishing code from the monorepo to downstream individual repositories +which are much easier to consume, and this way you won’t have to import the entire Kubernetes +codebase! + +## Code organization and Kubernetes + +**FSM**: For someone just starting contributing to Kubernetes code-wise, what are the main things +they should consider in terms of code organization? How would you sum up the key concepts? + +**MJ**: I think one of the key things to keep in mind at least as you’re starting off is the concept +of staging directories. In the [`kubernetes/kubernetes`](https://github.com/kubernetes/kubernetes) +repository, you will come across a directory called +[`staging/`](https://github.com/kubernetes/kubernetes/tree/master/staging). The sub-folders in this +directory serve as a bunch of pseudo-repositories. For example, the +[`kubernetes/client-go`](https://github.com/kubernetes/client-go) repository that publishes releases +for `client-go` is actually a [staging +repo](https://github.com/kubernetes/kubernetes/tree/master/staging/src/k8s.io/client-go). + +**FSM**: So the concept of staging directories fundamentally impact contributions? + +**MJ**: Precisely, because if you’d like to contribute to any of the staging repos, you will need to +send in a PR to its corresponding staging directory in `kubernetes/kubernetes`. Once the code merges +there, we have a bot called the [`publishing-bot`](https://github.com/kubernetes/publishing-bot) +that will sync the merged commits to the required staging repositories (like +`kubernetes/client-go`). This way we get the benefits of a monorepo but we also can modularly +publish code for downstream consumption. PS: The `publishing-bot` needs more folks to help out! + +For more information on staging repositories, please see the [contributor +documentation](https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/staging.md). + +**FSM**: Speaking of contributions, the very high number of contributors, both individuals and +companies, must also be a challenge: how does the subproject operate in terms of making sure that +standards are being followed? + +**MJ**: When it comes to dependency management in the project, there is a [dedicated +team](https://github.com/kubernetes/org/blob/a106af09b8c345c301d072bfb7106b309c0ad8e9/config/kubernetes/org.yaml#L1329) +that helps review and approve dependency changes. These are folks who have helped lay the foundation +of much of the +[tooling](https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/vendor.md) +that Kubernetes uses today for dependency management. This tooling helps ensure there is a +consistent way that contributors can make changes to dependencies. The project has also worked on +additional tooling to signal statistics of dependencies that is being added or removed: +[`depstat`](https://github.com/kubernetes-sigs/depstat) + +Apart from dependency management, another crucial task that the project does is management of the +staging repositories. The tooling for achieving this (`publishing-bot`) is completely transparent to +contributors and helps ensure that the staging repos get a consistent view of contributions that are +submitted to `kubernetes/kubernetes`. + +Code Organization also works towards making sure that Kubernetes [stays on supported versions of +Go](https://github.com/kubernetes/enhancements/tree/cf6ee34e37f00d838872d368ec66d7a0b40ee4e6/keps/sig-release/3744-stay-on-supported-go-versions). The +linked KEP provides more context on why we need to do this. We collaborate with SIG Release to +ensure that we are testing Kubernetes as rigorously and as early as we can on Go releases and +working on changes that break our CI as a part of this. An example of how we track this process can +be found [here](https://github.com/kubernetes/release/issues/3076). + +## Release cycle and current priorities + +**FSM**: Is there anything that changes during the release cycle? + +**MJ** During the release cycle, specifically before code freeze, there are often changes that go in +that add/update/delete dependencies, fix code that needs fixing as part of our effort to stay on +supported versions of Go. + +Furthermore, some of these changes are also candidates for +[backporting](https://github.com/kubernetes/community/blob/master/contributors/devel/sig-release/cherry-picks.md) +to our supported release branches. + +**FSM**: Is there any major project or theme the subproject is working on right now that you would +like to highlight? + +**MJ**: I think one very interesting and immensely useful change that +has been recently added (and I take the opportunity to specifically +highlight the work of [Tim Hockin](https://github.com/thockin) on +this) is the introduction of [Go workspaces to the Kubernetes +repo](https://www.kubernetes.dev/blog/2024/03/19/go-workspaces-in-kubernetes/). A lot of our +current tooling for dependency management and code publishing, as well +as the experience of editing code in the Kubernetes repo, can be +significantly improved by this change. + +## Wrapping up + +**FSM**: How would someone interested in the topic start helping the subproject? + +**MJ**: The first step, as is the first step with any project in Kubernetes, is to join our slack: +[slack.k8s.io](https://slack.k8s.io), and after that join the `#k8s-code-organization` channel. There is also a +[code-organization office +hours](https://github.com/kubernetes/community/tree/master/sig-architecture#meetings) that takes +place that you can choose to attend. Timezones are hard, so feel free to also look at the recordings +or meeting notes and follow up on slack! + +**FSM**: Excellent, thank you! Any final comments you would like to share? + +**MJ**: The Code Organization subproject always needs help! Especially areas like the publishing +bot, so don’t hesitate to get involved in the `#k8s-code-organization` Slack channel. diff --git a/content/en/blog/_posts/2024-04-17-kubernetes-1.30.md b/content/en/blog/_posts/2024-04-17-kubernetes-1.30.md new file mode 100644 index 0000000000000..9fa5f03fb12d2 --- /dev/null +++ b/content/en/blog/_posts/2024-04-17-kubernetes-1.30.md @@ -0,0 +1,408 @@ +--- +layout: blog +title: 'Kubernetes v1.30: Uwubernetes' +date: 2024-04-17 +slug: kubernetes-v1-30-release +author: > + [Kubernetes v1.30 Release Team](https://github.com/kubernetes/sig-release/blob/master/releases/release-1.30/release-team.md) +--- + + +**Editors:** Amit Dsouza, Frederick Kautz, Kristin Martin, Abigail McCarthy, Natali Vlatko + +Announcing the release of Kubernetes v1.30: Uwubernetes, the cutest release! + +Similar to previous releases, the release of Kubernetes v1.30 introduces new stable, beta, and alpha +features. The consistent delivery of top-notch releases underscores the strength of our development +cycle and the vibrant support from our community. + +This release consists of 45 enhancements. Of those enhancements, 17 have graduated to Stable, 18 are +entering Beta, and 10 have graduated to Alpha. + +## Release theme and logo + +Kubernetes v1.30: *Uwubernetes* + +{{< figure src="/images/blog/2024-04-17-kubernetes-1.30-release/k8s-1.30.png" alt="Kubernetes v1.30 Uwubernetes logo" class="release-logo" >}} + +Kubernetes v1.30 makes your clusters cuter! + +Kubernetes is built and released by thousands of people from all over the world and all walks of +life. Most contributors are not being paid to do this; we build it for fun, to solve a problem, to +learn something, or for the simple love of the community. Many of us found our homes, our friends, +and our careers here. The Release Team is honored to be a part of the continued growth of +Kubernetes. + +For the people who built it, for the people who release it, and for the furries who keep all of our +clusters online, we present to you Kubernetes v1.30: Uwubernetes, the cutest release to date. The +name is a portmanteau of “kubernetes” and “UwU,” an emoticon used to indicate happiness or cuteness. +We’ve found joy here, but we’ve also brought joy from our outside lives that helps to make this +community as weird and wonderful and welcoming as it is. We’re so happy to share our work with you. + +UwU ♥️ + +## Improvements that graduated to stable in Kubernetes v1.30 {#graduations-to-stable} + +_This is a selection of some of the improvements that are now stable following the v1.30 release._ + +### Robust VolumeManager reconstruction after kubelet restart ([SIG Storage](https://github.com/kubernetes/community/tree/master/sig-storage)) + +This is a volume manager refactoring that allows the kubelet to populate additional information +about how existing volumes are mounted during the kubelet startup. In general, this makes volume +cleanup after kubelet restart or machine reboot more robust. + +This does not bring any changes for user or cluster administrators. We used the feature process and +feature gate `NewVolumeManagerReconstruction` to be able to fall back to the previous behavior in +case something goes wrong. Now that the feature is stable, the feature gate is locked and cannot be +disabled. + +### Prevent unauthorized volume mode conversion during volume restore ([SIG Storage](https://github.com/kubernetes/community/tree/master/sig-storage)) + +For Kubernetes v1.30, the control plane always prevents unauthorized changes to volume modes when +restoring a snapshot into a PersistentVolume. As a cluster administrator, you'll need to grant +permissions to the appropriate identity principals (for example: ServiceAccounts representing a +storage integration) if you need to allow that kind of change at restore time. + +{{< warning >}} +Action required before upgrading. The `prevent-volume-mode-conversion` feature flag is enabled by +default in the external-provisioner `v4.0.0` and external-snapshotter `v7.0.0`. Volume mode change +will be rejected when creating a PVC from a VolumeSnapshot unless you perform the steps described in +the the "Urgent Upgrade Notes" sections for the [external-provisioner +4.0.0](https://github.com/kubernetes-csi/external-provisioner/releases/tag/v4.0.0) and the +[external-snapshotter +v7.0.0](https://github.com/kubernetes-csi/external-snapshotter/releases/tag/v7.0.0). +{{< /warning >}} + +For more information on this feature also read [converting the volume mode of a +Snapshot](/docs/concepts/storage/volume-snapshots/#convert-volume-mode). + + +### Pod Scheduling Readiness ([SIG Scheduling](https://github.com/kubernetes/community/tree/master/sig-scheduling)) + +_Pod scheduling readiness_ graduates to stable this release, after being promoted to beta in +Kubernetes v1.27. + +This now-stable feature lets Kubernetes avoid trying to schedule a Pod that has been defined, when +the cluster doesn't yet have the resources provisioned to allow actually binding that Pod to a node. +That's not the only use case; the custom control on whether a Pod can be allowed to schedule also +lets you implement quota mechanisms, security controls, and more. + +Crucially, marking these Pods as exempt from scheduling cuts the work that the scheduler would +otherwise do, churning through Pods that can't or won't schedule onto the nodes your cluster +currently has. If you have [cluster +autoscaling](/docs/concepts/cluster-administration/cluster-autoscaling/) active, using scheduling +gates doesn't just cut the load on the scheduler, it can also save money. Without scheduling gates, +the autoscaler might otherwise launch a node that doesn't need to be started. + +In Kubernetes v1.30, by specifying (or removing) a Pod's `.spec.schedulingGates`, you can control +when a Pod is ready to be considered for scheduling. This is a stable feature and is now formally +part of the Kubernetes API definition for Pod. + +### Min domains in PodTopologySpread ([SIG Scheduling](https://github.com/kubernetes/community/tree/master/sig-scheduling)) + +The `minDomains` parameter for PodTopologySpread constraints graduates to stable this release, which +allows you to define the minimum number of domains. This feature is designed to be used with Cluster +Autoscaler. + +If you previously attempted use and there weren't enough domains already present, Pods would be +marked as unschedulable. The Cluster Autoscaler would then provision node(s) in new domain(s), and +you'd eventually get Pods spreading over enough domains. + +### Go workspaces for k/k ([SIG Architecture](https://github.com/kubernetes/community/tree/master/sig-architecture)) + +The Kubernetes repo now uses Go workspaces. This should not impact end users at all, but does have a +impact for developers of downstream projects. Switching to workspaces caused some breaking changes +in the flags to the various [k8s.io/code-generator](https://github.com/kubernetes/code-generator) +tools. Downstream consumers should look at +[`staging/src/k8s.io/code-generator/kube_codegen.sh`](https://github.com/kubernetes/code-generator/blob/master/kube_codegen.sh) +to see the changes. + +For full details on the changes and reasons why Go workspaces was introduced, read [Using Go +workspaces in Kubernetes](https://www.kubernetes.dev/blog/2024/03/19/go-workspaces-in-kubernetes/). + +## Improvements that graduated to beta in Kubernetes v1.30 {#graduations-to-beta} + +_This is a selection of some of the improvements that are now beta following the v1.30 release._ + +### Node log query ([SIG Windows](https://github.com/kubernetes/community/tree/master/sig-windows)) + +To help with debugging issues on nodes, Kubernetes v1.27 introduced a feature that allows fetching +logs of services running on the node. To use the feature, ensure that the `NodeLogQuery` feature +gate is enabled for that node, and that the kubelet configuration options `enableSystemLogHandler` +and `enableSystemLogQuery` are both set to true. + +Following the v1.30 release, this is now beta (you still need to enable the feature to use it, +though). + +On Linux the assumption is that service logs are available via journald. On Windows the assumption +is that service logs are available in the application log provider. Logs are also available by +reading files within `/var/log/` (Linux) or `C:\var\log\` (Windows). For more information, see the +[log query](/docs/concepts/cluster-administration/system-logs/#log-query) documentation. + +### CRD validation ratcheting ([SIG API Machinery](https://github.com/kubernetes/community/tree/master/sig-api-machinery)) + +You need to enable the `CRDValidationRatcheting` [feature +gate](/docs/reference/command-line-tools-reference/feature-gates/) to use this behavior, which then +applies to all CustomResourceDefinitions in your cluster. + +Provided you enabled the feature gate, Kubernetes implements _validation racheting_ for +CustomResourceDefinitions. The API server is willing to accept updates to resources that are not valid +after the update, provided that each part of the resource that failed to validate was not changed by +the update operation. In other words, any invalid part of the resource that remains invalid must +have already been wrong. You cannot use this mechanism to update a valid resource so that it becomes +invalid. + +This feature allows authors of CRDs to confidently add new validations to the OpenAPIV3 schema under +certain conditions. Users can update to the new schema safely without bumping the version of the +object or breaking workflows. + +### Contextual logging ([SIG Instrumentation](https://github.com/kubernetes/community/tree/master/sig-instrumentation)) + +Contextual Logging advances to beta in this release, empowering developers and operators to inject +customizable, correlatable contextual details like service names and transaction IDs into logs +through `WithValues` and `WithName`. This enhancement simplifies the correlation and analysis of log +data across distributed systems, significantly improving the efficiency of troubleshooting efforts. +By offering a clearer insight into the workings of your Kubernetes environments, Contextual Logging +ensures that operational challenges are more manageable, marking a notable step forward in +Kubernetes observability. + +### Make Kubernetes aware of the LoadBalancer behaviour ([SIG Network](https://github.com/kubernetes/community/tree/master/sig-network)) + +The `LoadBalancerIPMode` feature gate is now beta and is now enabled by default. This feature allows +you to set the `.status.loadBalancer.ingress.ipMode` for a Service with `type` set to +`LoadBalancer`. The `.status.loadBalancer.ingress.ipMode` specifies how the load-balancer IP +behaves. It may be specified only when the `.status.loadBalancer.ingress.ip` field is also +specified. See more details about [specifying IPMode of load balancer +status](/docs/concepts/services-networking/service/#load-balancer-ip-mode). + +### Structured Authentication Configuration ([SIG Auth](https://github.com/kubernetes/community/tree/master/sig-auth)) + +_Structured Authentication Configuration_ graduates to beta in this release. + +Kubernetes has had a long-standing need for a more flexible and extensible +authentication system. The current system, while powerful, has some limitations +that make it difficult to use in certain scenarios. For example, it is not +possible to use multiple authenticators of the same type (e.g., multiple JWT +authenticators) or to change the configuration without restarting the API server. The +Structured Authentication Configuration feature is the first step towards +addressing these limitations and providing a more flexible and extensible way +to configure authentication in Kubernetes. See more details about [structured +authentication configuration](/docs/reference/access-authn-authz/authentication/#using-authentication-configuration). + +### Structured Authorization Configuration ([SIG Auth](https://github.com/kubernetes/community/tree/master/sig-auth)) + +_Structured Authorization Configuration_ graduates to beta in this release. + +Kubernetes continues to evolve to meet the intricate requirements of system +administrators and developers alike. A critical aspect of Kubernetes that +ensures the security and integrity of the cluster is the API server +authorization. Until recently, the configuration of the authorization chain in +kube-apiserver was somewhat rigid, limited to a set of command-line flags and +allowing only a single webhook in the authorization chain. This approach, while +functional, restricted the flexibility needed by cluster administrators to +define complex, fine-grained authorization policies. The latest Structured +Authorization Configuration feature aims to revolutionize this aspect by introducing +a more structured and versatile way to configure the authorization chain, focusing +on enabling multiple webhooks and providing explicit control mechanisms. See more +details about [structured authorization configuration](/docs/reference/access-authn-authz/authorization/#configuring-the-api-server-using-an-authorization-config-file). + +## New alpha features + +### Speed up recursive SELinux label change ([SIG Storage](https://github.com/kubernetes/community/tree/master/sig-storage)) + +From the v1.27 release, Kubernetes already included an optimization that sets SELinux labels on the +contents of volumes, using only constant time. Kubernetes achieves that speed up using a mount +option. The slower legacy behavior requires the container runtime to recursively walk through the +whole volumes and apply SELinux labelling individually to each file and directory; this is +especially noticable for volumes with large amount of files and directories. + +Kubernetes v1.27 graduated this feature as beta, but limited it to ReadWriteOncePod volumes. The +corresponding feature gate is `SELinuxMountReadWriteOncePod`. It's still enabled by default and +remains beta in v1.30. + +Kubernetes v1.30 extends support for SELinux mount option to **all** volumes as alpha, with a +separate feature gate: `SELinuxMount`. This feature gate introduces a behavioral change when +multiple Pods with different SELinux labels share the same volume. See +[KEP](https://github.com/kubernetes/enhancements/tree/master/keps/sig-storage/1710-selinux-relabeling#behavioral-changes) +for details. + +We strongly encourage users that run Kubernetes with SELinux enabled to test this feature and +provide any feedback on the [KEP issue](https://kep.k8s.io/1710). + +| Feature gate | Stage in v1.30 | Behavior change | +|---|---|---| +| SELinuxMountReadWriteOncePod | Beta | No | +| SELinuxMount | Alpha | Yes | + +Both feature gates `SELinuxMountReadWriteOncePod` and `SELinuxMount` must be enabled to test this +feature on all volumes. + +This feature has no effect on Windows nodes or on Linux nodes without SELinux support. + +### Recursive Read-only (RRO) mounts ([SIG Node](https://github.com/kubernetes/community/tree/master/sig-node)) + +Introducing Recursive Read-Only (RRO) Mounts in alpha this release, you'll find a new layer of +security for your data. This feature lets you set volumes and their submounts as read-only, +preventing accidental modifications. Imagine deploying a critical application where data integrity +is key—RRO Mounts ensure that your data stays untouched, reinforcing your cluster's security with an +extra safeguard. This is especially crucial in tightly controlled environments, where even the +slightest change can have significant implications. + +### Job success/completion policy ([SIG Apps](https://github.com/kubernetes/community/tree/master/sig-apps)) + +From Kubernetes v1.30, indexed Jobs support `.spec.successPolicy` to define when a Job can be +declared succeeded based on succeeded Pods. This allows you to define two types of criteria: + +- `succeededIndexes` indicates that the Job can be declared succeeded when these indexes succeeded, + even if other indexes failed. +- `succeededCount` indicates that the Job can be declared succeeded when the number of succeeded + Indexes reaches this criterion. + +After the Job meets the success policy, the Job controller terminates the lingering Pods. + +### Traffic distribution for services ([SIG Network](https://github.com/kubernetes/community/tree/master/sig-network)) + +Kubernetes v1.30 introduces the `spec.trafficDistribution` field within a Kubernetes Service as +alpha. This allows you to express preferences for how traffic should be routed to Service endpoints. +While [traffic policies](/docs/reference/networking/virtual-ips/#traffic-policies) focus on strict +semantic guarantees, traffic distribution allows you to express _preferences_ (such as routing to +topologically closer endpoints). This can help optimize for performance, cost, or reliability. You +can use this field by enabling the `ServiceTrafficDistribution` feature gate for your cluster and +all of its nodes. In Kubernetes v1.30, the following field value is supported: + +`PreferClose`: Indicates a preference for routing traffic to endpoints that are topologically +proximate to the client. The interpretation of "topologically proximate" may vary across +implementations and could encompass endpoints within the same node, rack, zone, or even region. +Setting this value gives implementations permission to make different tradeoffs, for example +optimizing for proximity rather than equal distribution of load. You should not set this value if +such tradeoffs are not acceptable. + +If the field is not set, the implementation (like kube-proxy) will apply its default routing +strategy. + +See [Traffic Distribution](/docs/reference/networking/virtual-ips/#traffic-distribution) for more +details. + +### Storage Version Migration ([SIG API Machinery](https://github.com/kubernetes/community/tree/master/sig-api-machinery)) +Kubernetes v1.30 introduces a new built-in API for _StorageVersionMigration_. +Kubernetes relies on API data being actively re-written, to support some +maintenance activities related to at rest storage. Two prominent examples are +the versioned schema of stored resources (that is, the preferred storage schema +changing from v1 to v2 for a given resource) and encryption at rest (that is, +rewriting stale data based on a change in how the data should be encrypted). + +StorageVersionMigration is alpha API which was available [out of tree](https://github.com/kubernetes-sigs/kube-storage-version-migrator) before. + +See [storage version migration](/docs/tasks/manage-kubernetes-objects/storage-version-migration) for more details. + +## Graduations, deprecations and removals for Kubernetes v1.30 + +### Graduated to stable + +This lists all the features that graduated to stable (also known as _general availability_). For a +full list of updates including new features and graduations from alpha to beta, see the [release +notes](https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG/CHANGELOG-1.30.md). + +This release includes a total of 17 enhancements promoted to Stable: + +- [Container Resource based Pod Autoscaling](https://kep.k8s.io/1610) +- [Remove transient node predicates from KCCM's service controller](https://kep.k8s.io/3458) +- [Go workspaces for k/k](https://kep.k8s.io/4402) +- [Reduction of Secret-based Service Account Tokens](https://kep.k8s.io/2799) +- [CEL for Admission Control](https://kep.k8s.io/3488) +- [CEL-based admission webhook match conditions](https://kep.k8s.io/3716) +- [Pod Scheduling Readiness](https://kep.k8s.io/3521) +- [Min domains in PodTopologySpread](https://kep.k8s.io/3022) +- [Prevent unauthorised volume mode conversion during volume restore](https://kep.k8s.io/3141) +- [API Server Tracing](https://kep.k8s.io/647) +- [Cloud Dual-Stack --node-ip Handling](https://kep.k8s.io/3705) +- [AppArmor support](https://kep.k8s.io/24) +- [Robust VolumeManager reconstruction after kubelet restart](https://kep.k8s.io/3756) +- [kubectl delete: Add interactive(-i) flag](https://kep.k8s.io/3895) +- [Metric cardinality enforcement](https://kep.k8s.io/2305) +- [Field `status.hostIPs` added for Pod](https://kep.k8s.io/2681) +- [Aggregated Discovery](https://kep.k8s.io/3352) + +### Deprecations and removals + +#### Removed the SecurityContextDeny admission plugin, deprecated since v1.27 +([SIG Auth](https://github.com/kubernetes/community/tree/master/sig-auth), [SIG Security](https://github.com/kubernetes/community/tree/master/sig-security), and [SIG Testing](https://github.com/kubernetes/community/tree/master/sig-testing)) +With the removal of the SecurityContextDeny admission plugin, the Pod Security Admission plugin, +available since v1.25, is recommended instead. + +## Release notes + +Check out the full details of the Kubernetes v1.30 release in our [release +notes](https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG/CHANGELOG-1.30.md). + +## Availability + +Kubernetes v1.30 is available for download on +[GitHub](https://github.com/kubernetes/kubernetes/releases/tag/v1.30.0). To get started with +Kubernetes, check out these [interactive tutorials](/docs/tutorials/) or run +local Kubernetes clusters using [minikube](https://minikube.sigs.k8s.io/). You can also easily +install v1.30 using [kubeadm](/docs/setup/independent/create-cluster-kubeadm/). + +## Release team + +Kubernetes is only possible with the support, commitment, and hard work of its community. Each +release team is made up of dedicated community volunteers who work together to build the many pieces +that make up the Kubernetes releases you rely on. This requires the specialized skills of people +from all corners of our community, from the code itself to its documentation and project management. + +We would like to thank the entire [release team](https://github.com/kubernetes/sig-release/blob/master/releases/release-1.30/release-team.md) +for the hours spent hard at work to deliver the Kubernetes v1.30 release to our community. The +Release Team's membership ranges from first-time shadows to returning team leads with experience +forged over several release cycles. A very special thanks goes out our release lead, Kat Cosgrove, +for supporting us through a successful release cycle, advocating for us, making sure that we could +all contribute in the best way possible, and challenging us to improve the release process. + +## Project velocity + +The CNCF K8s DevStats project aggregates a number of interesting data points related to the velocity +of Kubernetes and various sub-projects. This includes everything from individual contributions to +the number of companies that are contributing and is an illustration of the depth and breadth of +effort that goes into evolving this ecosystem. + +In the v1.30 release cycle, which ran for 14 weeks (January 8 to April 17), we saw contributions +from [863 companies](https://k8s.devstats.cncf.io/d/9/companies-table?orgId=1&var-period_name=v1.29.0%20-%20now&var-metric=contributions) and [1391 individuals](https://k8s.devstats.cncf.io/d/66/developer-activity-counts-by-companies?orgId=1&var-period_name=v1.29.0%20-%20now&var-metric=contributions&var-repogroup_name=Kubernetes&var-repo_name=kubernetes%2Fkubernetes&var-country_name=All&var-companies=All). + + +## Event update + +* KubeCon + CloudNativeCon China 2024 will take place in Hong Kong, from 21 – 23 August 2024! You + can find more information about the conference and registration on the [event + site](https://events.linuxfoundation.org/kubecon-cloudnativecon-open-source-summit-ai-dev-china/). +* KubeCon + CloudNativeCon North America 2024 will take place in Salt Lake City, Utah, The United + States of America, from 12 – 15 November 2024! You can find more information about the conference + and registration on the [eventsite](https://events.linuxfoundation.org/kubecon-cloudnativecon-north-america/). + +## Upcoming release webinar + +Join members of the Kubernetes v1.30 release team on Thursday, May 23rd, 2024, at 9 A.M. PT to learn +about the major features of this release, as well as deprecations and removals to help plan for +upgrades. For more information and registration, visit the [event +page](https://community.cncf.io/events/details/cncf-cncf-online-programs-presents-cncf-live-webinar-kubernetes-130-release/) +on the CNCF Online Programs site. + +## Get involved + +The simplest way to get involved +with Kubernetes is by joining one of the many [Special Interest +Groups](https://github.com/kubernetes/community/blob/master/sig-list.md) (SIGs) that align with your +interests. Have something you’d like to broadcast to the Kubernetes community? Share your voice at +our weekly [community meeting](https://github.com/kubernetes/community/tree/master/communication), +and through the channels below. Thank you for your continued feedback and support. + +- Follow us on 𝕏 [@Kubernetesio](https://twitter.com/kubernetesio) for latest updates +- Join the community discussion on [Discuss](https://discuss.kubernetes.io/) +- Join the community on [Slack](http://slack.k8s.io/) +- Post questions (or answer questions) on [Stack + Overflow](http://stackoverflow.com/questions/tagged/kubernetes) +- Share your Kubernetes + [story](https://docs.google.com/a/linuxfoundation.org/forms/d/e/1FAIpQLScuI7Ye3VQHQTwBASrgkjQDSS5TP0g3AXfFhwSM9YpHgxRKFA/viewform) +- Read more about what’s happening with Kubernetes on the [blog](https://kubernetes.io/blog/) +- Learn more about the [Kubernetes Release + Team](https://github.com/kubernetes/sig-release/tree/master/release-team) + +*This blog was updated on April 19th, 2024 to highlight two additional changes not originally included in the release blog.* diff --git a/content/en/blog/_posts/2024-04-22-userns-beta/index.md b/content/en/blog/_posts/2024-04-22-userns-beta/index.md new file mode 100644 index 0000000000000..981565044182a --- /dev/null +++ b/content/en/blog/_posts/2024-04-22-userns-beta/index.md @@ -0,0 +1,159 @@ +--- +layout: blog +title: "Kubernetes 1.30: Beta Support For Pods With User Namespaces" +date: 2024-04-22 +slug: userns-beta +author: > + Rodrigo Campos Catelin (Microsoft), + Giuseppe Scrivano (Red Hat), + Sascha Grunert (Red Hat) +--- + +Linux provides different namespaces to isolate processes from each other. For +example, a typical Kubernetes pod runs within a network namespace to isolate the +network identity and a PID namespace to isolate the processes. + +One Linux namespace that was left behind is the [user +namespace](https://man7.org/linux/man-pages/man7/user_namespaces.7.html). This +namespace allows us to isolate the user and group identifiers (UIDs and GIDs) we +use inside the container from the ones on the host. + +This is a powerful abstraction that allows us to run containers as "root": we +are root inside the container and can do everything root can inside the pod, +but our interactions with the host are limited to what a non-privileged user can +do. This is great for limiting the impact of a container breakout. + +A container breakout is when a process inside a container can break out +onto the host using some unpatched vulnerability in the container runtime or the +kernel and can access/modify files on the host or other containers. If we +run our pods with user namespaces, the privileges the container has over the +rest of the host are reduced, and the files outside the container it can access +are limited too. + +In Kubernetes v1.25, we introduced support for user namespaces only for stateless +pods. Kubernetes 1.28 lifted that restriction, and now, with Kubernetes 1.30, we +are moving to beta! + +## What is a user namespace? + +Note: Linux user namespaces are a different concept from [Kubernetes +namespaces](/docs/concepts/overview/working-with-objects/namespaces/). +The former is a Linux kernel feature; the latter is a Kubernetes feature. + +User namespaces are a Linux feature that isolates the UIDs and GIDs of the +containers from the ones on the host. The identifiers in the container can be +mapped to identifiers on the host in a way where the host UID/GIDs used for +different containers never overlap. Furthermore, the identifiers can be mapped +to unprivileged, non-overlapping UIDs and GIDs on the host. This brings two key +benefits: + + * _Prevention of lateral movement_: As the UIDs and GIDs for different +containers are mapped to different UIDs and GIDs on the host, containers have a +harder time attacking each other, even if they escape the container boundaries. +For example, suppose container A runs with different UIDs and GIDs on the host +than container B. In that case, the operations it can do on container B's files and processes +are limited: only read/write what a file allows to others, as it will never +have permission owner or group permission (the UIDs/GIDs on the host are +guaranteed to be different for different containers). + + * _Increased host isolation_: As the UIDs and GIDs are mapped to unprivileged +users on the host, if a container escapes the container boundaries, even if it +runs as root inside the container, it has no privileges on the host. This +greatly protects what host files it can read/write, which process it can send +signals to, etc. Furthermore, capabilities granted are only valid inside the +user namespace and not on the host, limiting the impact a container +escape can have. + +{{< figure src="/images/blog/2024-04-22-userns-beta/userns-ids.png" alt="Image showing IDs 0-65535 are reserved to the host, pods use higher IDs" title="User namespace IDs allocation" >}} + + +Without using a user namespace, a container running as root in the case of a +container breakout has root privileges on the node. If some capabilities +were granted to the container, the capabilities are valid on the host too. None +of this is true when using user namespaces (modulo bugs, of course 🙂). + +## Changes in 1.30 + +In Kubernetes 1.30, besides moving user namespaces to beta, the contributors +working on this feature: + + * Introduced a way for the kubelet to use custom ranges for the UIDs/GIDs mapping + * Have added a way for Kubernetes to enforce that the runtime supports all the features + needed for user namespaces. If they are not supported, Kubernetes will show a + clear error when trying to create a pod with user namespaces. Before 1.30, if + the container runtime didn't support user namespaces, the pod could be created + without a user namespace. + * Added more tests, including [tests in the + cri-tools](https://github.com/kubernetes-sigs/cri-tools/pull/1354) + repository. + +You can check the +[documentation](/docs/concepts/workloads/pods/user-namespaces/#set-up-a-node-to-support-user-namespaces) +on user namespaces for how to configure custom ranges for the mapping. + +## Demo + +A few months ago, [CVE-2024-21626][runc-cve] was disclosed. This **vulnerability +score is 8.6 (HIGH)**. It allows an attacker to escape a container and +**read/write to any path on the node and other pods hosted on the same node**. + +Rodrigo created a demo that exploits [CVE 2024-21626][runc-cve] and shows how +the exploit, which works without user namespaces, **is mitigated when user +namespaces are in use.** + +{{< youtube id="07y5bl5UDdA" title="Mitigation of CVE-2024-21626 on Kubernetes by enabling User Namespace support" class="youtube-quote-sm" >}} + +Please note that with user namespaces, an attacker can do on the host file system +what the permission bits for "others" allow. Therefore, the CVE is not +completely prevented, but the impact is greatly reduced. + +[runc-cve]: https://github.com/opencontainers/runc/security/advisories/GHSA-xr7r-f8xq-vfvv + +## Node system requirements + +There are requirements on the Linux kernel version and the container +runtime to use this feature. + +On Linux you need Linux 6.3 or greater. This is because the feature relies on a +kernel feature named idmap mounts, and support for using idmap mounts with tmpfs +was merged in Linux 6.3. + +Suppose you are using [CRI-O][crio] with crun; as always, you can expect support for +Kubernetes 1.30 with CRI-O 1.30. Please note you also need [crun][crun] 1.9 or +greater. If you are using CRI-O with [runc][runc], this is still not supported. + +Containerd support is currently targeted for [containerd][containerd] 2.0, and +the same crun version requirements apply. If you are using containerd with runc, +this is still not supported. + +Please note that containerd 1.7 added _experimental_ support for user +namespaces, as implemented in Kubernetes 1.25 and 1.26. We did a redesign in +Kubernetes 1.27, which requires changes in the container runtime. Those changes +are not present in containerd 1.7, so it only works with user namespaces +support in Kubernetes 1.25 and 1.26. + +Another limitation of containerd 1.7 is that it needs to change the +ownership of every file and directory inside the container image during Pod +startup. This has a storage overhead and can significantly impact the +container startup latency. Containerd 2.0 will probably include an implementation +that will eliminate the added startup latency and storage overhead. Consider +this if you plan to use containerd 1.7 with user namespaces in +production. + +None of these containerd 1.7 limitations apply to CRI-O. + +[crio]: https://cri-o.io/ +[crun]: https://github.com/containers/crun +[runc]: https://github.com/opencontainers/runc/ +[containerd]: https://containerd.io/ + +## How do I get involved? + +You can reach SIG Node by several means: +- Slack: [#sig-node](https://kubernetes.slack.com/messages/sig-node) +- [Mailing list](https://groups.google.com/forum/#!forum/kubernetes-sig-node) +- [Open Community Issues/PRs](https://github.com/kubernetes/community/labels/sig%2Fnode) + +You can also contact us directly: +- GitHub: @rata @giuseppe @saschagrunert +- Slack: @rata @giuseppe @sascha diff --git a/content/en/blog/_posts/2024-04-22-userns-beta/userns-ids.xcf b/content/en/blog/_posts/2024-04-22-userns-beta/userns-ids.xcf new file mode 100644 index 0000000000000..6124a7ba504b3 Binary files /dev/null and b/content/en/blog/_posts/2024-04-22-userns-beta/userns-ids.xcf differ diff --git a/content/en/blog/_posts/2024-04-23-recursive-read-only-mounts.md b/content/en/blog/_posts/2024-04-23-recursive-read-only-mounts.md new file mode 100644 index 0000000000000..95c12b2a65b7f --- /dev/null +++ b/content/en/blog/_posts/2024-04-23-recursive-read-only-mounts.md @@ -0,0 +1,108 @@ +--- +layout: blog +title: 'Kubernetes 1.30: Read-only volume mounts can be finally literally read-only' +date: 2024-04-23 +slug: recursive-read-only-mounts +author: > + Akihiro Suda (NTT) +--- + +Read-only volume mounts have been a feature of Kubernetes since the beginning. +Surprisingly, read-only mounts are not completely read-only under certain conditions on Linux. +As of the v1.30 release, they can be made completely read-only, +with alpha support for _recursive read-only mounts_. + +## Read-only volume mounts are not really read-only by default + +Volume mounts can be deceptively complicated. + +You might expect that the following manifest makes everything under `/mnt` in the containers read-only: +```yaml +--- +apiVersion: v1 +kind: Pod +spec: + volumes: + - name: mnt + hostPath: + path: /mnt + containers: + - volumeMounts: + - name: mnt + mountPath: /mnt + readOnly: true +``` + +However, any sub-mounts beneath `/mnt` may still be writable! +For example, consider that `/mnt/my-nfs-server` is writeable on the host. +Inside the container, writes to `/mnt/*` will be rejected but `/mnt/my-nfs-server/*` will still be writeable. + +## New mount option: recursiveReadOnly + +Kubernetes 1.30 added a new mount option `recursiveReadOnly` so as to make submounts recursively read-only. + +The option can be enabled as follows: +{{< highlight yaml "linenos=false,hl_lines=14-17" >}} +--- +apiVersion: v1 +kind: Pod +spec: + volumes: + - name: mnt + hostPath: + path: /mnt + containers: + - volumeMounts: + - name: mnt + mountPath: /mnt + readOnly: true + # NEW + # Possible values are `Enabled`, `IfPossible`, and `Disabled`. + # Needs to be specified in conjunction with `readOnly: true`. + recursiveReadOnly: Enabled +{{< /highlight >}} + +This is implemented by applying the `MOUNT_ATTR_RDONLY` attribute with the `AT_RECURSIVE` flag +using [`mount_setattr(2)`](https://man7.org/linux/man-pages/man2/mount_setattr.2.html) added in +Linux kernel v5.12. + +For backwards compatibility, the `recursiveReadOnly` field is not a replacement for `readOnly`, +but is used _in conjunction_ with it. +To get a properly recursive read-only mount, you must set both fields. + +## Feature availability {#availability} + +To enable `recursiveReadOnly` mounts, the following components have to be used: + +* Kubernetes: v1.30 or later, with the `RecursiveReadOnlyMounts` + [feature gate](/docs/reference/command-line-tools-reference/feature-gates/) enabled. + As of v1.30, the gate is marked as alpha. + +* CRI runtime: + * containerd: v2.0 or later + +* OCI runtime: + * runc: v1.1 or later + * crun: v1.8.6 or later + +* Linux kernel: v5.12 or later + +## What's next? + +Kubernetes SIG Node hope - and expect - that the feature will be promoted to beta and eventually +general availability (GA) in future releases of Kubernetes, so that users no longer need to enable +the feature gate manually. + +The default value of `recursiveReadOnly` will still remain `Disabled`, for backwards compatibility. + +## How can I learn more? + + +Please check out the [documentation](/docs/concepts/storage/volumes/#read-only-mounts) +for the further details of `recursiveReadOnly` mounts. + +## How to get involved? + +This feature is driven by the SIG Node community. Please join us to connect with +the community and share your ideas and feedback around the above feature and +beyond. We look forward to hearing from you! diff --git a/content/en/blog/_posts/2024-04-24-validating-admission-policy-ga/index.md b/content/en/blog/_posts/2024-04-24-validating-admission-policy-ga/index.md new file mode 100644 index 0000000000000..ce7141c2df83f --- /dev/null +++ b/content/en/blog/_posts/2024-04-24-validating-admission-policy-ga/index.md @@ -0,0 +1,287 @@ +------ +layout: blog +title: "Kubernetes 1.30: Validating Admission Policy Is Generally Available" +slug: validating-admission-policy-ga +date: 2024-04-24 +author: > + Jiahui Feng (Google) +--- + +On behalf of the Kubernetes project, I am excited to announce that ValidatingAdmissionPolicy has reached +**general availability** +as part of Kubernetes 1.30 release. If you have not yet read about this new declarative alternative to +validating admission webhooks, it may be interesting to read our +[previous post](/blog/2022/12/20/validating-admission-policies-alpha/) about the new feature. +If you have already heard about ValidatingAdmissionPolicies and you are eager to try them out, +there is no better time to do it than now. + +Let's have a taste of a ValidatingAdmissionPolicy, by replacing a simple webhook. + +## Example admission webhook +First, let's take a look at an example of a simple webhook. Here is an excerpt from a webhook that +enforces `runAsNonRoot`, `readOnlyRootFilesystem`, `allowPrivilegeEscalation`, and `privileged` to be set to the least permissive values. + +```go +func verifyDeployment(deploy *appsv1.Deployment) error { + var errs []error + for i, c := range deploy.Spec.Template.Spec.Containers { + if c.Name == "" { + return fmt.Errorf("container %d has no name", i) + } + if c.SecurityContext == nil { + errs = append(errs, fmt.Errorf("container %q does not have SecurityContext", c.Name)) + } + if c.SecurityContext.RunAsNonRoot == nil || !*c.SecurityContext.RunAsNonRoot { + errs = append(errs, fmt.Errorf("container %q must set RunAsNonRoot to true in its SecurityContext", c.Name)) + } + if c.SecurityContext.ReadOnlyRootFilesystem == nil || !*c.SecurityContext.ReadOnlyRootFilesystem { + errs = append(errs, fmt.Errorf("container %q must set ReadOnlyRootFilesystem to true in its SecurityContext", c.Name)) + } + if c.SecurityContext.AllowPrivilegeEscalation != nil && *c.SecurityContext.AllowPrivilegeEscalation { + errs = append(errs, fmt.Errorf("container %q must NOT set AllowPrivilegeEscalation to true in its SecurityContext", c.Name)) + } + if c.SecurityContext.Privileged != nil && *c.SecurityContext.Privileged { + errs = append(errs, fmt.Errorf("container %q must NOT set Privileged to true in its SecurityContext", c.Name)) + } + } + return errors.NewAggregate(errs) +} +``` + +Check out [What are admission webhooks?](/docs/reference/access-authn-authz/extensible-admission-controllers/#what-are-admission-webhooks) +Or, see the [full code](webhook.go) of this webhook to follow along with this walkthrough. + +## The policy +Now let's try to recreate the validation faithfully with a ValidatingAdmissionPolicy. +```yaml +apiVersion: admissionregistration.k8s.io/v1 +kind: ValidatingAdmissionPolicy +metadata: + name: "pod-security.policy.example.com" +spec: + failurePolicy: Fail + matchConstraints: + resourceRules: + - apiGroups: ["apps"] + apiVersions: ["v1"] + operations: ["CREATE", "UPDATE"] + resources: ["deployments"] + validations: + - expression: object.spec.template.spec.containers.all(c, has(c.securityContext) && has(c.securityContext.runAsNonRoot) && c.securityContext.runAsNonRoot) + message: 'all containers must set runAsNonRoot to true' + - expression: object.spec.template.spec.containers.all(c, has(c.securityContext) && has(c.securityContext.readOnlyRootFilesystem) && c.securityContext.readOnlyRootFilesystem) + message: 'all containers must set readOnlyRootFilesystem to true' + - expression: object.spec.template.spec.containers.all(c, !has(c.securityContext) || !has(c.securityContext.allowPrivilegeEscalation) || !c.securityContext.allowPrivilegeEscalation) + message: 'all containers must NOT set allowPrivilegeEscalation to true' + - expression: object.spec.template.spec.containers.all(c, !has(c.securityContext) || !has(c.securityContext.Privileged) || !c.securityContext.Privileged) + message: 'all containers must NOT set privileged to true' +``` +Create the policy with `kubectl`. Great, no complain so far. But let's get the policy object back and take a look at its status. +```shell +kubectl get -oyaml validatingadmissionpolicies/pod-security.policy.example.com +``` +```yaml + status: + typeChecking: + expressionWarnings: + - fieldRef: spec.validations[3].expression + warning: | + apps/v1, Kind=Deployment: ERROR: :1:76: undefined field 'Privileged' + | object.spec.template.spec.containers.all(c, !has(c.securityContext) || !has(c.securityContext.Privileged) || !c.securityContext.Privileged) + | ...........................................................................^ + ERROR: :1:128: undefined field 'Privileged' + | object.spec.template.spec.containers.all(c, !has(c.securityContext) || !has(c.securityContext.Privileged) || !c.securityContext.Privileged) + | ...............................................................................................................................^ + +``` +The policy was checked against its matched type, which is `apps/v1.Deployment`. +Looking at the `fieldRef`, the problem was with the 3rd expression (index starts with 0) +The expression in question accessed an undefined `Privileged` field. +Ahh, looks like it was a copy-and-paste error. The field name should be in lowercase. + +```yaml +apiVersion: admissionregistration.k8s.io/v1 +kind: ValidatingAdmissionPolicy +metadata: + name: "pod-security.policy.example.com" +spec: + failurePolicy: Fail + matchConstraints: + resourceRules: + - apiGroups: ["apps"] + apiVersions: ["v1"] + operations: ["CREATE", "UPDATE"] + resources: ["deployments"] + validations: + - expression: object.spec.template.spec.containers.all(c, has(c.securityContext) && has(c.securityContext.runAsNonRoot) && c.securityContext.runAsNonRoot) + message: 'all containers must set runAsNonRoot to true' + - expression: object.spec.template.spec.containers.all(c, has(c.securityContext) && has(c.securityContext.readOnlyRootFilesystem) && c.securityContext.readOnlyRootFilesystem) + message: 'all containers must set readOnlyRootFilesystem to true' + - expression: object.spec.template.spec.containers.all(c, !has(c.securityContext) || !has(c.securityContext.allowPrivilegeEscalation) || !c.securityContext.allowPrivilegeEscalation) + message: 'all containers must NOT set allowPrivilegeEscalation to true' + - expression: object.spec.template.spec.containers.all(c, !has(c.securityContext) || !has(c.securityContext.privileged) || !c.securityContext.privileged) + message: 'all containers must NOT set privileged to true' +``` +Check its status again, and you should see all warnings cleared. + +Next, let's create a namespace for our tests. +```shell +kubectl create namespace policy-test +``` +Then, I bind the policy to the namespace. But at this point, I set the action to `Warn` +so that the policy prints out [warnings](/blog/2020/09/03/warnings/) instead of rejecting the requests. +This is especially useful to collect results from all expressions during development and automated testing. +```yaml +apiVersion: admissionregistration.k8s.io/v1 +kind: ValidatingAdmissionPolicyBinding +metadata: + name: "pod-security.policy-binding.example.com" +spec: + policyName: "pod-security.policy.example.com" + validationActions: ["Warn"] + matchResources: + namespaceSelector: + matchLabels: + "kubernetes.io/metadata.name": "policy-test" +``` +Tests out policy enforcement. +```shell +kubectl create -n policy-test -f- < + [Anish Ramasekar](https://github.com/aramase) (Microsoft) +--- + +With Kubernetes 1.30, we (SIG Auth) are moving Structured Authentication Configuration to beta. + +Today's article is about _authentication_: finding out who's performing a task, and checking +that they are who they say they are. Check back in tomorrow to find about what's new in +Kubernetes v1.30 around _authorization_ (deciding what someone can and can't access). + +## Motivation +Kubernetes has had a long-standing need for a more flexible and extensible +authentication system. The current system, while powerful, has some limitations +that make it difficult to use in certain scenarios. For example, it is not +possible to use multiple authenticators of the same type (e.g., multiple JWT +authenticators) or to change the configuration without restarting the API server. The +Structured Authentication Configuration feature is the first step towards +addressing these limitations and providing a more flexible and extensible way +to configure authentication in Kubernetes. + +## What is structured authentication configuration? +Kubernetes v1.30 builds on the experimental support for configurating authentication based on +a file, that was added as alpha in Kubernetes v1.30. At this beta stage, Kubernetes only supports configuring JWT +authenticators, which serve as the next iteration of the existing OIDC +authenticator. JWT authenticator is an authenticator to +authenticate Kubernetes users using JWT compliant tokens. The authenticator +will attempt to parse a raw ID token, verify it's been signed by the configured +issuer. + +The Kubernetes project added configuration from a file so that it can provide more +flexibility than using command line options (which continue to work, and are still supported). +Supporting a configuration file also makes it easy to deliver further improvements in upcoming +releases. + +### Benefits of structured authentication configuration +Here's why using a configuration file to configure cluster authentication is a benefit: +1. **Multiple JWT authenticators**: You can configure multiple JWT authenticators + simultaneously. This allows you to use multiple identity providers (e.g., + Okta, Keycloak, GitLab) without needing to use an intermediary like Dex + that handles multiplexing between multiple identity providers. +2. **Dynamic configuration**: You can change the configuration without + restarting the API server. This allows you to add, remove, or modify + authenticators without disrupting the API server. +3. **Any JWT-compliant token**: You can use any JWT-compliant token for + authentication. This allows you to use tokens from any identity provider that + supports JWT. The minimum valid JWT payload must contain the claims documented + in [structured authentication configuration](/docs/reference/access-authn-authz/authentication/#using-authentication-configuration) + page in the Kubernetes documentation. +4. **CEL (Common Expression Language) support**: You can use [CEL](/docs/reference/using-api/cel/) + to determine whether the token's claims match the user's attributes in Kubernetes (e.g., + username, group). This allows you to use complex logic to determine whether a + token is valid. +5. **Multiple audiences**: You can configure multiple audiences for a single + authenticator. This allows you to use the same authenticator for multiple + audiences, such as using a different OAuth client for `kubectl` and dashboard. +6. **Using identity providers that don't support OpenID connect discovery**: You + can use identity providers that don't support [OpenID Connect + discovery](https://openid.net/specs/openid-connect-discovery-1_0.html). The only + requirement is to host the discovery document at a different location than the + issuer (such as locally in the cluster) and specify the `issuer.discoveryURL` in + the configuration file. + +## How to use Structured Authentication Configuration +To use structured authentication configuration, you specify +the path to the authentication configuration using the `--authentication-config` +command line argument in the API server. The configuration file is a YAML file +that specifies the authenticators and their configuration. Here is an example +configuration file that configures two JWT authenticators: + +```yaml +apiVersion: apiserver.config.k8s.io/v1beta1 +kind: AuthenticationConfiguration +# Someone with a valid token from either of these issuers could authenticate +# against this cluster. +jwt: +- issuer: + url: https://issuer1.example.com + audiences: + - audience1 + - audience2 + audienceMatchPolicy: MatchAny + claimValidationRules: + expression: 'claims.hd == "example.com"' + message: "the hosted domain name must be example.com" + claimMappings: + username: + expression: 'claims.username' + groups: + expression: 'claims.groups' + uid: + expression: 'claims.uid' + extra: + - key: 'example.com/tenant' + expression: 'claims.tenant' + userValidationRules: + - expression: "!user.username.startsWith('system:')" + message: "username cannot use reserved system: prefix" +# second authenticator that exposes the discovery document at a different location +# than the issuer +- issuer: + url: https://issuer2.example.com + discoveryURL: https://discovery.example.com/.well-known/openid-configuration + audiences: + - audience3 + - audience4 + audienceMatchPolicy: MatchAny + claimValidationRules: + expression: 'claims.hd == "example.com"' + message: "the hosted domain name must be example.com" + claimMappings: + username: + expression: 'claims.username' + groups: + expression: 'claims.groups' + uid: + expression: 'claims.uid' + extra: + - key: 'example.com/tenant' + expression: 'claims.tenant' + userValidationRules: + - expression: "!user.username.startsWith('system:')" + message: "username cannot use reserved system: prefix" +``` + +## Migration from command line arguments to configuration file +The Structured Authentication Configuration feature is designed to be +backwards-compatible with the existing approach, based on command line options, for +configuring the JWT authenticator. This means that you can continue to use the existing +command-line options to configure the JWT authenticator. However, we (Kubernetes SIG Auth) +recommend migrating to the new configuration file-based approach, as it provides more +flexibility and extensibility. + +{{% alert title="Note" color="primary" %}} +If you specify `--authentication-config` along with any of the `--oidc-*` command line arguments, this is +a misconfiguration. In this situation, the API server reports an error and then immediately exits. + +If you want to switch to using structured authentication configuration, you have to remove the `--oidc-*` +command line arguments, and use the configuration file instead. +{{% /alert %}} + +Here is an example of how to migrate from the command-line flags to the +configuration file: + +### Command-line arguments +```bash +--oidc-issuer-url=https://issuer.example.com +--oidc-client-id=example-client-id +--oidc-username-claim=username +--oidc-groups-claim=groups +--oidc-username-prefix=oidc: +--oidc-groups-prefix=oidc: +--oidc-required-claim="hd=example.com" +--oidc-required-claim="admin=true" +--oidc-ca-file=/path/to/ca.pem +``` + +There is no equivalent in the configuration file for the `--oidc-signing-algs`. +For Kubernetes v1.30, the authenticator supports all the asymmetric algorithms listed in +[`oidc.go`](https://github.com/kubernetes/kubernetes/blob/b4935d910dcf256288694391ef675acfbdb8e7a3/staging/src/k8s.io/apiserver/plugin/pkg/authenticator/token/oidc/oidc.go#L222-L233). + +### Configuration file +```yaml +apiVersion: apiserver.config.k8s.io/v1beta1 +kind: AuthenticationConfiguration +jwt: +- issuer: + url: https://issuer.example.com + audiences: + - example-client-id + certificateAuthority: + claimMappings: + username: + claim: username + prefix: "oidc:" + groups: + claim: groups + prefix: "oidc:" + claimValidationRules: + - claim: hd + requiredValue: "example.com" + - claim: admin + requiredValue: "true" +``` + +## What's next? +For Kubernetes v1.31, we expect the feature to stay in beta while we get more +feedback. In the coming releases, we want to investigate: +- Making distributed claims work via CEL expressions. +- Egress selector configuration support for calls to `issuer.url` and + `issuer.discoveryURL`. + +You can learn more about this feature on the [structured authentication +configuration](/docs/reference/access-authn-authz/authentication/#using-authentication-configuration) +page in the Kubernetes documentation. You can also follow along on the +[KEP-3331](https://kep.k8s.io/3331) to track progress across the coming +Kubernetes releases. + +## Try it out +In this post, I have covered the benefits the Structured Authentication +Configuration feature brings in Kubernetes v1.30. To use this feature, you must specify the path to the +authentication configuration using the `--authentication-config` command line +argument. From Kubernetes v1.30, the feature is in beta and enabled by default. +If you want to keep using command line arguments instead of a configuration file, +those will continue to work as-is. + +We would love to hear your feedback on this feature. Please reach out to us on the +[#sig-auth-authenticators-dev](https://kubernetes.slack.com/archives/C04UMAUC4UA) +channel on Kubernetes Slack (for an invitation, visit [https://slack.k8s.io/](https://slack.k8s.io/)). + +## How to get involved +If you are interested in getting involved in the development of this feature, +share feedback, or participate in any other ongoing SIG Auth projects, please +reach out on the [#sig-auth](https://kubernetes.slack.com/archives/C0EN96KUY) +channel on Kubernetes Slack. + +You are also welcome to join the bi-weekly [SIG Auth +meetings](https://github.com/kubernetes/community/blob/master/sig-auth/README.md#meetings) +held every-other Wednesday. diff --git a/content/en/blog/_posts/2024-04-26-structured-authz-beta.md b/content/en/blog/_posts/2024-04-26-structured-authz-beta.md new file mode 100644 index 0000000000000..e0149d220b7b4 --- /dev/null +++ b/content/en/blog/_posts/2024-04-26-structured-authz-beta.md @@ -0,0 +1,334 @@ +--- +layout: blog +title: 'Kubernetes 1.30: Multi-Webhook and Modular Authorization Made Much Easier' +date: 2024-04-26 +slug: multi-webhook-and-modular-authorization-made-much-easier +author: > + [Rita Zhang](https://github.com/ritazh) (Microsoft), + [Jordan Liggitt](https://github.com/liggitt) (Google), + [Nabarun Pal](https://github.com/palnabarun) (VMware), + [Leigh Capili](https://github.com/stealthybox) (VMware) +--- + +With Kubernetes 1.30, we (SIG Auth) are moving Structured Authorization +Configuration to beta. + +Today's article is about _authorization_: deciding what someone can and cannot +access. Check a previous article from yesterday to find about what's new in +Kubernetes v1.30 around _authentication_ (finding out who's performing a task, +and checking that they are who they say they are). + +## Introduction +Kubernetes continues to evolve to meet the intricate requirements of system +administrators and developers alike. A critical aspect of Kubernetes that +ensures the security and integrity of the cluster is the API server +authorization. Until recently, the configuration of the authorization chain in +kube-apiserver was somewhat rigid, limited to a set of command-line flags and +allowing only a single webhook in the authorization chain. This approach, while +functional, restricted the flexibility needed by cluster administrators to +define complex, fine-grained authorization policies. The latest Structured +Authorization Configuration feature ([KEP-3221](https://kep.k8s.io/3221)) aims +to revolutionize this aspect by introducing a more structured and versatile way +to configure the authorization chain, focusing on enabling multiple webhooks and +providing explicit control mechanisms. + +## The Need for Improvement +Cluster administrators have long sought the ability to specify multiple +authorization webhooks within the API Server handler chain and have control over +detailed behavior like timeout and failure policy for each webhook. This need +arises from the desire to create layered security policies, where requests can +be validated against multiple criteria or sets of rules in a specific order. The +previous limitations also made it difficult to dynamically configure the +authorizer chain, leaving no room to manage complex authorization scenarios +efficiently. + +The [Structured Authorization Configuration +feature](/docs/reference/access-authn-authz/authorization/#configuring-the-api-server-using-an-authorization-config-file) +addresses these limitations by introducing a configuration file format to +configure the Kubernetes API Server Authorization chain. This format allows +specifying multiple webhooks in the authorization chain (all other authorization +types are specified no more than once). Each webhook authorizer has well-defined +parameters, including timeout settings, failure policies, and conditions for +invocation with [CEL](/docs/reference/using-api/cel/) rules to pre-filter +requests before they are dispatched to webhooks, helping you prevent unnecessary +invocations. The configuration also supports automatic reloading, ensuring +changes can be applied dynamically without restarting the kube-apiserver. This +feature addresses current limitations and opens up new possibilities for +securing and managing Kubernetes clusters more effectively. + +## Sample Configurations +Here is a sample structured authorization configuration along with descriptions +for all fields, their defaults, and possible values. + +```yaml +apiVersion: apiserver.config.k8s.io/v1beta1 +kind: AuthorizationConfiguration +authorizers: + - type: Webhook + # Name used to describe the authorizer + # This is explicitly used in monitoring machinery for metrics + # Note: + # - Validation for this field is similar to how K8s labels are validated today. + # Required, with no default + name: webhook + webhook: + # The duration to cache 'authorized' responses from the webhook + # authorizer. + # Same as setting `--authorization-webhook-cache-authorized-ttl` flag + # Default: 5m0s + authorizedTTL: 30s + # The duration to cache 'unauthorized' responses from the webhook + # authorizer. + # Same as setting `--authorization-webhook-cache-unauthorized-ttl` flag + # Default: 30s + unauthorizedTTL: 30s + # Timeout for the webhook request + # Maximum allowed is 30s. + # Required, with no default. + timeout: 3s + # The API version of the authorization.k8s.io SubjectAccessReview to + # send to and expect from the webhook. + # Same as setting `--authorization-webhook-version` flag + # Required, with no default + # Valid values: v1beta1, v1 + subjectAccessReviewVersion: v1 + # MatchConditionSubjectAccessReviewVersion specifies the SubjectAccessReview + # version the CEL expressions are evaluated against + # Valid values: v1 + # Required, no default value + matchConditionSubjectAccessReviewVersion: v1 + # Controls the authorization decision when a webhook request fails to + # complete or returns a malformed response or errors evaluating + # matchConditions. + # Valid values: + # - NoOpinion: continue to subsequent authorizers to see if one of + # them allows the request + # - Deny: reject the request without consulting subsequent authorizers + # Required, with no default. + failurePolicy: Deny + connectionInfo: + # Controls how the webhook should communicate with the server. + # Valid values: + # - KubeConfig: use the file specified in kubeConfigFile to locate the + # server. + # - InClusterConfig: use the in-cluster configuration to call the + # SubjectAccessReview API hosted by kube-apiserver. This mode is not + # allowed for kube-apiserver. + type: KubeConfig + # Path to KubeConfigFile for connection info + # Required, if connectionInfo.Type is KubeConfig + kubeConfigFile: /kube-system-authz-webhook.yaml + # matchConditions is a list of conditions that must be met for a request to be sent to this + # webhook. An empty list of matchConditions matches all requests. + # There are a maximum of 64 match conditions allowed. + # + # The exact matching logic is (in order): + # 1. If at least one matchCondition evaluates to FALSE, then the webhook is skipped. + # 2. If ALL matchConditions evaluate to TRUE, then the webhook is called. + # 3. If at least one matchCondition evaluates to an error (but none are FALSE): + # - If failurePolicy=Deny, then the webhook rejects the request + # - If failurePolicy=NoOpinion, then the error is ignored and the webhook is skipped + matchConditions: + # expression represents the expression which will be evaluated by CEL. Must evaluate to bool. + # CEL expressions have access to the contents of the SubjectAccessReview in v1 version. + # If version specified by subjectAccessReviewVersion in the request variable is v1beta1, + # the contents would be converted to the v1 version before evaluating the CEL expression. + # + # Documentation on CEL: https://kubernetes.io/docs/reference/using-api/cel/ + # + # only send resource requests to the webhook + - expression: has(request.resourceAttributes) + # only intercept requests to kube-system + - expression: request.resourceAttributes.namespace == 'kube-system' + # don't intercept requests from kube-system service accounts + - expression: !('system:serviceaccounts:kube-system' in request.user.groups) + - type: Node + name: node + - type: RBAC + name: rbac + - type: Webhook + name: in-cluster-authorizer + webhook: + authorizedTTL: 5m + unauthorizedTTL: 30s + timeout: 3s + subjectAccessReviewVersion: v1 + failurePolicy: NoOpinion + connectionInfo: + type: InClusterConfig +``` + +The following configuration examples illustrate real-world scenarios that need +the ability to specify multiple webhooks with distinct settings, precedence +order, and failure modes. + +### Protecting Installed CRDs +Ensuring of Custom Resource Definitions (CRDs) availability at cluster startup +has been a key demand. One of the blockers of having a controller reconcile +those CRDs is having a protection mechanism for them, which can be achieved +through multiple authorization webhooks. This was not possible before as +specifying multiple authorization webhooks in the Kubernetes API Server +authorization chain was simply not possible. Now, with the Structured +Authorization Configuration feature, administrators can specify multiple +webhooks, offering a solution where RBAC falls short, especially when denying +permissions to 'non-system' users for certain CRDs. + +Assuming the following for this scenario: +- The "protected" CRDs are installed. +- They can only be modified by users in the group `admin`. + +```yaml +apiVersion: apiserver.config.k8s.io/v1beta1 +kind: AuthorizationConfiguration +authorizers: + - type: Webhook + name: system-crd-protector + webhook: + unauthorizedTTL: 30s + timeout: 3s + subjectAccessReviewVersion: v1 + matchConditionSubjectAccessReviewVersion: v1 + failurePolicy: Deny + connectionInfo: + type: KubeConfig + kubeConfigFile: /files/kube-system-authz-webhook.yaml + matchConditions: + # only send resource requests to the webhook + - expression: has(request.resourceAttributes) + # only intercept requests for CRDs + - expression: request.resourceAttributes.resource.resource = "customresourcedefinitions" + - expression: request.resourceAttributes.resource.group = "" + # only intercept update, patch, delete, or deletecollection requests + - expression: request.resourceAttributes.verb in ['update', 'patch', 'delete','deletecollection'] + - type: Node + - type: RBAC +``` + +### Preventing unnecessarily nested webhooks +A system administrator wants to apply specific validations to requests before +handing them off to webhooks using frameworks like Open Policy Agent. In the +past, this would require running nested webhooks within the one added to the +authorization chain to achieve the desired result. The Structured Authorization +Configuration feature simplifies this process, offering a structured API to +selectively trigger additional webhooks when needed. It also enables +administrators to set distinct failure policies for each webhook, ensuring more +consistent and predictable responses. + +```yaml +apiVersion: apiserver.config.k8s.io/v1beta1 +kind: AuthorizationConfiguration +authorizers: + - type: Webhook + name: system-crd-protector + webhook: + unauthorizedTTL: 30s + timeout: 3s + subjectAccessReviewVersion: v1 + matchConditionSubjectAccessReviewVersion: v1 + failurePolicy: Deny + connectionInfo: + type: KubeConfig + kubeConfigFile: /files/kube-system-authz-webhook.yaml + matchConditions: + # only send resource requests to the webhook + - expression: has(request.resourceAttributes) + # only intercept requests for CRDs + - expression: request.resourceAttributes.resource.resource = "customresourcedefinitions" + - expression: request.resourceAttributes.resource.group = "" + # only intercept update, patch, delete, or deletecollection requests + - expression: request.resourceAttributes.verb in ['update', 'patch', 'delete','deletecollection'] + - type: Node + - type: RBAC + - name: opa + type: Webhook + webhook: + unauthorizedTTL: 30s + timeout: 3s + subjectAccessReviewVersion: v1 + matchConditionSubjectAccessReviewVersion: v1 + failurePolicy: Deny + connectionInfo: + type: KubeConfig + kubeConfigFile: /files/opa-default-authz-webhook.yaml + matchConditions: + # only send resource requests to the webhook + - expression: has(request.resourceAttributes) + # only intercept requests to default namespace + - expression: request.resourceAttributes.namespace == 'default' + # don't intercept requests from default service accounts + - expression: !('system:serviceaccounts:default' in request.user.groups) +``` + +## What's next? +From Kubernetes 1.30, the feature is in beta and enabled by default. For +Kubernetes v1.31, we expect the feature to stay in beta while we get more +feedback from users. Once it is ready for GA, the feature flag will be removed, +and the configuration file version will be promoted to v1. + +Learn more about this feature on the [structured authorization +configuration](/docs/reference/access-authn-authz/authorization/#configuring-the-api-server-using-an-authorization-config-file) +Kubernetes doc website. You can also follow along with +[KEP-3221](https://kep.k8s.io/3221) to track progress in coming Kubernetes +releases. + +## Call to action +In this post, we have covered the benefits of the Structured Authorization +Configuration feature in Kubernetes v1.30 and a few sample configurations for +real-world scenarios. To use this feature, you must specify the path to the +authorization configuration using the `--authorization-config` command line +argument. From Kubernetes 1.30, the feature is in beta and enabled by default. +If you want to keep using command line flags instead of a configuration file, +those will continue to work as-is. Specifying both `--authorization-config` and +`--authorization-modes`/`--authorization-webhook-*` won't work. You need to drop +the older flags from your kube-apiserver command. + +The following kind Cluster configuration sets that command argument on the +APIserver to load an AuthorizationConfiguration from a file +(`authorization_config.yaml`) in the files folder. Any needed kubeconfig and +certificate files can also be put in the files directory. +```yaml +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +featureGates: + StructuredAuthorizationConfiguration: true # enabled by default in v1.30 +kubeadmConfigPatches: + - | + kind: ClusterConfiguration + metadata: + name: config + apiServer: + extraArgs: + authorization-config: "/files/authorization_config.yaml" + extraVolumes: + - name: files + hostPath: "/files" + mountPath: "/files" + readOnly: true +nodes: +- role: control-plane + extraMounts: + - hostPath: files + containerPath: /files +``` + +We would love to hear your feedback on this feature. In particular, we would +like feedback from Kubernetes cluster administrators and authorization webhook +implementors as they build their integrations with this new API. Please reach +out to us on the +[#sig-auth-authorizers-dev](https://kubernetes.slack.com/archives/C05EZFX1Z2L) +channel on Kubernetes Slack. + +## How to get involved +If you are interested in helping develop this feature, sharing feedback, or +participating in any other ongoing SIG Auth projects, please reach out on the +[#sig-auth](https://kubernetes.slack.com/archives/C0EN96KUY) channel on +Kubernetes Slack. + +You are also welcome to join the bi-weekly [SIG Auth +meetings](https://github.com/kubernetes/community/blob/master/sig-auth/README.md#meetings) +held every other Wednesday. + +## Acknowledgments +This feature was driven by contributors from several different companies. We +would like to extend a huge thank you to everyone who contributed their time and +effort to make this possible. \ No newline at end of file diff --git a/content/en/case-studies/_index.html b/content/en/case-studies/_index.html index 28bdab44afc5f..c9c120bf2b60a 100644 --- a/content/en/case-studies/_index.html +++ b/content/en/case-studies/_index.html @@ -5,6 +5,10 @@ abstract: A collection of users running Kubernetes in production. layout: basic class: gridPage +body_class: caseStudies cid: caseStudies +menu: + main: + weight: 60 --- diff --git a/content/en/docs/concepts/architecture/cgroups.md b/content/en/docs/concepts/architecture/cgroups.md index b96d89e0d6dd4..9e9f97eada5c5 100644 --- a/content/en/docs/concepts/architecture/cgroups.md +++ b/content/en/docs/concepts/architecture/cgroups.md @@ -38,7 +38,7 @@ cgroup v2 offers several improvements over cgroup v1, such as the following: Some Kubernetes features exclusively use cgroup v2 for enhanced resource management and isolation. For example, the -[MemoryQoS](/blog/2021/11/26/qos-memory-resources/) feature improves memory QoS +[MemoryQoS](/docs/concepts/workloads/pods/pod-qos/#memory-qos-with-cgroup-v2) feature improves memory QoS and relies on cgroup v2 primitives. diff --git a/content/en/docs/concepts/architecture/garbage-collection.md b/content/en/docs/concepts/architecture/garbage-collection.md index 4b36d850b55bb..ffc648014e47a 100644 --- a/content/en/docs/concepts/architecture/garbage-collection.md +++ b/content/en/docs/concepts/architecture/garbage-collection.md @@ -139,9 +139,9 @@ until disk usage reaches the `LowThresholdPercent` value. #### Garbage collection for unused container images {#image-maximum-age-gc} -{{< feature-state for_k8s_version="v1.29" state="alpha" >}} +{{< feature-state feature_gate_name="ImageMaximumGCAge" >}} -As an alpha feature, you can specify the maximum time a local image can be unused for, +As a beta feature, you can specify the maximum time a local image can be unused for, regardless of disk usage. This is a kubelet setting that you configure for each node. To configure the setting, enable the `ImageMaximumGCAge` @@ -151,6 +151,13 @@ and also set a value for the `ImageMaximumGCAge` field in the kubelet configurat The value is specified as a Kubernetes _duration_; for example, you can set the configuration field to `3d12h`, which means 3 days and 12 hours. +{{< note >}} +This feature does not track image usage across kubelet restarts. If the kubelet +is restarted, the tracked image age is reset, causing the kubelet to wait the full +`ImageMaximumGCAge` duration before qualifying images for garbage collection +based on image age. +{{< /note>}} + ### Container garbage collection {#container-image-garbage-collection} The kubelet garbage collects unused containers based on the following variables, diff --git a/content/en/docs/concepts/architecture/leases.md b/content/en/docs/concepts/architecture/leases.md index b07f4db3de256..065a4f944f3f2 100644 --- a/content/en/docs/concepts/architecture/leases.md +++ b/content/en/docs/concepts/architecture/leases.md @@ -1,5 +1,8 @@ --- title: Leases +api_metadata: +- apiVersion: "coordination.k8s.io/v1" + kind: "Lease" content_type: concept weight: 30 --- @@ -33,7 +36,7 @@ instances are on stand-by. ## API server identity -{{< feature-state for_k8s_version="v1.26" state="beta" >}} +{{< feature-state feature_gate_name="APIServerIdentity" >}} Starting in Kubernetes v1.26, each `kube-apiserver` uses the Lease API to publish its identity to the rest of the system. While not particularly useful on its own, this provides a mechanism for clients to diff --git a/content/en/docs/concepts/architecture/mixed-version-proxy.md b/content/en/docs/concepts/architecture/mixed-version-proxy.md index 36588430c1f32..1045c83119ec6 100644 --- a/content/en/docs/concepts/architecture/mixed-version-proxy.md +++ b/content/en/docs/concepts/architecture/mixed-version-proxy.md @@ -8,7 +8,7 @@ weight: 220 -{{< feature-state state="alpha" for_k8s_version="v1.28" >}} +{{< feature-state feature_gate_name="UnknownVersionInteroperabilityProxy" >}} Kubernetes {{< skew currentVersion >}} includes an alpha feature that lets an {{< glossary_tooltip text="API Server" term_id="kube-apiserver" >}} diff --git a/content/en/docs/concepts/architecture/nodes.md b/content/en/docs/concepts/architecture/nodes.md index 6473d35a17e25..636dfac5c878c 100644 --- a/content/en/docs/concepts/architecture/nodes.md +++ b/content/en/docs/concepts/architecture/nodes.md @@ -3,6 +3,9 @@ reviewers: - caesarxuchao - dchen1107 title: Nodes +api_metadata: +- apiVersion: "v1" + kind: "Node" content_type: concept weight: 10 --- @@ -115,9 +118,9 @@ are enabled, kubelets are only authorized to create/modify their own Node resour {{< note >}} As mentioned in the [Node name uniqueness](#node-name-uniqueness) section, when Node configuration needs to be updated, it is a good practice to re-register -the node with the API server. For example, if the kubelet being restarted with -the new set of `--node-labels`, but the same Node name is used, the change will -not take an effect, as labels are being set on the Node registration. +the node with the API server. For example, if the kubelet is being restarted with +a new set of `--node-labels`, but the same Node name is used, the change will +not take effect, as labels are only set (or modified) upon Node registration with the API server. Pods already scheduled on the Node may misbehave or cause issues if the Node configuration will be changed on kubelet restart. For example, already running @@ -280,7 +283,7 @@ If you want to explicitly reserve resources for non-Pod processes, see ## Node topology -{{< feature-state state="stable" for_k8s_version="v1.27" >}} +{{< feature-state feature_gate_name="TopologyManager" >}} If you have enabled the `TopologyManager` [feature gate](/docs/reference/command-line-tools-reference/feature-gates/), then @@ -290,7 +293,7 @@ for more information. ## Graceful node shutdown {#graceful-node-shutdown} -{{< feature-state state="beta" for_k8s_version="v1.21" >}} +{{< feature-state feature_gate_name="GracefulNodeShutdown" >}} The kubelet attempts to detect node system shutdown and terminates pods running on the node. @@ -374,7 +377,7 @@ Message: Pod was terminated in response to imminent node shutdown. ### Pod Priority based graceful node shutdown {#pod-priority-graceful-node-shutdown} -{{< feature-state state="beta" for_k8s_version="v1.24" >}} +{{< feature-state feature_gate_name="GracefulNodeShutdownBasedOnPodPriority" >}} To provide more flexibility during graceful node shutdown around the ordering of pods during shutdown, graceful node shutdown honors the PriorityClass for @@ -471,7 +474,7 @@ are emitted under the kubelet subsystem to monitor node shutdowns. ## Non-graceful node shutdown handling {#non-graceful-node-shutdown} -{{< feature-state state="stable" for_k8s_version="v1.28" >}} +{{< feature-state feature_gate_name="NodeOutOfServiceVolumeDetach" >}} A node shutdown action may not be detected by kubelet's Node Shutdown Manager, either because the command does not trigger the inhibitor locks mechanism used by @@ -513,14 +516,44 @@ During a non-graceful shutdown, Pods are terminated in the two phases: recovered since the user was the one who originally added the taint. {{< /note >}} +### Forced storage detach on timeout {#storage-force-detach-on-timeout} + +In any situation where a pod deletion has not succeeded for 6 minutes, kubernetes will +force detach volumes being unmounted if the node is unhealthy at that instant. Any +workload still running on the node that uses a force-detached volume will cause a +violation of the +[CSI specification](https://github.com/container-storage-interface/spec/blob/master/spec.md#controllerunpublishvolume), +which states that `ControllerUnpublishVolume` "**must** be called after all +`NodeUnstageVolume` and `NodeUnpublishVolume` on the volume are called and succeed". +In such circumstances, volumes on the node in question might encounter data corruption. + +The forced storage detach behaviour is optional; users might opt to use the "Non-graceful +node shutdown" feature instead. + +Force storage detach on timeout can be disabled by setting the `disable-force-detach-on-timeout` +config field in `kube-controller-manager`. Disabling the force detach on timeout feature means +that a volume that is hosted on a node that is unhealthy for more than 6 minutes will not have +its associated +[VolumeAttachment](/docs/reference/kubernetes-api/config-and-storage-resources/volume-attachment-v1/) +deleted. + +After this setting has been applied, unhealthy pods still attached to a volumes must be recovered +via the [Non-Graceful Node Shutdown](#non-graceful-node-shutdown) procedure mentioned above. + +{{< note >}} +- Caution must be taken while using the [Non-Graceful Node Shutdown](#non-graceful-node-shutdown) procedure. +- Deviation from the steps documented above can result in data corruption. +{{< /note >}} + ## Swap memory management {#swap-memory} -{{< feature-state state="beta" for_k8s_version="v1.28" >}} +{{< feature-state feature_gate_name="NodeSwap" >}} To enable swap on a node, the `NodeSwap` feature gate must be enabled on -the kubelet, and the `--fail-swap-on` command line flag or `failSwapOn` +the kubelet (default is true), and the `--fail-swap-on` command line flag or `failSwapOn` [configuration setting](/docs/reference/config-api/kubelet-config.v1beta1/) -must be set to false. +must be set to false. +To allow Pods to utilize swap, `swapBehavior` should not be set to `NoSwap` (which is the default behavior) in the kubelet config. {{< warning >}} When the memory swap feature is turned on, Kubernetes data such as the content @@ -532,17 +565,16 @@ specify how a node will use swap memory. For example, ```yaml memorySwap: - swapBehavior: UnlimitedSwap + swapBehavior: LimitedSwap ``` -- `UnlimitedSwap` (default): Kubernetes workloads can use as much swap memory as they - request, up to the system limit. +- `NoSwap` (default): Kubernetes workloads will not use swap. - `LimitedSwap`: The utilization of swap memory by Kubernetes workloads is subject to limitations. Only Pods of Burstable QoS are permitted to employ swap. If configuration for `memorySwap` is not specified and the feature gate is enabled, by default the kubelet will apply the same behaviour as the -`UnlimitedSwap` setting. +`NoSwap` setting. With `LimitedSwap`, Pods that do not fall under the Burstable QoS classification (i.e. `BestEffort`/`Guaranteed` Qos Pods) are prohibited from utilizing swap memory. @@ -578,6 +610,8 @@ Learn more about the following: * [API definition for Node](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#node-v1-core). * [Node](https://git.k8s.io/design-proposals-archive/architecture/architecture.md#the-kubernetes-node) section of the architecture design document. +* [Cluster autoscaling](/docs/concepts/cluster-administration/cluster-autoscaling/) to + manage the number and size of nodes in your cluster. * [Taints and Tolerations](/docs/concepts/scheduling-eviction/taint-and-toleration/). * [Node Resource Managers](/docs/concepts/policy/node-resource-managers/). * [Resource Management for Windows nodes](/docs/concepts/configuration/windows-resource-management/). diff --git a/content/en/docs/concepts/cluster-administration/_index.md b/content/en/docs/concepts/cluster-administration/_index.md index 2c7baf1d9871e..456069c980175 100644 --- a/content/en/docs/concepts/cluster-administration/_index.md +++ b/content/en/docs/concepts/cluster-administration/_index.md @@ -52,6 +52,7 @@ Before choosing a guide, here are some considerations: ## Managing a cluster * Learn how to [manage nodes](/docs/concepts/architecture/nodes/). + * Read about [cluster autoscaling](/docs/concepts/cluster-administration/cluster-autoscaling/). * Learn how to set up and manage the [resource quota](/docs/concepts/policy/resource-quotas/) for shared clusters. diff --git a/content/en/docs/concepts/cluster-administration/addons.md b/content/en/docs/concepts/cluster-administration/addons.md index 7c2ab269e4a63..c46fc6940ec51 100644 --- a/content/en/docs/concepts/cluster-administration/addons.md +++ b/content/en/docs/concepts/cluster-administration/addons.md @@ -1,7 +1,7 @@ --- title: Installing Addons content_type: concept -weight: 120 +weight: 150 --- @@ -82,7 +82,7 @@ installation instructions. The list does not try to be exhaustive. * [Spiderpool](https://github.com/spidernet-io/spiderpool) is an underlay and RDMA networking solution for Kubernetes. Spiderpool is supported on bare metal, virtual machines, and public cloud environments. -* [Weave Net](https://www.weave.works/docs/net/latest/kubernetes/kube-addon/) +* [Weave Net](https://github.com/rajch/weave#using-weave-on-kubernetes) provides networking and network policy, will carry on working on both sides of a network partition, and does not require an external database. @@ -109,6 +109,10 @@ installation instructions. The list does not try to be exhaustive. [Events](/docs/reference/kubernetes-api/cluster-resources/event-v1/) or [Node conditions](/docs/concepts/architecture/nodes/#condition). +## Instrumentation + +* [kube-state-metrics](/docs/concepts/cluster-administration/kube-state-metrics) + ## Legacy Add-ons There are several other add-ons documented in the deprecated diff --git a/content/en/docs/concepts/cluster-administration/cluster-autoscaling.md b/content/en/docs/concepts/cluster-administration/cluster-autoscaling.md new file mode 100644 index 0000000000000..495943b65a27a --- /dev/null +++ b/content/en/docs/concepts/cluster-administration/cluster-autoscaling.md @@ -0,0 +1,117 @@ +--- +title: Cluster Autoscaling +linkTitle: Cluster Autoscaling +description: >- + Automatically manage the nodes in your cluster to adapt to demand. +content_type: concept +weight: 120 +--- + + + +Kubernetes requires {{< glossary_tooltip text="nodes" term_id="node" >}} in your cluster to +run {{< glossary_tooltip text="pods" term_id="pod" >}}. This means providing capacity for +the workload Pods and for Kubernetes itself. + +You can adjust the amount of resources available in your cluster automatically: +_node autoscaling_. You can either change the number of nodes, or change the capacity +that nodes provide. The first approach is referred to as _horizontal scaling_, while the +second is referred to as _vertical scaling_. + +Kubernetes can even provide multidimensional automatic scaling for nodes. + + + +## Manual node management + +You can manually manage node-level capacity, where you configure a fixed amount of nodes; +you can use this approach even if the provisioning (the process to set up, manage, and +decommission) for these nodes is automated. + +This page is about taking the next step, and automating management of the amount of +node capacity (CPU, memory, and other node resources) available in your cluster. + +## Automatic horizontal scaling {#autoscaling-horizontal} + +### Cluster Autoscaler + +You can use the [Cluster Autoscaler](https://github.com/kubernetes/autoscaler/tree/master/cluster-autoscaler) to manage the scale of your nodes automatically. +The cluster autoscaler can integrate with a cloud provider, or with Kubernetes' +[cluster API](https://github.com/kubernetes/autoscaler/blob/c6b754c359a8563050933a590f9a5dece823c836/cluster-autoscaler/cloudprovider/clusterapi/README.md), +to achieve the actual node management that's needed. + +The cluster autoscaler adds nodes when there are unschedulable Pods, and +removes nodes when those nodes are empty. + +#### Cloud provider integrations {#cluster-autoscaler-providers} + +The [README](https://github.com/kubernetes/autoscaler/tree/c6b754c359a8563050933a590f9a5dece823c836/cluster-autoscaler#readme) +for the cluster autoscaler lists some of the cloud provider integrations +that are available. + +## Cost-aware multidimensional scaling {#autoscaling-multi-dimension} + +### Karpenter {#autoscaler-karpenter} + +[Karpenter](https://karpenter.sh/) supports direct node management, via +plugins that integrate with specific cloud providers, and can manage nodes +for you whilst optimizing for overall cost. + +> Karpenter automatically launches just the right compute resources to +> handle your cluster's applications. It is designed to let you take +> full advantage of the cloud with fast and simple compute provisioning +> for Kubernetes clusters. + +The Karpenter tool is designed to integrate with a cloud provider that +provides API-driven server management, and where the price information for +available servers is also available via a web API. + +For example, if you start some more Pods in your cluster, the Karpenter +tool might buy a new node that is larger than one of the nodes you are +already using, and then shut down an existing node once the new node +is in service. + +#### Cloud provider integrations {#karpenter-providers} + +{{% thirdparty-content vendor="true" %}} + +There are integrations available between Karpenter's core and the following +cloud providers: + +- [Amazon Web Services](https://github.com/aws/karpenter-provider-aws) +- [Azure](https://github.com/Azure/karpenter-provider-azure) + + +## Related components + +### Descheduler + +The [descheduler](https://github.com/kubernetes-sigs/descheduler) can help you +consolidate Pods onto a smaller number of nodes, to help with automatic scale down +when the cluster has space capacity. + +### Sizing a workload based on cluster size + +#### Cluster proportional autoscaler + +For workloads that need to be scaled based on the size of the cluster (for example +`cluster-dns` or other system components), you can use the +[_Cluster Proportional Autoscaler_](https://github.com/kubernetes-sigs/cluster-proportional-autoscaler).
+ +The Cluster Proportional Autoscaler watches the number of schedulable nodes +and cores, and scales the number of replicas of the target workload accordingly. + +#### Cluster proportional vertical autoscaler + +If the number of replicas should stay the same, you can scale your workloads vertically according to the cluster size using +the [_Cluster Proportional Vertical Autoscaler_](https://github.com/kubernetes-sigs/cluster-proportional-vertical-autoscaler). +This project is in **beta** and can be found on GitHub. + +While the Cluster Proportional Autoscaler scales the number of replicas of a workload, the Cluster Proportional Vertical Autoscaler +adjusts the resource requests for a workload (for example a Deployment or DaemonSet) based on the number of nodes and/or cores +in the cluster. + + +## {{% heading "whatsnext" %}} + +- Read about [workload-level autoscaling](/docs/concepts/workloads/autoscaling/) diff --git a/content/en/docs/concepts/cluster-administration/kube-state-metrics.md b/content/en/docs/concepts/cluster-administration/kube-state-metrics.md new file mode 100644 index 0000000000000..4be0318fdf867 --- /dev/null +++ b/content/en/docs/concepts/cluster-administration/kube-state-metrics.md @@ -0,0 +1,46 @@ +--- +title: Metrics for Kubernetes Object States +content_type: concept +weight: 75 +description: >- + kube-state-metrics, an add-on agent to generate and expose cluster-level metrics. +--- + +The state of Kubernetes objects in the Kubernetes API can be exposed as metrics. +An add-on agent called [kube-state-metrics](https://github.com/kubernetes/kube-state-metrics) can connect to the Kubernetes API server and expose a HTTP endpoint with metrics generated from the state of individual objects in the cluster. +It exposes various information about the state of objects like labels and annotations, startup and termination times, status or the phase the object currently is in. +For example, containers running in pods create a `kube_pod_container_info` metric. +This includes the name of the container, the name of the pod it is part of, the {{< glossary_tooltip text="namespace" term_id="namespace" >}} the pod is running in, the name of the container image, the ID of the image, the image name from the spec of the container, the ID of the running container and the ID of the pod as labels. + +{{% thirdparty-content single="true" %}} + +An external component that is able and capable to scrape the endpoint of kube-state-metrics (for example via Prometheus) can now be used to enable the following use cases. + +## Example: using metrics from kube-state-metrics to query the cluster state {#example-kube-state-metrics-query-1} + +Metric series generated by kube-state-metrics are helpful to gather further insights into the cluster, as they can be used for querying. + +If you use Prometheus or another tool that uses the same query language, the following PromQL query returns the number of pods that are not ready: + +``` +count(kube_pod_status_ready{condition="false"}) by (namespace, pod) +``` + +## Example: alerting based on from kube-state-metrics {#example-kube-state-metrics-alert-1} + +Metrics generated from kube-state-metrics also allow for alerting on issues in the cluster. + +If you use Prometheus or a similar tool that uses the same alert rule language, the following alert will fire if there are pods that have been in a `Terminating` state for more than 5 minutes: + +```yaml +groups: +- name: Pod state + rules: + - alert: PodsBlockedInTerminatingState + expr: count(kube_pod_deletion_timestamp) by (namespace, pod) * count(kube_pod_status_reason{reason="NodeLost"} == 0) by (namespace, pod) > 0 + for: 5m + labels: + severity: page + annotations: + summary: Pod {{$labels.namespace}}/{{$labels.pod}} blocked in Terminating state. +``` diff --git a/content/en/docs/concepts/cluster-administration/logging.md b/content/en/docs/concepts/cluster-administration/logging.md index 7b8722537f182..5cc9429578bf0 100644 --- a/content/en/docs/concepts/cluster-administration/logging.md +++ b/content/en/docs/concepts/cluster-administration/logging.md @@ -97,19 +97,26 @@ The usual way to access this is by running `kubectl logs`. {{< feature-state for_k8s_version="v1.21" state="stable" >}} -You can configure the kubelet to rotate logs automatically. - -If you configure rotation, the kubelet is responsible for rotating container logs and managing the +The kubelet is responsible for rotating container logs and managing the logging directory structure. The kubelet sends this information to the container runtime (using CRI), and the runtime writes the container logs to the given location. You can configure two kubelet [configuration settings](/docs/reference/config-api/kubelet-config.v1beta1/), -`containerLogMaxSize` and `containerLogMaxFiles`, +`containerLogMaxSize` (default 10Mi) and `containerLogMaxFiles` (default 5), using the [kubelet configuration file](/docs/tasks/administer-cluster/kubelet-config-file/). These settings let you configure the maximum size for each log file and the maximum number of files allowed for each container respectively. +In order to perform an efficient log rotation in clusters where the volume of the logs generated by +the workload is large, kubelet also provides a mechanism to tune how the logs are rotated in +terms of how many concurrent log rotations can be performed and the interval at which the logs are +monitored and rotated as required. +You can configure two kubelet [configuration settings](/docs/reference/config-api/kubelet-config.v1beta1/), +`containerLogMaxWorkers` and `containerLogMonitorInterval` using the +[kubelet configuration file](/docs/tasks/administer-cluster/kubelet-config-file/). + + When you run [`kubectl logs`](/docs/reference/generated/kubectl/kubectl-commands#logs) as in the basic logging example, the kubelet on the node handles the request and reads directly from the log file. The kubelet returns the content of the log file. @@ -150,7 +157,7 @@ If systemd is not present, the kubelet and container runtime write to `.log` fil run the kubelet via a helper tool, `kube-log-runner`, and use that tool to redirect kubelet logs to a directory that you choose. -The kubelet always directs your container runtime to write logs into directories within +By default, kubelet directs your container runtime to write logs into directories within `/var/log/pods`. For more information on `kube-log-runner`, read [System Logs](/docs/concepts/cluster-administration/system-logs/#klog). @@ -168,7 +175,7 @@ If you want to have logs written elsewhere, you can indirectly run the kubelet via a helper tool, `kube-log-runner`, and use that tool to redirect kubelet logs to a directory that you choose. -However, the kubelet always directs your container runtime to write logs within the +However, by default, kubelet directs your container runtime to write logs within the directory `C:\var\log\pods`. For more information on `kube-log-runner`, read [System Logs](/docs/concepts/cluster-administration/system-logs/#klog). @@ -182,6 +189,22 @@ the `/var/log` directory, bypassing the default logging mechanism (the component do not write to the systemd journal). You can use Kubernetes' storage mechanisms to map persistent storage into the container that runs the component. +Kubelet allows changing the pod logs directory from default `/var/log/pods` +to a custom path. This adjustment can be made by configuring the `podLogsDir` +parameter in the kubelet's configuration file. + +{{< caution >}} +It's important to note that the default location `/var/log/pods` has been in use for +an extended period and certain processes might implicitly assume this path. +Therefore, altering this parameter must be approached with caution and at your own risk. + +Another caveat to keep in mind is that the kubelet supports the location being on the same +disk as `/var`. Otherwise, if the logs are on a separate filesystem from `/var`, +then the kubelet will not track that filesystem's usage, potentially leading to issues if +it fills up. + +{{< /caution >}} + For details about etcd and its logs, view the [etcd documentation](https://etcd.io/docs/). Again, you can use Kubernetes' storage mechanisms to map persistent storage into the container that runs the component. @@ -202,7 +225,7 @@ as your responsibility. ## Cluster-level logging architectures -While Kubernetes does not provide a native solution for cluster-level logging, there are +While Kubernetes does not provide a native solution for cluster-level logging, there are several common approaches you can consider. Here are some options: * Use a node-level logging agent that runs on every node. diff --git a/content/en/docs/concepts/cluster-administration/system-logs.md b/content/en/docs/concepts/cluster-administration/system-logs.md index 1feeecd3db7e5..6af3effcdd5dc 100644 --- a/content/en/docs/concepts/cluster-administration/system-logs.md +++ b/content/en/docs/concepts/cluster-administration/system-logs.md @@ -122,7 +122,7 @@ second line.} ### Contextual Logging -{{< feature-state for_k8s_version="v1.24" state="alpha" >}} +{{< feature-state for_k8s_version="v1.30" state="beta" >}} Contextual logging builds on top of structured logging. It is primarily about how developers use logging calls: code based on that concept is more flexible @@ -133,8 +133,9 @@ If developers use additional functions like `WithValues` or `WithName` in their components, then log entries contain additional information that gets passed into functions by their caller. -Currently this is gated behind the `StructuredLogging` feature gate and -disabled by default. The infrastructure for this was added in 1.24 without +For Kubernetes {{< skew currentVersion >}}, this is gated behind the `ContextualLogging` +[feature gate](/docs/reference/command-line-tools-reference/feature-gates/) and is +enabled by default. The infrastructure for this was added in 1.24 without modifying components. The [`component-base/logs/example`](https://github.com/kubernetes/kubernetes/blob/v1.24.0-beta.0/staging/src/k8s.io/component-base/logs/example/cmd/logger.go) command demonstrates how to use the new logging calls and how a component @@ -147,14 +148,14 @@ $ go run . --help --feature-gates mapStringBool A set of key=value pairs that describe feature gates for alpha/experimental features. Options are: AllAlpha=true|false (ALPHA - default=false) AllBeta=true|false (BETA - default=false) - ContextualLogging=true|false (ALPHA - default=false) + ContextualLogging=true|false (BETA - default=true) $ go run . --feature-gates ContextualLogging=true ... -I0404 18:00:02.916429 451895 logger.go:94] "example/myname: runtime" foo="bar" duration="1m0s" -I0404 18:00:02.916447 451895 logger.go:95] "example: another runtime" foo="bar" duration="1m0s" +I0222 15:13:31.645988 197901 example.go:54] "runtime" logger="example.myname" foo="bar" duration="1m0s" +I0222 15:13:31.646007 197901 example.go:55] "another runtime" logger="example" foo="bar" duration="1h0m0s" duration="1m0s" ``` -The `example` prefix and `foo="bar"` were added by the caller of the function +The `logger` key and `foo="bar"` were added by the caller of the function which logs the `runtime` message and `duration="1m0s"` value, without having to modify that function. @@ -165,8 +166,8 @@ is not in the log output anymore: ```console $ go run . --feature-gates ContextualLogging=false ... -I0404 18:03:31.171945 452150 logger.go:94] "runtime" duration="1m0s" -I0404 18:03:31.171962 452150 logger.go:95] "another runtime" duration="1m0s" +I0222 15:14:40.497333 198174 example.go:54] "runtime" duration="1m0s" +I0222 15:14:40.497346 198174 example.go:55] "another runtime" duration="1h0m0s" duration="1m0s" ``` ### JSON log format @@ -238,17 +239,17 @@ The `logrotate` tool rotates logs daily, or once the log size is greater than 10 ## Log query -{{< feature-state for_k8s_version="v1.27" state="alpha" >}} +{{< feature-state feature_gate_name="NodeLogQuery" >}} To help with debugging issues on nodes, Kubernetes v1.27 introduced a feature that allows viewing logs of services running on the node. To use the feature, ensure that the `NodeLogQuery` [feature gate](/docs/reference/command-line-tools-reference/feature-gates/) is enabled for that node, and that the kubelet configuration options `enableSystemLogHandler` and `enableSystemLogQuery` are both set to true. On Linux -we assume that service logs are available via journald. On Windows we assume that service logs are available -in the application log provider. On both operating systems, logs are also available by reading files within +the assumption is that service logs are available via journald. On Windows the assumption is that service logs are +available in the application log provider. On both operating systems, logs are also available by reading files within `/var/log/`. -Provided you are authorized to interact with node objects, you can try out this alpha feature on all your nodes or +Provided you are authorized to interact with node objects, you can try out this feature on all your nodes or just a subset. Here is an example to retrieve the kubelet service logs from a node: ```shell @@ -293,4 +294,4 @@ kubectl get --raw "/api/v1/nodes/node-1.example/proxy/logs/?query=kubelet&patter * Read about [Contextual Logging](https://github.com/kubernetes/enhancements/tree/master/keps/sig-instrumentation/3077-contextual-logging) * Read about [deprecation of klog flags](https://github.com/kubernetes/enhancements/tree/master/keps/sig-instrumentation/2845-deprecate-klog-specific-flags-in-k8s-components) * Read about the [Conventions for logging severity](https://github.com/kubernetes/community/blob/master/contributors/devel/sig-instrumentation/logging.md) - +* Read about [Log Query](https://kep.k8s.io/2258) diff --git a/content/en/docs/concepts/cluster-administration/system-traces.md b/content/en/docs/concepts/cluster-administration/system-traces.md index aaaf342b57042..7f2dc3d4c6fd3 100644 --- a/content/en/docs/concepts/cluster-administration/system-traces.md +++ b/content/en/docs/concepts/cluster-administration/system-traces.md @@ -22,6 +22,9 @@ with the gRPC exporter and can be collected and routed to tracing backends using ## Trace Collection +Kubernetes components have built-in gRPC exporters for OTLP to export traces, either with an OpenTelemetry Collector, +or without an OpenTelemetry Collector. + For a complete guide to collecting traces and using the collector, see [Getting Started with the OpenTelemetry Collector](https://opentelemetry.io/docs/collector/getting-started/). However, there are a few things to note that are specific to Kubernetes components. @@ -47,6 +50,16 @@ service: exporters: [logging] ``` +To directly emit traces to a backend without utilizing a collector, +specify the endpoint field in the Kubernetes tracing configuration file with the desired trace backend address. +This method negates the need for a collector and simplifies the overall structure. + +For trace backend header configuration, including authentication details, environment variables can be used with `OTEL_EXPORTER_OTLP_HEADERS`, +see [OTLP Exporter Configuration](https://opentelemetry.io/docs/languages/sdk-configuration/otlp-exporter/). + +Additionally, for trace resource attribute configuration such as Kubernetes cluster name, namespace, Pod name, etc., +environment variables can also be used with `OTEL_RESOURCE_ATTRIBUTES`, see [OTLP Kubernetes Resource](https://opentelemetry.io/docs/specs/semconv/resource/k8s/). + ## Component traces ### kube-apiserver traces @@ -76,7 +89,7 @@ For more information about the `TracingConfiguration` struct, see ### kubelet traces -{{< feature-state for_k8s_version="v1.27" state="beta" >}} +{{< feature-state feature_gate_name="KubeletTracing" >}} The kubelet CRI interface and authenticated http servers are instrumented to generate trace spans. As with the apiserver, the endpoint and sampling rate are configurable. @@ -129,4 +142,6 @@ there are no guarantees of backwards compatibility for tracing instrumentation. ## {{% heading "whatsnext" %}} * Read about [Getting Started with the OpenTelemetry Collector](https://opentelemetry.io/docs/collector/getting-started/) +* Read about [OTLP Exporter Configuration](https://opentelemetry.io/docs/languages/sdk-configuration/otlp-exporter/) + diff --git a/content/en/docs/concepts/configuration/configmap.md b/content/en/docs/concepts/configuration/configmap.md index eca8455db89f5..49ece878fc8c5 100644 --- a/content/en/docs/concepts/configuration/configmap.md +++ b/content/en/docs/concepts/configuration/configmap.md @@ -1,5 +1,8 @@ --- title: ConfigMaps +api_metadata: +- apiVersion: "v1" + kind: "ConfigMap" content_type: concept weight: 20 --- @@ -205,6 +208,42 @@ ConfigMaps consumed as environment variables are not updated automatically and r A container using a ConfigMap as a [subPath](/docs/concepts/storage/volumes#using-subpath) volume mount will not receive ConfigMap updates. {{< /note >}} + +### Using Configmaps as environment variables + +To use a Configmap in an {{< glossary_tooltip text="environment variable" term_id="container-env-variables" >}} +in a Pod: + +1. For each container in your Pod specification, add an environment variable + for each Configmap key that you want to use to the + `env[].valueFrom.configMapKeyRef` field. +1. Modify your image and/or command line so that the program looks for values + in the specified environment variables. + +This is an example of defining a ConfigMap as a pod environment variable: +```yaml +apiVersion: v1 +kind: Pod +metadata: + name: env-configmap +spec: + containers: + - name: envars-test-container + image: nginx + env: + - name: CONFIGMAP_USERNAME + valueFrom: + configMapKeyRef: + name: myconfigmap + key: username + +``` + +It's important to note that the range of characters allowed for environment +variable names in pods is [restricted](/docs/tasks/inject-data-application/define-environment-variable-container/#using-environment-variables-inside-of-your-config). +If any keys do not meet the rules, those keys are not made available to your container, though +the Pod is allowed to start. + ## Immutable ConfigMaps {#configmap-immutable} {{< feature-state for_k8s_version="v1.21" state="stable" >}} diff --git a/content/en/docs/concepts/configuration/manage-resources-containers.md b/content/en/docs/concepts/configuration/manage-resources-containers.md index d5c4134fd31df..4d21ec995051f 100644 --- a/content/en/docs/concepts/configuration/manage-resources-containers.md +++ b/content/en/docs/concepts/configuration/manage-resources-containers.md @@ -616,7 +616,7 @@ available amount is simultaneously allocated to Pods. The API server restricts quantities of extended resources to whole numbers. Examples of _valid_ quantities are `3`, `3000m` and `3Ki`. Examples of -_invalid_ quantities are `0.5` and `1500m`. +_invalid_ quantities are `0.5` and `1500m` (because `1500m` would result in `1.5`). {{< note >}} Extended resources replace Opaque Integer Resources. diff --git a/content/en/docs/concepts/configuration/secret.md b/content/en/docs/concepts/configuration/secret.md index e692491273e39..e27f86cc0ebe8 100644 --- a/content/en/docs/concepts/configuration/secret.md +++ b/content/en/docs/concepts/configuration/secret.md @@ -2,6 +2,9 @@ reviewers: - mikedanese title: Secrets +api_metadata: +- apiVersion: "v1" + kind: "Secret" content_type: concept feature: title: Secret and configuration management @@ -564,25 +567,10 @@ in a Pod: For instructions, refer to [Define container environment variables using Secret data](/docs/tasks/inject-data-application/distribute-credentials-secure/#define-container-environment-variables-using-secret-data). -#### Invalid environment variables {#restriction-env-from-invalid} - -If your environment variable definitions in your Pod specification are -considered to be invalid environment variable names, those keys aren't made -available to your container. The Pod is allowed to start. - -Kubernetes adds an Event with the reason set to `InvalidVariableNames` and a -message that lists the skipped invalid keys. The following example shows a Pod that refers to a Secret named `mysecret`, where `mysecret` contains 2 invalid keys: `1badkey` and `2alsobad`. - -```shell -kubectl get events -``` - -The output is similar to: - -``` -LASTSEEN FIRSTSEEN COUNT NAME KIND SUBOBJECT TYPE REASON -0s 0s 1 dapi-test-pod Pod Warning InvalidEnvironmentVariableNames kubelet, 127.0.0.1 Keys [1badkey, 2alsobad] from the EnvFrom secret default/mysecret were skipped since they are considered invalid environment variable names. -``` +It's important to note that the range of characters allowed for environment variable +names in pods is [restricted](/docs/tasks/inject-data-application/define-environment-variable-container/#using-environment-variables-inside-of-your-config). +If any keys do not meet the rules, those keys are not made available to your container, though +the Pod is allowed to start. ### Container image pull Secrets {#using-imagepullsecrets} diff --git a/content/en/docs/concepts/containers/container-lifecycle-hooks.md b/content/en/docs/concepts/containers/container-lifecycle-hooks.md index 9cb9fa367779d..21d6acc1d6286 100644 --- a/content/en/docs/concepts/containers/container-lifecycle-hooks.md +++ b/content/en/docs/concepts/containers/container-lifecycle-hooks.md @@ -56,8 +56,7 @@ There are three types of hook handlers that can be implemented for Containers: Resources consumed by the command are counted against the Container. * HTTP - Executes an HTTP request against a specific endpoint on the Container. * Sleep - Pauses the container for a specified duration. - The "Sleep" action is available when the [feature gate](/docs/reference/command-line-tools-reference/feature-gates/) - `PodLifecycleSleepAction` is enabled. + This is a beta-level feature default enabled by the `PodLifecycleSleepAction` [feature gate](/docs/reference/command-line-tools-reference/feature-gates/). ### Hook handler execution diff --git a/content/en/docs/concepts/containers/images.md b/content/en/docs/concepts/containers/images.md index 9b36a6b72803d..8602d6c98d15b 100644 --- a/content/en/docs/concepts/containers/images.md +++ b/content/en/docs/concepts/containers/images.md @@ -161,7 +161,7 @@ which is 300 seconds (5 minutes). ### Image pull per runtime class -{{< feature-state for_k8s_version="v1.29" state="alpha" >}} +{{< feature-state feature_gate_name="RuntimeClassInImageCriApi" >}} Kubernetes includes alpha support for performing image pulls based on the RuntimeClass of a Pod. If you enable the `RuntimeClassInImageCriApi` [feature gate](/docs/reference/command-line-tools-reference/feature-gates/), diff --git a/content/en/docs/concepts/extend-kubernetes/api-extension/_index.md b/content/en/docs/concepts/extend-kubernetes/api-extension/_index.md index 454e491be8d17..6f67d445ecc9f 100644 --- a/content/en/docs/concepts/extend-kubernetes/api-extension/_index.md +++ b/content/en/docs/concepts/extend-kubernetes/api-extension/_index.md @@ -2,3 +2,18 @@ title: Extending the Kubernetes API weight: 30 --- + +Custom resources are extensions of the Kubernetes API. Kubernetes provides two ways to add custom resources to your cluster: + +- The [CustomResourceDefinition](/docs/concepts/extend-kubernetes/api-extension/custom-resources/) + (CRD) mechanism allows you to declaratively define a new custom API with an API group, kind, and + schema that you specify. + The Kubernetes control plane serves and handles the storage of your custom resource. CRDs allow you to + create new types of resources for your cluster without writing and running a custom API server. +- The [aggregation layer](/docs/concepts/extend-kubernetes/api-extension/apiserver-aggregation/) + sits behind the primary API server, which acts as a proxy. + This arrangement is called API Aggregation (AA), which allows you to provide + specialized implementations for your custom resources by writing and + deploying your own API server. + The main API server delegates requests to your API server for the custom APIs that you specify, + making them available to all of its clients. diff --git a/content/en/docs/concepts/extend-kubernetes/api-extension/custom-resources.md b/content/en/docs/concepts/extend-kubernetes/api-extension/custom-resources.md index aafb04fd83f3f..5e8ac0a935c24 100644 --- a/content/en/docs/concepts/extend-kubernetes/api-extension/custom-resources.md +++ b/content/en/docs/concepts/extend-kubernetes/api-extension/custom-resources.md @@ -3,6 +3,9 @@ title: Custom Resources reviewers: - enisoc - deads2k +api_metadata: +- apiVersion: "apiextensions.k8s.io/v1" + kind: "CustomResourceDefinition" content_type: concept weight: 10 --- @@ -292,6 +295,50 @@ When you add a custom resource, you can access it using: (generating one is an advanced undertaking, but some projects may provide a client along with the CRD or AA). + +## Custom resource field selectors + +[Field Selectors](/docs/concepts/overview/working-with-objects/field-selectors/) +let clients select custom resources based on the value of one or more resource +fields. + +All custom resources support the `metadata.name` and `metadata.namespace` field +selectors. + +Fields declared in a {{< glossary_tooltip term_id="CustomResourceDefinition" text="CustomResourceDefinition" >}} +may also be used with field selectors when included in the `spec.versions[*].selectableFields` field of the +{{< glossary_tooltip term_id="CustomResourceDefinition" text="CustomResourceDefinition" >}}. + +### Selectable fields for custom resources {#crd-selectable-fields} + +{{< feature-state feature_gate_name="CustomResourceFieldSelectors" >}} + +You need to enable the `CustomResourceFieldSelectors` +[feature gate](/docs/reference/command-line-tools-reference/feature-gates/) to +use this behavior, which then applies to all CustomResourceDefinitions in your +cluster. + +The `spec.versions[*].selectableFields` field of a {{< glossary_tooltip term_id="CustomResourceDefinition" text="CustomResourceDefinition" >}} may be used to +declare which other fields in a custom resource may be used in field selectors. +The following example adds the `.spec.color` and `.spec.size` fields as +selectable fields. + +{{% code_sample file="customresourcedefinition/shirt-resource-definition.yaml" %}} + +Field selectors can then be used to get only resources with with a `color` of `blue`: + +```shell +kubectl get shirts.stable.example.com --field-selector spec.color=blue +``` + +The output should be: + +``` +NAME COLOR SIZE +example1 blue S +example2 blue M +``` + ## {{% heading "whatsnext" %}} * Learn how to [Extend the Kubernetes API with the aggregation layer](/docs/concepts/extend-kubernetes/api-extension/apiserver-aggregation/). diff --git a/content/en/docs/concepts/extend-kubernetes/compute-storage-net/device-plugins.md b/content/en/docs/concepts/extend-kubernetes/compute-storage-net/device-plugins.md index 6516179150e43..6752c43a0d88d 100644 --- a/content/en/docs/concepts/extend-kubernetes/compute-storage-net/device-plugins.md +++ b/content/en/docs/concepts/extend-kubernetes/compute-storage-net/device-plugins.md @@ -454,7 +454,8 @@ pluginapi.Device{ID: "25102017", Health: pluginapi.Healthy, Topology:&pluginapi. Here are some examples of device plugin implementations: -* The [AMD GPU device plugin](https://github.com/RadeonOpenCompute/k8s-device-plugin) +* [Akri](https://github.com/project-akri/akri), which lets you easily expose heterogeneous leaf devices (such as IP cameras and USB devices). +* The [AMD GPU device plugin](https://github.com/ROCm/k8s-device-plugin) * The [generic device plugin](https://github.com/squat/generic-device-plugin) for generic Linux devices and USB devices * The [Intel device plugins](https://github.com/intel/intel-device-plugins-for-kubernetes) for Intel GPU, FPGA, QAT, VPU, SGX, DSA, DLB and IAA devices diff --git a/content/en/docs/concepts/extend-kubernetes/compute-storage-net/network-plugins.md b/content/en/docs/concepts/extend-kubernetes/compute-storage-net/network-plugins.md index cae75f99e334a..089d0c418381c 100644 --- a/content/en/docs/concepts/extend-kubernetes/compute-storage-net/network-plugins.md +++ b/content/en/docs/concepts/extend-kubernetes/compute-storage-net/network-plugins.md @@ -54,19 +54,6 @@ that plugin or [networking provider](/docs/concepts/cluster-administration/netwo ## Network Plugin Requirements -For plugin developers and users who regularly build or deploy Kubernetes, the plugin may also need -specific configuration to support kube-proxy. The iptables proxy depends on iptables, and the -plugin may need to ensure that container traffic is made available to iptables. For example, if -the plugin connects containers to a Linux bridge, the plugin must set the -`net/bridge/bridge-nf-call-iptables` sysctl to `1` to ensure that the iptables proxy functions -correctly. If the plugin does not use a Linux bridge, but uses something like Open vSwitch or -some other mechanism instead, it should ensure container traffic is appropriately routed for the -proxy. - -By default, if no kubelet network plugin is specified, the `noop` plugin is used, which sets -`net/bridge/bridge-nf-call-iptables=1` to ensure simple configurations (like Docker with a bridge) -work correctly with the iptables proxy. - ### Loopback CNI In addition to the CNI plugin installed on the nodes for implementing the Kubernetes network diff --git a/content/en/docs/concepts/overview/components.md b/content/en/docs/concepts/overview/components.md index 28b633c141a29..177354fa47812 100644 --- a/content/en/docs/concepts/overview/components.md +++ b/content/en/docs/concepts/overview/components.md @@ -31,7 +31,7 @@ as well as detecting and responding to cluster events (for example, starting up `{{< glossary_tooltip text="replicas" term_id="replica" >}}` field is unsatisfied). Control plane components can be run on any machine in the cluster. However, -for simplicity, set up scripts typically start all control plane components on +for simplicity, setup scripts typically start all control plane components on the same machine, and do not run user containers on this machine. See [Creating Highly Available clusters with kubeadm](/docs/setup/production-environment/tools/kubeadm/high-availability/) for an example control plane setup that runs across multiple machines. @@ -150,4 +150,4 @@ Learn more about the following: * Etcd's official [documentation](https://etcd.io/docs/). * Several [container runtimes](/docs/setup/production-environment/container-runtimes/) in Kubernetes. * Integrating with cloud providers using [cloud-controller-manager](/docs/concepts/architecture/cloud-controller/). - * [kubectl](/docs/reference/generated/kubectl/kubectl-commands) commands. \ No newline at end of file + * [kubectl](/docs/reference/generated/kubectl/kubectl-commands) commands. diff --git a/content/en/docs/concepts/overview/kubernetes-api.md b/content/en/docs/concepts/overview/kubernetes-api.md index ceec7e1eacd3d..c8e5840ad0bf2 100644 --- a/content/en/docs/concepts/overview/kubernetes-api.md +++ b/content/en/docs/concepts/overview/kubernetes-api.md @@ -22,21 +22,139 @@ external components communicate with one another. The Kubernetes API lets you query and manipulate the state of API objects in Kubernetes (for example: Pods, Namespaces, ConfigMaps, and Events). -Most operations can be performed through the -[kubectl](/docs/reference/kubectl/) command-line interface or other -command-line tools, such as -[kubeadm](/docs/reference/setup-tools/kubeadm/), which in turn use the -API. However, you can also access the API directly using REST calls. +Most operations can be performed through the [kubectl](/docs/reference/kubectl/) +command-line interface or other command-line tools, such as +[kubeadm](/docs/reference/setup-tools/kubeadm/), which in turn use the API. +However, you can also access the API directly using REST calls. Kubernetes +provides a set of [client libraries](/docs/reference/using-api/client-libraries/) +for those looking to +write applications using the Kubernetes API. + +Each Kubernetes cluster publishes the specification of the APIs that the cluster serves. +There are two mechanisms that Kubernetes uses to publish these API specifications; both are useful +to enable automatic interoperability. For example, the `kubectl` tool fetches and caches the API +specification for enabling command-line completion and other features. +The two supported mechanisms are as follows: + +- [The Discovery API](#discovery-api) provides information about the Kubernetes APIs: + API names, resources, versions, and supported operations. This is a Kubernetes + specific term as it is a separate API from the Kubernetes OpenAPI. + It is intended to be a brief summary of the available resources and it does not + detail specific schema for the resources. For reference about resource schemas, + please refer to the OpenAPI document. + +- The [Kubernetes OpenAPI Document](#openapi-interface-definition) provides (full) + [OpenAPI v2.0 and 3.0 schemas](https://www.openapis.org/) for all Kubernetes API +endpoints. + The OpenAPI v3 is the preferred method for accessing OpenAPI as it +provides + a more comprehensive and accurate view of the API. It includes all the available + API paths, as well as all resources consumed and produced for every operations + on every endpoints. It also includes any extensibility components that a cluster supports. + The data is a complete specification and is significantly larger than that from the + Discovery API. + +## Discovery API + +Kubernetes publishes a list of all group versions and resources supported via +the Discovery API. This includes the following for each resource: + +- Name +- Cluster or namespaced scope +- Endpoint URL and supported verbs +- Alternative names +- Group, version, kind + +The API is available both aggregated and unaggregated form. The aggregated +discovery serves two endpoints while the unaggregated discovery serves a +separate endpoint for each group version. + +### Aggregated discovery + +{{< feature-state feature_gate_name="AggregatedDiscoveryEndpoint" >}} + +Kubernetes offers stable support for _aggregated discovery_, publishing +all resources supported by a cluster through two endpoints (`/api` and +`/apis`). Requesting this +endpoint drastically reduces the number of requests sent to fetch the +discovery data from the cluster. You can access the data by +requesting the respective endpoints with an `Accept` header indicating +the aggregated discovery resource: +`Accept: application/json;v=v2;g=apidiscovery.k8s.io;as=APIGroupDiscoveryList`. -Consider using one of the [client libraries](/docs/reference/using-api/client-libraries/) -if you are writing an application using the Kubernetes API. +Without indicating the resource type using the `Accept` header, the default +response for the `/api` and `/apis` endpoint is an unaggregated discovery +document. + +The [discovery document](https://github.com/kubernetes/kubernetes/blob/release-{{< skew currentVersion >}}/api/discovery/aggregated_v2.json) +for the built-in resources can be found in the Kubernetes GitHub repository. +This Github document can be used as a reference of the base set of the available resources +if a Kubernetes cluster is not available to query. + +The endpoint also supports ETag and protobuf encoding. + +### Unaggregated discovery + +Without discovery aggregation, discovery is published in levels, with the root +endpoints publishing discovery information for downstream documents. + +A list of all group versions supported by a cluster is published at +the `/api` and `/apis` endpoints. Example: + +``` +{ + "kind": "APIGroupList", + "apiVersion": "v1", + "groups": [ + { + "name": "apiregistration.k8s.io", + "versions": [ + { + "groupVersion": "apiregistration.k8s.io/v1", + "version": "v1" + } + ], + "preferredVersion": { + "groupVersion": "apiregistration.k8s.io/v1", + "version": "v1" + } + }, + { + "name": "apps", + "versions": [ + { + "groupVersion": "apps/v1", + "version": "v1" + } + ], + "preferredVersion": { + "groupVersion": "apps/v1", + "version": "v1" + } + }, + ... +} +``` + +Additional requests are needed to obtain the discovery document for each group version at +`/apis//` (for example: +`/apis/rbac.authorization.k8s.io/v1alpha1`), which advertises the list of +resources served under a particular group version. These endpoints are used by +kubectl to fetch the list of resources supported by a cluster. -## OpenAPI specification {#api-specification} + -Complete API details are documented using [OpenAPI](https://www.openapis.org/). +## OpenAPI interface definition +For details about the OpenAPI specifications, see the [OpenAPI documentation](https://www.openapis.org/). + +Kubernetes serves both OpenAPI v2.0 and OpenAPI v3.0. OpenAPI v3 is the +preferred method of accessing the OpenAPI because it offers a more comprehensive +(lossless) representation of Kubernetes resources. Due to limitations of OpenAPI +version 2, certain fields are dropped from the published OpenAPI including but not +limited to `default`, `nullable`, `oneOf`. ### OpenAPI V2 The Kubernetes API server serves an aggregated OpenAPI v2 spec via the @@ -74,15 +192,10 @@ request headers as follows: -Kubernetes implements an alternative Protobuf based serialization format that -is primarily intended for intra-cluster communication. For more information -about this format, see the [Kubernetes Protobuf serialization](https://git.k8s.io/design-proposals-archive/api-machinery/protobuf.md) design proposal and the -Interface Definition Language (IDL) files for each schema located in the Go -packages that define the API objects. ### OpenAPI V3 -{{< feature-state state="stable" for_k8s_version="v1.27" >}} +{{< feature-state feature_gate_name="OpenAPIV3" >}} Kubernetes supports publishing a description of its APIs as OpenAPI v3. @@ -149,36 +262,25 @@ Refer to the table below for accepted request headers. -A Golang implementation to fetch the OpenAPI V3 is provided in the package `k8s.io/client-go/openapi3`. +A Golang implementation to fetch the OpenAPI V3 is provided in the package +[`k8s.io/client-go/openapi3`](https://pkg.go.dev/k8s.io/client-go/openapi3). -## Persistence - -Kubernetes stores the serialized state of objects by writing them into -{{< glossary_tooltip term_id="etcd" >}}. - -## API Discovery +Kubernetes {{< skew currentVersion >}} publishes +OpenAPI v2.0 and v3.0; there are no plans to support 3.1 in the near future. -A list of all group versions supported by a cluster is published at -the `/api` and `/apis` endpoints. Each group version also advertises -the list of resources supported via `/apis//` (for -example: `/apis/rbac.authorization.k8s.io/v1alpha1`). These endpoints -are used by kubectl to fetch the list of resources supported by a -cluster. - -### Aggregated Discovery +### Protobuf serialization -{{< feature-state state="beta" for_k8s_version="v1.27" >}} +Kubernetes implements an alternative Protobuf based serialization format that +is primarily intended for intra-cluster communication. For more information +about this format, see the [Kubernetes Protobuf serialization](https://git.k8s.io/design-proposals-archive/api-machinery/protobuf.md) +design proposal and the +Interface Definition Language (IDL) files for each schema located in the Go +packages that define the API objects. -Kubernetes offers beta support for aggregated discovery, publishing -all resources supported by a cluster through two endpoints (`/api` and -`/apis`) compared to one for every group version. Requesting this -endpoint drastically reduces the number of requests sent to fetch the -discovery for the average Kubernetes cluster. This may be accessed by -requesting the respective endpoints with an Accept header indicating -the aggregated discovery resource: -`Accept: application/json;v=v2beta1;g=apidiscovery.k8s.io;as=APIGroupDiscoveryList`. +## Persistence -The endpoint also supports ETag and protobuf encoding. +Kubernetes stores the serialized state of objects by writing them into +{{< glossary_tooltip term_id="etcd" >}}. ## API groups and versioning @@ -238,8 +340,6 @@ ways that require deleting all existing alpha objects prior to upgrade. Refer to [API versions reference](/docs/reference/using-api/#api-versioning) for more details on the API version level definitions. - - ## API Extension The Kubernetes API can be extended in one of two ways: diff --git a/content/en/docs/concepts/overview/working-with-objects/field-selectors.md b/content/en/docs/concepts/overview/working-with-objects/field-selectors.md index 86f89dcace1ae..25ecf6987afb9 100644 --- a/content/en/docs/concepts/overview/working-with-objects/field-selectors.md +++ b/content/en/docs/concepts/overview/working-with-objects/field-selectors.md @@ -32,6 +32,20 @@ kubectl get ingress --field-selector foo.bar=baz Error from server (BadRequest): Unable to find "ingresses" that match label selector "", field selector "foo.bar=baz": "foo.bar" is not a known field selector: only "metadata.name", "metadata.namespace" ``` +### List of supported fields + +| Kind | Fields | +| ------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Pod | `spec.nodeName`
`spec.restartPolicy`
`spec.schedulerName`
`spec.serviceAccountName`
`spec.hostNetwork`
`status.phase`
`status.podIP`
`status.nominatedNodeName` | +| Event | `involvedObject.kind`
`involvedObject.namespace`
`involvedObject.name`
`involvedObject.uid`
`involvedObject.apiVersion`
`involvedObject.resourceVersion`
`involvedObject.fieldPath`
`reason`
`reportingComponent`
`source`
`type` | +| Secret | `type` | +| Namespace | `status.phase` | +| ReplicaSet | `status.replicas` | +| ReplicationController | `status.replicas` | +| Job | `status.successful` | +| Node | `spec.unschedulable` | +| CertificateSigningRequest | `spec.signerName` | + ## Supported operators You can use the `=`, `==`, and `!=` operators with field selectors (`=` and `==` mean the same thing). This `kubectl` command, for example, selects all Kubernetes Services that aren't in the `default` namespace: @@ -58,4 +72,4 @@ You can use field selectors across multiple resource types. This `kubectl` comma ```shell kubectl get statefulsets,services --all-namespaces --field-selector metadata.namespace!=default -``` +``` \ No newline at end of file diff --git a/content/en/docs/concepts/overview/working-with-objects/namespaces.md b/content/en/docs/concepts/overview/working-with-objects/namespaces.md index 29d9ff857cbcf..3b17fe8a89ac1 100644 --- a/content/en/docs/concepts/overview/working-with-objects/namespaces.md +++ b/content/en/docs/concepts/overview/working-with-objects/namespaces.md @@ -4,13 +4,16 @@ reviewers: - mikedanese - thockin title: Namespaces +api_metadata: +- apiVersion: "v1" + kind: "Namespace" content_type: concept weight: 45 --- -In Kubernetes, _namespaces_ provides a mechanism for isolating groups of resources within a single cluster. Names of resources need to be unique within a namespace, but not across namespaces. Namespace-based scoping is applicable only for namespaced {{< glossary_tooltip text="objects" term_id="object" >}} _(e.g. Deployments, Services, etc)_ and not for cluster-wide objects _(e.g. StorageClass, Nodes, PersistentVolumes, etc)_. +In Kubernetes, _namespaces_ provide a mechanism for isolating groups of resources within a single cluster. Names of resources need to be unique within a namespace, but not across namespaces. Namespace-based scoping is applicable only for namespaced {{< glossary_tooltip text="objects" term_id="object" >}} _(e.g. Deployments, Services, etc.)_ and not for cluster-wide objects _(e.g. StorageClass, Nodes, PersistentVolumes, etc.)_. diff --git a/content/en/docs/concepts/policy/limit-range.md b/content/en/docs/concepts/policy/limit-range.md index ed3e12cd463db..b9a2a5ebc5709 100644 --- a/content/en/docs/concepts/policy/limit-range.md +++ b/content/en/docs/concepts/policy/limit-range.md @@ -2,6 +2,9 @@ reviewers: - nelvadas title: Limit Ranges +api_metadata: +- apiVersion: "v1" + kind: "LimitRange" content_type: concept weight: 10 --- diff --git a/content/en/docs/concepts/policy/resource-quotas.md b/content/en/docs/concepts/policy/resource-quotas.md index d3a3a3966b691..6c10100506625 100644 --- a/content/en/docs/concepts/policy/resource-quotas.md +++ b/content/en/docs/concepts/policy/resource-quotas.md @@ -2,6 +2,9 @@ reviewers: - derekwaynecarr title: Resource Quotas +api_metadata: +- apiVersion: "v1" + kind: "ResourceQuota" content_type: concept weight: 20 --- @@ -146,8 +149,8 @@ Refer to [Logging Architecture](/docs/concepts/cluster-administration/logging/) ## Object Count Quota -You can set quota for the total number of certain resources of all standard, -namespaced resource types using the following syntax: +You can set quota for *the total number of one particular resource kind* in the Kubernetes API, +using the following syntax: * `count/.` for resources from non-core groups * `count/` for resources from the core group @@ -165,16 +168,21 @@ Here is an example set of resources users may want to put under object count quo * `count/jobs.batch` * `count/cronjobs.batch` -The same syntax can be used for custom resources. +If you define a quota this way, it applies to Kubernetes' APIs that are part of the API server, and +to any custom resources backed by a CustomResourceDefinition. If you use [API aggregation](/docs/concepts/extend-kubernetes/api-extension/apiserver-aggregation/) to +add additional, custom APIs that are not defined as CustomResourceDefinitions, the core Kubernetes +control plane does not enforce quota for the aggregated API. The extension API server is expected to +provide quota enforcement if that's appropriate for the custom API. For example, to create a quota on a `widgets` custom resource in the `example.com` API group, use `count/widgets.example.com`. -When using `count/*` resource quota, an object is charged against the quota if it exists in server storage. +When using such a resource quota (nearly for all object kinds), an object is charged +against the quota if the object kind exists (is defined) in the control plane. These types of quotas are useful to protect against exhaustion of storage resources. For example, you may want to limit the number of Secrets in a server given their large size. Too many Secrets in a cluster can actually prevent servers and controllers from starting. You can set a quota for Jobs to protect against a poorly configured CronJob. CronJobs that create too many Jobs in a namespace can lead to a denial of service. -It is also possible to do generic object count quota on a limited set of resources. +There is another syntax only to set the same type of quota for certain resources. The following types are supported: | Resource Name | Description | @@ -194,6 +202,8 @@ created in a single namespace that are not terminal. You might want to set a `po quota on a namespace to avoid the case where a user creates many small pods and exhausts the cluster's supply of Pod IPs. +You can find more examples on [Viewing and Setting Quotas](#viewing-and-setting-quotas). + ## Quota Scopes Each quota can have an associated set of `scopes`. A quota will only measure usage for a resource if it matches diff --git a/content/en/docs/concepts/scheduling-eviction/api-eviction.md b/content/en/docs/concepts/scheduling-eviction/api-eviction.md index 5da823d566ee2..b1aea442e8be2 100644 --- a/content/en/docs/concepts/scheduling-eviction/api-eviction.md +++ b/content/en/docs/concepts/scheduling-eviction/api-eviction.md @@ -11,11 +11,11 @@ using a client of the {{}}. You may be able to attempt the eviction again later. You might also see this - response because of API rate limiting. + response because of API rate limiting. * `500 Internal Server Error`: the eviction is not allowed because there is a misconfiguration, like if multiple PodDisruptionBudgets reference the same Pod. If the Pod you want to evict isn't part of a workload that has a PodDisruptionBudget, the API server always returns `200 OK` and allows the -eviction. +eviction. If the API server allows the eviction, the Pod is deleted as follows: @@ -103,12 +103,12 @@ If the API server allows the eviction, the Pod is deleted as follows: ## Troubleshooting stuck evictions In some cases, your applications may enter a broken state, where the Eviction -API will only return `429` or `500` responses until you intervene. This can -happen if, for example, a ReplicaSet creates pods for your application but new +API will only return `429` or `500` responses until you intervene. This can +happen if, for example, a ReplicaSet creates pods for your application but new pods do not enter a `Ready` state. You may also notice this behavior in cases where the last evicted Pod had a long termination grace period. -If you notice stuck evictions, try one of the following solutions: +If you notice stuck evictions, try one of the following solutions: * Abort or pause the automated operation causing the issue. Investigate the stuck application before you restart the operation. diff --git a/content/en/docs/concepts/scheduling-eviction/assign-pod-node.md b/content/en/docs/concepts/scheduling-eviction/assign-pod-node.md index 8aa1e97200891..374f044b5fee6 100644 --- a/content/en/docs/concepts/scheduling-eviction/assign-pod-node.md +++ b/content/en/docs/concepts/scheduling-eviction/assign-pod-node.md @@ -96,7 +96,7 @@ define. Some of the benefits of affinity and anti-affinity include: The affinity feature consists of two types of affinity: - *Node affinity* functions like the `nodeSelector` field but is more expressive and - allows you to specify soft rules. + allows you to specify soft rules. - *Inter-pod affinity/anti-affinity* allows you to constrain Pods against labels on other Pods. @@ -254,13 +254,13 @@ the node label that the system uses to denote the domain. For examples, see [Well-Known Labels, Annotations and Taints](/docs/reference/labels-annotations-taints/). {{< note >}} -Inter-pod affinity and anti-affinity require substantial amount of +Inter-pod affinity and anti-affinity require substantial amounts of processing which can slow down scheduling in large clusters significantly. We do not recommend using them in clusters larger than several hundred nodes. {{< /note >}} {{< note >}} -Pod anti-affinity requires nodes to be consistently labelled, in other words, +Pod anti-affinity requires nodes to be consistently labeled, in other words, every node in the cluster must have an appropriate label matching `topologyKey`. If some or all nodes are missing the specified `topologyKey` label, it can lead to unintended behavior. @@ -305,22 +305,22 @@ Pod affinity rule uses the "hard" `requiredDuringSchedulingIgnoredDuringExecution`, while the anti-affinity rule uses the "soft" `preferredDuringSchedulingIgnoredDuringExecution`. -The affinity rule specifies that the scheduler is allowed to place the example Pod +The affinity rule specifies that the scheduler is allowed to place the example Pod on a node only if that node belongs to a specific [zone](/docs/concepts/scheduling-eviction/topology-spread-constraints/) -where other Pods have been labeled with `security=S1`. -For instance, if we have a cluster with a designated zone, let's call it "Zone V," -consisting of nodes labeled with `topology.kubernetes.io/zone=V`, the scheduler can -assign the Pod to any node within Zone V, as long as there is at least one Pod within -Zone V already labeled with `security=S1`. Conversely, if there are no Pods with `security=S1` +where other Pods have been labeled with `security=S1`. +For instance, if we have a cluster with a designated zone, let's call it "Zone V," +consisting of nodes labeled with `topology.kubernetes.io/zone=V`, the scheduler can +assign the Pod to any node within Zone V, as long as there is at least one Pod within +Zone V already labeled with `security=S1`. Conversely, if there are no Pods with `security=S1` labels in Zone V, the scheduler will not assign the example Pod to any node in that zone. -The anti-affinity rule specifies that the scheduler should try to avoid scheduling the Pod +The anti-affinity rule specifies that the scheduler should try to avoid scheduling the Pod on a node if that node belongs to a specific [zone](/docs/concepts/scheduling-eviction/topology-spread-constraints/) -where other Pods have been labeled with `security=S2`. -For instance, if we have a cluster with a designated zone, let's call it "Zone R," -consisting of nodes labeled with `topology.kubernetes.io/zone=R`, the scheduler should avoid -assigning the Pod to any node within Zone R, as long as there is at least one Pod within -Zone R already labeled with `security=S2`. Conversely, the anti-affinity rule does not impact +where other Pods have been labeled with `security=S2`. +For instance, if we have a cluster with a designated zone, let's call it "Zone R," +consisting of nodes labeled with `topology.kubernetes.io/zone=R`, the scheduler should avoid +assigning the Pod to any node within Zone R, as long as there is at least one Pod within +Zone R already labeled with `security=S2`. Conversely, the anti-affinity rule does not impact scheduling into Zone R if there are no Pods with `security=S2` labels. To get yourself more familiar with the examples of Pod affinity and anti-affinity, @@ -360,23 +360,23 @@ null `namespaceSelector` matches the namespace of the Pod where the rule is defi #### matchLabelKeys -{{< feature-state for_k8s_version="v1.29" state="alpha" >}} +{{< feature-state feature_gate_name="MatchLabelKeysInPodAffinity" >}} {{< note >}} -The `matchLabelKeys` field is a alpha-level field and is disabled by default in +The `matchLabelKeys` field is an alpha-level field and is disabled by default in Kubernetes {{< skew currentVersion >}}. When you want to use it, you have to enable it via the `MatchLabelKeysInPodAffinity` [feature gate](/docs/reference/command-line-tools-reference/feature-gates/). {{< /note >}} Kubernetes includes an optional `matchLabelKeys` field for Pod affinity -or anti-affinity. The field specifies keys for the labels that should match with the incoming Pod's labels, +or anti-affinity. The field specifies keys for the labels that should match with the incoming Pod's labels, when satisfying the Pod (anti)affinity. The keys are used to look up values from the pod labels; those key-value labels are combined (using `AND`) with the match restrictions defined using the `labelSelector` field. The combined -filtering selects the set of existing pods that will be taken into Pod (anti)affinity calculation. +filtering selects the set of existing pods that will be taken into Pod (anti)affinity calculation. A common use case is to use `matchLabelKeys` with `pod-template-hash` (set on Pods managed as part of a Deployment, where the value is unique for each revision). @@ -391,37 +391,38 @@ metadata: ... spec: template: - affinity: - podAffinity: - requiredDuringSchedulingIgnoredDuringExecution: - - labelSelector: - matchExpressions: - - key: app - operator: In - values: - - database - topologyKey: topology.kubernetes.io/zone - # Only Pods from a given rollout are taken into consideration when calculating pod affinity. - # If you update the Deployment, the replacement Pods follow their own affinity rules - # (if there are any defined in the new Pod template) - matchLabelKeys: - - pod-template-hash + spec: + affinity: + podAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + - labelSelector: + matchExpressions: + - key: app + operator: In + values: + - database + topologyKey: topology.kubernetes.io/zone + # Only Pods from a given rollout are taken into consideration when calculating pod affinity. + # If you update the Deployment, the replacement Pods follow their own affinity rules + # (if there are any defined in the new Pod template) + matchLabelKeys: + - pod-template-hash ``` #### mismatchLabelKeys -{{< feature-state for_k8s_version="v1.29" state="alpha" >}} +{{< feature-state feature_gate_name="MatchLabelKeysInPodAffinity" >}} {{< note >}} -The `mismatchLabelKeys` field is a alpha-level field and is disabled by default in +The `mismatchLabelKeys` field is an alpha-level field and is disabled by default in Kubernetes {{< skew currentVersion >}}. When you want to use it, you have to enable it via the `MatchLabelKeysInPodAffinity` [feature gate](/docs/reference/command-line-tools-reference/feature-gates/). {{< /note >}} Kubernetes includes an optional `mismatchLabelKeys` field for Pod affinity -or anti-affinity. The field specifies keys for the labels that should **not** match with the incoming Pod's labels, +or anti-affinity. The field specifies keys for the labels that should **not** match with the incoming Pod's labels, when satisfying the Pod (anti)affinity. One example use case is to ensure Pods go to the topology domain (node, zone, etc) where only Pods from the same tenant or team are scheduled in. @@ -437,22 +438,22 @@ metadata: ... spec: affinity: - podAffinity: + podAffinity: requiredDuringSchedulingIgnoredDuringExecution: # ensure that pods associated with this tenant land on the correct node pool - matchLabelKeys: - tenant topologyKey: node-pool - podAntiAffinity: + podAntiAffinity: requiredDuringSchedulingIgnoredDuringExecution: # ensure that pods associated with this tenant can't schedule to nodes used for another tenant - mismatchLabelKeys: - - tenant # whatever the value of the "tenant" label for this Pod, prevent + - tenant # whatever the value of the "tenant" label for this Pod, prevent # scheduling to nodes in any pool where any Pod from a different # tenant is running. labelSelector: # We have to have the labelSelector which selects only Pods with the tenant label, - # otherwise this Pod would hate Pods from daemonsets as well, for example, + # otherwise this Pod would hate Pods from daemonsets as well, for example, # which aren't supposed to have the tenant label. matchExpressions: - key: tenant @@ -560,7 +561,7 @@ where each web server is co-located with a cache, on three separate nodes. | *webserver-1* | *webserver-2* | *webserver-3* | | *cache-1* | *cache-2* | *cache-3* | -The overall effect is that each cache instance is likely to be accessed by a single client, that +The overall effect is that each cache instance is likely to be accessed by a single client that is running on the same node. This approach aims to minimize both skew (imbalanced load) and latency. You might have other reasons to use Pod anti-affinity. @@ -585,11 +586,12 @@ Some of the limitations of using `nodeName` to select nodes are: for example OutOfmemory or OutOfcpu. - Node names in cloud environments are not always predictable or stable. -{{< note >}} +{{< warning >}} `nodeName` is intended for use by custom schedulers or advanced use cases where you need to bypass any configured schedulers. Bypassing the schedulers might lead to -failed Pods if the assigned Nodes get oversubscribed. You can use [node affinity](#node-affinity) or a the [`nodeselector` field](#nodeselector) to assign a Pod to a specific Node without bypassing the schedulers. -{{}} +failed Pods if the assigned Nodes get oversubscribed. You can use [node affinity](#node-affinity) +or the [`nodeSelector` field](#nodeselector) to assign a Pod to a specific Node without bypassing the schedulers. +{{}} Here is an example of a Pod spec using the `nodeName` field: @@ -632,13 +634,13 @@ The following operators can only be used with `nodeAffinity`. | Operator | Behaviour | | :------------: | :-------------: | -| `Gt` | The supplied value will be parsed as an integer, and that integer is less than the integer that results from parsing the value of a label named by this selector | -| `Lt` | The supplied value will be parsed as an integer, and that integer is greater than the integer that results from parsing the value of a label named by this selector | +| `Gt` | The supplied value will be parsed as an integer, and that integer is less than the integer that results from parsing the value of a label named by this selector | +| `Lt` | The supplied value will be parsed as an integer, and that integer is greater than the integer that results from parsing the value of a label named by this selector | {{}} -`Gt` and `Lt` operators will not work with non-integer values. If the given value -doesn't parse as an integer, the pod will fail to get scheduled. Also, `Gt` and `Lt` +`Gt` and `Lt` operators will not work with non-integer values. If the given value +doesn't parse as an integer, the pod will fail to get scheduled. Also, `Gt` and `Lt` are not available for `podAffinity`. {{}} diff --git a/content/en/docs/concepts/scheduling-eviction/dynamic-resource-allocation.md b/content/en/docs/concepts/scheduling-eviction/dynamic-resource-allocation.md index 47420240d94df..f68f078f42b8f 100644 --- a/content/en/docs/concepts/scheduling-eviction/dynamic-resource-allocation.md +++ b/content/en/docs/concepts/scheduling-eviction/dynamic-resource-allocation.md @@ -9,13 +9,16 @@ weight: 65 -{{< feature-state for_k8s_version="v1.27" state="alpha" >}} +{{< feature-state feature_gate_name="DynamicResourceAllocation" >}} Dynamic resource allocation is an API for requesting and sharing resources between pods and containers inside a pod. It is a generalization of the persistent volumes API for generic resources. Third-party resource drivers are -responsible for tracking and allocating resources. Different kinds of -resources support arbitrary parameters for defining requirements and +responsible for tracking and allocating resources, with additional support +provided by Kubernetes via _structured parameters_ (introduced in Kubernetes 1.30). +When a driver uses structured parameters, Kubernetes handles scheduling +and resource allocation without having to communicate with the driver. +Different kinds of resources support arbitrary parameters for defining requirements and initialization. ## {{% heading "prerequisites" %}} @@ -41,14 +44,14 @@ ResourceClass driver. ResourceClaim -: Defines a particular resource instances that is required by a +: Defines a particular resource instance that is required by a workload. Created by a user (lifecycle managed manually, can be shared between different Pods) or for individual Pods by the control plane based on a ResourceClaimTemplate (automatic lifecycle, typically used by just one Pod). ResourceClaimTemplate -: Defines the spec and some meta data for creating +: Defines the spec and some metadata for creating ResourceClaims. Created by a user when deploying a workload. PodSchedulingContext @@ -56,11 +59,39 @@ PodSchedulingContext to coordinate pod scheduling when ResourceClaims need to be allocated for a Pod. +ResourceSlice +: Used with structured parameters to publish information about resources + that are available in the cluster. + +ResourceClaimParameters +: Contain the parameters for a ResourceClaim which influence scheduling, + in a format that is understood by Kubernetes (the "structured parameter + model"). Additional parameters may be embedded in an opaque + extension, for use by the vendor driver when setting up the underlying + resource. + +ResourceClassParameters +: Similar to ResourceClaimParameters, the ResourceClassParameters provides + a type for ResourceClass parameters which is understood by Kubernetes. + Parameters for ResourceClass and ResourceClaim are stored in separate objects, typically using the type defined by a {{< glossary_tooltip term_id="CustomResourceDefinition" text="CRD" >}} that was created when installing a resource driver. +The developer of a resource driver decides whether they want to handle these +parameters in their own external controller or instead rely on Kubernetes to +handle them through the use of structured parameters. A +custom controller provides more flexibility, but cluster autoscaling is not +going to work reliably for node-local resources. Structured parameters enable +cluster autoscaling, but might not satisfy all use-cases. + +When a driver uses structured parameters, it is still possible to let the +end-user specify parameters with vendor-specific CRDs. When doing so, the +driver needs to translate those +custom parameters into the in-tree types. Alternatively, a driver may also +document how to use the in-tree types directly. + The `core/v1` `PodSpec` defines ResourceClaims that are needed for a Pod in a `resourceClaims` field. Entries in that list reference either a ResourceClaim or a ResourceClaimTemplate. When referencing a ResourceClaim, all Pods using @@ -129,8 +160,11 @@ spec: ## Scheduling +### Without structured parameters + In contrast to native resources (CPU, RAM) and extended resources (managed by a -device plugin, advertised by kubelet), the scheduler has no knowledge of what +device plugin, advertised by kubelet), without structured parameters +the scheduler has no knowledge of what dynamic resources are available in a cluster or how they could be split up to satisfy the requirements of a specific ResourceClaim. Resource drivers are responsible for that. They mark ResourceClaims as "allocated" once resources @@ -172,6 +206,27 @@ ResourceClaims, and thus scheduling the next pod gets delayed. {{< /note >}} +### With structured parameters + +When a driver uses structured parameters, the scheduler takes over the +responsibility of allocating resources to a ResourceClaim whenever a pod needs +them. It does so by retrieving the full list of available resources from +ResourceSlice objects, tracking which of those resources have already been +allocated to existing ResourceClaims, and then selecting from those resources +that remain. The exact resources selected are subject to the constraints +provided in any ResourceClaimParameters or ResourceClassParameters associated +with the ResourceClaim. + +The chosen resource is recorded in the ResourceClaim status together with any +vendor-specific parameters, so when a pod is about to start on a node, the +resource driver on the node has all the information it needs to prepare the +resource. + +By using structured parameters, the scheduler is able to reach a decision +without communicating with any DRA resource drivers. It is also able to +schedule multiple pods quickly by keeping information about ResourceClaim +allocations in memory and writing this information to the ResourceClaim objects +in the background while concurrently binding the pod to a node. ## Monitoring resources @@ -193,7 +248,13 @@ was not enabled in the scheduler at the time when the Pod got scheduled detects this and tries to make the Pod runnable by triggering allocation and/or reserving the required ResourceClaims. -However, it is better to avoid this because a Pod that is assigned to a node +{{< note >}} + +This only works with resource drivers that don't use structured parameters. + +{{< /note >}} + +It is better to avoid bypassing the scheduler because a Pod that is assigned to a node blocks normal resources (RAM, CPU) that then cannot be used for other Pods while the Pod is stuck. To make a Pod run on a specific node while still going through the normal scheduling flow, create the Pod with a node selector that @@ -255,4 +316,5 @@ be installed. Please refer to the driver's documentation for details. ## {{% heading "whatsnext" %}} - For more information on the design, see the -[Dynamic Resource Allocation KEP](https://github.com/kubernetes/enhancements/blob/master/keps/sig-node/3063-dynamic-resource-allocation/README.md). +[Dynamic Resource Allocation KEP](https://github.com/kubernetes/enhancements/blob/master/keps/sig-node/3063-dynamic-resource-allocation/README.md) + and the [Structured Parameters KEP](https://github.com/kubernetes/enhancements/tree/master/keps/sig-node/4381-dra-structured-parameters). diff --git a/content/en/docs/concepts/scheduling-eviction/kube-scheduler.md b/content/en/docs/concepts/scheduling-eviction/kube-scheduler.md index 4dc27d80b8f42..313d56fe34da7 100644 --- a/content/en/docs/concepts/scheduling-eviction/kube-scheduler.md +++ b/content/en/docs/concepts/scheduling-eviction/kube-scheduler.md @@ -62,7 +62,7 @@ kube-scheduler selects a node for the pod in a 2-step operation: The _filtering_ step finds the set of Nodes where it's feasible to schedule the Pod. For example, the PodFitsResources filter checks whether a -candidate Node has enough available resource to meet a Pod's specific +candidate Node has enough available resources to meet a Pod's specific resource requests. After this step, the node list contains any suitable Nodes; often, there will be more than one. If the list is empty, that Pod isn't (yet) schedulable. diff --git a/content/en/docs/concepts/scheduling-eviction/node-pressure-eviction.md b/content/en/docs/concepts/scheduling-eviction/node-pressure-eviction.md index 1f3e84fb5e5f2..76f930721ef6e 100644 --- a/content/en/docs/concepts/scheduling-eviction/node-pressure-eviction.md +++ b/content/en/docs/concepts/scheduling-eviction/node-pressure-eviction.md @@ -169,9 +169,10 @@ The kubelet has the following default hard eviction thresholds: - `nodefs.available<10%` - `imagefs.available<15%` - `nodefs.inodesFree<5%` (Linux nodes) +- `imagefs.inodesFree<5%` (Linux nodes) These default values of hard eviction thresholds will only be set if none -of the parameters is changed. If you changed the value of any parameter, +of the parameters is changed. If you change the value of any parameter, then the values of other parameters will not be inherited as the default values and will be set to zero. In order to provide custom values, you should provide all the thresholds respectively. diff --git a/content/en/docs/concepts/scheduling-eviction/pod-overhead.md b/content/en/docs/concepts/scheduling-eviction/pod-overhead.md index 2610ea80ad998..f16e1ca0ef6c9 100644 --- a/content/en/docs/concepts/scheduling-eviction/pod-overhead.md +++ b/content/en/docs/concepts/scheduling-eviction/pod-overhead.md @@ -36,9 +36,12 @@ You need to make sure a `RuntimeClass` is utilized which defines the `overhead` To work with Pod overhead, you need a RuntimeClass that defines the `overhead` field. As an example, you could use the following RuntimeClass definition with a virtualization container -runtime that uses around 120MiB per Pod for the virtual machine and the guest OS: +runtime (in this example, Kata Containers combined with the Firecracker virtual machine monitor) +that uses around 120MiB per Pod for the virtual machine and the guest OS: ```yaml +# You need to change this example to match the actual runtime name, and per-Pod +# resource overhead, that the container runtime is adding in your cluster. apiVersion: node.k8s.io/v1 kind: RuntimeClass metadata: diff --git a/content/en/docs/concepts/scheduling-eviction/pod-priority-preemption.md b/content/en/docs/concepts/scheduling-eviction/pod-priority-preemption.md index d5607f48f5927..c6b8da1838f09 100644 --- a/content/en/docs/concepts/scheduling-eviction/pod-priority-preemption.md +++ b/content/en/docs/concepts/scheduling-eviction/pod-priority-preemption.md @@ -64,7 +64,7 @@ and it cannot be prefixed with `system-`. A PriorityClass object can have any 32-bit integer value smaller than or equal to 1 billion. This means that the range of values for a PriorityClass object is -from -2147483648 to 1000000000 inclusive. Larger numbers are reserved for +from -2147483648 to 1000000000 inclusive. Larger numbers are reserved for built-in PriorityClasses that represent critical system Pods. A cluster admin should create one PriorityClass object for each such mapping that they want. @@ -182,8 +182,8 @@ When Pod priority is enabled, the scheduler orders pending Pods by their priority and a pending Pod is placed ahead of other pending Pods with lower priority in the scheduling queue. As a result, the higher priority Pod may be scheduled sooner than Pods with lower priority if -its scheduling requirements are met. If such Pod cannot be scheduled, -scheduler will continue and tries to schedule other lower priority Pods. +its scheduling requirements are met. If such Pod cannot be scheduled, the +scheduler will continue and try to schedule other lower priority Pods. ## Preemption @@ -199,7 +199,7 @@ the Pods are gone, P can be scheduled on the Node. ### User exposed information When Pod P preempts one or more Pods on Node N, `nominatedNodeName` field of Pod -P's status is set to the name of Node N. This field helps scheduler track +P's status is set to the name of Node N. This field helps the scheduler track resources reserved for Pod P and also gives users information about preemptions in their clusters. @@ -209,8 +209,8 @@ After victim Pods are preempted, they get their graceful termination period. If another node becomes available while scheduler is waiting for the victim Pods to terminate, scheduler may use the other node to schedule Pod P. As a result `nominatedNodeName` and `nodeName` of Pod spec are not always the same. Also, if -scheduler preempts Pods on Node N, but then a higher priority Pod than Pod P -arrives, scheduler may give Node N to the new higher priority Pod. In such a +the scheduler preempts Pods on Node N, but then a higher priority Pod than Pod P +arrives, the scheduler may give Node N to the new higher priority Pod. In such a case, scheduler clears `nominatedNodeName` of Pod P. By doing this, scheduler makes Pod P eligible to preempt Pods on another Node. @@ -256,9 +256,9 @@ the Node is not considered for preemption. If a pending Pod has inter-pod {{< glossary_tooltip text="affinity" term_id="affinity" >}} to one or more of the lower-priority Pods on the Node, the inter-Pod affinity -rule cannot be satisfied in the absence of those lower-priority Pods. In this case, +rule cannot be satisfied in the absence of those lower-priority Pods. In this case, the scheduler does not preempt any Pods on the Node. Instead, it looks for another -Node. The scheduler might find a suitable Node or it might not. There is no +Node. The scheduler might find a suitable Node or it might not. There is no guarantee that the pending Pod can be scheduled. Our recommended solution for this problem is to create inter-Pod affinity only @@ -288,7 +288,7 @@ enough demand and if we find an algorithm with reasonable performance. ## Troubleshooting -Pod priority and pre-emption can have unwanted side effects. Here are some +Pod priority and preemption can have unwanted side effects. Here are some examples of potential problems and ways to deal with them. ### Pods are preempted unnecessarily @@ -361,7 +361,7 @@ to get evicted. The kubelet ranks pods for eviction based on the following facto 1. Whether the starved resource usage exceeds requests 1. Pod Priority - 1. Amount of resource usage relative to requests + 1. Amount of resource usage relative to requests See [Pod selection for kubelet eviction](/docs/concepts/scheduling-eviction/node-pressure-eviction/#pod-selection-for-kubelet-eviction) for more details. diff --git a/content/en/docs/concepts/scheduling-eviction/pod-scheduling-readiness.md b/content/en/docs/concepts/scheduling-eviction/pod-scheduling-readiness.md index 0b671ecbfcbe7..9b6f98066b2a3 100644 --- a/content/en/docs/concepts/scheduling-eviction/pod-scheduling-readiness.md +++ b/content/en/docs/concepts/scheduling-eviction/pod-scheduling-readiness.md @@ -6,10 +6,10 @@ weight: 40 -{{< feature-state for_k8s_version="v1.27" state="beta" >}} +{{< feature-state for_k8s_version="v1.30" state="stable" >}} Pods were considered ready for scheduling once created. Kubernetes scheduler -does its due diligence to find nodes to place all pending Pods. However, in a +does its due diligence to find nodes to place all pending Pods. However, in a real-world case, some Pods may stay in a "miss-essential-resources" state for a long period. These Pods actually churn the scheduler (and downstream integrators like Cluster AutoScaler) in an unnecessary manner. @@ -59,7 +59,7 @@ The output is: ``` To inform scheduler this Pod is ready for scheduling, you can remove its `schedulingGates` entirely -by re-applying a modified manifest: +by reapplying a modified manifest: {{% code_sample file="pods/pod-without-scheduling-gates.yaml" %}} @@ -79,7 +79,7 @@ Given the test-pod doesn't request any CPU/memory resources, it's expected that transited from previous `SchedulingGated` to `Running`: ```none -NAME READY STATUS RESTARTS AGE IP NODE +NAME READY STATUS RESTARTS AGE IP NODE test-pod 1/1 Running 0 15s 10.0.0.4 node-2 ``` @@ -89,13 +89,11 @@ The metric `scheduler_pending_pods` comes with a new label `"gated"` to distingu has been tried scheduling but claimed as unschedulable, or explicitly marked as not ready for scheduling. You can use `scheduler_pending_pods{queue="gated"}` to check the metric result. -## Mutable Pod Scheduling Directives - -{{< feature-state for_k8s_version="v1.27" state="beta" >}} +## Mutable Pod scheduling directives You can mutate scheduling directives of Pods while they have scheduling gates, with certain constraints. -At a high level, you can only tighten the scheduling directives of a Pod. In other words, the updated -directives would cause the Pods to only be able to be scheduled on a subset of the nodes that it would +At a high level, you can only tighten the scheduling directives of a Pod. In other words, the updated +directives would cause the Pods to only be able to be scheduled on a subset of the nodes that it would previously match. More concretely, the rules for updating a Pod's scheduling directives are as follows: 1. For `.spec.nodeSelector`, only additions are allowed. If absent, it will be allowed to be set. @@ -107,8 +105,8 @@ previously match. More concretely, the rules for updating a Pod's scheduling dir or `fieldExpressions` are allowed, and no changes to existing `matchExpressions` and `fieldExpressions` will be allowed. This is because the terms in `.requiredDuringSchedulingIgnoredDuringExecution.NodeSelectorTerms`, are ORed - while the expressions in `nodeSelectorTerms[].matchExpressions` and - `nodeSelectorTerms[].fieldExpressions` are ANDed. + while the expressions in `nodeSelectorTerms[].matchExpressions` and + `nodeSelectorTerms[].fieldExpressions` are ANDed. 4. For `.preferredDuringSchedulingIgnoredDuringExecution`, all updates are allowed. This is because preferred terms are not authoritative, and so policy controllers diff --git a/content/en/docs/concepts/scheduling-eviction/resource-bin-packing.md b/content/en/docs/concepts/scheduling-eviction/resource-bin-packing.md index c666c14f215d3..46930cc062edd 100644 --- a/content/en/docs/concepts/scheduling-eviction/resource-bin-packing.md +++ b/content/en/docs/concepts/scheduling-eviction/resource-bin-packing.md @@ -58,8 +58,8 @@ Within the `scoringStrategy` field, you can configure two parameters: `requested `resources`. The `shape` in the `requestedToCapacityRatio` parameter allows the user to tune the function as least requested or most requested based on `utilization` and `score` values. The `resources` parameter -consists of `name` of the resource to be considered during scoring and `weight` -specify the weight of each resource. +comprises both the `name` of the resource to be considered during scoring and +its corresponding `weight`, which specifies the weight of each resource. Below is an example configuration that sets the bin packing behavior for extended resources `intel.com/foo` and `intel.com/bar` diff --git a/content/en/docs/concepts/scheduling-eviction/scheduler-perf-tuning.md b/content/en/docs/concepts/scheduling-eviction/scheduler-perf-tuning.md index 786b6ed984190..fd499c550f4a4 100644 --- a/content/en/docs/concepts/scheduling-eviction/scheduler-perf-tuning.md +++ b/content/en/docs/concepts/scheduling-eviction/scheduler-perf-tuning.md @@ -77,7 +77,7 @@ If you don't specify a threshold, Kubernetes calculates a figure using a linear formula that yields 50% for a 100-node cluster and yields 10% for a 5000-node cluster. The lower bound for the automatic value is 5%. -This means that, the kube-scheduler always scores at least 5% of your cluster no +This means that the kube-scheduler always scores at least 5% of your cluster no matter how large the cluster is, unless you have explicitly set `percentageOfNodesToScore` to be smaller than 5. diff --git a/content/en/docs/concepts/scheduling-eviction/scheduling-framework.md b/content/en/docs/concepts/scheduling-eviction/scheduling-framework.md index 618f5586f68e5..63a8c7d3e6fec 100644 --- a/content/en/docs/concepts/scheduling-eviction/scheduling-framework.md +++ b/content/en/docs/concepts/scheduling-eviction/scheduling-framework.md @@ -83,7 +83,7 @@ the Pod is put into the active queue or the backoff queue so that the scheduler will retry the scheduling of the Pod. {{< note >}} -QueueingHint evaluation during scheduling is a beta-level feature. +QueueingHint evaluation during scheduling is a beta-level feature. The v1.28 release series initially enabled the associated feature gate; however, after the discovery of an excessive memory footprint, the Kubernetes project set that feature gate to be disabled by default. In Kubernetes {{< skew currentVersion >}}, this feature gate is @@ -113,7 +113,7 @@ called for that node. Nodes may be evaluated concurrently. ### PostFilter {#post-filter} -These plugins are called after Filter phase, but only when no feasible nodes +These plugins are called after the Filter phase, but only when no feasible nodes were found for the pod. Plugins are called in their configured order. If any postFilter plugin marks the node as `Schedulable`, the remaining plugins will not be called. A typical PostFilter implementation is preemption, which diff --git a/content/en/docs/concepts/scheduling-eviction/taint-and-toleration.md b/content/en/docs/concepts/scheduling-eviction/taint-and-toleration.md index d2e78c98a88cf..6e5d0bad86571 100644 --- a/content/en/docs/concepts/scheduling-eviction/taint-and-toleration.md +++ b/content/en/docs/concepts/scheduling-eviction/taint-and-toleration.md @@ -62,7 +62,15 @@ tolerations: effect: "NoSchedule" ``` -Here's an example of a pod that uses tolerations: +The default Kubernetes scheduler takes taints and tolerations into account when +selecting a node to run a particular Pod. However, if you manually specify the +`.spec.nodeName` for a Pod, that action bypasses the scheduler; the Pod is then +bound onto the node where you assigned it, even if there are `NoSchedule` +taints on that node that you selected. +If this happens and the node also has a `NoExecute` taint set, the kubelet will +eject the Pod unless there is an appropriate tolerance set. + +Here's an example of a pod that has some tolerations defined: {{% code_sample file="pods/pod-with-toleration.yaml" %}} @@ -84,7 +92,7 @@ An empty `effect` matches all effects with key `key1`. {{< /note >}} -The above example used `effect` of `NoSchedule`. Alternatively, you can use `effect` of `PreferNoSchedule`. +The above example used the `effect` of `NoSchedule`. Alternatively, you can use the `effect` of `PreferNoSchedule`. The allowed values for the `effect` field are: @@ -227,7 +235,7 @@ are true. The following taints are built in: * `node.kubernetes.io/network-unavailable`: Node's network is unavailable. * `node.kubernetes.io/unschedulable`: Node is unschedulable. * `node.cloudprovider.kubernetes.io/uninitialized`: When the kubelet is started - with "external" cloud provider, this taint is set on a node to mark it + with an "external" cloud provider, this taint is set on a node to mark it as unusable. After a controller from the cloud-controller-manager initializes this node, the kubelet removes this taint. diff --git a/content/en/docs/concepts/scheduling-eviction/topology-spread-constraints.md b/content/en/docs/concepts/scheduling-eviction/topology-spread-constraints.md index 03a0172cb2cb7..d82dcdd065e1b 100644 --- a/content/en/docs/concepts/scheduling-eviction/topology-spread-constraints.md +++ b/content/en/docs/concepts/scheduling-eviction/topology-spread-constraints.md @@ -60,7 +60,7 @@ spec: # Configure a topology spread constraint topologySpreadConstraints: - maxSkew: - minDomains: # optional; beta since v1.25 + minDomains: # optional topologyKey: whenUnsatisfiable: labelSelector: @@ -71,7 +71,7 @@ spec: ``` You can read more about this field by running `kubectl explain Pod.spec.topologySpreadConstraints` or -refer to [scheduling](/docs/reference/kubernetes-api/workload-resources/pod-v1/#scheduling) section of the API reference for Pod. +refer to the [scheduling](/docs/reference/kubernetes-api/workload-resources/pod-v1/#scheduling) section of the API reference for Pod. ### Spread constraint definition @@ -96,11 +96,11 @@ your cluster. Those fields are: A domain is a particular instance of a topology. An eligible domain is a domain whose nodes match the node selector. + {{< note >}} - The `MinDomainsInPodTopologySpread` [feature gate](/docs/reference/command-line-tools-reference/feature-gates/) - enables `minDomains` for pod topology spread. Starting from v1.28, - the `MinDomainsInPodTopologySpread` gate - is enabled by default. In older Kubernetes clusters it might be explicitly + Before Kubernetes v1.30, the `minDomains` field was only available if the + `MinDomainsInPodTopologySpread` [feature gate](/docs/reference/command-line-tools-reference/feature-gates/) + was enabled (default since v1.28). In older Kubernetes clusters it might be explicitly disabled or the field might not be available. {{< /note >}} @@ -254,7 +254,7 @@ follows the API definition of the field; however, the behavior is more likely to confusing and troubleshooting is less straightforward. You need a mechanism to ensure that all the nodes in a topology domain (such as a -cloud provider region) are labelled consistently. +cloud provider region) are labeled consistently. To avoid you needing to manually label nodes, most clusters automatically populate well-known labels such as `kubernetes.io/hostname`. Check whether your cluster supports this. @@ -263,7 +263,7 @@ your cluster supports this. ### Example: one topology spread constraint {#example-one-topologyspreadconstraint} -Suppose you have a 4-node cluster where 3 Pods labelled `foo: bar` are located in +Suppose you have a 4-node cluster where 3 Pods labeled `foo: bar` are located in node1, node2 and node3 respectively: {{}} @@ -290,7 +290,7 @@ can use a manifest similar to: {{% code_sample file="pods/topology-spread-constraints/one-constraint.yaml" %}} From that manifest, `topologyKey: zone` implies the even distribution will only be applied -to nodes that are labelled `zone: ` (nodes that don't have a `zone` label +to nodes that are labeled `zone: ` (nodes that don't have a `zone` label are skipped). The field `whenUnsatisfiable: DoNotSchedule` tells the scheduler to let the incoming Pod stay pending if the scheduler can't find a way to satisfy the constraint. @@ -494,7 +494,7 @@ There are some implicit conventions worth noting here: above example, if you remove the incoming Pod's labels, it can still be placed onto nodes in zone `B`, since the constraints are still satisfied. However, after that placement, the degree of imbalance of the cluster remains unchanged - it's still zone `A` - having 2 Pods labelled as `foo: bar`, and zone `B` having 1 Pod labelled as + having 2 Pods labeled as `foo: bar`, and zone `B` having 1 Pod labeled as `foo: bar`. If this is not what you expect, update the workload's `topologySpreadConstraints[*].labelSelector` to match the labels in the pod template. @@ -618,7 +618,7 @@ section of the enhancement proposal about Pod topology spread constraints. because, in this case, those topology domains won't be considered until there is at least one node in them. - You can work around this by using an cluster autoscaling tool that is aware of + You can work around this by using a cluster autoscaling tool that is aware of Pod topology spread constraints and is also aware of the overall set of topology domains. diff --git a/content/en/docs/concepts/security/_index.md b/content/en/docs/concepts/security/_index.md index 50edcda94a3f6..47d4ef8d365f6 100644 --- a/content/en/docs/concepts/security/_index.md +++ b/content/en/docs/concepts/security/_index.md @@ -3,4 +3,127 @@ title: "Security" weight: 85 description: > Concepts for keeping your cloud-native workload secure. +simple_list: true --- + +This section of the Kubernetes documentation aims to help you learn to run +workloads more securely, and about the essential aspects of keeping a +Kubernetes cluster secure. + +Kubernetes is based on a cloud-native architecture, and draws on advice from the +{{< glossary_tooltip text="CNCF" term_id="cncf" >}} about good practice for +cloud native information security. + +Read [Cloud Native Security and Kubernetes](/docs/concepts/security/cloud-native-security/) +for the broader context about how to secure your cluster and the applications that +you're running on it. + +## Kubernetes security mechanisms {#security-mechanisms} + +Kubernetes includes several APIs and security controls, as well as ways to +define [policies](#policies) that can form part of how you manage information security. + +### Control plane protection + +A key security mechanism for any Kubernetes cluster is to +[control access to the Kubernetes API](/docs/concepts/security/controlling-access). + +Kubernetes expects you to configure and use TLS to provide +[data encryption in transit](/docs/tasks/tls/managing-tls-in-a-cluster/) +within the control plane, and between the control plane and its clients. +You can also enable [encryption at rest](/docs/tasks/administer-cluster/encrypt-data/) +for the data stored within Kubernetes control plane; this is separate from using +encryption at rest for your own workloads' data, which might also be a good idea. + +### Secrets + +The [Secret](/docs/concepts/configuration/secret/) API provides basic protection for +configuration values that require confidentiality. + +### Workload protection + +Enforce [Pod security standards](/docs/concepts/security/pod-security-standards/) to +ensure that Pods and their containers are isolated appropriately. You can also use +[RuntimeClasses](/docs/concepts/containers/runtime-class) to define custom isolation +if you need it. + +[Network policies](/docs/concepts/services-networking/network-policies/) let you control +network traffic between Pods, or between Pods and the network outside your cluster. + +You can deploy security controls from the wider ecosystem to implement preventative +or detective controls around Pods, their containers, and the images that run in them. + +### Auditing + +Kubernetes [audit logging](/docs/tasks/debug/debug-cluster/audit/) provides a +security-relevant, chronological set of records documenting the sequence of actions +in a cluster. The cluster audits the activities generated by users, by applications +that use the Kubernetes API, and by the control plane itself. + +## Cloud provider security + +{{% thirdparty-content vendor="true" %}} + +If you are running a Kubernetes cluster on your own hardware or a different cloud provider, +consult your documentation for security best practices. +Here are links to some of the popular cloud providers' security documentation: + +{{< table caption="Cloud provider security" >}} + +IaaS Provider | Link | +-------------------- | ------------ | +Alibaba Cloud | https://www.alibabacloud.com/trust-center | +Amazon Web Services | https://aws.amazon.com/security | +Google Cloud Platform | https://cloud.google.com/security | +Huawei Cloud | https://www.huaweicloud.com/intl/en-us/securecenter/overallsafety | +IBM Cloud | https://www.ibm.com/cloud/security | +Microsoft Azure | https://docs.microsoft.com/en-us/azure/security/azure-security | +Oracle Cloud Infrastructure | https://www.oracle.com/security | +VMware vSphere | https://www.vmware.com/security/hardening-guides | + +{{< /table >}} + +## Policies + +You can define security policies using Kubernetes-native mechanisms, +such as [NetworkPolicy](/docs/concepts/services-networking/network-policies/) +(declarative control over network packet filtering) or +[ValidatingAdmisisonPolicy](/docs/reference/access-authn-authz/validating-admission-policy/) (declarative restrictions on what changes +someone can make using the Kubernetes API). + +However, you can also rely on policy implementations from the wider +ecosystem around Kubernetes. Kubernetes provides extension mechanisms +to let those ecosystem projects implement their own policy controls +on source code review, container image approval, API access controls, +networking, and more. + +For more information about policy mechanisms and Kubernetes, +read [Policies](/docs/concepts/policy/). + +## {{% heading "whatsnext" %}} + +Learn about related Kubernetes security topics: + +* [Securing your cluster](/docs/tasks/administer-cluster/securing-a-cluster/) +* [Known vulnerabilities](/docs/reference/issues-security/official-cve-feed/) + in Kubernetes (and links to further information) +* [Data encryption in transit](/docs/tasks/tls/managing-tls-in-a-cluster/) for the control plane +* [Data encryption at rest](/docs/tasks/administer-cluster/encrypt-data/) +* [Controlling Access to the Kubernetes API](/docs/concepts/security/controlling-access) +* [Network policies](/docs/concepts/services-networking/network-policies/) for Pods +* [Secrets in Kubernetes](/docs/concepts/configuration/secret/) +* [Pod security standards](/docs/concepts/security/pod-security-standards/) +* [RuntimeClasses](/docs/concepts/containers/runtime-class) + +Learn the context: + + +* [Cloud Native Security and Kubernetes](/docs/concepts/security/cloud-native-security/) + +Get certified: + +* [Certified Kubernetes Security Specialist](https://training.linuxfoundation.org/certification/certified-kubernetes-security-specialist/) + certification and official training course. + +Read more in this section: + diff --git a/content/en/docs/concepts/security/cloud-native-security.md b/content/en/docs/concepts/security/cloud-native-security.md new file mode 100644 index 0000000000000..d8f4ccdd7b998 --- /dev/null +++ b/content/en/docs/concepts/security/cloud-native-security.md @@ -0,0 +1,225 @@ +--- +title: "Cloud Native Security and Kubernetes" +linkTitle: "Cloud Native Security" +weight: 10 + +# The section index lists this explicitly +hide_summary: true + +description: > + Concepts for keeping your cloud-native workload secure. +--- + +Kubernetes is based on a cloud-native architecture, and draws on advice from the +{{< glossary_tooltip text="CNCF" term_id="cncf" >}} about good practice for +cloud native information security. + +Read on through this page for an overview of how Kubernetes is designed to +help you deploy a secure cloud native platform. + +## Cloud native information security + +{{< comment >}} +There are localized versions available of this whitepaper; if you can link to one of those +when localizing, that's even better. +{{< /comment >}} + +The CNCF [white paper](https://github.com/cncf/tag-security/tree/main/security-whitepaper) +on cloud native security defines security controls and practices that are +appropriate to different _lifecycle phases_. + +## _Develop_ lifecycle phase {#lifecycle-phase-develop} + +- Ensure the integrity of development environments. +- Design applications following good practice for information security, + appropriate for your context. +- Consider end user security as part of solution design. + +To achieve this, you can: + +1. Adopt an architecture, such as [zero trust](https://glossary.cncf.io/zero-trust-architecture/), + that minimizes attack surfaces, even for internal threats. +1. Define a code review process that considers security concerns. +1. Build a _threat model_ of your system or application that identifies + trust boundaries. Use that to model to identify risks and to help find + ways to treat those risks. +1. Incorporate advanced security automation, such as _fuzzing_ and + [security chaos engineering](https://glossary.cncf.io/security-chaos-engineering/), + where it's justified. + +## _Distribute_ lifecycle phase {#lifecycle-phase-distribute} + +- Ensure the security of the supply chain for container images you execute. +- Ensure the security of the supply chain for the cluster and other components + that execute your application. An example of another component might be an + external database that your cloud-native application uses for persistence. + +To achieve this, you can: + +1. Scan container images and other artifacts for known vulnerabilities. +1. Ensure that software distribution uses encryption in transit, with + a chain of trust for the software source. +1. Adopt and follow processes to update dependencies when updates are + available, especially in response to security announcements. +1. Use validation mechanisms such as digital certificates for supply + chain assurance. +1. Subscribe to feeds and other mechanisms to alert you to security + risks. +1. Restrict access to artifacts. Place container images in a + [private registry](/docs/concepts/containers/images/#using-a-private-registry) + that only allows authorized clients to pull images. + +## _Deploy_ lifecycle phase {#lifecycle-phase-deploy} + +Ensure appropriate restrictions on what can be deployed, who can deploy it, +and where it can be deployed to. +You can enforce measures from the _distribute_ phase, such as verifying the +cryptographic identity of container image artifacts. + +When you deploy Kubernetes, you also set the foundation for your +applications' runtime environment: a Kubernetes cluster (or +multiple clusters). +That IT infrastructure must provide the security guarantees that higher +layers expect. + +## _Runtime_ lifecycle phase {#lifecycle-phase-runtime} + +The Runtime phase comprises three critical areas: [compute](#protection-runtime-compute), +[access](#protection-runtime-access), and [storage](#protection-runtime-storage). + + +### Runtime protection: access {#protection-runtime-access} + +The Kubernetes API is what makes your cluster work. Protecting this API is key +to providing effective cluster security. + +Other pages in the Kubernetes documentation have more detail about how to set up +specific aspects of access control. The [security checklist](/docs/concepts/security/security-checklist/) +has a set of suggested basic checks for your cluster. + +Beyond that, securing your cluster means implementing effective +[authentication](/docs/concepts/security/controlling-access/#authentication) and +[authorization](/docs/concepts/security/controlling-access/#authorization) for API access. Use [ServiceAccounts](/docs/concepts/security/service-accounts/) to +provide and manage security identities for workloads and cluster +components. + +Kubernetes uses TLS to protect API traffic; make sure to deploy the cluster using +TLS (including for traffic between nodes and the control plane), and protect the +encryption keys. If you use Kubernetes' own API for +[CertificateSigningRequests](/docs/reference/access-authn-authz/certificate-signing-requests/#certificate-signing-requests), +pay special attention to restricting misuse there. + +### Runtime protection: compute {#protection-runtime-compute} + +{{< glossary_tooltip text="Containers" term_id="container" >}} provide two +things: isolation between different applications, and a mechanism to combine +those isolated applications to run on the same host computer. Those two +aspects, isolation and aggregation, mean that runtime security involves +trade-offs and finding an appropriate balance. + +Kubernetes relies on a {{< glossary_tooltip text="container runtime" term_id="container-runtime" >}} +to actually set up and run containers. The Kubernetes project does +not recommend a specific container runtime and you should make sure that +the runtime(s) that you choose meet your information security needs. + +To protect your compute at runtime, you can: + +1. Enforce [Pod security standards](/docs/concepts/security/pod-security-standards/) + for applications, to help ensure they run with only the necessary privileges. +1. Run a specialized operating system on your nodes that is designed specifically + for running containerized workloads. This is typically based on a read-only + operating system (_immutable image_) that provides only the services + essential for running containers. + + Container-specific operating systems help to isolate system components and + present a reduced attack surface in case of a container escape. +1. Define [ResourceQuotas](/docs/concepts/policy/resource-quotas/) to + fairly allocate shared resources, and use + mechanisms such as [LimitRanges](/docs/concepts/policy/limit-range/) + to ensure that Pods specify their resource requirements. +1. Partition workloads across different nodes. + Use [node isolation](/docs/concepts/scheduling-eviction/assign-pod-node/#node-isolation-restriction) + mechanisms, either from Kubernetes itself or from the ecosystem, to ensure that + Pods with different trust contexts are run on separate sets of nodes. +1. Use a {{< glossary_tooltip text="container runtime" term_id="container-runtime" >}} + that provides security restrictions. +1. On Linux nodes, use a Linux security module such as [AppArmor](/docs/tutorials/security/apparmor/) + or [seccomp](/docs/tutorials/security/seccomp/). + +### Runtime protection: storage {#protection-runtime-storage} + +To protect storage for your cluster and the applications that run there, you can: + +1. Integrate your cluster with an external storage plugin that provides encryption at + rest for volumes. +1. Enable [encryption at rest](/docs/tasks/administer-cluster/encrypt-data/) for + API objects. +1. Protect data durability using backups. Verify that you can restore these, whenever you need to. +1. Authenticate connections between cluster nodes and any network storage they rely + upon. +1. Implement data encryption within your own application. + +For encryption keys, generating these within specialized hardware provides +the best protection against disclosure risks. A _hardware security module_ +can let you perform cryptographic operations without allowing the security +key to be copied elsewhere. + +### Networking and security + +You should also consider network security measures, such as +[NetworkPolicy](/docs/concepts/services-networking/network-policies/) or a +[service mesh](https://glossary.cncf.io/service-mesh/). +Some network plugins for Kubernetes provide encryption for your +cluster network, using technologies such as a virtual +private network (VPN) overlay. +By design, Kubernetes lets you use your own networking plugin for your +cluster (if you use managed Kubernetes, the person or organization +managing your cluster may have chosen a network plugin for you). + +The network plugin you choose and the way you integrate it can have a +strong impact on the security of information in transit. + +### Observability and runtime security + +Kubernetes lets you extend your cluster with extra tooling. You can set up third +party solutions to help you monitor or troubleshoot your applications and the +clusters they are running. You also get some basic observability features built +in to Kubernetes itself. Your code running in containers can generate logs, +publish metrics or provide other observability data; at deploy time, you need to +make sure your cluster provides an appropriate level of protection there. + +If you set up a metrics dashboard or something similar, review the chain of components +that populate data into that dashboard, as well as the dashboard itself. Make sure +that the whole chain is designed with enough resilience and enough integrity protection +that you can rely on it even during an incident where your cluster might be degraded. + +Where appropriate, deploy security measures below the level of Kubernetes +itself, such as cryptographically measured boot, or authenticated distribution +of time (which helps ensure the fidelity of logs and audit records). + +For a high assurance environment, deploy cryptographic protections to ensure that +logs are both tamper-proof and confidential. + +## {{% heading "whatsnext" %}} + +### Cloud native security {#further-reading-cloud-native} + +* CNCF [white paper](https://github.com/cncf/tag-security/tree/main/security-whitepaper) + on cloud native security. +* CNCF [white paper](https://github.com/cncf/tag-security/blob/f80844baaea22a358f5b20dca52cd6f72a32b066/supply-chain-security/supply-chain-security-paper/CNCF_SSCP_v1.pdf) + on good practices for securing a software supply chain. +* [Fixing the Kubernetes clusterf\*\*k: Understanding security from the kernel up](https://archive.fosdem.org/2020/schedule/event/kubernetes/) (FOSDEM 2020) +* [Kubernetes Security Best Practices](https://www.youtube.com/watch?v=wqsUfvRyYpw) (Kubernetes Forum Seoul 2019) +* [Towards Measured Boot Out of the Box](https://www.youtube.com/watch?v=EzSkU3Oecuw) (Linux Security Summit 2016) + +### Kubernetes and information security {#further-reading-k8s} + +* [Kubernetes security](/docs/concepts/security/) +* [Securing your cluster](/docs/tasks/administer-cluster/securing-a-cluster/) +* [Data encryption in transit](/docs/tasks/tls/managing-tls-in-a-cluster/) for the control plane +* [Data encryption at rest](/docs/tasks/administer-cluster/encrypt-data/) +* [Secrets in Kubernetes](/docs/concepts/configuration/secret/) +* [Controlling Access to the Kubernetes API](/docs/concepts/security/controlling-access) +* [Network policies](/docs/concepts/services-networking/network-policies/) for Pods +* [Pod security standards](/docs/concepts/security/pod-security-standards/) +* [RuntimeClasses](/docs/concepts/containers/runtime-class) diff --git a/content/en/docs/concepts/security/multi-tenancy.md b/content/en/docs/concepts/security/multi-tenancy.md index d6ddd1c60a8ec..caf764eb006d1 100755 --- a/content/en/docs/concepts/security/multi-tenancy.md +++ b/content/en/docs/concepts/security/multi-tenancy.md @@ -291,7 +291,7 @@ sandboxing implementations are available: * [gVisor](https://gvisor.dev/) intercepts syscalls from containers and runs them through a userspace kernel, written in Go, with limited access to the underlying host. -* [Kata Containers](https://katacontainers.io/) is an OCI compliant runtime that allows you to run +* [Kata Containers](https://katacontainers.io/) provide a secure container runtime that allows you to run containers in a VM. The hardware virtualization available in Kata offers an added layer of security for containers running untrusted code. diff --git a/content/en/docs/concepts/security/overview.md b/content/en/docs/concepts/security/overview.md deleted file mode 100644 index 29b4d8d55ba7f..0000000000000 --- a/content/en/docs/concepts/security/overview.md +++ /dev/null @@ -1,160 +0,0 @@ ---- -reviewers: -- zparnold -title: Overview of Cloud Native Security -description: > - A model for thinking about Kubernetes security in the context of Cloud Native security. -content_type: concept -weight: 1 ---- - - - -This overview defines a model for thinking about Kubernetes security in the context of Cloud Native security. - -{{< warning >}} -This container security model provides suggestions, not proven information security policies. -{{< /warning >}} - - - -## The 4C's of Cloud Native security - -You can think about security in layers. The 4C's of Cloud Native security are Cloud, -Clusters, Containers, and Code. - -{{< note >}} -This layered approach augments the [defense in depth](https://en.wikipedia.org/wiki/Defense_in_depth_(computing)) -computing approach to security, which is widely regarded as a best practice for securing -software systems. -{{< /note >}} - -{{< figure src="/images/docs/4c.png" title="The 4C's of Cloud Native Security" class="diagram-large" >}} - -Each layer of the Cloud Native security model builds upon the next outermost layer. -The Code layer benefits from strong base (Cloud, Cluster, Container) security layers. -You cannot safeguard against poor security standards in the base layers by addressing -security at the Code level. - -## Cloud - -In many ways, the Cloud (or co-located servers, or the corporate datacenter) is the -[trusted computing base](https://en.wikipedia.org/wiki/Trusted_computing_base) -of a Kubernetes cluster. If the Cloud layer is vulnerable (or -configured in a vulnerable way) then there is no guarantee that the components built -on top of this base are secure. Each cloud provider makes security recommendations -for running workloads securely in their environment. - -### Cloud provider security - -If you are running a Kubernetes cluster on your own hardware or a different cloud provider, -consult your documentation for security best practices. -Here are links to some of the popular cloud providers' security documentation: - -{{< table caption="Cloud provider security" >}} - -IaaS Provider | Link | --------------------- | ------------ | -Alibaba Cloud | https://www.alibabacloud.com/trust-center | -Amazon Web Services | https://aws.amazon.com/security | -Google Cloud Platform | https://cloud.google.com/security | -Huawei Cloud | https://www.huaweicloud.com/intl/en-us/securecenter/overallsafety | -IBM Cloud | https://www.ibm.com/cloud/security | -Microsoft Azure | https://docs.microsoft.com/en-us/azure/security/azure-security | -Oracle Cloud Infrastructure | https://www.oracle.com/security | -VMware vSphere | https://www.vmware.com/security/hardening-guides | - -{{< /table >}} - -### Infrastructure security {#infrastructure-security} - -Suggestions for securing your infrastructure in a Kubernetes cluster: - -{{< table caption="Infrastructure security" >}} - -Area of Concern for Kubernetes Infrastructure | Recommendation | ---------------------------------------------- | -------------- | -Network access to API Server (Control plane) | All access to the Kubernetes control plane is not allowed publicly on the internet and is controlled by network access control lists restricted to the set of IP addresses needed to administer the cluster.| -Network access to Nodes (nodes) | Nodes should be configured to _only_ accept connections (via network access control lists) from the control plane on the specified ports, and accept connections for services in Kubernetes of type NodePort and LoadBalancer. If possible, these nodes should not be exposed on the public internet entirely. -Kubernetes access to Cloud Provider API | Each cloud provider needs to grant a different set of permissions to the Kubernetes control plane and nodes. It is best to provide the cluster with cloud provider access that follows the [principle of least privilege](https://en.wikipedia.org/wiki/Principle_of_least_privilege) for the resources it needs to administer. The [Kops documentation](https://github.com/kubernetes/kops/blob/master/docs/iam_roles.md#iam-roles) provides information about IAM policies and roles. -Access to etcd | Access to etcd (the datastore of Kubernetes) should be limited to the control plane only. Depending on your configuration, you should attempt to use etcd over TLS. More information can be found in the [etcd documentation](https://github.com/etcd-io/etcd/tree/master/Documentation). -etcd Encryption | Wherever possible it's a good practice to encrypt all storage at rest, and since etcd holds the state of the entire cluster (including Secrets) its disk should especially be encrypted at rest. - -{{< /table >}} - -## Cluster - -There are two areas of concern for securing Kubernetes: - -* Securing the cluster components that are configurable -* Securing the applications which run in the cluster - -### Components of the Cluster {#cluster-components} - -If you want to protect your cluster from accidental or malicious access and adopt -good information practices, read and follow the advice about -[securing your cluster](/docs/tasks/administer-cluster/securing-a-cluster/). - -### Components in the cluster (your application) {#cluster-applications} - -Depending on the attack surface of your application, you may want to focus on specific -aspects of security. For example: If you are running a service (Service A) that is critical -in a chain of other resources and a separate workload (Service B) which is -vulnerable to a resource exhaustion attack, then the risk of compromising Service A -is high if you do not limit the resources of Service B. The following table lists -areas of security concerns and recommendations for securing workloads running in Kubernetes: - -Area of Concern for Workload Security | Recommendation | ------------------------------- | --------------------- | -RBAC Authorization (Access to the Kubernetes API) | https://kubernetes.io/docs/reference/access-authn-authz/rbac/ -Authentication | https://kubernetes.io/docs/concepts/security/controlling-access/ -Application secrets management (and encrypting them in etcd at rest) | https://kubernetes.io/docs/concepts/configuration/secret/
https://kubernetes.io/docs/tasks/administer-cluster/encrypt-data/ -Ensuring that pods meet defined Pod Security Standards | https://kubernetes.io/docs/concepts/security/pod-security-standards/#policy-instantiation -Quality of Service (and Cluster resource management) | https://kubernetes.io/docs/tasks/configure-pod-container/quality-service-pod/ -Network Policies | https://kubernetes.io/docs/concepts/services-networking/network-policies/ -TLS for Kubernetes Ingress | https://kubernetes.io/docs/concepts/services-networking/ingress/#tls - -## Container - -Container security is outside the scope of this guide. Here are general recommendations and -links to explore this topic: - -Area of Concern for Containers | Recommendation | ------------------------------- | -------------- | -Container Vulnerability Scanning and OS Dependency Security | As part of an image build step, you should scan your containers for known vulnerabilities. -Image Signing and Enforcement | Sign container images to maintain a system of trust for the content of your containers. -Disallow privileged users | When constructing containers, consult your documentation for how to create users inside of the containers that have the least level of operating system privilege necessary in order to carry out the goal of the container. -Use container runtime with stronger isolation | Select [container runtime classes](/docs/concepts/containers/runtime-class/) that provide stronger isolation. - -## Code - -Application code is one of the primary attack surfaces over which you have the most control. -While securing application code is outside of the Kubernetes security topic, here -are recommendations to protect application code: - -### Code security - -{{< table caption="Code security" >}} - -Area of Concern for Code | Recommendation | --------------------------| -------------- | -Access over TLS only | If your code needs to communicate by TCP, perform a TLS handshake with the client ahead of time. With the exception of a few cases, encrypt everything in transit. Going one step further, it's a good idea to encrypt network traffic between services. This can be done through a process known as mutual TLS authentication or [mTLS](https://en.wikipedia.org/wiki/Mutual_authentication) which performs a two sided verification of communication between two certificate holding services. | -Limiting port ranges of communication | This recommendation may be a bit self-explanatory, but wherever possible you should only expose the ports on your service that are absolutely essential for communication or metric gathering. | -3rd Party Dependency Security | It is a good practice to regularly scan your application's third party libraries for known security vulnerabilities. Each programming language has a tool for performing this check automatically. | -Static Code Analysis | Most languages provide a way for a snippet of code to be analyzed for any potentially unsafe coding practices. Whenever possible you should perform checks using automated tooling that can scan codebases for common security errors. Some of the tools can be found at: https://owasp.org/www-community/Source_Code_Analysis_Tools | -Dynamic probing attacks | There are a few automated tools that you can run against your service to try some of the well known service attacks. These include SQL injection, CSRF, and XSS. One of the most popular dynamic analysis tools is the [OWASP Zed Attack proxy](https://www.zaproxy.org/) tool. | - -{{< /table >}} - -## {{% heading "whatsnext" %}} - -Learn about related Kubernetes security topics: - -* [Pod security standards](/docs/concepts/security/pod-security-standards/) -* [Network policies for Pods](/docs/concepts/services-networking/network-policies/) -* [Controlling Access to the Kubernetes API](/docs/concepts/security/controlling-access) -* [Securing your cluster](/docs/tasks/administer-cluster/securing-a-cluster/) -* [Data encryption in transit](/docs/tasks/tls/managing-tls-in-a-cluster/) for the control plane -* [Data encryption at rest](/docs/tasks/administer-cluster/encrypt-data/) -* [Secrets in Kubernetes](/docs/concepts/configuration/secret/) -* [Runtime class](/docs/concepts/containers/runtime-class) diff --git a/content/en/docs/concepts/security/pod-security-admission.md b/content/en/docs/concepts/security/pod-security-admission.md index 95a2d6e3f4b88..c4caa6905d38d 100644 --- a/content/en/docs/concepts/security/pod-security-admission.md +++ b/content/en/docs/concepts/security/pod-security-admission.md @@ -121,7 +121,7 @@ current policy level: - Any metadata updates **except** changes to the seccomp or AppArmor annotations: - `seccomp.security.alpha.kubernetes.io/pod` (deprecated) - `container.seccomp.security.alpha.kubernetes.io/*` (deprecated) - - `container.apparmor.security.beta.kubernetes.io/*` + - `container.apparmor.security.beta.kubernetes.io/*` (deprecated) - Valid updates to `.spec.activeDeadlineSeconds` - Valid updates to `.spec.tolerations` diff --git a/content/en/docs/concepts/security/pod-security-standards.md b/content/en/docs/concepts/security/pod-security-standards.md index 886137f0f75d9..fb9cab9d15c8c 100644 --- a/content/en/docs/concepts/security/pod-security-standards.md +++ b/content/en/docs/concepts/security/pod-security-standards.md @@ -5,7 +5,7 @@ title: Pod Security Standards description: > A detailed look at the different policy levels defined in the Pod Security Standards. content_type: concept -weight: 10 +weight: 15 --- @@ -170,8 +170,21 @@ fail validation. AppArmor -

On supported hosts, the runtime/default AppArmor profile is applied by default. The baseline policy should prevent overriding or disabling the default AppArmor profile, or restrict overrides to an allowed set of profiles.

+

On supported hosts, the RuntimeDefault AppArmor profile is applied by default. The baseline policy should prevent overriding or disabling the default AppArmor profile, or restrict overrides to an allowed set of profiles.

Restricted Fields

+
    +
  • spec.securityContext.appArmorProfile.type
  • +
  • spec.containers[*].securityContext.appArmorProfile.type
  • +
  • spec.initContainers[*].securityContext.appArmorProfile.type
  • +
  • spec.ephemeralContainers[*].securityContext.appArmorProfile.type
  • +
+

Allowed Values

+
    +
  • Undefined/nil
  • +
  • RuntimeDefault
  • +
  • Localhost
  • +
+
  • metadata.annotations["container.apparmor.security.beta.kubernetes.io/*"]
@@ -532,4 +545,3 @@ kernel. This allows for workloads requiring heightened permissions to still be i Additionally, the protection of sandboxed workloads is highly dependent on the method of sandboxing. As such, no single recommended profile is recommended for all sandboxed workloads. - diff --git a/content/en/docs/concepts/security/rbac-good-practices.md b/content/en/docs/concepts/security/rbac-good-practices.md index 0d8b09e0ebadb..f935061674b10 100644 --- a/content/en/docs/concepts/security/rbac-good-practices.md +++ b/content/en/docs/concepts/security/rbac-good-practices.md @@ -56,7 +56,7 @@ In cases where a workload requires powerful permissions, consider the following [Taints and Toleration](/docs/concepts/scheduling-eviction/taint-and-toleration/), [NodeAffinity](/docs/concepts/scheduling-eviction/assign-pod-node/#node-affinity), or [PodAntiAffinity](/docs/concepts/scheduling-eviction/assign-pod-node/#inter-pod-affinity-and-anti-affinity) - to ensure pods don't run alongside untrusted or less-trusted Pods. Pay especial attention to + to ensure pods don't run alongside untrusted or less-trusted Pods. Pay special attention to situations where less-trustworthy Pods are not meeting the **Restricted** Pod Security Standard. ### Hardening @@ -130,8 +130,8 @@ reading data from other containers, and abusing the credentials of system servic You should only allow access to create PersistentVolume objects for: -- users (cluster operators) that need this access for their work, and who you trust, -- the Kubernetes control plane components which creates PersistentVolumes based on PersistentVolumeClaims +- Users (cluster operators) that need this access for their work, and who you trust. +- The Kubernetes control plane components which creates PersistentVolumes based on PersistentVolumeClaims that are configured for automatic provisioning. This is usually setup by the Kubernetes provider or by the operator when installing a CSI driver. @@ -181,6 +181,14 @@ Users with control over `validatingwebhookconfigurations` or `mutatingwebhookcon can control webhooks that can read any object admitted to the cluster, and in the case of mutating webhooks, also mutate admitted objects. +### Namespace modification + +Users who can perform **patch** operations on Namespace objects (through a namespaced RoleBinding to a Role with that access) can modify +labels on that namespace. In clusters where Pod Security Admission is used, this may allow a user to configure the namespace +for a more permissive policy than intended by the administrators. +For clusters where NetworkPolicy is used, users may be set labels that indirectly allow +access to services that an administrator did not intend to allow. + ## Kubernetes RBAC - denial of service risks {#denial-of-service-risks} ### Object creation denial-of-service {#object-creation-dos} diff --git a/content/en/docs/concepts/security/security-checklist.md b/content/en/docs/concepts/security/security-checklist.md index 6987a6b92aaf1..e78b8da0c5dff 100644 --- a/content/en/docs/concepts/security/security-checklist.md +++ b/content/en/docs/concepts/security/security-checklist.md @@ -177,10 +177,10 @@ Seccomp is only available on Linux nodes. #### AppArmor -[AppArmor](https://apparmor.net/) is a Linux kernel security module that can +[AppArmor](/docs/tutorials/security/apparmor/) is a Linux kernel security module that can provide an easy way to implement Mandatory Access Control (MAC) and better -auditing through system logs. To [enable AppArmor in Kubernetes](/docs/tutorials/security/apparmor/), -at least version 1.4 is required. Like seccomp, AppArmor is also configured +auditing through system logs. A default AppArmor profile is enforced on nodes that support it, or a custom profile can be configured. +Like seccomp, AppArmor is also configured through profiles, where each profile is either running in enforcing mode, which blocks access to disallowed resources or complain mode, which only reports violations. AppArmor profiles are enforced on a per-container basis, with an diff --git a/content/en/docs/concepts/security/service-accounts.md b/content/en/docs/concepts/security/service-accounts.md index a7b3d54d76d33..088591bbb21df 100644 --- a/content/en/docs/concepts/security/service-accounts.md +++ b/content/en/docs/concepts/security/service-accounts.md @@ -2,8 +2,11 @@ title: Service Accounts description: > Learn about ServiceAccount objects in Kubernetes. +api_metadata: +- apiVersion: "v1" + kind: "ServiceAccount" content_type: concept -weight: 10 +weight: 25 --- diff --git a/content/en/docs/concepts/services-networking/dns-pod-service.md b/content/en/docs/concepts/services-networking/dns-pod-service.md index 29eb675abdf37..951131cfdb9ca 100644 --- a/content/en/docs/concepts/services-networking/dns-pod-service.md +++ b/content/en/docs/concepts/services-networking/dns-pod-service.md @@ -213,7 +213,7 @@ When you set `setHostnameAsFQDN: true` in the Pod spec, the kubelet writes the P {{< note >}} In Linux, the hostname field of the kernel (the `nodename` field of `struct utsname`) is limited to 64 characters. -If a Pod enables this feature and its FQDN is longer than 64 character, it will fail to start. The Pod will remain in `Pending` status (`ContainerCreating` as seen by `kubectl`) generating error events, such as Failed to construct FQDN from Pod hostname and cluster domain, FQDN `long-FQDN` is too long (64 characters is the max, 70 characters requested). One way of improving user experience for this scenario is to create an [admission webhook controller](/docs/reference/access-authn-authz/extensible-admission-controllers/#admission-webhooks) to control FQDN size when users create top level objects, for example, Deployment. +If a Pod enables this feature and its FQDN is longer than 64 character, it will fail to start. The Pod will remain in `Pending` status (`ContainerCreating` as seen by `kubectl`) generating error events, such as Failed to construct FQDN from Pod hostname and cluster domain, FQDN `long-FQDN` is too long (64 characters is the max, 70 characters requested). One way of improving user experience for this scenario is to create an [admission webhook controller](/docs/reference/access-authn-authz/extensible-admission-controllers/#what-are-admission-webhooks) to control FQDN size when users create top level objects, for example, Deployment. {{< /note >}} ### Pod's DNS Policy diff --git a/content/en/docs/concepts/services-networking/endpoint-slices.md b/content/en/docs/concepts/services-networking/endpoint-slices.md index 15e38744872a2..e283e48b5b372 100644 --- a/content/en/docs/concepts/services-networking/endpoint-slices.md +++ b/content/en/docs/concepts/services-networking/endpoint-slices.md @@ -2,6 +2,9 @@ reviewers: - freehan title: EndpointSlices +api_metadata: +- apiVersion: "discovery.k8s.io/v1" + kind: "EndpointSlice" content_type: concept weight: 60 description: >- diff --git a/content/en/docs/concepts/services-networking/ingress-controllers.md b/content/en/docs/concepts/services-networking/ingress-controllers.md index 1546e5e1a59a7..d8621b4f944fe 100644 --- a/content/en/docs/concepts/services-networking/ingress-controllers.md +++ b/content/en/docs/concepts/services-networking/ingress-controllers.md @@ -39,7 +39,7 @@ Kubernetes as a project supports and maintains [AWS](https://github.com/kubernet * [Emissary-Ingress](https://www.getambassador.io/products/api-gateway) API Gateway is an [Envoy](https://www.envoyproxy.io)-based ingress controller. * [EnRoute](https://getenroute.io/) is an [Envoy](https://www.envoyproxy.io) based API gateway that can run as an ingress controller. -* [Easegress IngressController](https://github.com/megaease/easegress/blob/main/doc/reference/ingresscontroller.md) is an [Easegress](https://megaease.com/easegress/) based API gateway that can run as an ingress controller. +* [Easegress IngressController](https://megaease.com/docs/easegress/04.cloud-native/4.1.kubernetes-ingress-controller/) is an [Easegress](https://megaease.com/easegress/) based API gateway that can run as an ingress controller. * F5 BIG-IP [Container Ingress Services for Kubernetes](https://clouddocs.f5.com/containers/latest/userguide/kubernetes/) lets you use an Ingress to configure F5 BIG-IP virtual servers. * [FortiADC Ingress Controller](https://docs.fortinet.com/document/fortiadc/7.0.0/fortiadc-ingress-controller/742835/fortiadc-ingress-controller-overview) support the Kubernetes Ingress resources and allows you to manage FortiADC objects from Kubernetes diff --git a/content/en/docs/concepts/services-networking/ingress.md b/content/en/docs/concepts/services-networking/ingress.md index 89888cb5d32af..2989a22a81936 100644 --- a/content/en/docs/concepts/services-networking/ingress.md +++ b/content/en/docs/concepts/services-networking/ingress.md @@ -2,6 +2,11 @@ reviewers: - bprashanth title: Ingress +api_metadata: +- apiVersion: "networking.k8s.io/v1" + kind: "Ingress" +- apiVersion: "networking.k8s.io/v1" + kind: "IngressClass" content_type: concept description: >- Make your HTTP (or HTTPS) network service available using a protocol-aware configuration @@ -636,7 +641,7 @@ Please check the documentation of the relevant [Ingress controller](/docs/concep You can expose a Service in multiple ways that don't directly involve the Ingress resource: * Use [Service.Type=LoadBalancer](/docs/concepts/services-networking/service/#loadbalancer) -* Use [Service.Type=NodePort](/docs/concepts/services-networking/service/#nodeport) +* Use [Service.Type=NodePort](/docs/concepts/services-networking/service/#type-nodeport) ## {{% heading "whatsnext" %}} diff --git a/content/en/docs/concepts/services-networking/network-policies.md b/content/en/docs/concepts/services-networking/network-policies.md index e2120adf4690f..06cb3ba06ccdf 100644 --- a/content/en/docs/concepts/services-networking/network-policies.md +++ b/content/en/docs/concepts/services-networking/network-policies.md @@ -5,39 +5,41 @@ reviewers: - danwinship title: Network Policies content_type: concept +api_metadata: +- apiVersion: "networking.k8s.io/v1" + kind: "NetworkPolicy" weight: 70 description: >- If you want to control traffic flow at the IP address or port level (OSI layer 3 or 4), NetworkPolicies allow you to specify rules for traffic flow within your cluster, and also between Pods and the outside world. Your cluster must use a network plugin that supports NetworkPolicy enforcement. - --- If you want to control traffic flow at the IP address or port level for TCP, UDP, and SCTP protocols, then you might consider using Kubernetes NetworkPolicies for particular applications in your cluster. -NetworkPolicies are an application-centric construct which allow you to specify how a {{< -glossary_tooltip text="pod" term_id="pod">}} is allowed to communicate with various network +NetworkPolicies are an application-centric construct which allow you to specify how a +{{< glossary_tooltip text="pod" term_id="pod">}} is allowed to communicate with various network "entities" (we use the word "entity" here to avoid overloading the more common terms such as "endpoints" and "services", which have specific Kubernetes connotations) over the network. NetworkPolicies apply to a connection with a pod on one or both ends, and are not relevant to other connections. The entities that a Pod can communicate with are identified through a combination of the following -3 identifiers: +three identifiers: 1. Other pods that are allowed (exception: a pod cannot block access to itself) -2. Namespaces that are allowed -3. IP blocks (exception: traffic to and from the node where a Pod is running is always allowed, +1. Namespaces that are allowed +1. IP blocks (exception: traffic to and from the node where a Pod is running is always allowed, regardless of the IP address of the Pod or the node) -When defining a pod- or namespace- based NetworkPolicy, you use a +When defining a pod- or namespace-based NetworkPolicy, you use a {{< glossary_tooltip text="selector" term_id="selector">}} to specify what traffic is allowed to and from the Pod(s) that match the selector. -Meanwhile, when IP based NetworkPolicies are created, we define policies based on IP blocks (CIDR ranges). +Meanwhile, when IP-based NetworkPolicies are created, we define policies based on IP blocks (CIDR ranges). ## Prerequisites @@ -46,12 +48,12 @@ Network policies are implemented by the [network plugin](/docs/concepts/extend-k To use network policies, you must be using a networking solution which supports NetworkPolicy. Creating a NetworkPolicy resource without a controller that implements it will have no effect. -## The Two Sorts of Pod Isolation +## The two sorts of pod isolation There are two sorts of isolation for a pod: isolation for egress, and isolation for ingress. They concern what connections may be established. "Isolation" here is not absolute, rather it means "some restrictions apply". The alternative, "non-isolated for $direction", means that no -restrictions apply in the stated direction. The two sorts of isolation (or not) are declared +restrictions apply in the stated direction. The two sorts of isolation (or not) are declared independently, and are both relevant for a connection from one pod to another. By default, a pod is non-isolated for egress; all outbound connections are allowed. @@ -93,7 +95,7 @@ solution supports network policy. {{< /note >}} __Mandatory Fields__: As with all other Kubernetes config, a NetworkPolicy needs `apiVersion`, -`kind`, and `metadata` fields. For general information about working with config files, see +`kind`, and `metadata` fields. For general information about working with config files, see [Configure a Pod to Use a ConfigMap](/docs/tasks/configure-pod-container/configure-pod-configmap/), and [Object Management](/docs/concepts/overview/working-with-objects/object-management). @@ -227,7 +229,7 @@ that explicitly allows that. {{% code_sample file="service/networking/network-policy-allow-all-ingress.yaml" %}} With this policy in place, no additional policy or policies can cause any incoming connection to -those pods to be denied. This policy has no effect on isolation for egress from any pod. +those pods to be denied. This policy has no effect on isolation for egress from any pod. ### Default deny all egress traffic @@ -247,7 +249,7 @@ explicitly allows all outgoing connections from pods in that namespace. {{% code_sample file="service/networking/network-policy-allow-all-egress.yaml" %}} With this policy in place, no additional policy or policies can cause any outgoing connection from -those pods to be denied. This policy has no effect on isolation for ingress to any pod. +those pods to be denied. This policy has no effect on isolation for ingress to any pod. ### Default deny all ingress and all egress traffic @@ -261,8 +263,8 @@ ingress or egress traffic. ## Network traffic filtering -NetworkPolicy is defined for [layer 4](https://en.wikipedia.org/wiki/OSI_model#Layer_4:_Transport_layer) -connections (TCP, UDP, and optionally SCTP). For all the other protocols, the behaviour may vary +NetworkPolicy is defined for [layer 4](https://en.wikipedia.org/wiki/OSI_model#Layer_4:_Transport_layer) +connections (TCP, UDP, and optionally SCTP). For all the other protocols, the behaviour may vary across network plugins. {{< note >}} @@ -273,7 +275,7 @@ protocol NetworkPolicies. When a `deny all` network policy is defined, it is only guaranteed to deny TCP, UDP and SCTP connections. For other protocols, such as ARP or ICMP, the behaviour is undefined. The same applies to allow rules: when a specific pod is allowed as ingress source or egress destination, -it is undefined what happens with (for example) ICMP packets. Protocols such as ICMP may be allowed by some +it is undefined what happens with (for example) ICMP packets. Protocols such as ICMP may be allowed by some network plugins and denied by others. ## Targeting a range of ports @@ -286,8 +288,8 @@ This is achievable with the usage of the `endPort` field, as the following examp {{% code_sample file="service/networking/networkpolicy-multiport-egress.yaml" %}} -The above rule allows any Pod with label `role=db` on the namespace `default` to communicate -with any IP within the range `10.0.0.0/24` over TCP, provided that the target +The above rule allows any Pod with label `role=db` on the namespace `default` to communicate +with any IP within the range `10.0.0.0/24` over TCP, provided that the target port is between the range 32000 and 32768. The following restrictions apply when using this field: @@ -299,7 +301,7 @@ The following restrictions apply when using this field: {{< note >}} Your cluster must be using a {{< glossary_tooltip text="CNI" term_id="cni" >}} plugin that supports the `endPort` field in NetworkPolicy specifications. -If your [network plugin](/docs/concepts/extend-kubernetes/compute-storage-net/network-plugins/) +If your [network plugin](/docs/concepts/extend-kubernetes/compute-storage-net/network-plugins/) does not support the `endPort` field and you specify a NetworkPolicy with that, the policy will be applied only for the single `port` field. {{< /note >}} @@ -310,8 +312,8 @@ In this scenario, your `Egress` NetworkPolicy targets more than one namespace us label names. For this to work, you need to label the target namespaces. For example: ```shell - kubectl label namespace frontend namespace=frontend - kubectl label namespace backend namespace=backend +kubectl label namespace frontend namespace=frontend +kubectl label namespace backend namespace=backend ``` Add the labels under `namespaceSelector` in your NetworkPolicy document. For example: @@ -360,32 +362,31 @@ NetworkPolicy. When a new NetworkPolicy object is created, it may take some time for a network plugin to handle the new object. If a pod that is affected by a NetworkPolicy is created before the network plugin has completed NetworkPolicy handling, -that pod may be started unprotected, and isolation rules will be applied when +that pod may be started unprotected, and isolation rules will be applied when the NetworkPolicy handling is completed. Once the NetworkPolicy is handled by a network plugin, -1. All newly created pods affected by a given NetworkPolicy will be isolated before -they are started. -Implementations of NetworkPolicy must ensure that filtering is effective throughout -the Pod lifecycle, even from the very first instant that any container in that Pod is started. -Because they are applied at Pod level, NetworkPolicies apply equally to init containers, -sidecar containers, and regular containers. +1. All newly created pods affected by a given NetworkPolicy will be isolated before they are started. + Implementations of NetworkPolicy must ensure that filtering is effective throughout + the Pod lifecycle, even from the very first instant that any container in that Pod is started. + Because they are applied at Pod level, NetworkPolicies apply equally to init containers, + sidecar containers, and regular containers. -2. Allow rules will be applied eventually after the isolation rules (or may be applied at the same time). -In the worst case, a newly created pod may have no network connectivity at all when it is first started, if -isolation rules were already applied, but no allow rules were applied yet. +1. Allow rules will be applied eventually after the isolation rules (or may be applied at the same time). + In the worst case, a newly created pod may have no network connectivity at all when it is first started, if + isolation rules were already applied, but no allow rules were applied yet. Every created NetworkPolicy will be handled by a network plugin eventually, but there is no way to tell from the Kubernetes API when exactly that happens. Therefore, pods must be resilient against being started up with different network -connectivity than expected. If you need to make sure the pod can reach certain destinations +connectivity than expected. If you need to make sure the pod can reach certain destinations before being started, you can use an [init container](/docs/concepts/workloads/pods/init-containers/) to wait for those destinations to be reachable before kubelet starts the app containers. Every NetworkPolicy will be applied to all selected pods eventually. -Because the network plugin may implement NetworkPolicy in a distributed manner, +Because the network plugin may implement NetworkPolicy in a distributed manner, it is possible that pods may see a slightly inconsistent view of network policies when the pod is first created, or when pods or policies change. For example, a newly-created pod that is supposed to be able to reach both Pod A @@ -395,16 +396,18 @@ but cannot reach Pod B until a few seconds later. ## NetworkPolicy and `hostNetwork` pods NetworkPolicy behaviour for `hostNetwork` pods is undefined, but it should be limited to 2 possibilities: + - The network plugin can distinguish `hostNetwork` pod traffic from all other traffic (including being able to distinguish traffic from different `hostNetwork` pods on the same node), and will apply NetworkPolicy to `hostNetwork` pods just like it does to pod-network pods. -- The network plugin cannot properly distinguish `hostNetwork` pod traffic, - and so it ignores `hostNetwork` pods when matching `podSelector` and `namespaceSelector`. - Traffic to/from `hostNetwork` pods is treated the same as all other traffic to/from the node IP. +- The network plugin cannot properly distinguish `hostNetwork` pod traffic, + and so it ignores `hostNetwork` pods when matching `podSelector` and `namespaceSelector`. + Traffic to/from `hostNetwork` pods is treated the same as all other traffic to/from the node IP. (This is the most common implementation.) This applies when + 1. a `hostNetwork` pod is selected by `spec.podSelector`. ```yaml @@ -416,7 +419,7 @@ This applies when ... ``` -2. a `hostNetwork` pod is selected by a `podSelector` or `namespaceSelector` in an `ingress` or `egress` rule. +1. a `hostNetwork` pod is selected by a `podSelector` or `namespaceSelector` in an `ingress` or `egress` rule. ```yaml ... @@ -437,7 +440,7 @@ from a `hostNetwork` Pod using an `ipBlock` rule. As of Kubernetes {{< skew currentVersion >}}, the following functionality does not exist in the NetworkPolicy API, but you might be able to implement workarounds using Operating System components (such as SELinux, OpenVSwitch, IPTables, and so on) or Layer 7 technologies (Ingress -controllers, Service Mesh implementations) or admission controllers. In case you are new to +controllers, Service Mesh implementations) or admission controllers. In case you are new to network security in Kubernetes, its worth noting that the following User Stories cannot (yet) be implemented using the NetworkPolicy API. diff --git a/content/en/docs/concepts/services-networking/service.md b/content/en/docs/concepts/services-networking/service.md index fd992995288da..bd09e179f2aa9 100644 --- a/content/en/docs/concepts/services-networking/service.md +++ b/content/en/docs/concepts/services-networking/service.md @@ -2,6 +2,9 @@ reviewers: - bprashanth title: Service +api_metadata: +- apiVersion: "v1" + kind: "Service" feature: title: Service discovery and load balancing description: > @@ -216,7 +219,8 @@ metadata: name: my-service spec: ports: - - protocol: TCP + - name: http + protocol: TCP port: 80 targetPort: 9376 ``` @@ -238,8 +242,7 @@ metadata: kubernetes.io/service-name: my-service addressType: IPv4 ports: - - name: '' # empty because port 9376 is not assigned as a well-known - # port (by IANA) + - name: http # should match with the name of the service port defined above appProtocol: http protocol: TCP port: 9376 @@ -619,9 +622,19 @@ You can integrate with [Gateway](https://gateway-api.sigs.k8s.io/) rather than S can define your own (provider specific) annotations on the Service that specify the equivalent detail. {{< /note >}} +#### Node liveness impact on load balancer traffic + +Load balancer health checks are critical to modern applications. They are used to +determine which server (virtual machine, or IP address) the load balancer should +dispatch traffic to. The Kubernetes APIs do not define how health checks have to be +implemented for Kubernetes managed load balancers, instead it's the cloud providers +(and the people implementing integration code) who decide on the behavior. Load +balancer health checks are extensively used within the context of supporting the +`externalTrafficPolicy` field for Services. + #### Load balancers with mixed protocol types -{{< feature-state for_k8s_version="v1.26" state="stable" >}} +{{< feature-state feature_gate_name="MixedProtocolLBService" >}} By default, for LoadBalancer type of Services, when there is more than one port defined, all ports must have the same protocol, and the protocol must be one which is supported @@ -670,9 +683,9 @@ Unprefixed names are reserved for end-users. #### Specifying IPMode of load balancer status {#load-balancer-ip-mode} -{{< feature-state for_k8s_version="v1.29" state="alpha" >}} +{{< feature-state feature_gate_name="LoadBalancerIPMode" >}} -Starting as Alpha in Kubernetes 1.29, +As a Beta feature in Kubernetes 1.30, a [feature gate](/docs/reference/command-line-tools-reference/feature-gates/) named `LoadBalancerIPMode` allows you to set the `.status.loadBalancer.ingress.ipMode` for a Service with `type` set to `LoadBalancer`. @@ -852,9 +865,19 @@ You can use a headless Service to interface with other service discovery mechani without being tied to Kubernetes' implementation. For headless Services, a cluster IP is not allocated, kube-proxy does not handle -these Services, and there is no load balancing or proxying done by the platform -for them. How DNS is automatically configured depends on whether the Service has -selectors defined: +these Services, and there is no load balancing or proxying done by the platform for them. + +A headless Service allows a client to connect to whichever Pod it prefers, directly. Services that are headless don't +configure routes and packet forwarding using +[virtual IP addresses and proxies](/docs/reference/networking/virtual-ips/); instead, headless Services report the +endpoint IP addresses of the individual pods via internal DNS records, served through the cluster's +[DNS service](/docs/concepts/services-networking/dns-pod-service/). +To define a headless Service, you make a Service with `.spec.type` set to ClusterIP (which is also the default for `type`), +and you additionally set `.spec.clusterIP` to None. + +The string value None is a special case and is not the same as leaving the `.spec.clusterIP` field unset. + +How DNS is automatically configured depends on whether the Service has selectors defined: ### With selectors @@ -967,6 +990,35 @@ to control how Kubernetes routes traffic to healthy (“ready”) backends. See [Traffic Policies](/docs/reference/networking/virtual-ips/#traffic-policies) for more details. +### Trafic distribution + +{{< feature-state feature_gate_name="ServiceTrafficDistribution" >}} + +The `.spec.trafficDistribution` field provides another way to influence traffic +routing within a Kubernetes Service. While traffic policies focus on strict +semantic guarantees, traffic distribution allows you to express _preferences_ +(such as routing to topologically closer endpoints). This can help optimize for +performance, cost, or reliability. This optional field can be used if you have +enabled the `ServiceTrafficDistribution` [feature +gate](/docs/reference/command-line-tools-reference/feature-gates/) for your +cluster and all of its nodes. In Kubernetes {{< skew currentVersion >}}, the +following field value is supported: + +`PreferClose` +: Indicates a preference for routing traffic to endpoints that are topologically + proximate to the client. The interpretation of "topologically proximate" may + vary across implementations and could encompass endpoints within the same + node, rack, zone, or even region. Setting this value gives implementations + permission to make different tradeoffs, e.g. optimizing for proximity rather + than equal distribution of load. Users should not set this value if such + tradeoffs are not acceptable. + +If the field is not set, the implementation will apply its default routing strategy. + +See [Traffic +Distribution](/docs/reference/networking/virtual-ips/#traffic-distribution) for +more details + ### Session stickiness If you want to make sure that connections from a particular client are passed to diff --git a/content/en/docs/concepts/services-networking/topology-aware-routing.md b/content/en/docs/concepts/services-networking/topology-aware-routing.md index 7092946e85b65..05e93549ebff8 100644 --- a/content/en/docs/concepts/services-networking/topology-aware-routing.md +++ b/content/en/docs/concepts/services-networking/topology-aware-routing.md @@ -198,3 +198,8 @@ yet cover some relevant and plausible situations. ## {{% heading "whatsnext" %}} * Follow the [Connecting Applications with Services](/docs/tutorials/services/connect-applications-service/) tutorial +* Learn about the + [trafficDistribution](/docs/concepts/services-networking/service/#trafic-distribution) + field, which is closely related to the `service.kubernetes.io/topology-mode` + annotation and provides flexible options for traffic routing within + Kubernetes. diff --git a/content/en/docs/concepts/storage/dynamic-provisioning.md b/content/en/docs/concepts/storage/dynamic-provisioning.md index 54ab391d80636..4356e3d3d3497 100644 --- a/content/en/docs/concepts/storage/dynamic-provisioning.md +++ b/content/en/docs/concepts/storage/dynamic-provisioning.md @@ -17,7 +17,8 @@ calls to their cloud or storage provider to create new storage volumes, and then create [`PersistentVolume` objects](/docs/concepts/storage/persistent-volumes/) to represent them in Kubernetes. The dynamic provisioning feature eliminates the need for cluster administrators to pre-provision storage. Instead, it -automatically provisions storage when it is requested by users. +automatically provisions storage when users create +[`PersistentVolumeClaim` objects](/docs/concepts/storage/persistent-volumes/). @@ -119,9 +120,10 @@ When a default `StorageClass` exists in a cluster and a user creates a `DefaultStorageClass` admission controller automatically adds the `storageClassName` field pointing to the default storage class. -Note that there can be at most one *default* storage class on a cluster, or -a `PersistentVolumeClaim` without `storageClassName` explicitly specified cannot -be created. +Note that if you set the `storageclass.kubernetes.io/is-default-class` +annotation to true on more than one StorageClass in your cluster, and you then +create a `PersistentVolumeClaim` with no `storageClassName` set, Kubernetes +uses the most recently created default StorageClass. ## Topology Awareness @@ -130,4 +132,3 @@ Zones in a Region. Single-Zone storage backends should be provisioned in the Zon Pods are scheduled. This can be accomplished by setting the [Volume Binding Mode](/docs/concepts/storage/storage-classes/#volume-binding-mode). - diff --git a/content/en/docs/concepts/storage/ephemeral-volumes.md b/content/en/docs/concepts/storage/ephemeral-volumes.md index f92f544768fd0..f1968dabeae2d 100644 --- a/content/en/docs/concepts/storage/ephemeral-volumes.md +++ b/content/en/docs/concepts/storage/ephemeral-volumes.md @@ -18,7 +18,7 @@ particular PersistentVolumeClaim and PersistentVolume. -Some application need additional storage but don't care whether that +Some applications need additional storage but don't care whether that data is stored persistently across restarts. For example, caching services are often limited by memory size and can move infrequently used data into storage that is slower than memory with little impact diff --git a/content/en/docs/concepts/storage/persistent-volumes.md b/content/en/docs/concepts/storage/persistent-volumes.md index 59a50ed009116..65041f5587d3a 100644 --- a/content/en/docs/concepts/storage/persistent-volumes.md +++ b/content/en/docs/concepts/storage/persistent-volumes.md @@ -6,6 +6,9 @@ reviewers: - msau42 - xing-yang title: Persistent Volumes +api_metadata: +- apiVersion: "v1" + kind: "PersistentVolume" feature: title: Storage orchestration description: > @@ -506,30 +509,33 @@ PersistentVolume types are implemented as plugins. Kubernetes currently supports mounted on nodes. * [`nfs`](/docs/concepts/storage/volumes/#nfs) - Network File System (NFS) storage -The following types of PersistentVolume are deprecated. -This means that support is still available but will be removed in a future Kubernetes release. +The following types of PersistentVolume are deprecated but still available. +If you are using these volume types except for `flexVolume`, `cephfs` and `rbd`, +please install corresponding CSI drivers. +* [`awsElasticBlockStore`](/docs/concepts/storage/volumes/#awselasticblockstore) - AWS Elastic Block Store (EBS) + (**migration on by default** starting v1.23) +* [`azureDisk`](/docs/concepts/storage/volumes/#azuredisk) - Azure Disk + (**migration on by default** starting v1.23) * [`azureFile`](/docs/concepts/storage/volumes/#azurefile) - Azure File - (**deprecated** in v1.21) + (**migration on by default** starting v1.24) +* [`cephfs`](/docs/concepts/storage/volumes/#cephfs) - CephFS volume + (**deprecated** starting v1.28, no migration plan, support will be removed in a future release) +* [`cinder`](/docs/concepts/storage/volumes/#cinder) - Cinder (OpenStack block storage) + (**migration on by default** starting v1.21) * [`flexVolume`](/docs/concepts/storage/volumes/#flexvolume) - FlexVolume - (**deprecated** in v1.23) + (**deprecated** starting v1.23, no migration plan and no plan to remove support) +* [`gcePersistentDisk`](/docs/concepts/storage/volumes/#gcePersistentDisk) - GCE Persistent Disk + (**migration on by default** starting v1.23) * [`portworxVolume`](/docs/concepts/storage/volumes/#portworxvolume) - Portworx volume - (**deprecated** in v1.25) -* [`vsphereVolume`](/docs/concepts/storage/volumes/#vspherevolume) - vSphere VMDK volume - (**deprecated** in v1.19) -* [`cephfs`](/docs/concepts/storage/volumes/#cephfs) - CephFS volume - (**deprecated** in v1.28) + (**deprecated** starting v1.25) * [`rbd`](/docs/concepts/storage/volumes/#rbd) - Rados Block Device (RBD) volume - (**deprecated** in v1.28) + (**deprecated** starting v1.28, no migration plan, support will be removed in a future release) +* [`vsphereVolume`](/docs/concepts/storage/volumes/#vspherevolume) - vSphere VMDK volume + (**migration on by default** starting v1.25) Older versions of Kubernetes also supported the following in-tree PersistentVolume types: -* [`awsElasticBlockStore`](/docs/concepts/storage/volumes/#awselasticblockstore) - AWS Elastic Block Store (EBS) - (**not available** in v1.27) -* [`azureDisk`](/docs/concepts/storage/volumes/#azuredisk) - Azure Disk - (**not available** in v1.27) -* [`cinder`](/docs/concepts/storage/volumes/#cinder) - Cinder (OpenStack block storage) - (**not available** in v1.26) * `photonPersistentDisk` - Photon controller persistent disk. (**not available** starting v1.15) * `scaleIO` - ScaleIO volume. diff --git a/content/en/docs/concepts/storage/volumes.md b/content/en/docs/concepts/storage/volumes.md index b7dbf54651a07..a673ecf27b9cc 100644 --- a/content/en/docs/concepts/storage/volumes.md +++ b/content/en/docs/concepts/storage/volumes.md @@ -5,6 +5,9 @@ reviewers: - thockin - msau42 title: Volumes +api_metadata: +- apiVersion: "" + kind: "Volume" content_type: concept weight: 10 --- @@ -62,12 +65,14 @@ a different volume. Kubernetes supports several types of volumes. -### awsElasticBlockStore (removed) {#awselasticblockstore} +### awsElasticBlockStore (deprecated) {#awselasticblockstore} -Kubernetes {{< skew currentVersion >}} does not include a `awsElasticBlockStore` volume type. +In Kubernetes {{< skew currentVersion >}}, all operations for the in-tree `awsElasticBlockStore` type +are redirected to the `ebs.csi.aws.com` {{< glossary_tooltip text="CSI" term_id="csi" >}} driver. + The AWSElasticBlockStore in-tree storage driver was deprecated in the Kubernetes v1.19 release and then removed entirely in the v1.27 release. @@ -75,12 +80,13 @@ and then removed entirely in the v1.27 release. The Kubernetes project suggests that you use the [AWS EBS](https://github.com/kubernetes-sigs/aws-ebs-csi-driver) third party storage driver instead. -### azureDisk (removed) {#azuredisk} +### azureDisk (deprecated) {#azuredisk} -Kubernetes {{< skew currentVersion >}} does not include a `azureDisk` volume type. +In Kubernetes {{< skew currentVersion >}}, all operations for the in-tree `azureDisk` type +are redirected to the `disk.csi.azure.com` {{< glossary_tooltip text="CSI" term_id="csi" >}} driver. The AzureDisk in-tree storage driver was deprecated in the Kubernetes v1.19 release and then removed entirely in the v1.27 release. @@ -118,7 +124,7 @@ Azure File CSI driver does not support using same volume with different fsgroups To disable the `azureFile` storage plugin from being loaded by the controller manager and the kubelet, set the `InTreePluginAzureFileUnregister` flag to `true`. -### cephfs +### cephfs (deprecated) {#cephfs} {{< feature-state for_k8s_version="v1.28" state="deprecated" >}} {{< note >}} @@ -139,12 +145,13 @@ You must have your own Ceph server running with the share exported before you ca See the [CephFS example](https://github.com/kubernetes/examples/tree/master/volumes/cephfs/) for more details. -### cinder (removed) {#cinder} +### cinder (deprecated) {#cinder} -Kubernetes {{< skew currentVersion >}} does not include a `cinder` volume type. +In Kubernetes {{< skew currentVersion >}}, all operations for the in-tree `cinder` type +are redirected to the `cinder.csi.openstack.org` {{< glossary_tooltip text="CSI" term_id="csi" >}} driver. The OpenStack Cinder in-tree storage driver was deprecated in the Kubernetes v1.11 release and then removed entirely in the v1.26 release. @@ -194,7 +201,7 @@ keyed with `log_level`. {{< note >}} -* You must create a [ConfigMap](/docs/tasks/configure-pod-container/configure-pod-configmap/) +* You must [create a ConfigMap](/docs/tasks/configure-pod-container/configure-pod-configmap/#create-a-configmap) before you can use it. * A ConfigMap is always mounted as `readOnly`. @@ -295,9 +302,10 @@ beforehand so that Kubernetes hosts can access them. See the [fibre channel example](https://github.com/kubernetes/examples/tree/master/staging/volumes/fibre_channel) for more details. -### gcePersistentDisk (removed) {#gcepersistentdisk} +### gcePersistentDisk (deprecated) {#gcepersistentdisk} -Kubernetes {{< skew currentVersion >}} does not include a `gcePersistentDisk` volume type. +In Kubernetes {{< skew currentVersion >}}, all operations for the in-tree `gcePersistentDisk` type +are redirected to the `pd.csi.storage.gke.io` {{< glossary_tooltip text="CSI" term_id="csi" >}} driver. The `gcePersistentDisk` in-tree storage driver was deprecated in the Kubernetes v1.17 release and then removed entirely in the v1.28 release. @@ -308,9 +316,23 @@ third party storage driver instead. ### gitRepo (deprecated) {#gitrepo} {{< warning >}} -The `gitRepo` volume type is deprecated. To provision a container with a git repo, mount an -[EmptyDir](#emptydir) into an InitContainer that clones the repo using git, then mount the +The `gitRepo` volume type is deprecated. + +To provision a Pod that has a Git repository mounted, you can +mount an +[`emptyDir`](#emptydir) volume into an [init container](/docs/concepts/workloads/pods/init-containers/) that +clones the repo using Git, then mount the [EmptyDir](#emptydir) into the Pod's container. + +--- + +You can restrict the use of `gitRepo` volumes in your cluster using +[policies](/docs/concepts/policy/) such as +[ValidatingAdmissionPolicy](/docs/reference/access-authn-authz/validating-admission-policy/). +You can use the following Common Expression Language (CEL) expression as +part of a policy to reject use of `gitRepo` volumes: +`has(object.spec.volumes) || !object.spec.volumes.exists(v, has(v.gitRepo))`. + {{< /warning >}} A `gitRepo` volume is an example of a volume plugin. This plugin @@ -859,7 +881,7 @@ To turn off the `vsphereVolume` plugin from being loaded by the controller manag ## Using subPath {#using-subpath} Sometimes, it is useful to share one volume for multiple uses in a single pod. -The `volumeMounts.subPath` property specifies a sub-path inside the referenced volume +The `volumeMounts[*].subPath` property specifies a sub-path inside the referenced volume instead of its root. The following example shows how to configure a Pod with a LAMP stack (Linux Apache MySQL PHP) @@ -1162,7 +1184,7 @@ Mount propagation allows for sharing volumes mounted by a container to other containers in the same pod, or even to other pods on the same node. Mount propagation of a volume is controlled by the `mountPropagation` field -in `Container.volumeMounts`. Its values are: +in `containers[*].volumeMounts`. Its values are: * `None` - This volume mount will not receive any subsequent mounts that are mounted to this volume or any of its subdirectories by the host. @@ -1208,7 +1230,65 @@ in `Container.volumeMounts`. Its values are: (unmounted) by the containers on termination. {{< /warning >}} +## Read-only mounts + +A mount can be made read-only by setting the `.spec.containers[].volumeMounts[].readOnly` +field to `true`. +This does not make the volume itself read-only, but that specific container will +not be able to write to it. +Other containers in the Pod may mount the same volume as read-write. + +On Linux, read-only mounts are not recursively read-only by default. +For example, consider a Pod which mounts the hosts `/mnt` as a `hostPath` volume. If +there is another filesystem mounted read-write on `/mnt/` (such as tmpfs, +NFS, or USB storage), the volume mounted into the container(s) will also have a writeable +`/mnt/`, even if the mount itself was specified as read-only. + +### Recursive read-only mounts + +{{< feature-state feature_gate_name="RecursiveReadOnlyMounts" >}} + +Recursive read-only mounts can be enabled by setting the +`RecursiveReadOnlyMounts` [feature gate](/docs/reference/command-line-tools-reference/feature-gates/) +for kubelet and kube-apiserver, and setting the `.spec.containers[].volumeMounts[].recursiveReadOnly` +field for a pod. + +The allowed values are: + +* `Disabled` (default): no effect. + +* `Enabled`: makes the mount recursively read-only. + Needs all the following requirements to be satisfied: + * `readOnly` is set to `true` + * `mountPropagation` is unset, or, set to `None` + * The host is running with Linux kernel v5.12 or later + * The [CRI-level](/docs/concepts/architecture/cri) container runtime supports recursive read-only mounts + * The OCI-level container runtime supports recursive read-only mounts. + It will fail if any of these is not true. + +* `IfPossible`: attempts to apply `Enabled`, and falls back to `Disabled` + if the feature is not supported by the kernel or the runtime class. + +Example: +{{% code_sample file="storage/rro.yaml" %}} + +When this property is recognized by kubelet and kube-apiserver, +the `.status.containerStatuses[].volumeMounts[].recursiveReadOnly` field is set to either +`Enabled` or `Disabled`. + + +#### Implementations {#implementations-rro} + +{{% thirdparty-content %}} + +The following container runtimes are known to support recursive read-only mounts. + +CRI-level: +- [containerd](https://containerd.io/), since v2.0 +OCI-level: +- [runc](https://runc.io/), since v1.1 +- [crun](https://github.com/containers/crun), since v1.8.6 ## {{% heading "whatsnext" %}} diff --git a/content/en/docs/concepts/windows/intro.md b/content/en/docs/concepts/windows/intro.md index 3e22aa7d624f0..dcf4db95b9910 100644 --- a/content/en/docs/concepts/windows/intro.md +++ b/content/en/docs/concepts/windows/intro.md @@ -352,6 +352,40 @@ Windows Server SAC release The Kubernetes [version-skew policy](/docs/setup/release/version-skew-policy/) also applies. +## Hardware recommendations and considerations {#windows-hardware-recommendations} + +{{% thirdparty-content %}} + +{{< note >}} +The following hardware specifications outlined here should be regarded as sensible default values. +They are not intended to represent minimum requirements or specific recommendations for production environments. +Depending on the requirements for your workload these values may need to be adjusted. +{{< /note >}} + +- 64-bit processor 4 CPU cores or more, capable of supporting virtualization +- 8GB or more of RAM +- 50GB or more of free disk space + +Refer to +[Hardware requirements for Windows Server Microsoft documentation](https://learn.microsoft.com/en-us/windows-server/get-started/hardware-requirements) +for the most up-to-date information on minimum hardware requirements. For guidance on deciding on resources for +production worker nodes refer to [Production worker nodes Kubernetes documentation](https://kubernetes.io/docs/setup/production-environment/#production-worker-nodes). + +To optimize system resources, if a graphical user interface is not required, +it may be preferable to use a Windows Server OS installation that excludes +the [Windows Desktop Experience](https://learn.microsoft.com/en-us/windows-server/get-started/install-options-server-core-desktop-experience) +installation option, as this configuration typically frees up more system +resources. + +In assessing disk space for Windows worker nodes, take note that Windows container images are typically larger than +Linux container images, with container image sizes ranging +from [300MB to over 10GB](https://techcommunity.microsoft.com/t5/containers/nano-server-x-server-core-x-server-which-base-image-is-the-right/ba-p/2835785) +for a single image. Additionally, take note that the `C:` drive in Windows containers represents a virtual free size of +20GB by default, which is not the actual consumed space, but rather the disk size for which a single container can grow +to occupy when using local storage on the host. +See [Containers on Windows - Container Storage Documentation](https://learn.microsoft.com/en-us/virtualization/windowscontainers/manage-containers/container-storage#storage-limits) +for more detail. + ## Getting help and troubleshooting {#troubleshooting} Your main source of help for troubleshooting your Kubernetes cluster should start @@ -374,6 +408,17 @@ reported previously and comment with your experience on the issue and add additi logs. SIG Windows channel on the Kubernetes Slack is also a great avenue to get some initial support and troubleshooting ideas prior to creating a ticket. +### Validating the Windows cluster operability + +The Kubernetes project provides a _Windows Operational Readiness_ specification, +accompanied by a structured test suite. This suite is split into two sets of tests, +core and extended, each containing categories aimed at testing specific areas. +It can be used to validate all the functionalities of a Windows and hybrid system +(mixed with Linux nodes) with full coverage. + +To set up the project on a newly created cluster, refer to the instructions in the +[project guide](https://github.com/kubernetes-sigs/windows-operational-readiness/blob/main/README.md). + ## Deployment tools The kubeadm tool helps you to deploy a Kubernetes cluster, providing the control @@ -388,4 +433,4 @@ For a detailed explanation of Windows distribution channels see the Information on the different Windows Server servicing channels including their support models can be found at -[Windows Server servicing channels](https://docs.microsoft.com/en-us/windows-server/get-started/servicing-channels-comparison). +[Windows Server servicing channels](https://docs.microsoft.com/en-us/windows-server/get-started/servicing-channels-comparison). \ No newline at end of file diff --git a/content/en/docs/concepts/workloads/autoscaling.md b/content/en/docs/concepts/workloads/autoscaling.md new file mode 100644 index 0000000000000..ff154d71599be --- /dev/null +++ b/content/en/docs/concepts/workloads/autoscaling.md @@ -0,0 +1,142 @@ +--- +title: Autoscaling Workloads +description: >- + With autoscaling, you can automatically update your workloads in one way or another. This allows your cluster to react to changes in resource demand more elastically and efficiently. +content_type: concept +weight: 40 +--- + + + +In Kubernetes, you can _scale_ a workload depending on the current demand of resources. +This allows your cluster to react to changes in resource demand more elastically and efficiently. + +When you scale a workload, you can either increase or decrease the number of replicas managed by +the workload, or adjust the resources available to the replicas in-place. + +The first approach is referred to as _horizontal scaling_, while the second is referred to as +_vertical scaling_. + +There are manual and automatic ways to scale your workloads, depending on your use case. + + + +## Scaling workloads manually + +Kubernetes supports _manual scaling_ of workloads. Horizontal scaling can be done +using the `kubectl` CLI. +For vertical scaling, you need to _patch_ the resource definition of your workload. + +See below for examples of both strategies. + +- **Horizontal scaling**: [Running multiple instances of your app](/docs/tutorials/kubernetes-basics/scale/scale-intro/) +- **Vertical scaling**: [Resizing CPU and memory resources assigned to containers](/docs/tasks/configure-pod-container/resize-container-resources) + +## Scaling workloads automatically + +Kubernetes also supports _automatic scaling_ of workloads, which is the focus of this page. + +The concept of _Autoscaling_ in Kubernetes refers to the ability to automatically update an +object that manages a set of Pods (for example a +{{< glossary_tooltip text="Deployment" term_id="deployment" >}}). + +### Scaling workloads horizontally + +In Kubernetes, you can automatically scale a workload horizontally using a _HorizontalPodAutoscaler_ (HPA). + +It is implemented as a Kubernetes API resource and a {{< glossary_tooltip text="controller" term_id="controller" >}} +and periodically adjusts the number of {{< glossary_tooltip text="replicas" term_id="replica" >}} +in a workload to match observed resource utilization such as CPU or memory usage. + +There is a [walkthrough tutorial](/docs/tasks/run-application/horizontal-pod-autoscale-walkthrough) of configuring a HorizontalPodAutoscaler for a Deployment. + +### Scaling workloads vertically + +{{< feature-state for_k8s_version="v1.25" state="stable" >}} + +You can automatically scale a workload vertically using a _VerticalPodAutoscaler_ (VPA). +Unlike the HPA, the VPA doesn't come with Kubernetes by default, but is a separate project +that can be found [on GitHub](https://github.com/kubernetes/autoscaler/tree/9f87b78df0f1d6e142234bb32e8acbd71295585a/vertical-pod-autoscaler). + +Once installed, it allows you to create {{< glossary_tooltip text="CustomResourceDefinitions" term_id="customresourcedefinition" >}} +(CRDs) for your workloads which define _how_ and _when_ to scale the resources of the managed replicas. + +{{< note >}} +You will need to have the [Metrics Server](https://github.com/kubernetes-sigs/metrics-server) +installed to your cluster for the HPA to work. +{{< /note >}} + +At the moment, the VPA can operate in four different modes: + +{{< table caption="Different modes of the VPA" >}} +Mode | Description +:----|:----------- +`Auto` | Currently, `Recreate` might change to in-place updates in the future +`Recreate` | The VPA assigns resource requests on pod creation as well as updates them on existing pods by evicting them when the requested resources differ significantly from the new recommendation +`Initial` | The VPA only assigns resource requests on pod creation and never changes them later. +`Off` | The VPA does not automatically change the resource requirements of the pods. The recommendations are calculated and can be inspected in the VPA object. +{{< /table >}} + +#### Requirements for in-place resizing + +{{< feature-state for_k8s_version="v1.27" state="alpha" >}} + +Resizing a workload in-place **without** restarting the {{< glossary_tooltip text="Pods" term_id="pod" >}} +or its {{< glossary_tooltip text="Containers" term_id="container" >}} requires Kubernetes version 1.27 or later. +Additionally, the `InPlaceVerticalScaling` feature gate needs to be enabled. + +{{< feature-gate-description name="InPlacePodVerticalScaling" >}} + +### Autoscaling based on cluster size + +For workloads that need to be scaled based on the size of the cluster (for example +`cluster-dns` or other system components), you can use the +[_Cluster Proportional Autoscaler_](https://github.com/kubernetes-sigs/cluster-proportional-autoscaler). +Just like the VPA, it is not part of the Kubernetes core, but hosted as its +own project on GitHub. + +The Cluster Proportional Autoscaler watches the number of schedulable {{< glossary_tooltip text="nodes" term_id="node" >}} +and cores and scales the number of replicas of the target workload accordingly. + +If the number of replicas should stay the same, you can scale your workloads vertically according to the cluster size using +the [_Cluster Proportional Vertical Autoscaler_](https://github.com/kubernetes-sigs/cluster-proportional-vertical-autoscaler). +The project is **currently in beta** and can be found on GitHub. + +While the Cluster Proportional Autoscaler scales the number of replicas of a workload, the Cluster Proportional Vertical Autoscaler +adjusts the resource requests for a workload (for example a Deployment or DaemonSet) based on the number of nodes and/or cores +in the cluster. + +### Event driven Autoscaling + +It is also possible to scale workloads based on events, for example using the +[_Kubernetes Event Driven Autoscaler_ (**KEDA**)](https://keda.sh/). + +KEDA is a CNCF graduated enabling you to scale your workloads based on the number +of events to be processed, for example the amount of messages in a queue. There exists +a wide range of adapters for different event sources to choose from. + +### Autoscaling based on schedules + +Another strategy for scaling your workloads is to **schedule** the scaling operations, for example in order to +reduce resource consumption during off-peak hours. + +Similar to event driven autoscaling, such behavior can be achieved using KEDA in conjunction with +its [`Cron` scaler](https://keda.sh/docs/2.13/scalers/cron/). The `Cron` scaler allows you to define schedules +(and time zones) for scaling your workloads in or out. + +## Scaling cluster infrastructure + +If scaling workloads isn't enough to meet your needs, you can also scale your cluster infrastructure itself. + +Scaling the cluster infrastructure normally means adding or removing {{< glossary_tooltip text="nodes" term_id="node" >}}. +Read [cluster autoscaling](/docs/concepts/cluster-administration/cluster-autoscaling/) +for more information. + +## {{% heading "whatsnext" %}} + +- Learn more about scaling horizontally + - [Scale a StatefulSet](/docs/tasks/run-application/scale-stateful-set/) + - [HorizontalPodAutoscaler Walkthrough](/docs/tasks/run-application/horizontal-pod-autoscale-walkthrough/) +- [Resize Container Resources In-Place](/docs/tasks/configure-pod-container/resize-container-resources/) +- [Autoscale the DNS Service in a Cluster](/docs/tasks/administer-cluster/dns-horizontal-autoscaling/) +- Learn about [cluster autoscaling](/docs/concepts/cluster-administration/cluster-autoscaling/) diff --git a/content/en/docs/concepts/workloads/controllers/cron-jobs.md b/content/en/docs/concepts/workloads/controllers/cron-jobs.md index 2ffdda8b34664..cf9bddf694fd6 100644 --- a/content/en/docs/concepts/workloads/controllers/cron-jobs.md +++ b/content/en/docs/concepts/workloads/controllers/cron-jobs.md @@ -4,6 +4,9 @@ reviewers: - soltysh - janetkuo title: CronJob +api_metadata: +- apiVersion: "batch/v1" + kind: "CronJob" content_type: concept description: >- A CronJob starts one-time Jobs on a repeating schedule. @@ -158,12 +161,17 @@ When `.spec.suspend` changes from `true` to `false` on an existing CronJob witho ### Jobs history limits -The `.spec.successfulJobsHistoryLimit` and `.spec.failedJobsHistoryLimit` fields are optional. -These fields specify how many completed and failed Jobs should be kept. -By default, they are set to 3 and 1 respectively. Setting a limit to `0` corresponds to keeping -none of the corresponding kind of Jobs after they finish. +The `.spec.successfulJobsHistoryLimit` and `.spec.failedJobsHistoryLimit` fields specify +how many completed and failed Jobs should be kept. Both fields are optional. -For another way to clean up Jobs automatically, see [Clean up finished Jobs automatically](/docs/concepts/workloads/controllers/job/#clean-up-finished-jobs-automatically). +* `.spec.successfulJobsHistoryLimit`: This field specifies the number of successful finished +jobs to keep. The default value is `3`. Setting this field to `0` will not keep any successful jobs. + +* `.spec.failedJobsHistoryLimit`: This field specifies the number of failed finished jobs to keep. +The default value is `1`. Setting this field to `0` will not keep any failed jobs. + +For another way to clean up Jobs automatically, see +[Clean up finished Jobs automatically](/docs/concepts/workloads/controllers/job/#clean-up-finished-jobs-automatically). ### Time zones diff --git a/content/en/docs/concepts/workloads/controllers/daemonset.md b/content/en/docs/concepts/workloads/controllers/daemonset.md index bd7cca541b339..682c0595a68ca 100644 --- a/content/en/docs/concepts/workloads/controllers/daemonset.md +++ b/content/en/docs/concepts/workloads/controllers/daemonset.md @@ -6,6 +6,9 @@ reviewers: - janetkuo - kow3ns title: DaemonSet +api_metadata: +- apiVersion: "apps/v1" + kind: "DaemonSet" description: >- A DaemonSet defines Pods that provide node-local facilities. These might be fundamental to the operation of your cluster, such as a networking helper tool, or be part of an add-on. content_type: concept diff --git a/content/en/docs/concepts/workloads/controllers/deployment.md b/content/en/docs/concepts/workloads/controllers/deployment.md index 9b1e5f065bd06..e39e6f0f81f1c 100644 --- a/content/en/docs/concepts/workloads/controllers/deployment.md +++ b/content/en/docs/concepts/workloads/controllers/deployment.md @@ -2,6 +2,9 @@ reviewers: - janetkuo title: Deployments +api_metadata: +- apiVersion: "apps/v1" + kind: "Deployment" feature: title: Automated rollouts and rollbacks description: > diff --git a/content/en/docs/concepts/workloads/controllers/job.md b/content/en/docs/concepts/workloads/controllers/job.md index be5775973b83d..6a9a916aed412 100644 --- a/content/en/docs/concepts/workloads/controllers/job.md +++ b/content/en/docs/concepts/workloads/controllers/job.md @@ -4,6 +4,9 @@ reviewers: - erictune - soltysh title: Jobs +api_metadata: +- apiVersion: "batch/v1" + kind: "Job" content_type: concept description: >- Jobs represent one-off tasks that run to completion and then stop. @@ -550,6 +553,62 @@ terminating Pods only once these Pods reach the terminal `Failed` phase. This be to `podReplacementPolicy: Failed`. For more information, see [Pod replacement policy](#pod-replacement-policy). {{< /note >}} +## Success policy {#success-policy} + +{{< feature-state feature_gate_name="JobSuccessPolicy" >}} + +{{< note >}} +You can only configure a success policy for an Indexed Job if you have the +`JobSuccessPolicy` [feature gate](/docs/reference/command-line-tools-reference/feature-gates/) +enabled in your cluster. +{{< /note >}} + +When creating an Indexed Job, you can define when a Job can be declared as succeeded using a `.spec.successPolicy`, +based on the pods that succeeded. + +By default, a Job succeeds when the number of succeeded Pods equals `.spec.completions`. +These are some situations where you might want additional control for declaring a Job succeeded: + +* When running simulations with different parameters, + you might not need all the simulations to succeed for the overall Job to be successful. +* When following a leader-worker pattern, only the success of the leader determines the success or + failure of a Job. Examples of this are frameworks like MPI and PyTorch etc. + +You can configure a success policy, in the `.spec.successPolicy` field, +to meet the above use cases. This policy can handle Job success based on the +succeeded pods. After the Job meets the success policy, the job controller terminates the lingering Pods. +A success policy is defined by rules. Each rule can take one of the following forms: + +* When you specify the `succeededIndexes` only, + once all indexes specified in the `succeededIndexes` succeed, the job controller marks the Job as succeeded. + The `succeededIndexes` must be a list of intervals between 0 and `.spec.completions-1`. +* When you specify the `succeededCount` only, + once the number of succeeded indexes reaches the `succeededCount`, the job controller marks the Job as succeeded. +* When you specify both `succeededIndexes` and `succeededCount`, + once the number of succeeded indexes from the subset of indexes specified in the `succeededIndexes` reaches the `succeededCount`, + the job controller marks the Job as succeeded. + +Note that when you specify multiple rules in the `.spec.succeessPolicy.rules`, +the job controller evaluates the rules in order. Once the Job meets a rule, the job controller ignores remaining rules. + +Here is a manifest for a Job with `successPolicy`: + +{{% code_sample file="/controllers/job-success-policy.yaml" %}} + +In the example above, both `succeededIndexes` and `succeededCount` have been specified. +Therefore, the job controller will mark the Job as succeeded and terminate the lingering Pods +when either of the specified indexes, 0, 2, or 3, succeed. +The Job that meets the success policy gets the `SuccessCriteriaMet` condition. +After the removal of the lingering Pods is issued, the Job gets the `Complete` condition. + +Note that the `succeededIndexes` is represented as intervals separated by a hyphen. +The number are listed in represented by the first and last element of the series, separated by a hyphen. + +{{< note >}} +When you specify both a success policy and some terminating policies such as `.spec.backoffLimit` and `.spec.podFailurePolicy`, +once the Job meets either policy, the job controller respects the terminating policy and ignores the success policy. +{{< /note >}} + ## Job termination and cleanup When a Job completes, no more Pods are created, but the Pods are [usually](#pod-backoff-failure-policy) not deleted either. @@ -750,7 +809,7 @@ reset to the current time. This means that the `.spec.activeDeadlineSeconds` timer will be stopped and reset when a Job is suspended and resumed. When you suspend a Job, any running Pods that don't have a status of `Completed` -will be [terminated](/docs/concepts/workloads/pods/pod-lifecycle/#pod-termination). +will be [terminated](/docs/concepts/workloads/pods/pod-lifecycle/#pod-termination) with a SIGTERM signal. The Pod's graceful termination period will be honored and your Pod must handle this signal in this period. This may involve saving progress for later or undoing changes. Pods terminated this way will not count @@ -1006,6 +1065,50 @@ status: terminating: 3 # three Pods are terminating and have not yet reached the Failed phase ``` +### Delegation of managing a Job object to external controller + +{{< feature-state feature_gate_name="JobManagedBy" >}} + +{{< note >}} +You can only set the `managedBy` field on Jobs if you enable the `JobManagedBy` +[feature gate](/docs/reference/command-line-tools-reference/feature-gates/) +(disabled by default). +{{< /note >}} + +This feature allows you to disable the built-in Job controller, for a specific +Job, and delegate reconciliation of the Job to an external controller. + +You indicate the controller that reconciles the Job by setting a custom value +for the `spec.managedBy` field - any value +other than `kubernetes.io/job-controller`. The value of the field is immutable. + +{{< note >}} +When using this feature, make sure the controller indicated by the field is +installed, otherwise the Job may not be reconciled at all. +{{< /note >}} + +{{< note >}} +When developing an external Job controller be aware that your controller needs +to operate in a fashion conformant with the definitions of the API spec and +status fields of the Job object. + +Please review these in detail in the [Job API](/docs/reference/kubernetes-api/workload-resources/job-v1/). +We also recommend that you run the e2e conformance tests for the Job object to +verify your implementation. + +Finally, when developing an external Job controller make sure it does not use the +`batch.kubernetes.io/job-tracking` finalizer, reserved for the built-in controller. +{{< /note >}} + +{{< warning >}} +If you are considering to disable the `JobManagedBy` feature gate, or to +downgrade the cluster to a version without the feature gate enabled, check if +there are jobs with a custom value of the `spec.managedBy` field. If there +are such jobs, there is a risk that they might be reconciled by two controllers +after the operation: the built-in Job controller and the external controller +indicated by the field value. +{{< /warning >}} + ## Alternatives ### Bare Pods diff --git a/content/en/docs/concepts/workloads/controllers/replicaset.md b/content/en/docs/concepts/workloads/controllers/replicaset.md index c419f98fe1a04..28aa6423636c4 100644 --- a/content/en/docs/concepts/workloads/controllers/replicaset.md +++ b/content/en/docs/concepts/workloads/controllers/replicaset.md @@ -4,6 +4,9 @@ reviewers: - bprashanth - madhusudancs title: ReplicaSet +api_metadata: +- apiVersion: "apps/v1" + kind: "ReplicaSet" feature: title: Self-healing anchor: How a ReplicaSet works @@ -92,15 +95,14 @@ Namespace: default Selector: tier=frontend Labels: app=guestbook tier=frontend -Annotations: kubectl.kubernetes.io/last-applied-configuration: - {"apiVersion":"apps/v1","kind":"ReplicaSet","metadata":{"annotations":{},"labels":{"app":"guestbook","tier":"frontend"},"name":"frontend",... +Annotations: Replicas: 3 current / 3 desired Pods Status: 3 Running / 0 Waiting / 0 Succeeded / 0 Failed Pod Template: Labels: tier=frontend Containers: php-redis: - Image: gcr.io/google_samples/gb-frontend:v3 + Image: us-docker.pkg.dev/google-samples/containers/gke/gb-frontend:v5 Port: Host Port: Environment: @@ -109,9 +111,9 @@ Pod Template: Events: Type Reason Age From Message ---- ------ ---- ---- ------- - Normal SuccessfulCreate 117s replicaset-controller Created pod: frontend-wtsmm - Normal SuccessfulCreate 116s replicaset-controller Created pod: frontend-b2zdv - Normal SuccessfulCreate 116s replicaset-controller Created pod: frontend-vcmts + Normal SuccessfulCreate 13s replicaset-controller Created pod: frontend-gbgfx + Normal SuccessfulCreate 13s replicaset-controller Created pod: frontend-rwz57 + Normal SuccessfulCreate 13s replicaset-controller Created pod: frontend-wkl7w ``` And lastly you can check for the Pods brought up: @@ -124,16 +126,16 @@ You should see Pod information similar to: ``` NAME READY STATUS RESTARTS AGE -frontend-b2zdv 1/1 Running 0 6m36s -frontend-vcmts 1/1 Running 0 6m36s -frontend-wtsmm 1/1 Running 0 6m36s +frontend-gbgfx 1/1 Running 0 10m +frontend-rwz57 1/1 Running 0 10m +frontend-wkl7w 1/1 Running 0 10m ``` You can also verify that the owner reference of these pods is set to the frontend ReplicaSet. To do this, get the yaml of one of the Pods running: ```shell -kubectl get pods frontend-b2zdv -o yaml +kubectl get pods frontend-gbgfx -o yaml ``` The output will look similar to this, with the frontend ReplicaSet's info set in the metadata's ownerReferences field: @@ -142,11 +144,11 @@ The output will look similar to this, with the frontend ReplicaSet's info set in apiVersion: v1 kind: Pod metadata: - creationTimestamp: "2020-02-12T07:06:16Z" + creationTimestamp: "2024-02-28T22:30:44Z" generateName: frontend- labels: tier: frontend - name: frontend-b2zdv + name: frontend-gbgfx namespace: default ownerReferences: - apiVersion: apps/v1 @@ -154,7 +156,7 @@ metadata: controller: true kind: ReplicaSet name: frontend - uid: f391f6db-bb9b-4c09-ae74-6a1f77f3d5cf + uid: e129deca-f864-481b-bb16-b27abfd92292 ... ``` diff --git a/content/en/docs/concepts/workloads/controllers/replicationcontroller.md b/content/en/docs/concepts/workloads/controllers/replicationcontroller.md index 58477a978e5b2..cc0fb40db78e2 100644 --- a/content/en/docs/concepts/workloads/controllers/replicationcontroller.md +++ b/content/en/docs/concepts/workloads/controllers/replicationcontroller.md @@ -3,6 +3,9 @@ reviewers: - bprashanth - janetkuo title: ReplicationController +api_metadata: +- apiVersion: "v1" + kind: "ReplicationController" content_type: concept weight: 90 description: >- diff --git a/content/en/docs/concepts/workloads/controllers/statefulset.md b/content/en/docs/concepts/workloads/controllers/statefulset.md index b0176108cea75..54c06cfb8beba 100644 --- a/content/en/docs/concepts/workloads/controllers/statefulset.md +++ b/content/en/docs/concepts/workloads/controllers/statefulset.md @@ -7,6 +7,9 @@ reviewers: - kow3ns - smarterclayton title: StatefulSets +api_metadata: +- apiVersion: "apps/v1" + kind: "StatefulSet" content_type: concept description: >- A StatefulSet runs a group of Pods, and maintains a sticky identity for each of those Pods. This is useful for managing @@ -44,8 +47,8 @@ that provides a set of stateless replicas. ## Limitations * The storage for a given Pod must either be provisioned by a - [PersistentVolume Provisioner](https://github.com/kubernetes/examples/tree/master/staging/persistent-volume-provisioning/README.md) - based on the requested `storage class`, or pre-provisioned by an admin. + [PersistentVolume Provisioner](/docs/concepts/storage/dynamic-provisioning/) ([examples here](https://github.com/kubernetes/examples/tree/master/staging/persistent-volume-provisioning/README.md)) + based on the requested _storage class_, or pre-provisioned by an admin. * Deleting and/or scaling a StatefulSet down will *not* delete the volumes associated with the StatefulSet. This is done to ensure data safety, which is generally more valuable than an automatic purge of all related StatefulSet resources. @@ -141,10 +144,14 @@ validation error during StatefulSet creation. ### Volume Claim Templates -You can set the `.spec.volumeClaimTemplates` which can provide stable storage using -[PersistentVolumes](/docs/concepts/storage/persistent-volumes/) provisioned by a PersistentVolume -Provisioner. +You can set the `.spec.volumeClaimTemplates` field to create a +[PersistentVolumeClaim](/docs/concepts/storage/persistent-volumes/). +This will provide stable storage to the StatefulSet if either +* The StorageClass specified for the volume claim is set up to use [dynamic + provisioning](/docs/concepts/storage/dynamic-provisioning/), or +* The cluster already contains a PersistentVolume with the correct StorageClass + and sufficient available storage space. ### Minimum ready seconds @@ -488,5 +495,4 @@ the `.spec.replicas` field automatically. Read the {{< api-reference page="workload-resources/stateful-set-v1" >}} object definition to understand the API for stateful sets. * Read about [PodDisruptionBudget](/docs/concepts/workloads/pods/disruptions/) and how - you can use it to manage application availability during disruptions. - + you can use it to manage application availability during disruptions. \ No newline at end of file diff --git a/content/en/docs/concepts/cluster-administration/manage-deployment.md b/content/en/docs/concepts/workloads/management.md similarity index 68% rename from content/en/docs/concepts/cluster-administration/manage-deployment.md rename to content/en/docs/concepts/workloads/management.md index da2a8142a0664..1a9ffe00df625 100644 --- a/content/en/docs/concepts/cluster-administration/manage-deployment.md +++ b/content/en/docs/concepts/workloads/management.md @@ -1,5 +1,5 @@ --- -title: Managing Resources +title: Managing Workloads content_type: concept reviewers: - janetkuo @@ -8,14 +8,14 @@ weight: 40 -You've deployed your application and exposed it via a service. Now what? Kubernetes provides a +You've deployed your application and exposed it via a Service. Now what? Kubernetes provides a number of tools to help you manage your application deployment, including scaling and updating. ## Organizing resource configurations -Many applications require multiple resources to be created, such as a Deployment and a Service. +Many applications require multiple resources to be created, such as a Deployment along with a Service. Management of multiple resources can be simplified by grouping them together in the same file (separated by `---` in YAML). For example: @@ -32,9 +32,9 @@ service/my-nginx-svc created deployment.apps/my-nginx created ``` -The resources will be created in the order they appear in the file. Therefore, it's best to -specify the service first, since that will ensure the scheduler can spread the pods associated -with the service as they are created by the controller(s), such as Deployment. +The resources will be created in the order they appear in the manifest. Therefore, it's best to +specify the Service first, since that will ensure the scheduler can spread the pods associated +with the Service as they are created by the controller(s), such as Deployment. `kubectl apply` also accepts multiple `-f` arguments: @@ -50,7 +50,7 @@ directory. If the tiers of your application bind to each other using DNS, you ca the components of your stack together. A URL can also be specified as a configuration source, which is handy for deploying directly from -configuration files checked into GitHub: +manifests in your source control system: ```shell kubectl apply -f https://k8s.io/examples/application/nginx/nginx-deployment.yaml @@ -60,6 +60,27 @@ kubectl apply -f https://k8s.io/examples/application/nginx/nginx-deployment.yaml deployment.apps/my-nginx created ``` +If you need to define more manifests, such as adding a ConfigMap, you can do that too. + +### External tools + +This section lists only the most common tools used for managing workloads on Kubernetes. To see a larger list, view +[Application definition and image build](https://landscape.cncf.io/guide#app-definition-and-development--application-definition-image-build) +in the {{< glossary_tooltip text="CNCF" term_id="cncf" >}} Landscape. + +#### Helm {#external-tool-helm} + +{{% thirdparty-content single="true" %}} + +[Helm](https://helm.sh/) is a tool for managing packages of pre-configured +Kubernetes resources. These packages are known as _Helm charts_. + +#### Kustomize {#external-tool-kustomize} + +[Kustomize](https://kustomize.io/) traverses a Kubernetes manifest to add, remove or update configuration options. +It is available both as a standalone binary and as a [native feature](/docs/tasks/manage-kubernetes-objects/kustomization/) +of kubectl. + ## Bulk operations in kubectl Resource creation isn't the only operation that `kubectl` can perform in bulk. It can also extract @@ -94,26 +115,32 @@ deployment.apps "my-nginx" deleted service "my-nginx-svc" deleted ``` +### Chaining and filtering + Because `kubectl` outputs resource names in the same syntax it accepts, you can chain operations using `$()` or `xargs`: ```shell -kubectl get $(kubectl create -f docs/concepts/cluster-administration/nginx/ -o name | grep service) -kubectl create -f docs/concepts/cluster-administration/nginx/ -o name | grep service | xargs -i kubectl get {} +kubectl get $(kubectl create -f docs/concepts/cluster-administration/nginx/ -o name | grep service/ ) +kubectl create -f docs/concepts/cluster-administration/nginx/ -o name | grep service/ | xargs -i kubectl get '{}' ``` +The output might be similar to: + ```none NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE my-nginx-svc LoadBalancer 10.0.0.208 80/TCP 0s ``` -With the above commands, we first create resources under `examples/application/nginx/` and print +With the above commands, first you create resources under `examples/application/nginx/` and print the resources created with `-o name` output format (print each resource as resource/name). -Then we `grep` only the "service", and then print it with `kubectl get`. +Then you `grep` only the Service, and then print it with [`kubectl get`](/docs/reference/kubectl/generated/kubectl_get/). + +### Recursive operations on local files If you happen to organize your resources across several subdirectories within a particular directory, you can recursively perform the operations on the subdirectories also, by specifying -`--recursive` or `-R` alongside the `--filename,-f` flag. +`--recursive` or `-R` alongside the `--filename`/`-f` argument. For instance, assume there is a directory `project/k8s/development` that holds all of the {{< glossary_tooltip text="manifests" term_id="manifest" >}} needed for the development environment, @@ -130,7 +157,7 @@ project/k8s/development ``` By default, performing a bulk operation on `project/k8s/development` will stop at the first level -of the directory, not processing any subdirectories. If we had tried to create the resources in +of the directory, not processing any subdirectories. If you had tried to create the resources in this directory using the following command, we would have encountered an error: ```shell @@ -141,7 +168,7 @@ kubectl apply -f project/k8s/development error: you must provide one or more resources by argument or filename (.json|.yaml|.yml|stdin) ``` -Instead, specify the `--recursive` or `-R` flag with the `--filename,-f` flag as such: +Instead, specify the `--recursive` or `-R` command line argument along with the `--filename`/`-f` argument: ```shell kubectl apply -f project/k8s/development --recursive @@ -153,10 +180,10 @@ deployment.apps/my-deployment created persistentvolumeclaim/my-pvc created ``` -The `--recursive` flag works with any operation that accepts the `--filename,-f` flag such as: -`kubectl {create,get,delete,describe,rollout}` etc. +The `--recursive` argument works with any operation that accepts the `--filename`/`-f` argument such as: +`kubectl create`, `kubectl get`, `kubectl delete`, `kubectl describe`, or even `kubectl rollout`. -The `--recursive` flag also works when multiple `-f` arguments are provided: +The `--recursive` argument also works when multiple `-f` arguments are provided: ```shell kubectl apply -f project/k8s/namespaces -f project/k8s/development --recursive @@ -173,6 +200,90 @@ persistentvolumeclaim/my-pvc created If you're interested in learning more about `kubectl`, go ahead and read [Command line tool (kubectl)](/docs/reference/kubectl/). +## Updating your application without an outage + +At some point, you'll eventually need to update your deployed application, typically by specifying +a new image or image tag. `kubectl` supports several update operations, each of which is applicable +to different scenarios. + +You can run multiple copies of your app, and use a _rollout_ to gradually shift the traffic to +new healthy Pods. Eventually, all the running Pods would have the new software. + +This section of the page guides you through how to create and update applications with Deployments. + +Let's say you were running version 1.14.2 of nginx: + +```shell +kubectl create deployment my-nginx --image=nginx:1.14.2 +``` + +```none +deployment.apps/my-nginx created +``` + +Ensure that there is 1 replica: + +```shell +kubectl scale --replicas 1 deployments/my-nginx --subresource='scale' --type='merge' -p '{"spec":{"replicas": 1}}' +``` + +```none +deployment.apps/my-nginx scaled +``` + +and allow Kubernetes to add more temporary replicas during a rollout, by setting a _surge maximum_ of +100%: + +```shell +kubectl patch --type='merge' -p '{"spec":{"strategy":{"rollingUpdate":{"maxSurge": "100%" }}}}' +``` + +```none +deployment.apps/my-nginx patched +``` + +To update to version 1.16.1, change `.spec.template.spec.containers[0].image` from `nginx:1.14.2` +to `nginx:1.16.1` using `kubectl edit`: + +```shell +kubectl edit deployment/my-nginx +# Change the manifest to use the newer container image, then save your changes +``` + +That's it! The Deployment will declaratively update the deployed nginx application progressively +behind the scene. It ensures that only a certain number of old replicas may be down while they are +being updated, and only a certain number of new replicas may be created above the desired number +of pods. To learn more details about how this happens, +visit [Deployment](/docs/concepts/workloads/controllers/deployment/). + +You can use rollouts with DaemonSets, Deployments, or StatefulSets. + +### Managing rollouts + +You can use [`kubectl rollout`](/docs/reference/kubectl/generated/kubectl_rollout/) to manage a +progressive update of an existing application. + +For example: + +```shell +kubectl apply -f my-deployment.yaml + +# wait for rollout to finish +kubectl rollout status deployment/my-deployment --timeout 10m # 10 minute timeout +``` + +or + +```shell +kubectl apply -f backing-stateful-component.yaml + +# don't wait for rollout to finish, just check the status +kubectl rollout status statefulsets/backing-stateful-component --watch=false +``` + +You can also pause, resume or cancel a rollout. +Visit [`kubectl rollout`](/docs/reference/kubectl/generated/kubectl_rollout/) to learn more. + ## Canary deployments @@ -229,13 +340,10 @@ each release that will receive live production traffic (in this case, 3:1). Once you're confident, you can update the stable track to the new application release and remove the canary one. -For a more concrete example, check the -[tutorial of deploying Ghost](https://github.com/kelseyhightower/talks/tree/master/kubecon-eu-2016/demo#deploy-a-canary). - ## Updating annotations Sometimes you would want to attach annotations to resources. Annotations are arbitrary -non-identifying metadata for retrieval by API clients such as tools, libraries, etc. +non-identifying metadata for retrieval by API clients such as tools or libraries. This can be done with `kubectl annotate`. For example: ```shell @@ -253,7 +361,7 @@ metadata: ``` For more information, see [annotations](/docs/concepts/overview/working-with-objects/annotations/) -and [kubectl annotate](/docs/reference/generated/kubectl/kubectl-commands/#annotate) document. +and [kubectl annotate](/docs/reference/kubectl/generated/kubectl_annotate/). ## Scaling your application @@ -283,6 +391,7 @@ To have the system automatically choose the number of nginx replicas as needed, ranging from 1 to 3, do: ```shell +# This requires an existing source of container and Pod metrics kubectl autoscale deployment/my-nginx --min=1 --max=3 ``` @@ -292,8 +401,8 @@ horizontalpodautoscaler.autoscaling/my-nginx autoscaled Now your nginx replicas will be scaled up and down as needed, automatically. -For more information, please see [kubectl scale](/docs/reference/generated/kubectl/kubectl-commands/#scale), -[kubectl autoscale](/docs/reference/generated/kubectl/kubectl-commands/#autoscale) and +For more information, please see [kubectl scale](/docs/reference/kubectl/generated/kubectl_scale/), +[kubectl autoscale](/docs/reference/kubectl/generated/kubectl_autoscale/) and [horizontal pod autoscaler](/docs/tasks/run-application/horizontal-pod-autoscale/) document. ## In-place updates of resources @@ -305,7 +414,7 @@ Sometimes it's necessary to make narrow, non-disruptive updates to resources you It is suggested to maintain a set of configuration files in source control (see [configuration as code](https://martinfowler.com/bliki/InfrastructureAsCode.html)), so that they can be maintained and versioned along with the code for the resources they configure. -Then, you can use [`kubectl apply`](/docs/reference/generated/kubectl/kubectl-commands/#apply) +Then, you can use [`kubectl apply`](/docs/reference/kubectl/generated/kubectl_apply/) to push your configuration changes to the cluster. This command will compare the version of the configuration that you're pushing with the previous @@ -320,23 +429,11 @@ kubectl apply -f https://k8s.io/examples/application/nginx/nginx-deployment.yaml deployment.apps/my-nginx configured ``` -Note that `kubectl apply` attaches an annotation to the resource in order to determine the changes -to the configuration since the previous invocation. When it's invoked, `kubectl apply` does a -three-way diff between the previous configuration, the provided input and the current -configuration of the resource, in order to determine how to modify the resource. - -Currently, resources are created without this annotation, so the first invocation of `kubectl -apply` will fall back to a two-way diff between the provided input and the current configuration -of the resource. During this first invocation, it cannot detect the deletion of properties set -when the resource was created. For this reason, it will not remove them. - -All subsequent calls to `kubectl apply`, and other commands that modify the configuration, such as -`kubectl replace` and `kubectl edit`, will update the annotation, allowing subsequent calls to -`kubectl apply` to detect and perform deletions using a three-way diff. +To learn more about the underlying mechanism, read [server-side apply](/docs/reference/using-api/server-side-apply/). ### kubectl edit -Alternatively, you may also update resources with `kubectl edit`: +Alternatively, you may also update resources with [`kubectl edit`](/docs/reference/kubectl/generated/kubectl_edit/): ```shell kubectl edit deployment/my-nginx @@ -359,15 +456,17 @@ rm /tmp/nginx.yaml This allows you to do more significant changes more easily. Note that you can specify the editor with your `EDITOR` or `KUBE_EDITOR` environment variables. -For more information, please see [kubectl edit](/docs/reference/generated/kubectl/kubectl-commands/#edit) document. +For more information, please see [kubectl edit](/docs/reference/kubectl/generated/kubectl_edit/). ### kubectl patch -You can use `kubectl patch` to update API objects in place. This command supports JSON patch, -JSON merge patch, and strategic merge patch. See +You can use [`kubectl patch`](/docs/reference/kubectl/generated/kubectl_patch/) to update API objects in place. +This subcommand supports JSON patch, +JSON merge patch, and strategic merge patch. + +See [Update API Objects in Place Using kubectl patch](/docs/tasks/manage-kubernetes-objects/update-api-object-kubectl-patch/) -and -[kubectl patch](/docs/reference/generated/kubectl/kubectl-commands/#patch). +for more details. ## Disruptive updates @@ -385,48 +484,7 @@ deployment.apps/my-nginx deleted deployment.apps/my-nginx replaced ``` -## Updating your application without a service outage - -At some point, you'll eventually need to update your deployed application, typically by specifying -a new image or image tag, as in the canary deployment scenario above. `kubectl` supports several -update operations, each of which is applicable to different scenarios. - -We'll guide you through how to create and update applications with Deployments. - -Let's say you were running version 1.14.2 of nginx: - -```shell -kubectl create deployment my-nginx --image=nginx:1.14.2 -``` - -```none -deployment.apps/my-nginx created -``` - -with 3 replicas (so the old and new revisions can coexist): - -```shell -kubectl scale deployment my-nginx --current-replicas=1 --replicas=3 -``` - -```none -deployment.apps/my-nginx scaled -``` - -To update to version 1.16.1, change `.spec.template.spec.containers[0].image` from `nginx:1.14.2` -to `nginx:1.16.1` using the previous kubectl commands. - -```shell -kubectl edit deployment/my-nginx -``` - -That's it! The Deployment will declaratively update the deployed nginx application progressively -behind the scene. It ensures that only a certain number of old replicas may be down while they are -being updated, and only a certain number of new replicas may be created above the desired number -of pods. To learn more details about it, visit [Deployment page](/docs/concepts/workloads/controllers/deployment/). ## {{% heading "whatsnext" %}} - Learn about [how to use `kubectl` for application introspection and debugging](/docs/tasks/debug/debug-application/debug-running-pod/). -- See [Configuration Best Practices and Tips](/docs/concepts/configuration/overview/). - diff --git a/content/en/docs/concepts/workloads/pods/_index.md b/content/en/docs/concepts/workloads/pods/_index.md index 1132c38793c5a..713648bf2098e 100644 --- a/content/en/docs/concepts/workloads/pods/_index.md +++ b/content/en/docs/concepts/workloads/pods/_index.md @@ -2,6 +2,9 @@ reviewers: - erictune title: Pods +api_metadata: +- apiVersion: "v1" + kind: "Pod" content_type: concept weight: 10 no_list: true @@ -19,10 +22,10 @@ containers which are relatively tightly coupled. In non-cloud contexts, applications executed on the same physical or virtual machine are analogous to cloud applications executed on the same logical host. As well as application containers, a Pod can contain -[init containers](/docs/concepts/workloads/pods/init-containers/) that run +{{< glossary_tooltip text="init containers" term_id="init-container" >}} that run during Pod startup. You can also inject -[ephemeral containers](/docs/concepts/workloads/pods/ephemeral-containers/) -for debugging if your cluster offers this. +{{< glossary_tooltip text="ephemeral containers" term_id="ephemeral-container" >}} +for debugging a running Pod. @@ -39,6 +42,26 @@ further sub-isolations applied. A Pod is similar to a set of containers with shared namespaces and shared filesystem volumes. +Pods in a Kubernetes cluster are used in two main ways: + +* **Pods that run a single container**. The "one-container-per-Pod" model is the + most common Kubernetes use case; in this case, you can think of a Pod as a + wrapper around a single container; Kubernetes manages Pods rather than managing + the containers directly. +* **Pods that run multiple containers that need to work together**. A Pod can + encapsulate an application composed of + [multiple co-located containers](#how-pods-manage-multiple-containers) that are + tightly coupled and need to share resources. These co-located containers + form a single cohesive unit. + + Grouping multiple co-located and co-managed containers in a single Pod is a + relatively advanced use case. You should use this pattern only in specific + instances in which your containers are tightly coupled. + + You don't need to run multiple containers to provide replication (for resilience + or capacity); if you need multiple replicas, see + [Workload management](/docs/concepts/workloads/controllers/). + ## Using Pods The following is an example of a Pod which consists of a container running the image `nginx:1.14.2`. @@ -61,26 +84,6 @@ term_id="deployment" >}} or {{< glossary_tooltip text="Job" term_id="job" >}}. If your Pods need to track state, consider the {{< glossary_tooltip text="StatefulSet" term_id="statefulset" >}} resource. -Pods in a Kubernetes cluster are used in two main ways: - -* **Pods that run a single container**. The "one-container-per-Pod" model is the - most common Kubernetes use case; in this case, you can think of a Pod as a - wrapper around a single container; Kubernetes manages Pods rather than managing - the containers directly. -* **Pods that run multiple containers that need to work together**. A Pod can - encapsulate an application composed of multiple co-located containers that are - tightly coupled and need to share resources. These co-located containers - form a single cohesive unit of service—for example, one container serving data - stored in a shared volume to the public, while a separate _sidecar_ container - refreshes or updates those files. - The Pod wraps these containers, storage resources, and an ephemeral network - identity together as a single unit. - - {{< note >}} - Grouping multiple co-located and co-managed containers in a single Pod is a - relatively advanced use case. You should use this pattern only in specific - instances in which your containers are tightly coupled. - {{< /note >}} Each Pod is meant to run a single instance of a given application. If you want to scale your application horizontally (to provide more overall resources by running @@ -93,36 +96,10 @@ See [Pods and controllers](#pods-and-controllers) for more information on how Kubernetes uses workload resources, and their controllers, to implement application scaling and auto-healing. -### How Pods manage multiple containers - -Pods are designed to support multiple cooperating processes (as containers) that form -a cohesive unit of service. The containers in a Pod are automatically co-located and -co-scheduled on the same physical or virtual machine in the cluster. The containers -can share resources and dependencies, communicate with one another, and coordinate -when and how they are terminated. - -For example, you might have a container that -acts as a web server for files in a shared volume, and a separate "sidecar" container -that updates those files from a remote source, as in the following diagram: - -{{< figure src="/images/docs/pod.svg" alt="Pod creation diagram" class="diagram-medium" >}} - -Some Pods have {{< glossary_tooltip text="init containers" term_id="init-container" >}} -as well as {{< glossary_tooltip text="app containers" term_id="app-container" >}}. -By default, init containers run and complete before the app containers are started. - -{{< feature-state for_k8s_version="v1.29" state="beta" >}} - -Enabled by default, the `SidecarContainers` [feature gate](/docs/reference/command-line-tools-reference/feature-gates/) -allows you to specify `restartPolicy: Always` for init containers. -Setting the `Always` restart policy ensures that the init containers where you set it are -kept running during the entire lifetime of the Pod. -See [Sidecar containers and restartPolicy](/docs/concepts/workloads/pods/init-containers/#sidecar-containers-and-restartpolicy) -for more details. - Pods natively provide two kinds of shared resources for their constituent containers: [networking](#pod-networking) and [storage](#pod-storage). + ## Working with Pods You'll rarely create individual Pods directly in Kubernetes—even singleton Pods. This @@ -150,17 +127,19 @@ the name should follow the more restrictive rules for a {{< feature-state state="stable" for_k8s_version="v1.25" >}} You should set the `.spec.os.name` field to either `windows` or `linux` to indicate the OS on -which you want the pod to run. These two are the only operating systems supported for now by -Kubernetes. In future, this list may be expanded. - -In Kubernetes v{{< skew currentVersion >}}, the value you set for this field has no -effect on {{< glossary_tooltip text="scheduling" term_id="kube-scheduler" >}} of the pods. -Setting the `.spec.os.name` helps to identify the pod OS -authoritatively and is used for validation. The kubelet refuses to run a Pod where you have -specified a Pod OS, if this isn't the same as the operating system for the node where -that kubelet is running. +which you want the pod to run. These two are the only operating systems supported for now by +Kubernetes. In the future, this list may be expanded. + +In Kubernetes v{{< skew currentVersion >}}, the value of `.spec.os.name` does not affect +how the {{< glossary_tooltip text="kube-scheduler" term_id="kube-scheduler" >}} +picks a Pod to run a node. In any cluster where there is more than one operating system for +running nodes, you should set the +[kubernetes.io/os](/docs/reference/labels-annotations-taints/#kubernetes-io-os) +label correctly on each node, and define pods with a `nodeSelector` based on the operating system +label, the kube-scheduler assigns your pod to a node based on other criteria and may or may not +succeed in picking a suitable node placement where the node OS is right for the containers in that Pod. The [Pod security standards](/docs/concepts/security/pod-security-standards/) also use this -field to avoid enforcing policies that aren't relevant to that operating system. +field to avoid enforcing policies that aren't relevant to the operating system. ### Pods and controllers @@ -190,6 +169,10 @@ Each controller for a workload resource uses the `PodTemplate` inside the worklo object to make actual Pods. The `PodTemplate` is part of the desired state of whatever workload resource you used to run your app. +When you create a Pod, you can include +[environment variables](/docs/tasks/inject-data-application/define-environment-variable-container/) +in the Pod template for the containers that run in the Pod. + The sample below is a manifest for a simple Job with a `template` that starts one container. The container in that Pod prints a message then pauses. @@ -343,6 +326,57 @@ The `spec` of a static Pod cannot refer to other API objects {{< glossary_tooltip text="Secret" term_id="secret" >}}, etc). {{< /note >}} +## Pods with multiple containers {#how-pods-manage-multiple-containers} + +Pods are designed to support multiple cooperating processes (as containers) that form +a cohesive unit of service. The containers in a Pod are automatically co-located and +co-scheduled on the same physical or virtual machine in the cluster. The containers +can share resources and dependencies, communicate with one another, and coordinate +when and how they are terminated. + + +Pods in a Kubernetes cluster are used in two main ways: + +* **Pods that run a single container**. The "one-container-per-Pod" model is the + most common Kubernetes use case; in this case, you can think of a Pod as a + wrapper around a single container; Kubernetes manages Pods rather than managing + the containers directly. +* **Pods that run multiple containers that need to work together**. A Pod can + encapsulate an application composed of + multiple co-located containers that are + tightly coupled and need to share resources. These co-located containers + form a single cohesive unit of service—for example, one container serving data + stored in a shared volume to the public, while a separate + {{< glossary_tooltip text="sidecar container" term_id="sidecar-container" >}} + refreshes or updates those files. + The Pod wraps these containers, storage resources, and an ephemeral network + identity together as a single unit. + +For example, you might have a container that +acts as a web server for files in a shared volume, and a separate +[sidecar container](/docs/concepts/workloads/pods/sidecar-containers/) +that updates those files from a remote source, as in the following diagram: + +{{< figure src="/images/docs/pod.svg" alt="Pod creation diagram" class="diagram-medium" >}} + +Some Pods have {{< glossary_tooltip text="init containers" term_id="init-container" >}} +as well as {{< glossary_tooltip text="app containers" term_id="app-container" >}}. +By default, init containers run and complete before the app containers are started. + +You can also have [sidecar containers](/docs/concepts/workloads/pods/sidecar-containers/) +that provide auxiliary services to the main application Pod (for example: a service mesh). + +{{< feature-state for_k8s_version="v1.29" state="beta" >}} + +Enabled by default, the `SidecarContainers` [feature gate](/docs/reference/command-line-tools-reference/feature-gates/) +allows you to specify `restartPolicy: Always` for init containers. +Setting the `Always` restart policy ensures that the containers where you set it are +treated as _sidecars_ that are kept running during the entire lifetime of the Pod. +Containers that you explicitly define as sidecar containers +start up before the main application Pod and remain running until the Pod is +shut down. + + ## Container probes A _probe_ is a diagnostic performed periodically by the kubelet on a container. To perform a diagnostic, the kubelet can invoke different actions: diff --git a/content/en/docs/concepts/workloads/pods/disruptions.md b/content/en/docs/concepts/workloads/pods/disruptions.md index 1d2b33d55f5d7..83befbe71d931 100644 --- a/content/en/docs/concepts/workloads/pods/disruptions.md +++ b/content/en/docs/concepts/workloads/pods/disruptions.md @@ -5,7 +5,7 @@ reviewers: - davidopp title: Disruptions content_type: concept -weight: 60 +weight: 70 --- diff --git a/content/en/docs/concepts/workloads/pods/downward-api.md b/content/en/docs/concepts/workloads/pods/downward-api.md index e084c92abd8be..aac5314da2649 100644 --- a/content/en/docs/concepts/workloads/pods/downward-api.md +++ b/content/en/docs/concepts/workloads/pods/downward-api.md @@ -77,7 +77,6 @@ The following information is available through environment variables `status.hostIPs` : the IP addresses is a dual-stack version of `status.hostIP`, the first is always the same as `status.hostIP`. - The field is available if you enable the `PodHostIPs` [feature gate](/docs/reference/command-line-tools-reference/feature-gates/). `status.podIP` : the pod's primary IP address (usually, its IPv4 address) diff --git a/content/en/docs/concepts/workloads/pods/ephemeral-containers.md b/content/en/docs/concepts/workloads/pods/ephemeral-containers.md index dfd7c366c114d..efdf0e1a0c771 100644 --- a/content/en/docs/concepts/workloads/pods/ephemeral-containers.md +++ b/content/en/docs/concepts/workloads/pods/ephemeral-containers.md @@ -4,7 +4,7 @@ reviewers: - yujuhong title: Ephemeral Containers content_type: concept -weight: 80 +weight: 60 --- diff --git a/content/en/docs/concepts/workloads/pods/init-containers.md b/content/en/docs/concepts/workloads/pods/init-containers.md index 480d4cee80b9e..54143f8ea69e2 100644 --- a/content/en/docs/concepts/workloads/pods/init-containers.md +++ b/content/en/docs/concepts/workloads/pods/init-containers.md @@ -331,8 +331,10 @@ for resource usage apply: Quota and limits are applied based on the effective Pod request and limit. -Pod level control groups (cgroups) are based on the effective Pod request and -limit, the same as the scheduler. +### Init containers and Linux cgroups {#cgroups} + +On Linux, resource allocations for Pod level control groups (cgroups) are based on the effective Pod +request and limit, the same as the scheduler. {{< comment >}} This section also present under [sidecar containers](/docs/concepts/workloads/pods/sidecar-containers/) page. diff --git a/content/en/docs/concepts/workloads/pods/pod-lifecycle.md b/content/en/docs/concepts/workloads/pods/pod-lifecycle.md index ff73d7bc2310a..f33840f450dd4 100644 --- a/content/en/docs/concepts/workloads/pods/pod-lifecycle.md +++ b/content/en/docs/concepts/workloads/pods/pod-lifecycle.md @@ -145,6 +145,58 @@ finish time for that container's period of execution. If a container has a `preStop` hook configured, this hook runs before the container enters the `Terminated` state. +## How Pods handle problems with containers {#container-restarts} + +Kubernetes manages container failures within Pods using a [`restartPolicy`](#restart-policy) defined in the Pod `spec`. This policy determines how Kubernetes reacts to containers exiting due to errors or other reasons, which falls in the following sequence: + +1. **Initial crash**: Kubernetes attempts an immediate restart based on the Pod `restartPolicy`. +1. **Repeated crashes**: After the the initial crash Kubernetes applies an exponential + backoff delay for subsequent restarts, described in [`restartPolicy`](#restart-policy). + This prevents rapid, repeated restart attempts from overloading the system. +1. **CrashLoopBackOff state**: This indicates that the backoff delay mechanism is currently + in effect for a given container that is in a crash loop, failing and restarting repeatedly. +1. **Backoff reset**: If a container runs successfully for a certain duration + (e.g., 10 minutes), Kubernetes resets the backoff delay, treating any new crash + as the first one. + +In practice, a `CrashLoopBackOff` is a condition or event that might be seen as output +from the `kubectl` command, while describing or listing Pods, when a container in the Pod +fails to start properly and then continually tries and fails in a loop. + +In other words, when a container enters the crash loop, Kubernetes applies the +exponential backoff delay mentioned in the [Container restart policy](#restart-policy). +This mechanism prevents a faulty container from overwhelming the system with continuous +failed start attempts. + +The `CrashLoopBackOff` can be caused by issues like the following: + +* Application errors that cause the container to exit. +* Configuration errors, such as incorrect environment variables or missing + configuration files. +* Resource constraints, where the container might not have enough memory or CPU + to start properly. +* Health checks failing if the application doesn't start serving within the + expected time. +* Container liveness probes or startup probes returning a `Failure` result + as mentioned in the [probes section](#container-probes). + +To investigate the root cause of a `CrashLoopBackOff` issue, a user can: + +1. **Check logs**: Use `kubectl logs ` to check the logs of the container. + This is often the most direct way to diagnose the issue causing the crashes. +1. **Inspect events**: Use `kubectl describe pod ` to see events + for the Pod, which can provide hints about configuration or resource issues. +1. **Review configuration**: Ensure that the Pod configuration, including + environment variables and mounted volumes, is correct and that all required + external resources are available. +1. **Check resource limits**: Make sure that the container has enough CPU + and memory allocated. Sometimes, increasing the resources in the Pod definition + can resolve the issue. +1. **Debug application**: There might exist bugs or misconfigurations in the + application code. Running this container image locally or in a development + environment can help diagnose application specific issues. + + ## Container restart policy {#restart-policy} The `spec` of a Pod has a `restartPolicy` field with possible values Always, OnFailure, @@ -156,17 +208,22 @@ in the Pod and to regular [init containers](/docs/concepts/workloads/pods/init-c ignore the Pod-level `restartPolicy` field: in Kubernetes, a sidecar is defined as an entry inside `initContainers` that has its container-level `restartPolicy` set to `Always`. For init containers that exit with an error, the kubelet restarts the init container if -the Pod level `restartPolicy` is either `OnFailure` or `Always`. +the Pod level `restartPolicy` is either `OnFailure` or `Always`: + +* `Always`: Automatically restarts the container after any termination. +* `OnFailure`: Only restarts the container if it exits with an error (non-zero exit status). +* `Never`: Does not automatically restart the terminated container. When the kubelet is handling container restarts according to the configured restart policy, that only applies to restarts that make replacement containers inside the same Pod and running on the same node. After containers in a Pod exit, the kubelet -restarts them with an exponential back-off delay (10s, 20s,40s, …), that is capped at -five minutes. Once a container has executed for 10 minutes without any problems, the -kubelet resets the restart backoff timer for that container. +restarts them with an exponential backoff delay (10s, 20s, 40s, …), that is capped at +300 seconds (5 minutes). Once a container has executed for 10 minutes without any +problems, the kubelet resets the restart backoff timer for that container. [Sidecar containers and Pod lifecycle](/docs/concepts/workloads/pods/sidecar-containers/#sidecar-containers-and-pod-lifecycle) explains the behaviour of `init containers` when specify `restartpolicy` field on it. + ## Pod conditions A Pod has a PodStatus, which has an array of diff --git a/content/en/docs/concepts/workloads/pods/pod-qos.md b/content/en/docs/concepts/workloads/pods/pod-qos.md index 491a4af2effb0..b164b02206333 100644 --- a/content/en/docs/concepts/workloads/pods/pod-qos.md +++ b/content/en/docs/concepts/workloads/pods/pod-qos.md @@ -87,7 +87,7 @@ Containers in a Pod can request other resources (not CPU or memory) and still be ## Memory QoS with cgroup v2 -{{< feature-state for_k8s_version="v1.22" state="alpha" >}} +{{< feature-state feature_gate_name="MemoryQoS" >}} Memory QoS uses the memory controller of cgroup v2 to guarantee memory resources in Kubernetes. Memory requests and limits of containers in pod are used to set specific interfaces `memory.min` diff --git a/content/en/docs/concepts/workloads/pods/sidecar-containers.md b/content/en/docs/concepts/workloads/pods/sidecar-containers.md index 23df85aeb7a32..86a577156c377 100644 --- a/content/en/docs/concepts/workloads/pods/sidecar-containers.md +++ b/content/en/docs/concepts/workloads/pods/sidecar-containers.md @@ -9,21 +9,43 @@ weight: 50 Sidecar containers are the secondary containers that run along with the main application container within the same {{< glossary_tooltip text="Pod" term_id="pod" >}}. -These containers are used to enhance or to extend the functionality of the main application -container by providing additional services, or functionality such as logging, monitoring, +These containers are used to enhance or to extend the functionality of the primary _app +container_ by providing additional services, or functionality such as logging, monitoring, security, or data synchronization, without directly altering the primary application code. +Typically, you only have one app container in a Pod. For example, if you have a web +application that requires a local webserver, the local webserver is a sidecar and the +web application itself is the app container. + -## Enabling sidecar containers +## Sidecar containers in Kubernetes {#pod-sidecar-containers} + +Kubernetes implements sidecar containers as a special case of +[init containers](/docs/concepts/workloads/pods/init-containers/); sidecar containers remain +running after Pod startup. This document uses the term _regular init containers_ to clearly +refer to containers that only run during Pod startup. + +Provided that your cluster has the `SidecarContainers` +[feature gate](/docs/reference/command-line-tools-reference/feature-gates/) enabled +(the feature is active by default since Kubernetes v1.29), you can specify a `restartPolicy` +for containers listed in a Pod's `initContainers` field. +These restartable _sidecar_ containers are independent from other init containers and from +the main application container(s) within the same pod. +These can be started, stopped, or restarted without effecting the main application container +and other init containers. + +You can also run a Pod with multiple containers that are not marked as init or sidecar +containers. This is appropriate if the containers within the Pod are required for the +Pod to work overall, but you don't need to control which containers start or stop first. +You could also do this if you need to support older versions of Kubernetes that don't +support a container-level `restartPolicy` field. -Enabled by default with Kubernetes 1.29, a -[feature gate](/docs/reference/command-line-tools-reference/feature-gates/) named -`SidecarContainers` allows you to specify a `restartPolicy` for containers listed in a -Pod's `initContainers` field. These restartable _sidecar_ containers are independent with -other [init containers](/docs/concepts/workloads/pods/init-containers/) and main -application container within the same pod. These can be started, stopped, or restarted -without effecting the main application container and other init containers. +### Example application {#sidecar-example} + +Here's an example of a Deployment with two containers, one of which is a sidecar: + +{{% code_sample language="yaml" file="application/deployment-sidecar.yaml" %}} ## Sidecar containers and Pod lifecycle @@ -35,8 +57,8 @@ If a `readinessProbe` is specified for this init container, its result will be u to determine the `ready` state of the Pod. Since these containers are defined as init containers, they benefit from the same -ordering and sequential guarantees as other init containers, allowing them to -be mixed with other init containers into complex Pod initialization flows. +ordering and sequential guarantees as regular init containers, allowing you to mix +sidecar containers with regular init containers for complex Pod initialization flows. Compared to regular init containers, sidecars defined within `initContainers` continue to run after they have started. This is important when there is more than one entry inside @@ -46,30 +68,28 @@ next init container from the ordered `.spec.initContainers` list. That status either becomes true because there is a process running in the container and no startup probe defined, or as a result of its `startupProbe` succeeding. -Here's an example of a Deployment with two containers, one of which is a sidecar: - -{{% code_sample language="yaml" file="application/deployment-sidecar.yaml" %}} +### Jobs with sidecar containers -This feature is also useful for running Jobs with sidecars, as the sidecar -container will not prevent the Job from completing after the main container -has finished. +If you define a Job that uses sidecar using Kubernetes-style init containers, +the sidecar container in each Pod does not prevent the Job from completing after the +main container has finished. Here's an example of a Job with two containers, one of which is a sidecar: {{% code_sample language="yaml" file="application/job/job-sidecar.yaml" %}} -## Differences from regular containers +## Differences from application containers -Sidecar containers run alongside regular containers in the same pod. However, they do not +Sidecar containers run alongside _app containers_ in the same pod. However, they do not execute the primary application logic; instead, they provide supporting functionality to the main application. Sidecar containers have their own independent lifecycles. They can be started, stopped, -and restarted independently of regular containers. This means you can update, scale, or +and restarted independently of app containers. This means you can update, scale, or maintain sidecar containers without affecting the primary application. Sidecar containers share the same network and storage namespaces with the primary -container This co-location allows them to interact closely and share resources. +container. This co-location allows them to interact closely and share resources. ## Differences from init containers @@ -81,9 +101,13 @@ throughout the lifecycle of the pod and can be started and stopped independently main container. Unlike [init containers](/docs/concepts/workloads/pods/init-containers/), sidecar containers support [probes](/docs/concepts/workloads/pods/pod-lifecycle/#types-of-probe) to control their lifecycle. -These containers can interact directly with the main application containers, sharing -the same network namespace, filesystem, and environment variables. They work closely -together to provide additional functionality. +Sidecar containers can interact directly with the main application containers, because +like init containers they always share the same network, and can optionally also share +volumes (filesystems). + +Init containers stop before the main containers start up, so init containers cannot +exchange messages with the app container in a Pod. Any data passing is one-way +(for example, an init container can put information inside an `emptyDir` volume). ## Resource sharing within containers @@ -112,8 +136,10 @@ for resource usage apply: Quota and limits are applied based on the effective Pod request and limit. -Pod level control groups (cgroups) are based on the effective Pod request and -limit, the same as the scheduler. +### Sidecar containers and Linux cgroups {#cgroups} + +On Linux, resource allocations for Pod level control groups (cgroups) are based on the effective Pod +request and limit, the same as the scheduler. ## {{% heading "whatsnext" %}} diff --git a/content/en/docs/concepts/workloads/pods/user-namespaces.md b/content/en/docs/concepts/workloads/pods/user-namespaces.md index 410b3c90524d2..4b9a1da89e49b 100644 --- a/content/en/docs/concepts/workloads/pods/user-namespaces.md +++ b/content/en/docs/concepts/workloads/pods/user-namespaces.md @@ -7,7 +7,7 @@ min-kubernetes-server-version: v1.25 --- -{{< feature-state for_k8s_version="v1.25" state="alpha" >}} +{{< feature-state for_k8s_version="v1.30" state="beta" >}} This page explains how user namespaces are used in Kubernetes pods. A user namespace isolates the user running inside the container from the one @@ -46,7 +46,26 @@ tmpfs, Secrets use a tmpfs, etc.) Some popular filesystems that support idmap mounts in Linux 6.3 are: btrfs, ext4, xfs, fat, tmpfs, overlayfs. -In addition, support is needed in the +In addition, the container runtime and its underlying OCI runtime must support +user namespaces. The following OCI runtimes offer support: + +* [crun](https://github.com/containers/crun) version 1.9 or greater (it's recommend version 1.13+). + + +{{< note >}} +Many OCI runtimes do not include the support needed for using user namespaces in +Linux pods. If you use a managed Kubernetes, or have downloaded it from packages +and set it up, it's likely that nodes in your cluster use a runtime that doesn't +include this support. For example, the most widely used OCI runtime is `runc`, +and version `1.1.z` of runc doesn't support all the features needed by the +Kubernetes implementation of user namespaces. + +If there is a newer release of runc than 1.1 available for use, check its +documentation and release notes for compatibility (look for idmap mounts support +in particular, because that is the missing feature). +{{< /note >}} + +To use user namespaces with Kubernetes, you also need to use a CRI {{< glossary_tooltip text="container runtime" term_id="container-runtime" >}} to use this feature with Kubernetes pods: @@ -137,20 +156,67 @@ use, see `man 7 user_namespaces`. ## Set up a node to support user namespaces -It is recommended that the host's files and host's processes use UIDs/GIDs in -the range of 0-65535. +By default, the kubelet assigns pods UIDs/GIDs above the range 0-65535, based on +the assumption that the host's files and processes use UIDs/GIDs within this +range, which is standard for most Linux distributions. This approach prevents +any overlap between the UIDs/GIDs of the host and those of the pods. + +Avoiding the overlap is important to mitigate the impact of vulnerabilities such +as [CVE-2021-25741][CVE-2021-25741], where a pod can potentially read arbitrary +files in the host. If the UIDs/GIDs of the pod and the host don't overlap, it is +limited what a pod would be able to do: the pod UID/GID won't match the host's +file owner/group. + +The kubelet can use a custom range for user IDs and group IDs for pods. To +configure a custom range, the node needs to have: + + * A user `kubelet` in the system (you cannot use any other username here) + * The binary `getsubids` installed (part of [shadow-utils][shadow-utils]) and + in the `PATH` for the kubelet binary. + * A configuration of subordinate UIDs/GIDs for the `kubelet` user (see + [`man 5 subuid`](https://man7.org/linux/man-pages/man5/subuid.5.html) and + [`man 5 subgid`](https://man7.org/linux/man-pages/man5/subgid.5.html)). + +This setting only gathers the UID/GID range configuration and does not change +the user executing the `kubelet`. + +You must follow some constraints for the subordinate ID range that you assign +to the `kubelet` user: + +* The subordinate user ID, that starts the UID range for Pods, **must** be a + multiple of 65536 and must also be greater than or equal to 65536. In other + words, you cannot use any ID from the range 0-65535 for Pods; the kubelet + imposes this restriction to make it difficult to create an accidentally insecure + configuration. + +* The subordinate ID count must be a multiple of 65536 + +* The subordinate ID count must be at least `65536 x ` where `` + is the maximum number of pods that can run on the node. + +* You must assign the same range for both user IDs and for group IDs, It doesn't + matter if other users have user ID ranges that don't align with the group ID + ranges. + +* None of the assigned ranges should overlap with any other assignment. + +* The subordinate configuration must be only one line. In other words, you can't + have multiple ranges. -The kubelet will assign UIDs/GIDs higher than that to pods. Therefore, to -guarantee as much isolation as possible, the UIDs/GIDs used by the host's files -and host's processes should be in the range 0-65535. +For example, you could define `/etc/subuid` and `/etc/subgid` to both have +these entries for the `kubelet` user: -Note that this recommendation is important to mitigate the impact of CVEs like -[CVE-2021-25741][CVE-2021-25741], where a pod can potentially read arbitrary -files in the hosts. If the UIDs/GIDs of the pod and the host don't overlap, it -is limited what a pod would be able to do: the pod UID/GID won't match the -host's file owner/group. +``` +# The format is +# name:firstID:count of IDs +# where +# - firstID is 65536 (the minimum value possible) +# - count of IDs is 110 (default limit for number of) * 65536 +kubelet:65536:7208960 +``` [CVE-2021-25741]: https://github.com/kubernetes/kubernetes/issues/104980 +[shadow-utils]: https://github.com/shadow-maint/shadow ## Integration with Pod security admission checks diff --git a/content/en/docs/contribute/analytics.md b/content/en/docs/contribute/analytics.md index f910c1d91b28a..57dea1f3fb3ad 100644 --- a/content/en/docs/contribute/analytics.md +++ b/content/en/docs/contribute/analytics.md @@ -14,9 +14,9 @@ This page contains information about the kubernetes.io analytics dashboard. -[View the dashboard](https://datastudio.google.com/reporting/fede2672-b2fd-402a-91d2-7473bdb10f04). +[View the dashboard](https://lookerstudio.google.com/u/0/reporting/fe615dc5-59b0-4db5-8504-ef9eacb663a9/page/4VDGB/). -This dashboard is built using Google Data Studio and shows information collected on kubernetes.io using Google Analytics. +This dashboard is built using [Google Looker Studio](https://lookerstudio.google.com/overview) and shows information collected on kubernetes.io using Google Analytics 4 since August 2022. ### Using the dashboard diff --git a/content/en/docs/contribute/localization.md b/content/en/docs/contribute/localization.md index f25c74de7f977..6beb811ab7f61 100644 --- a/content/en/docs/contribute/localization.md +++ b/content/en/docs/contribute/localization.md @@ -345,11 +345,11 @@ Releases | [All heading and subheading URLs](/releases) Translated documents must reside in their own `content/**/` subdirectory, but otherwise, follow the same URL path as the English source. For example, to prepare the [Kubernetes Basics](/docs/tutorials/kubernetes-basics/) tutorial for translation into German, -create a subfolder under the `content/de/` folder and copy the English source: +create a subdirectory under the `content/de/` directory and copy the English source or directory: ```shell mkdir -p content/de/docs/tutorials -cp content/en/docs/tutorials/kubernetes-basics.md content/de/docs/tutorials/kubernetes-basics.md +cp -ra content/en/docs/tutorials/kubernetes-basics/ content/de/docs/tutorials/ ``` Translation tools can speed up the translation process. For example, some diff --git a/content/en/docs/contribute/new-content/blogs-case-studies.md b/content/en/docs/contribute/new-content/blogs-case-studies.md index 72d234e7a84b1..368f93f226bb8 100644 --- a/content/en/docs/contribute/new-content/blogs-case-studies.md +++ b/content/en/docs/contribute/new-content/blogs-case-studies.md @@ -124,6 +124,10 @@ Submissions need to be in Markdown format to be used by the [Hugo](https://gohug for the blog. There are [many resources available](https://gohugo.io/documentation/) on how to use this technology stack. +For illustrations, diagrams or charts, the [figure shortcode](https://gohugo.io/content-management/shortcodes/#figure) +can be used. For other images, we strongly encourage use of alt attributes; if an image doesn't +need any alt attrribute, maybe it's not needed in the article at all. + We recognize that this requirement makes the process more difficult for less-familiar folks to submit, and we're constantly looking at solutions to lower this bar. If you have ideas on how to lower the barrier, please volunteer to help out. @@ -185,6 +189,17 @@ To submit a blog post follow these directions: - **Tutorials** that only apply to specific releases or versions and not all future versions - References to pre-GA APIs or features +### Mirroring from the Kubernetes Contributor Blog + +To mirror a blog post from the [Kubernetes contributor blog](https://www.kubernetes.dev/blog/), follow these guidelines: + +- Keep the blog content the same. If there are changes, they should be made to the original article first, and then to the mirrored article. +- The mirrored blog should have a `canonicalUrl`, that is, essentially the url of the original blog after it has been published. +- [Kubernetes contributor blogs](https://kubernetes.dev/blog) have their authors mentioned in the YAML header, while the Kubernetes blog posts mention authors in the blog content itself. This should be changed when mirroring the content. +- Publication dates stay the same as the original blog. + +All of the other guidelines and expectations detailed above apply as well. + ## Submit a case study Case studies highlight how organizations are using Kubernetes to solve real-world problems. The diff --git a/content/en/docs/contribute/participate/pr-wranglers.md b/content/en/docs/contribute/participate/pr-wranglers.md index cc00de9ce10da..ba3186c4fded7 100644 --- a/content/en/docs/contribute/participate/pr-wranglers.md +++ b/content/en/docs/contribute/participate/pr-wranglers.md @@ -19,9 +19,6 @@ see [Reviewing changes](/docs/contribute/review/). Each day in a week-long shift as PR Wrangler: -- Triage and tag incoming issues daily. See - [Triage and categorize issues](/docs/contribute/review/for-approvers/#triage-and-categorize-issues) - for guidelines on how SIG Docs uses metadata. - Review [open pull requests](https://github.com/kubernetes/website/pulls) for quality and adherence to the [Style](/docs/contribute/style/style-guide/) and [Content](/docs/contribute/style/content-guide/) guides. @@ -44,6 +41,19 @@ Each day in a week-long shift as PR Wrangler: issues as [good first issues](https://kubernetes.dev/docs/guide/help-wanted/#good-first-issue). - Using style fixups as good first issues is a good way to ensure a supply of easier tasks to help onboard new contributors. +- Also check for pull requests against the [reference docs generator](https://github.com/kubernetes-sigs/reference-docs) code, and review those (or bring in help). +- Support the [issue wrangler](/docs/contribute/participate/issue-wrangler/) to + triage and tag incoming issues daily. + See [Triage and categorize issues](/docs/contribute/review/for-approvers/#triage-and-categorize-issues) + for guidelines on how SIG Docs uses metadata. + +{{< note >}} +PR wrangler duties do not apply to localization PRs (non-English PRs). +Localization teams have their own processes and teams for reviewing their language PRs. +However, it's often helpful to ensure language PRs are labeled correctly, +review small non-language dependent PRs (like a link update), +or tag reviewers or contributors in long-running PRs (ones opened more than 6 months ago and have not been updated in a month or more). +{{< /note >}} ### Helpful GitHub queries for wranglers diff --git a/content/en/docs/contribute/style/hugo-shortcodes/index.md b/content/en/docs/contribute/style/hugo-shortcodes/index.md index 6112080eb8552..18ff7822406bb 100644 --- a/content/en/docs/contribute/style/hugo-shortcodes/index.md +++ b/content/en/docs/contribute/style/hugo-shortcodes/index.md @@ -49,6 +49,21 @@ Renders to: {{< feature-state for_k8s_version="v1.10" state="beta" >}} +### Feature state retrieval from description file + +To dynamically determine the state of the feature, make use of the `feature_gate_name` +shortcode parameter. The feature state details will be extracted from the corresponding feature gate +description file located in `content/en/docs/reference/command-line-tools-reference/feature-gates/`. +For example: + +``` +{{}} +``` + +Renders to: + +{{< feature-state feature_gate_name="NodeSwap" >}} + ## Feature gate description In a Markdown page (`.md` file) on this site, you can add a shortcode to diff --git a/content/en/docs/contribute/style/style-guide.md b/content/en/docs/contribute/style/style-guide.md index bb5c5d29a6593..318edf61b3847 100644 --- a/content/en/docs/contribute/style/style-guide.md +++ b/content/en/docs/contribute/style/style-guide.md @@ -116,17 +116,20 @@ The copy is called a "fork". | The copy is called a "fork." ## Inline code formatting -### Use code style for inline code, commands, and API objects {#code-style-inline-code} +### Use code style for inline code, commands {#code-style-inline-code} For inline code in an HTML document, use the `` tag. In a Markdown -document, use the backtick (`` ` ``). +document, use the backtick (`` ` ``). However, API kinds such as StatefulSet +or ConfigMap are written verbatim (no backticks); this allows using possessive +apostrophes. {{< table caption = "Do and Don't - Use code style for inline code, commands, and API objects" >}} Do | Don't :--| :----- -The `kubectl run` command creates a `Pod`. | The "kubectl run" command creates a pod. -The kubelet on each node acquires a `Lease`… | The kubelet on each node acquires a lease… -A `PersistentVolume` represents durable storage… | A Persistent Volume represents durable storage… +The `kubectl run` command creates a Pod. | The "kubectl run" command creates a Pod. +The kubelet on each node acquires a Lease… | The kubelet on each node acquires a `Lease`… +A PersistentVolume represents durable storage… | A `PersistentVolume` represents durable storage… +The CustomResourceDefinition's `.spec.group` field… | The `CustomResourceDefinition.spec.group` field… For declarative management, use `kubectl apply`. | For declarative management, use "kubectl apply". Enclose code samples with triple backticks. (\`\`\`)| Enclose code samples with any other syntax. Use single backticks to enclose inline code. For example, `var example = true`. | Use two asterisks (`**`) or an underscore (`_`) to enclose inline code. For example, **var example = true**. @@ -191,37 +194,60 @@ Set the value of `image` to nginx:1.16. | Set the value of `image` to `nginx:1.1 Set the value of the `replicas` field to 2. | Set the value of the `replicas` field to `2`. {{< /table >}} +However, consider quoting values where there is a risk that readers might confuse the value +with an API kind. + ## Referring to Kubernetes API resources This section talks about how we reference API resources in the documentation. ### Clarification about "resource" -Kubernetes uses the word "resource" to refer to API resources, such as `pod`, -`deployment`, and so on. We also use "resource" to talk about CPU and memory -requests and limits. Always refer to API resources as "API resources" to avoid -confusion with CPU and memory resources. +Kubernetes uses the word _resource_ to refer to API resources. For example, +the URL path `/apis/apps/v1/namespaces/default/deployments/my-app` represents a +Deployment named "my-app" in the "default" +{{< glossary_tooltip text="namespace" term_id="namespace" >}}. In HTTP jargon, +{{< glossary_tooltip text="namespace" term_id="namespace" >}} is a resource - +the same way that all web URLs identify a resource. + +Kubernetes documentation also uses "resource" to talk about CPU and memory +requests and limits. It's very often a good idea to refer to API resources +as "API resources"; that helps to avoid confusion with CPU and memory resources, +or with other kinds of resource. + +If you are using the lowercase plural form of a resource name, such as +`deployments` or `configmaps`, provide extra written context to help readers +understand what you mean. If you are using the term in a context where the +UpperCamelCase name could work too, and there is a risk of ambiguity, +consider using the API kind in UpperCamelCase. ### When to use Kubernetes API terminologies The different Kubernetes API terminologies are: -- Resource type: the name used in the API URL (such as `pods`, `namespaces`) -- Resource: a single instance of a resource type (such as `pod`, `secret`) -- Object: a resource that serves as a "record of intent". An object is a desired +- _API kinds_: the name used in the API URL (such as `pods`, `namespaces`). + API kinds are sometimes also called _resource types_. +- _API resource_: a single instance of an API kind (such as `pod`, `secret`). +- _Object_: a resource that serves as a "record of intent". An object is a desired state for a specific part of your cluster, which the Kubernetes control plane tries to maintain. + All objects in the Kubernetes API are also resources. -Always use "resource" or "object" when referring to an API resource in docs. -For example, use "a `Secret` object" over just "a `Secret`". +For clarity, you can add "resource" or "object" when referring to an API resource in Kubernetes +documentation. +An example: write "a Secret object" instead of "a Secret". +If it is clear just from the capitalization, you don't need to add the extra word. + +Consider rephrasing when that change helps avoid misunderstandings. A common situation is +when you want to start a sentence with an API kind, such as “Secret”; because English +and other languages capitalize at the start of sentences, readers cannot tell whether you +mean the API kind or the general concept. Rewording can help. ### API resource names Always format API resource names using [UpperCamelCase](https://en.wikipedia.org/wiki/Camel_case), -also known as PascalCase, and code formatting. - -For inline code in an HTML document, use the `` tag. In a Markdown document, use the backtick (`` ` ``). +also known as PascalCase. Do not write API kinds with code formatting. -Don't split an API object name into separate words. For example, use `PodTemplateList`, not Pod Template List. +Don't split an API object name into separate words. For example, use PodTemplateList, not Pod Template List. For more information about PascalCase and code formatting, please review the related guidance on [Use upper camel case for API objects](/docs/contribute/style/style-guide/#use-upper-camel-case-for-api-objects) @@ -237,7 +263,7 @@ guidance on [Kubernetes API terminology](/docs/reference/using-api/api-concepts/ {{< table caption = "Do and Don't - Don't include the command prompt" >}} Do | Don't :--| :----- -kubectl get pods | $ kubectl get pods +`kubectl get pods` | `$ kubectl get pods` {{< /table >}} ### Separate commands from output diff --git a/content/en/docs/home/_index.md b/content/en/docs/home/_index.md index 9256f06670f83..c1e731cc70171 100644 --- a/content/en/docs/home/_index.md +++ b/content/en/docs/home/_index.md @@ -13,9 +13,7 @@ hide_feedback: true menu: main: title: "Documentation" - weight: 20 - post: > -

Learn how to use Kubernetes with conceptual, tutorial, and reference documentation. You can even help contribute to the docs!

+ weight: 10 description: > Kubernetes is an open source container orchestration engine for automating deployment, scaling, and management of containerized applications. The open source project is hosted by the Cloud Native Computing Foundation. overview: > @@ -64,4 +62,6 @@ cards: - name: about title: About the documentation description: This website contains documentation for the current and previous 4 versions of Kubernetes. + button: "See available versions" + button_path: "/docs/home/supported-doc-versions" --- diff --git a/content/en/docs/home/supported-doc-versions.md b/content/en/docs/home/supported-doc-versions.md index fd3559a4d3786..a31268806416d 100644 --- a/content/en/docs/home/supported-doc-versions.md +++ b/content/en/docs/home/supported-doc-versions.md @@ -2,10 +2,7 @@ title: Available Documentation Versions content_type: custom layout: supported-versions -card: - name: about - weight: 10 - title: Available Documentation Versions +weight: 10 --- This website contains documentation for the current version of Kubernetes @@ -14,4 +11,4 @@ and the four previous versions of Kubernetes. The availability of documentation for a Kubernetes version is separate from whether that release is currently supported. Read [Support period](/releases/patch-releases/#support-period) to learn about -which versions of Kubernetes are officially supported, and for how long. \ No newline at end of file +which versions of Kubernetes are officially supported, and for how long. diff --git a/content/en/docs/reference/_index.md b/content/en/docs/reference/_index.md index 5be7d4c4b8887..a708d756340e7 100644 --- a/content/en/docs/reference/_index.md +++ b/content/en/docs/reference/_index.md @@ -79,7 +79,6 @@ operator to use or manage a cluster. * [kube-apiserver configuration (v1alpha1)](/docs/reference/config-api/apiserver-config.v1alpha1/) and * [kube-apiserver configuration (v1beta1)](/docs/reference/config-api/apiserver-config.v1beta1/) and [kube-apiserver configuration (v1)](/docs/reference/config-api/apiserver-config.v1/) -* [kube-apiserver encryption (v1)](/docs/reference/config-api/apiserver-encryption.v1/) * [kube-apiserver event rate limit (v1alpha1)](/docs/reference/config-api/apiserver-eventratelimit.v1alpha1/) * [kubelet configuration (v1alpha1)](/docs/reference/config-api/kubelet-config.v1alpha1/) and [kubelet configuration (v1beta1)](/docs/reference/config-api/kubelet-config.v1beta1/) diff --git a/content/en/docs/reference/access-authn-authz/admission-controllers.md b/content/en/docs/reference/access-authn-authz/admission-controllers.md index 2ce4f659da04c..9f6f31e3b641e 100644 --- a/content/en/docs/reference/access-authn-authz/admission-controllers.md +++ b/content/en/docs/reference/access-authn-authz/admission-controllers.md @@ -792,49 +792,6 @@ defined in the corresponding RuntimeClass. See also [Pod Overhead](/docs/concepts/scheduling-eviction/pod-overhead/) for more information. -### SecurityContextDeny {#securitycontextdeny} - -**Type**: Validating. - -{{< feature-state for_k8s_version="v1.27" state="deprecated" >}} - -{{< caution >}} -The Kubernetes project recommends that you **do not use** the -`SecurityContextDeny` admission controller. - -The `SecurityContextDeny` admission controller plugin is deprecated and disabled -by default. It will be removed in a future version. If you choose to enable the -`SecurityContextDeny` admission controller plugin, you must enable the -`SecurityContextDeny` feature gate as well. - -The `SecurityContextDeny` admission plugin is deprecated because it is outdated -and incomplete; it may be unusable or not do what you would expect. As -implemented, this plugin is unable to restrict all security-sensitive attributes -of the Pod API. For example, the `privileged` and `ephemeralContainers` fields -were never restricted by this plugin. - -The [Pod Security Admission](/docs/concepts/security/pod-security-admission/) -plugin enforcing the [Pod Security Standards](/docs/concepts/security/pod-security-standards/) -`Restricted` profile captures what this plugin was trying to achieve in a better -and up-to-date way. -{{< /caution >}} - -This admission controller will deny any Pod that attempts to set the following -[SecurityContext](/docs/reference/kubernetes-api/workload-resources/pod-v1/#security-context) -fields: -- `.spec.securityContext.supplementalGroups` -- `.spec.securityContext.seLinuxOptions` -- `.spec.securityContext.runAsUser` -- `.spec.securityContext.fsGroup` -- `.spec.(init)Containers[*].securityContext.seLinuxOptions` -- `.spec.(init)Containers[*].securityContext.runAsUser` - -For more historical context on this plugin, see -[The birth of PodSecurityPolicy](/blog/2022/08/23/podsecuritypolicy-the-historical-context/#the-birth-of-podsecuritypolicy) -from the Kubernetes blog article about PodSecurityPolicy and its removal. The -article details the PodSecurityPolicy historical context and the birth of the -`securityContext` field for Pods. - ### ServiceAccount {#serviceaccount} **Type**: Mutating and Validating. diff --git a/content/en/docs/reference/access-authn-authz/authentication.md b/content/en/docs/reference/access-authn-authz/authentication.md index f1cff56336a36..c7a0b0e3c15af 100644 --- a/content/en/docs/reference/access-authn-authz/authentication.md +++ b/content/en/docs/reference/access-authn-authz/authentication.md @@ -329,19 +329,42 @@ To enable the plugin, configure the following flags on the API server: | `--oidc-ca-file` | The path to the certificate for the CA that signed your identity provider's web certificate. Defaults to the host's root CAs. | `/etc/kubernetes/ssl/kc-ca.pem` | No | | `--oidc-signing-algs` | The signing algorithms accepted. Default is "RS256". | `RS512` | No | -##### Using Authentication Configuration +##### Authentication configuration from a file {#using-authentication-configuration} -{{< feature-state for_k8s_version="v1.29" state="alpha" >}} +{{< feature-state feature_gate_name="StructuredAuthenticationConfiguration" >}} JWT Authenticator is an authenticator to authenticate Kubernetes users using JWT compliant tokens. The authenticator will attempt to parse a raw ID token, verify it's been signed by the configured issuer. The public key to verify the signature is discovered from the issuer's public endpoint using OIDC discovery. -The API server can be configured to use a JWT authenticator via the `--authentication-config` flag. This flag takes a path to a file containing the `AuthenticationConfiguration`. An example configuration is provided below. -To use this config, the `StructuredAuthenticationConfiguration` [feature gate](/docs/reference/command-line-tools-reference/feature-gates/) -has to be enabled. +The minimum valid JWT payload must contain the following claims: +```yaml +{ + "iss": "https://example.com", // must match the issuer.url + "aud": ["my-app"], // at least one of the entries in issuer.audiences must match the "aud" claim in presented JWTs. + "exp": 1234567890, // token expiration as Unix time (the number of seconds elapsed since January 1, 1970 UTC) + "": "user" // this is the username claim configured in the claimMappings.username.claim or claimMappings.username.expression +} +``` + +The configuration file approach allows you to configure multiple JWT authenticators, each with a unique `issuer.url` and `issuer.discoveryURL`. The configuration file even allows you to specify [CEL](/docs/reference/using-api/cel/) +expressions to map claims to user attributes, and to validate claims and user information. The API server also automatically reloads the authenticators when the configuration file is modified. You can use +`apiserver_authentication_config_controller_automatic_reload_last_timestamp_seconds` metric to monitor the last time the configuration was reloaded by the API server. + +You must specify the path to the authentication configuration using the `--authentication-config` flag on the API server. If you want to use command line flags instead of the configuration file, those will continue to work as-is. +To access the new capabilities like configuring multiple authenticators, setting multiple audiences for an issuer, switch to using the configuration file. + +For Kubernetes v{{< skew currentVersion >}}, the structured authentication configuration file format +is beta-level, and the mechanism for using that configuration is also beta. Provided you didn't specifically +disable the `StructuredAuthenticationConfiguration` +[feature gate](/docs/reference/command-line-tools-reference/feature-gates/) for your cluster, +you can turn on structured authentication by specifying the `--authentication-config` command line +argument to the kube-apiserver. An example of the structured authentication configuration file is shown below. {{< note >}} -When the feature is enabled, setting both `--authentication-config` and any of the `--oidc-*` flags will result in an error. If you want to use the feature, you have to remove the `--oidc-*` flags and use the configuration file instead. +If you specify `--authentication-config` along with any of the `--oidc-*` command line arguments, this is +a misconfiguration. In this situation, the API server reports an error and then immediately exits. +If you want to switch to using structured authentication configuration, you have to remove the `--oidc-*` +command line arguments, and use the configuration file instead. {{< /note >}} ```yaml @@ -350,14 +373,37 @@ When the feature is enabled, setting both `--authentication-config` and any of t # CAUTION: this is an example configuration. # Do not use this for your own cluster! # -apiVersion: apiserver.config.k8s.io/v1alpha1 +apiVersion: apiserver.config.k8s.io/v1beta1 kind: AuthenticationConfiguration # list of authenticators to authenticate Kubernetes users using JWT compliant tokens. +# the maximum number of allowed authenticators is 64. jwt: - issuer: + # url must be unique across all authenticators. + # url must not conflict with issuer configured in --service-account-issuer. url: https://example.com # Same as --oidc-issuer-url. + # discoveryURL, if specified, overrides the URL used to fetch discovery + # information instead of using "{url}/.well-known/openid-configuration". + # The exact value specified is used, so "/.well-known/openid-configuration" + # must be included in discoveryURL if needed. + # + # The "issuer" field in the fetched discovery information must match the "issuer.url" field + # in the AuthenticationConfiguration and will be used to validate the "iss" claim in the presented JWT. + # This is for scenarios where the well-known and jwks endpoints are hosted at a different + # location than the issuer (such as locally in the cluster). + # discoveryURL must be different from url if specified and must be unique across all authenticators. + discoveryURL: https://discovery.example.com/.well-known/openid-configuration + # PEM encoded CA certificates used to validate the connection when fetching + # discovery information. If not set, the system verifier will be used. + # Same value as the content of the file referenced by the --oidc-ca-file flag. + certificateAuthority: + # audiences is the set of acceptable audiences the JWT must be issued to. + # At least one of the entries must match the "aud" claim in presented JWTs. audiences: - my-app # Same as --oidc-client-id. + - my-other-app + # this is required to be set to "MatchAny" when multiple audiences are specified. + audienceMatchPolicy: MatchAny # rules applied to validate token claims to authenticate users. claimValidationRules: # Same as --oidc-required-claim key=value. @@ -383,6 +429,13 @@ jwt: prefix: "" # Mutually exclusive with username.claim and username.prefix. # expression is a CEL expression that evaluates to a string. + # + # 1. If username.expression uses 'claims.email', then 'claims.email_verified' must be used in + # username.expression or extra[*].valueExpression or claimValidationRules[*].expression. + # An example claim validation rule expression that matches the validation automatically + # applied when username.claim is set to 'email' is 'claims.?email_verified.orValue(true)'. + # 2. If the username asserted based on username.expression is the empty string, the authentication + # request will fail. expression: 'claims.username + ":external-user"' # groups represents an option for the groups attribute. groups: @@ -442,7 +495,7 @@ jwt: {{< tabs name="example_configuration" >}} {{% tab name="Valid token" %}} ```yaml - apiVersion: apiserver.config.k8s.io/v1alpha1 + apiVersion: apiserver.config.k8s.io/v1beta1 kind: AuthenticationConfiguration jwt: - issuer: @@ -502,7 +555,7 @@ jwt: {{% /tab %}} {{% tab name="Fails claim validation" %}} ```yaml - apiVersion: apiserver.config.k8s.io/v1alpha1 + apiVersion: apiserver.config.k8s.io/v1beta1 kind: AuthenticationConfiguration jwt: - issuer: @@ -550,7 +603,7 @@ jwt: {{% /tab %}} {{% tab name="Fails user validation" %}} ```yaml - apiVersion: apiserver.config.k8s.io/v1alpha1 + apiVersion: apiserver.config.k8s.io/v1beta1 kind: AuthenticationConfiguration jwt: - issuer: @@ -614,12 +667,10 @@ jwt: {{% /tab %}} {{< /tabs >}} -Importantly, the API server is not an OAuth2 client, rather it can only be -configured to trust a single issuer. This allows the use of public providers, -such as Google, without trusting credentials issued to third parties. Admins who -wish to utilize multiple OAuth clients should explore providers which support the -`azp` (authorized party) claim, a mechanism for allowing one client to issue -tokens on behalf of another. +###### Limitations + +1. Distributed claims do not work via [CEL](/docs/reference/using-api/cel/) expressions. +1. Egress selector configuration is not supported for calls to `issuer.url` and `issuer.discoveryURL`. Kubernetes does not provide an OpenID Connect Identity Provider. You can use an existing public OpenID Connect Identity Provider (such as Google, or @@ -631,9 +682,15 @@ Tremolo Security's [OpenUnison](https://openunison.github.io/). For an identity provider to work with Kubernetes it must: -1. Support [OpenID connect discovery](https://openid.net/specs/openid-connect-discovery-1_0.html); not all do. -1. Run in TLS with non-obsolete ciphers -1. Have a CA signed certificate (even if the CA is not a commercial CA or is self signed) +1. Support [OpenID connect discovery](https://openid.net/specs/openid-connect-discovery-1_0.html) + + The public key to verify the signature is discovered from the issuer's public endpoint using OIDC discovery. + If you're using the authentication configuration file, the identity provider doesn't need to publicly expose the discovery endpoint. + You can host the discovery endpoint at a different location than the issuer (such as locally in the cluster) and specify the + `issuer.discoveryURL` in the configuration file. + +2. Run in TLS with non-obsolete ciphers +3. Have a CA signed certificate (even if the CA is not a commercial CA or is self signed) A note about requirement #3 above, requiring a CA signed certificate. If you deploy your own identity provider (as opposed to one of the cloud providers like Google or Microsoft) you MUST diff --git a/content/en/docs/reference/access-authn-authz/authorization.md b/content/en/docs/reference/access-authn-authz/authorization.md index 621cc9773b474..189c35bf109ad 100644 --- a/content/en/docs/reference/access-authn-authz/authorization.md +++ b/content/en/docs/reference/access-authn-authz/authorization.md @@ -211,33 +211,31 @@ so an earlier module has higher priority to allow or deny a request. ## Configuring the API Server using an Authorization Config File -{{< feature-state state="alpha" for_k8s_version="v1.29" >}} +{{< feature-state feature_gate_name="StructuredAuthorizationConfiguration" >}} The Kubernetes API server's authorizer chain can be configured using a configuration file. -You specify the path to that authorization configuration using the -`--authorization-config` command line argument. This feature enables -creation of authorization chains with multiple webhooks with well-defined -parameters that validate requests in a certain order and enables fine grained -control - such as explicit Deny on failures. An example configuration with -all possible values is provided below. +This feature enables the creation of authorization chains with multiple webhooks with well-defined parameters that validate requests in a particular order and allows fine-grained control – such as explicit Deny on failures. The configuration file approach even allows you to specify [CEL](/docs/reference/using-api/cel/) rules to pre-filter requests before they are dispatched to webhooks, helping you to prevent unnecessary invocations. The API server also automatically reloads the authorizer chain when the configuration file is modified. An example configuration with all possible values is provided below. -In order to customise the authorizer chain, you need to enable the -`StructuredAuthorizationConfiguration` [feature gate](/docs/reference/command-line-tools-reference/feature-gates/). +You must specify the path to the authorization configuration using the `--authorization-config`command line argument. If you want to keep using command line flags instead of a configuration file, those will continue to work as-is. To gain access to new authorization webhook capabilities like multiple webhooks, failure policy, and pre-filter rules, switch to putting options in an `--authorization-config` file. -Note: When the feature is enabled, setting both `--authorization-config` and +Starting Kubernetes v{{< skew currentVersion >}}, the configuration file format is +beta-level, and only requires specifying `--authorization-config` since the `StructuredAuthorizationConfiguration` feature gate is enabled by default. + +{{< caution >}} +If you want to keep using command line flags to configure authorization instead of a configuration file, those will continue to work as-is. + +When the feature is enabled, setting both `--authorization-config` and configuring an authorization webhook using the `--authorization-mode` and `--authorization-webhook-*` command line flags is not allowed. If done, there will be an error and API Server would exit right away. -{{< caution >}} -While the feature is in Alpha/Beta, there is no change if you want to keep on -using command line flags. When the feature goes Beta, the feature flag would -be turned on by default. The feature flag would be removed when feature goes GA. +Authorization Config file reloads when an observed file event occurs or a 1 minute poll is encountered. All non-webhook authorizer types are required to remain unchanged in the file on reload. Reload must not add or remove Node or RBAC +authorizers. They can be reordered, but cannot be added or removed. When configuring the authorizer chain using a config file, make sure all the -apiserver nodes have the file. Also, take a note of the apiserver configuration +apiserver nodes have the file. Take a note of the apiserver configuration when upgrading/downgrading the clusters. For example, if upgrading to v1.29+ clusters and using the config file, you would need to make sure the config file exists before upgrading the cluster. When downgrading to v1.28, you would need @@ -248,9 +246,8 @@ to add the flags back to their bootstrap mechanism. # # DO NOT USE THE CONFIG AS IS. THIS IS AN EXAMPLE. # -apiVersion: apiserver.config.k8s.io/v1alpha1 +apiVersion: apiserver.config.k8s.io/v1beta1 kind: AuthorizationConfiguration -# authorizers are defined in order of precedence authorizers: - type: Webhook # Name used to describe the authorizer @@ -283,7 +280,7 @@ authorizers: # MatchConditionSubjectAccessReviewVersion specifies the SubjectAccessReview # version the CEL expressions are evaluated against # Valid values: v1 - # Required only if matchConditions are specified, no default value + # Required, no default value matchConditionSubjectAccessReviewVersion: v1 # Controls the authorization decision when a webhook request fails to # complete or returns a malformed response or errors evaluating diff --git a/content/en/docs/reference/access-authn-authz/certificate-signing-requests.md b/content/en/docs/reference/access-authn-authz/certificate-signing-requests.md index b3d0a15238c8d..24b6cf6425e58 100644 --- a/content/en/docs/reference/access-authn-authz/certificate-signing-requests.md +++ b/content/en/docs/reference/access-authn-authz/certificate-signing-requests.md @@ -5,6 +5,12 @@ reviewers: - munnerz - enj title: Certificates and Certificate Signing Requests +api_metadata: +- apiVersion: "certificates.k8s.io/v1" + kind: "CertificateSigningRequest" + override_link_text: "CSR v1" +- apiVersion: "certificates.k8s.io/v1alpha1" + kind: "ClusterTrustBundle" content_type: concept weight: 25 --- @@ -608,3 +614,5 @@ kubectl config use-context myuser * View the source code for the kube-controller-manager built in [approver](https://github.com/kubernetes/kubernetes/blob/32ec6c212ec9415f604ffc1f4c1f29b782968ff1/pkg/controller/certificates/approver/sarapprove.go) * For details of X.509 itself, refer to [RFC 5280](https://tools.ietf.org/html/rfc5280#section-3.1) section 3.1 * For information on the syntax of PKCS#10 certificate signing requests, refer to [RFC 2986](https://tools.ietf.org/html/rfc2986) +* Read about the ClusterTrustBundle API: + * {{< page-api-reference kind="ClusterTrustBundle" >}} diff --git a/content/en/docs/reference/access-authn-authz/extensible-admission-controllers.md b/content/en/docs/reference/access-authn-authz/extensible-admission-controllers.md index 091a638d963e0..9323651c5798e 100644 --- a/content/en/docs/reference/access-authn-authz/extensible-admission-controllers.md +++ b/content/en/docs/reference/access-authn-authz/extensible-admission-controllers.md @@ -721,7 +721,7 @@ The `matchPolicy` for an admission webhooks defaults to `Equivalent`. ### Matching requests: `matchConditions` -{{< feature-state state="beta" for_k8s_version="v1.28" >}} +{{< feature-state feature_gate_name="AdmissionWebhookMatchConditions" >}} You can define _match conditions_ for webhooks if you need fine-grained request filtering. These conditions are useful if you find that match rules, `objectSelectors` and `namespaceSelectors` still diff --git a/content/en/docs/reference/access-authn-authz/service-accounts-admin.md b/content/en/docs/reference/access-authn-authz/service-accounts-admin.md index 1f1fa64f60b46..0f16071251a52 100644 --- a/content/en/docs/reference/access-authn-authz/service-accounts-admin.md +++ b/content/en/docs/reference/access-authn-authz/service-accounts-admin.md @@ -60,9 +60,105 @@ for a number of reasons: without many constraints and have namespaced names, such configuration is usually portable. +## Bound service account tokens + +ServiceAccount tokens can be bound to API objects that exist in the kube-apiserver. +This can be used to tie the validity of a token to the existence of another API object. +Supported object types are as follows: + +* Pod (used for projected volume mounts, see below) +* Secret (can be used to allow revoking a token by deleting the Secret) +* Node (in v1.30, creating new node-bound tokens is alpha, using existing node-bound tokens is beta) + +When a token is bound to an object, the object's `metadata.name` and `metadata.uid` are +stored as extra 'private claims' in the issued JWT. + +When a bound token is presented to the kube-apiserver, the service account authenticator +will extract and verify these claims. +If the referenced object no longer exists (or its `metadata.uid` does not match), +the request will not be authenticated. + +### Additional metadata in Pod bound tokens + +{{< feature-state feature_gate_name="ServiceAccountTokenPodNodeInfo" >}} + +When a service account token is bound to a Pod object, additional metadata is also +embedded into the token that indicates the value of the bound pod's `spec.nodeName` field, +and the uid of that Node, if available. + +This node information is **not** verified by the kube-apiserver when the token is used for authentication. +It is included so integrators do not have to fetch Pod or Node API objects to check the associated Node name +and uid when inspecting a JWT. + +### Verifying and inspecting private claims + +The `TokenReview` API can be used to verify and extract private claims from a token: + +1. First, assume you have a pod named `test-pod` and a service account named `my-sa`. +2. Create a token that is bound to this Pod: + +```shell +kubectl create token my-sa --bound-object-kind="Pod" --bound-object-name="test-pod" +``` + +3. Copy this token into a new file named `tokenreview.yaml`: + +```yaml +apiVersion: authentication.k8s.io/v1 +kind: TokenReview +spec: + token: +``` + +4. Submit this resource to the apiserver for review: + +```shell +kubectl create -o yaml -f tokenreview.yaml # we use '-o yaml' so we can inspect the output +``` + +You should see an output like below: + +```yaml +apiVersion: authentication.k8s.io/v1 +kind: TokenReview +metadata: + creationTimestamp: null +spec: + token: +status: + audiences: + - https://kubernetes.default.svc.cluster.local + authenticated: true + user: + extra: + authentication.kubernetes.io/credential-id: + - JTI=7ee52be0-9045-4653-aa5e-0da57b8dccdc + authentication.kubernetes.io/node-name: + - kind-control-plane + authentication.kubernetes.io/node-uid: + - 497e9d9a-47aa-4930-b0f6-9f2fb574c8c6 + authentication.kubernetes.io/pod-name: + - test-pod + authentication.kubernetes.io/pod-uid: + - e87dbbd6-3d7e-45db-aafb-72b24627dff5 + groups: + - system:serviceaccounts + - system:serviceaccounts:default + - system:authenticated + uid: f8b4161b-2e2b-11e9-86b7-2afc33b31a7e + username: system:serviceaccount:default:my-sa +``` + +{{< note >}} +Despite using `kubectl create -f` to create this resource, and defining it similar to +other resource types in Kubernetes, TokenReview is a special type and the kube-apiserver +does not actually persist the TokenReview object into etcd. +Hence `kubectl get tokenreview` is not a valid command. +{{< /note >}} + ## Bound service account token volume mechanism {#bound-service-account-token-volume} -{{< feature-state for_k8s_version="v1.22" state="stable" >}} +{{< feature-state feature_gate_name="BoundServiceAccountTokenVolume" >}} By default, the Kubernetes control plane (specifically, the [ServiceAccount admission controller](#serviceaccount-admission-controller)) @@ -249,7 +345,7 @@ it does the following when a Pod is created: ### Legacy ServiceAccount token tracking controller -{{< feature-state for_k8s_version="v1.28" state="stable" >}} +{{< feature-state feature_gate_name="LegacyServiceAccountTokenTracking" >}} This controller generates a ConfigMap called `kube-system/kube-apiserver-legacy-service-account-token-tracking` in the @@ -258,7 +354,7 @@ account tokens began to be monitored by the system. ### Legacy ServiceAccount token cleaner -{{< feature-state for_k8s_version="v1.29" state="beta" >}} +{{< feature-state feature_gate_name="LegacyServiceAccountTokenCleanUp" >}} The legacy ServiceAccount token cleaner runs as part of the `kube-controller-manager` and checks every 24 hours to see if any auto-generated diff --git a/content/en/docs/reference/access-authn-authz/validating-admission-policy.md b/content/en/docs/reference/access-authn-authz/validating-admission-policy.md index f7f705aa9f59e..2d0ae273442ad 100644 --- a/content/en/docs/reference/access-authn-authz/validating-admission-policy.md +++ b/content/en/docs/reference/access-authn-authz/validating-admission-policy.md @@ -9,7 +9,7 @@ content_type: concept -{{< feature-state state="beta" for_k8s_version="v1.28" >}} +{{< feature-state state="stable" for_k8s_version="v1.30" >}} This page provides an overview of Validating Admission Policy. diff --git a/content/en/docs/reference/command-line-tools-reference/feature-gates/admission-webhook-match-conditions.md b/content/en/docs/reference/command-line-tools-reference/feature-gates/admission-webhook-match-conditions.md index f213c21af4568..95395364754c2 100644 --- a/content/en/docs/reference/command-line-tools-reference/feature-gates/admission-webhook-match-conditions.md +++ b/content/en/docs/reference/command-line-tools-reference/feature-gates/admission-webhook-match-conditions.md @@ -12,7 +12,11 @@ stages: toVersion: "1.27" - stage: beta defaultValue: true - fromVersion: "1.28" + fromVersion: "1.28" + toVersion: "1.29" + - stage: stable + defaultValue: true + fromVersion: "1.30" --- Enable [match conditions](/docs/reference/access-authn-authz/extensible-admission-controllers/#matching-requests-matchconditions) on mutating & validating admission webhooks. diff --git a/content/en/docs/reference/command-line-tools-reference/feature-gates/aggregated-discovery-endpoint.md b/content/en/docs/reference/command-line-tools-reference/feature-gates/aggregated-discovery-endpoint.md index 1b82dec7618e3..047217ceedda8 100644 --- a/content/en/docs/reference/command-line-tools-reference/feature-gates/aggregated-discovery-endpoint.md +++ b/content/en/docs/reference/command-line-tools-reference/feature-gates/aggregated-discovery-endpoint.md @@ -13,6 +13,10 @@ stages: - stage: beta defaultValue: true fromVersion: "1.27" + toVersion: "1.29" + - stage: stable + defaultValue: true + fromVersion: "1.30" --- Enable a single HTTP endpoint `/discovery/` which supports native HTTP caching with ETags containing all APIResources known to the API server. diff --git a/content/en/docs/reference/command-line-tools-reference/feature-gates/api-self-subject-review.md b/content/en/docs/reference/command-line-tools-reference/feature-gates/api-self-subject-review.md index fd65f9919f866..dc706fb51af52 100644 --- a/content/en/docs/reference/command-line-tools-reference/feature-gates/api-self-subject-review.md +++ b/content/en/docs/reference/command-line-tools-reference/feature-gates/api-self-subject-review.md @@ -1,4 +1,5 @@ --- +# Removed from Kubernetes title: APISelfSubjectReview content_type: feature_gate _build: diff --git a/content/en/docs/reference/command-line-tools-reference/feature-gates/cloud-dual-stack-node-ips.md b/content/en/docs/reference/command-line-tools-reference/feature-gates/cloud-dual-stack-node-ips.md index 4a850e6135557..970fc6ae8e3d6 100644 --- a/content/en/docs/reference/command-line-tools-reference/feature-gates/cloud-dual-stack-node-ips.md +++ b/content/en/docs/reference/command-line-tools-reference/feature-gates/cloud-dual-stack-node-ips.md @@ -13,6 +13,11 @@ stages: - stage: beta defaultValue: true fromVersion: "1.29" + toVersion: "1.29" + - stage: stable + defaultValue: true + fromVersion: "1.30" + --- Enables dual-stack `kubelet --node-ip` with external cloud providers. See [Configure IPv4/IPv6 dual-stack](/docs/concepts/services-networking/dual-stack/#configure-ipv4-ipv6-dual-stack) diff --git a/content/en/docs/reference/command-line-tools-reference/feature-gates/contextual-logging.md b/content/en/docs/reference/command-line-tools-reference/feature-gates/contextual-logging.md index 9ae5102d64a3e..6416383f005d6 100644 --- a/content/en/docs/reference/command-line-tools-reference/feature-gates/contextual-logging.md +++ b/content/en/docs/reference/command-line-tools-reference/feature-gates/contextual-logging.md @@ -9,6 +9,9 @@ stages: - stage: alpha defaultValue: false fromVersion: "1.24" + - stage: beta + defaultValue: true + fromVersion: "1.30" --- -When you enable this feature gate, Kubernetes components that support - contextual logging add extra detail to log output. +Enables extra details in log output of Kubernetes components that support +contextual logging. diff --git a/content/en/docs/reference/command-line-tools-reference/feature-gates/crd-validation-ratcheting.md b/content/en/docs/reference/command-line-tools-reference/feature-gates/crd-validation-ratcheting.md index 165c3f1b5c35f..915929fe1197e 100644 --- a/content/en/docs/reference/command-line-tools-reference/feature-gates/crd-validation-ratcheting.md +++ b/content/en/docs/reference/command-line-tools-reference/feature-gates/crd-validation-ratcheting.md @@ -9,6 +9,10 @@ stages: - stage: alpha defaultValue: false fromVersion: "1.28" + toVersion: "1.29" + - stage: beta + defaultValue: true + fromVersion: "1.30" --- Enable updates to custom resources to contain violations of their OpenAPI schema if the offending portions of the resource diff --git a/content/en/docs/reference/command-line-tools-reference/feature-gates/custom-resource-field-selectors.md b/content/en/docs/reference/command-line-tools-reference/feature-gates/custom-resource-field-selectors.md new file mode 100644 index 0000000000000..5ef021173f8de --- /dev/null +++ b/content/en/docs/reference/command-line-tools-reference/feature-gates/custom-resource-field-selectors.md @@ -0,0 +1,16 @@ +--- +title: CustomResourceFieldSelectors +content_type: feature_gate +_build: + list: never + render: false + +stages: + - stage: alpha + defaultValue: false + fromVersion: "1.30" +--- + +Enable `selectableFields` in the +{{< glossary_tooltip term_id="CustomResourceDefinition" text="CustomResourceDefinition" >}} API to allow filtering +of custom resource **list**, **watch** and **deletecollection** requests. diff --git a/content/en/docs/reference/command-line-tools-reference/feature-gates/default-host-network-ports-in-pod-templates.md b/content/en/docs/reference/command-line-tools-reference/feature-gates/default-host-network-ports-in-pod-templates.md index 7fb7d0e432768..bb89ca38ec5ba 100644 --- a/content/en/docs/reference/command-line-tools-reference/feature-gates/default-host-network-ports-in-pod-templates.md +++ b/content/en/docs/reference/command-line-tools-reference/feature-gates/default-host-network-ports-in-pod-templates.md @@ -10,9 +10,12 @@ stages: defaultValue: false fromVersion: "1.28" --- -Changes when the default value of -`PodSpec.containers[*].ports[*].hostPort` -is assigned. The default is to only set a default value in Pods. +This feature gate controls the point at which a default value for +`.spec.containers[*].ports[*].hostPort` +is assigned, for Pods using `hostNetwork: true`. The default since Kubernetes v1.28 is to only set a default +value in Pods. -Enabling this means a default will be assigned even to embedded -PodSpecs (e.g. in a Deployment), which is the historical default. +Enabling this means a default will be assigned even to the `.spec` of an embedded +[PodTemplate](/docs/concepts/workloads/pods/#pod-templates) (for example, in a Deployment), +which is the way that older releases of Kubernetes worked. +You should migrate your code so that it does not rely on the legacy behavior. diff --git a/content/en/docs/reference/command-line-tools-reference/feature-gates/hpa-container-metrics.md b/content/en/docs/reference/command-line-tools-reference/feature-gates/hpa-container-metrics.md index 0beb5c474dfdd..84d076cb4b6a6 100644 --- a/content/en/docs/reference/command-line-tools-reference/feature-gates/hpa-container-metrics.md +++ b/content/en/docs/reference/command-line-tools-reference/feature-gates/hpa-container-metrics.md @@ -13,6 +13,10 @@ stages: - stage: beta defaultValue: true fromVersion: "1.27" + toVersion: "1.29" + - stage: stable + defaultValue: true + fromVersion: "1.30" --- -Enable the `HorizontalPodAutoscaler` to scale based on -metrics from individual containers in target pods. +Allow {{< glossary_tooltip text="HorizontalPodAutoscalers" term_id="horizontal-pod-autoscaler" >}} +to scale based on metrics from individual containers within target pods. \ No newline at end of file diff --git a/content/en/docs/reference/command-line-tools-reference/feature-gates/image-maximum-gc-age.md b/content/en/docs/reference/command-line-tools-reference/feature-gates/image-maximum-gc-age.md index 5860765283dbd..10a6b2334e9a8 100644 --- a/content/en/docs/reference/command-line-tools-reference/feature-gates/image-maximum-gc-age.md +++ b/content/en/docs/reference/command-line-tools-reference/feature-gates/image-maximum-gc-age.md @@ -8,6 +8,10 @@ _build: stages: - stage: alpha defaultValue: false - fromVersion: "1.29" + fromVersion: "1.29" + toVersion: "1.29" + - stage: beta + defaultValue: true + fromVersion: "1.30" --- Enables the kubelet configuration field `imageMaximumGCAge`, allowing an administrator to specify the age after which an image will be garbage collected. diff --git a/content/en/docs/reference/command-line-tools-reference/feature-gates/job-managed-by.md b/content/en/docs/reference/command-line-tools-reference/feature-gates/job-managed-by.md new file mode 100644 index 0000000000000..38733b6de66ff --- /dev/null +++ b/content/en/docs/reference/command-line-tools-reference/feature-gates/job-managed-by.md @@ -0,0 +1,14 @@ +--- +title: JobManagedBy +content_type: feature_gate + +_build: + list: never + render: false + +stages: + - stage: alpha + defaultValue: false + fromVersion: "1.30" +--- +Allows to delegate reconciliation of a Job object to an external controller. diff --git a/content/en/docs/reference/command-line-tools-reference/feature-gates/job-success-policy.md b/content/en/docs/reference/command-line-tools-reference/feature-gates/job-success-policy.md new file mode 100644 index 0000000000000..601680357ccc9 --- /dev/null +++ b/content/en/docs/reference/command-line-tools-reference/feature-gates/job-success-policy.md @@ -0,0 +1,14 @@ +--- +title: JobSuccessPolicy +content_type: feature_gate + +_build: + list: never + render: false + +stages: + - stage: alpha + defaultValue: false + fromVersion: "1.30" +--- +Allow users to specify when a Job can be declared as succeeded based on the set of succeeded pods. diff --git a/content/en/docs/reference/command-line-tools-reference/feature-gates/kube-proxy-draining-terminating-nodes.md b/content/en/docs/reference/command-line-tools-reference/feature-gates/kube-proxy-draining-terminating-nodes.md index e9628a85998eb..d0c1b00f8f385 100644 --- a/content/en/docs/reference/command-line-tools-reference/feature-gates/kube-proxy-draining-terminating-nodes.md +++ b/content/en/docs/reference/command-line-tools-reference/feature-gates/kube-proxy-draining-terminating-nodes.md @@ -9,6 +9,10 @@ stages: - stage: alpha defaultValue: false fromVersion: "1.28" + toVersion: "1.30" + - stage: beta + defaultValue: true + fromVersion: "1.30" --- Implement connection draining for terminating nodes for `externalTrafficPolicy: Cluster` services. diff --git a/content/en/docs/reference/command-line-tools-reference/feature-gates/legacy-service-account-token-clean-up.md b/content/en/docs/reference/command-line-tools-reference/feature-gates/legacy-service-account-token-clean-up.md index 698e25067f9a4..f22aaae479dff 100644 --- a/content/en/docs/reference/command-line-tools-reference/feature-gates/legacy-service-account-token-clean-up.md +++ b/content/en/docs/reference/command-line-tools-reference/feature-gates/legacy-service-account-token-clean-up.md @@ -13,6 +13,10 @@ stages: - stage: beta defaultValue: true fromVersion: "1.29" + toVersion: "1.29" + - stage: stable + defaultValue: true + fromVersion: "1.30" --- Enable cleaning up Secret-based [service account tokens](/docs/concepts/security/service-accounts/#get-a-token) diff --git a/content/en/docs/reference/command-line-tools-reference/feature-gates/load-balancer-ip-mode.md b/content/en/docs/reference/command-line-tools-reference/feature-gates/load-balancer-ip-mode.md index 1a46538eb7dec..6b87fd3abff38 100644 --- a/content/en/docs/reference/command-line-tools-reference/feature-gates/load-balancer-ip-mode.md +++ b/content/en/docs/reference/command-line-tools-reference/feature-gates/load-balancer-ip-mode.md @@ -9,6 +9,10 @@ stages: - stage: alpha defaultValue: false fromVersion: "1.29" + toVersion: "1.30" + - stage: beta + defaultValue: true + fromVersion: "1.30" --- Allows setting `ipMode` for Services where `type` is set to `LoadBalancer`. See [Specifying IPMode of load balancer status](/docs/concepts/services-networking/service/#load-balancer-ip-mode) diff --git a/content/en/docs/reference/command-line-tools-reference/feature-gates/min-domains-in-pod-topology-spread.md b/content/en/docs/reference/command-line-tools-reference/feature-gates/min-domains-in-pod-topology-spread.md index a971222564b77..ae8a3f7f383ad 100644 --- a/content/en/docs/reference/command-line-tools-reference/feature-gates/min-domains-in-pod-topology-spread.md +++ b/content/en/docs/reference/command-line-tools-reference/feature-gates/min-domains-in-pod-topology-spread.md @@ -17,6 +17,10 @@ stages: - stage: beta defaultValue: true fromVersion: "1.27" + toVersion: "1.29" + - stage: stable + defaultValue: true + fromVersion: "1.30" --- Enable `minDomains` in [Pod topology spread constraints](/docs/concepts/scheduling-eviction/topology-spread-constraints/). diff --git a/content/en/docs/reference/command-line-tools-reference/feature-gates/name-generation-retries.md b/content/en/docs/reference/command-line-tools-reference/feature-gates/name-generation-retries.md new file mode 100644 index 0000000000000..6f654f89faa52 --- /dev/null +++ b/content/en/docs/reference/command-line-tools-reference/feature-gates/name-generation-retries.md @@ -0,0 +1,19 @@ +--- +title: NameGenerationRetries +content_type: feature_gate + +_build: + list: never + render: false + +stages: + - stage: alpha + defaultValue: false + fromVersion: "1.30" + +--- +Enables retrying of object creation when the +{{< glossary_tooltip text="API server" term_id="kube-apiserver" >}} +is expected to generate a [name](/docs/concepts/overview/working-with-objects/names/#names). +When this feature is enabled, requests using `generateName` are retried automatically in case the +control plane detects a name conflict with an existing object, up to a limit of 8 total attempts. diff --git a/content/en/docs/reference/command-line-tools-reference/feature-gates/new-volume-manager-reconstruction.md b/content/en/docs/reference/command-line-tools-reference/feature-gates/new-volume-manager-reconstruction.md index f9242f0050912..d58e828c56cbc 100644 --- a/content/en/docs/reference/command-line-tools-reference/feature-gates/new-volume-manager-reconstruction.md +++ b/content/en/docs/reference/command-line-tools-reference/feature-gates/new-volume-manager-reconstruction.md @@ -13,16 +13,15 @@ stages: - stage: beta defaultValue: true fromVersion: "1.28" + toVersion: "1.29" + - stage: stable + defaultValue: true + fromVersion: "1.30" --- Enables improved discovery of mounted volumes during kubelet -startup. Since this code has been significantly refactored, we allow to opt-out in case kubelet -gets stuck at the startup or is not unmounting volumes from terminated Pods. Note that this -refactoring was behind `SELinuxMountReadWriteOncePod` alpha feature gate in Kubernetes 1.25. - - -Before Kubernetes v1.25, the kubelet used different default behavior for discovering mounted -volumes during the kubelet startup. If you disable this feature gate (it's enabled by default), you select -the legacy discovery behavior. +startup. Since the associated code had been significantly refactored, Kubernetes versions 1.25 to 1.29 +allowed you to opt-out in case the kubelet got stuck at the startup, or did not unmount volumes +from terminated Pods. -In Kubernetes v1.25 and v1.26, this behavior toggle was part of the `SELinuxMountReadWriteOncePod` -feature gate. +This refactoring was behind the `SELinuxMountReadWriteOncePod` feature gate in Kubernetes +releases 1.25 and 1.26. diff --git a/content/en/docs/reference/command-line-tools-reference/feature-gates/node-log-query.md b/content/en/docs/reference/command-line-tools-reference/feature-gates/node-log-query.md index efdc9bdc45ba1..6f6ce6ee9d3ac 100644 --- a/content/en/docs/reference/command-line-tools-reference/feature-gates/node-log-query.md +++ b/content/en/docs/reference/command-line-tools-reference/feature-gates/node-log-query.md @@ -9,5 +9,9 @@ stages: - stage: alpha defaultValue: false fromVersion: "1.27" + toVersion: "1.29" + - stage: beta + defaultValue: false + fromVersion: "1.30" --- Enables querying logs of node services using the `/logs` endpoint. diff --git a/content/en/docs/reference/command-line-tools-reference/feature-gates/pod-host-ips.md b/content/en/docs/reference/command-line-tools-reference/feature-gates/pod-host-ips.md index 81e919aa6f069..0f39a10790f3c 100644 --- a/content/en/docs/reference/command-line-tools-reference/feature-gates/pod-host-ips.md +++ b/content/en/docs/reference/command-line-tools-reference/feature-gates/pod-host-ips.md @@ -13,6 +13,10 @@ stages: - stage: beta defaultValue: true fromVersion: "1.29" + toVersion: "1.30" + - stage: stable + defaultValue: true + fromVersion: "1.30" --- Enable the `status.hostIPs` field for pods and the {{< glossary_tooltip term_id="downward-api" text="downward API" >}}. The field lets you expose host IP addresses to workloads. diff --git a/content/en/docs/reference/command-line-tools-reference/feature-gates/pod-lifecycle-sleep-action.md b/content/en/docs/reference/command-line-tools-reference/feature-gates/pod-lifecycle-sleep-action.md index 42509131ebaa8..bb5ede9ce1079 100644 --- a/content/en/docs/reference/command-line-tools-reference/feature-gates/pod-lifecycle-sleep-action.md +++ b/content/en/docs/reference/command-line-tools-reference/feature-gates/pod-lifecycle-sleep-action.md @@ -9,5 +9,9 @@ stages: - stage: alpha defaultValue: false fromVersion: "1.29" + toVersion: "1.29" + - stage: beta + defaultValue: true + fromVersion: "1.30" --- Enables the `sleep` action in Container lifecycle hooks. diff --git a/content/en/docs/reference/command-line-tools-reference/feature-gates/pod-scheduling-readiness.md b/content/en/docs/reference/command-line-tools-reference/feature-gates/pod-scheduling-readiness.md index 8b03ffb2daef1..24951cfc8294d 100644 --- a/content/en/docs/reference/command-line-tools-reference/feature-gates/pod-scheduling-readiness.md +++ b/content/en/docs/reference/command-line-tools-reference/feature-gates/pod-scheduling-readiness.md @@ -13,5 +13,9 @@ stages: - stage: beta defaultValue: true fromVersion: "1.27" + toVersion: "1.29" + - stage: stable + defaultValue: true + fromVersion: "1.30" --- Enable setting `schedulingGates` field to control a Pod's [scheduling readiness](/docs/concepts/scheduling-eviction/pod-scheduling-readiness). diff --git a/content/en/docs/reference/command-line-tools-reference/feature-gates/port-forward-websockets.md b/content/en/docs/reference/command-line-tools-reference/feature-gates/port-forward-websockets.md new file mode 100644 index 0000000000000..fb541f9f0ae15 --- /dev/null +++ b/content/en/docs/reference/command-line-tools-reference/feature-gates/port-forward-websockets.md @@ -0,0 +1,15 @@ +--- +title: PortForwardWebsockets +content_type: feature_gate +_build: + list: never + render: false + +stages: + - stage: alpha + defaultValue: false + fromVersion: "1.30" +--- +Allow WebSocket streaming of the +portforward sub-protocol (`port-forward`) from clients requesting +version v2 (`v2.portforward.k8s.io`) of the sub-protocol. diff --git a/content/en/docs/reference/command-line-tools-reference/feature-gates/readonly-apidata-volumes.md b/content/en/docs/reference/command-line-tools-reference/feature-gates/readonly-apidata-volumes.md new file mode 100644 index 0000000000000..6e2e37ed67b2d --- /dev/null +++ b/content/en/docs/reference/command-line-tools-reference/feature-gates/readonly-apidata-volumes.md @@ -0,0 +1,27 @@ +--- +# Removed from Kubernetes +title: ReadOnlyAPIDataVolumes +content_type: feature_gate + +_build: + list: never + render: false + +stages: + - stage: beta + defaultValue: true + fromVersion: "1.8" + toVersion: "1.9" + - stage: stable + fromVersion: "1.10" + toVersion: "1.10" + +removed: true +--- +Set [`configMap`](/docs/concepts/storage/volumes/#configmap), +[`secret`](/docs/concepts/storage/volumes/#secret), +[`downwardAPI`](/docs/concepts/storage/volumes/#downwardapi) and +[`projected`](/docs/concepts/storage/volumes/#projected) +{{< glossary_tooltip term_id="volume" text="volumes" >}} to be mounted read-only. + +Since Kubernetes v1.10, these volume types are always read-only and you cannot opt out. diff --git a/content/en/docs/reference/command-line-tools-reference/feature-gates/recursive-read-only-mounts.md b/content/en/docs/reference/command-line-tools-reference/feature-gates/recursive-read-only-mounts.md new file mode 100644 index 0000000000000..3ecca217d9d3c --- /dev/null +++ b/content/en/docs/reference/command-line-tools-reference/feature-gates/recursive-read-only-mounts.md @@ -0,0 +1,14 @@ +--- +title: RecursiveReadOnlyMounts +content_type: feature_gate +_build: + list: never + render: false + +stages: + - stage: alpha + defaultValue: false + fromVersion: "1.30" +--- +Enables support for recursive read-only mounts. +For more details, see [read-only mounts](/docs/concepts/storage/volumes/#read-only-mounts). diff --git a/content/en/docs/reference/command-line-tools-reference/feature-gates/relaxed-environment-variable-validation.md b/content/en/docs/reference/command-line-tools-reference/feature-gates/relaxed-environment-variable-validation.md new file mode 100644 index 0000000000000..862ae57214bae --- /dev/null +++ b/content/en/docs/reference/command-line-tools-reference/feature-gates/relaxed-environment-variable-validation.md @@ -0,0 +1,13 @@ +--- +title: RelaxedEnvironmentVariableValidation +content_type: feature_gate +_build: + list: never + render: false + +stages: + - stage: alpha + defaultValue: false + fromVersion: "1.30" +--- +Allow almost all printable ASCII characters in environment variables. diff --git a/content/en/docs/reference/command-line-tools-reference/feature-gates/remove-self-link.md b/content/en/docs/reference/command-line-tools-reference/feature-gates/remove-self-link.md index ff8b45a51e7a6..0e7a492be3057 100644 --- a/content/en/docs/reference/command-line-tools-reference/feature-gates/remove-self-link.md +++ b/content/en/docs/reference/command-line-tools-reference/feature-gates/remove-self-link.md @@ -1,4 +1,5 @@ --- +removed: true title: RemoveSelfLink content_type: feature_gate _build: @@ -17,6 +18,7 @@ stages: - stage: stable defaultValue: true fromVersion: "1.24" + toVersion: "1.29" --- Sets the `.metadata.selfLink` field to blank (empty string) for all objects and collections. This field has been deprecated since the Kubernetes v1.16 diff --git a/content/en/docs/reference/command-line-tools-reference/feature-gates/runtime-class-in-image-cri-api.md b/content/en/docs/reference/command-line-tools-reference/feature-gates/runtime-class-in-image-cri-api.md index 44628348839be..0f7cd164ca48d 100644 --- a/content/en/docs/reference/command-line-tools-reference/feature-gates/runtime-class-in-image-cri-api.md +++ b/content/en/docs/reference/command-line-tools-reference/feature-gates/runtime-class-in-image-cri-api.md @@ -10,5 +10,5 @@ stages: defaultValue: false fromVersion: "1.29" --- -Enables images to be pulled based on the [runtime class] -(/docs/concepts/containers/runtime-class/) of the pods that reference them. +Enables images to be pulled based on the [runtime class](/docs/concepts/containers/runtime-class/) +of the pods that reference them. diff --git a/content/en/docs/reference/command-line-tools-reference/feature-gates/selinux-mount.md b/content/en/docs/reference/command-line-tools-reference/feature-gates/selinux-mount.md new file mode 100644 index 0000000000000..124862976773c --- /dev/null +++ b/content/en/docs/reference/command-line-tools-reference/feature-gates/selinux-mount.md @@ -0,0 +1,20 @@ +--- +title: SELinuxMount +content_type: feature_gate +_build: + list: never + render: false + +stages: + - stage: alpha + defaultValue: false + fromVersion: "1.30" +--- +Speeds up container startup by allowing kubelet to mount volumes +for a Pod directly with the correct SELinux label instead of changing each file on the volumes +recursively. +It widens the performance improvements behind the `SELinuxMountReadWriteOncePod` +feature gate by extending the implementation to all volumes. + +Enabling the `SELinuxMount` feature gate requires the feature gate `SELinuxMountReadWriteOncePod` to +be enabled. diff --git a/content/en/docs/reference/command-line-tools-reference/feature-gates/service-account-token-jti.md b/content/en/docs/reference/command-line-tools-reference/feature-gates/service-account-token-jti.md index f4e9243184872..ab82953ada6da 100644 --- a/content/en/docs/reference/command-line-tools-reference/feature-gates/service-account-token-jti.md +++ b/content/en/docs/reference/command-line-tools-reference/feature-gates/service-account-token-jti.md @@ -9,6 +9,10 @@ stages: - stage: alpha defaultValue: false fromVersion: "1.29" + toVersion: "1.29" + - stage: beta + defaultValue: true + fromVersion: "1.30" --- Controls whether JTIs (UUIDs) are embedded into generated service account tokens, and whether these JTIs are recorded into the Kubernetes audit log for future requests made by these tokens. diff --git a/content/en/docs/reference/command-line-tools-reference/feature-gates/service-account-token-node-binding-validation.md b/content/en/docs/reference/command-line-tools-reference/feature-gates/service-account-token-node-binding-validation.md index fbdff26fd005a..94021587aef52 100644 --- a/content/en/docs/reference/command-line-tools-reference/feature-gates/service-account-token-node-binding-validation.md +++ b/content/en/docs/reference/command-line-tools-reference/feature-gates/service-account-token-node-binding-validation.md @@ -9,6 +9,10 @@ stages: - stage: alpha defaultValue: false fromVersion: "1.29" + toVersion: "1.29" + - stage: beta + defaultValue: true + fromVersion: "1.30" --- Controls whether the apiserver will validate a Node reference in service account tokens. diff --git a/content/en/docs/reference/command-line-tools-reference/feature-gates/service-account-token-pod-node-info.md b/content/en/docs/reference/command-line-tools-reference/feature-gates/service-account-token-pod-node-info.md index da5410122dd10..86d8940b55ec2 100644 --- a/content/en/docs/reference/command-line-tools-reference/feature-gates/service-account-token-pod-node-info.md +++ b/content/en/docs/reference/command-line-tools-reference/feature-gates/service-account-token-pod-node-info.md @@ -9,6 +9,10 @@ stages: - stage: alpha defaultValue: false fromVersion: "1.29" + toVersion: "1.29" + - stage: beta + defaultValue: true + fromVersion: "1.30" --- Controls whether the apiserver embeds the node name and uid for the associated node when issuing service account tokens bound to Pod objects. diff --git a/content/en/docs/reference/command-line-tools-reference/feature-gates/service-traffic-distribution.md b/content/en/docs/reference/command-line-tools-reference/feature-gates/service-traffic-distribution.md new file mode 100644 index 0000000000000..4c1e6d6c17933 --- /dev/null +++ b/content/en/docs/reference/command-line-tools-reference/feature-gates/service-traffic-distribution.md @@ -0,0 +1,16 @@ +--- +title: ServiceTrafficDistribution +content_type: feature_gate + +_build: + list: never + render: false + +stages: +- stage: alpha + defaultValue: false + fromVersion: "1.30" +--- +Allows usage of the optional `spec.trafficDistribution` field in Services. The +field offers a way to express preferences for how traffic is distributed to +Service endpoints. diff --git a/content/en/docs/reference/command-line-tools-reference/feature-gates/stable-load-balancer-node-set.md b/content/en/docs/reference/command-line-tools-reference/feature-gates/stable-load-balancer-node-set.md index faaa09e420011..e2968c340482d 100644 --- a/content/en/docs/reference/command-line-tools-reference/feature-gates/stable-load-balancer-node-set.md +++ b/content/en/docs/reference/command-line-tools-reference/feature-gates/stable-load-balancer-node-set.md @@ -9,6 +9,10 @@ stages: - stage: beta defaultValue: true fromVersion: "1.27" + toVersion: "1.29" + - stage: stable + defaultValue: true + fromVersion: "1.30" --- Enables less load balancer re-configurations by the service controller (KCCM) as an effect of changing node state. diff --git a/content/en/docs/reference/command-line-tools-reference/feature-gates/stateful-set-auto-delete-pvc.md b/content/en/docs/reference/command-line-tools-reference/feature-gates/stateful-set-auto-delete-pvc.md index 9075c90ea1c50..99967d2059258 100644 --- a/content/en/docs/reference/command-line-tools-reference/feature-gates/stateful-set-auto-delete-pvc.md +++ b/content/en/docs/reference/command-line-tools-reference/feature-gates/stateful-set-auto-delete-pvc.md @@ -12,7 +12,7 @@ stages: fromVersion: "1.23" toVersion: "1.26" - stage: beta - defaultValue: false + defaultValue: true fromVersion: "1.27" --- Allows the use of the optional `.spec.persistentVolumeClaimRetentionPolicy` field, diff --git a/content/en/docs/reference/command-line-tools-reference/feature-gates/storage-version-migrator.md b/content/en/docs/reference/command-line-tools-reference/feature-gates/storage-version-migrator.md new file mode 100644 index 0000000000000..01d9bd53b2304 --- /dev/null +++ b/content/en/docs/reference/command-line-tools-reference/feature-gates/storage-version-migrator.md @@ -0,0 +1,14 @@ +--- +title: StorageVersionMigrator +content_type: feature_gate +_build: + list: never + render: false + +stages: + - stage: alpha + defaultValue: false + fromVersion: "1.30" + toVersion: "1.32" +--- +Enables storage version migration. See [Migrate Kubernetes Objects Using Storage Version Migration](/docs/tasks/manage-kubernetes-objects/storage-version-migration) for more details. diff --git a/content/en/docs/reference/command-line-tools-reference/feature-gates/structured-authentication-configuration.md b/content/en/docs/reference/command-line-tools-reference/feature-gates/structured-authentication-configuration.md index 76836a9425872..11c4f11ab09b5 100644 --- a/content/en/docs/reference/command-line-tools-reference/feature-gates/structured-authentication-configuration.md +++ b/content/en/docs/reference/command-line-tools-reference/feature-gates/structured-authentication-configuration.md @@ -9,6 +9,10 @@ stages: - stage: alpha defaultValue: false fromVersion: "1.29" + toVersion: "1.29" + - stage: beta + defaultValue: true + fromVersion: "1.30" --- Enable [structured authentication configuration](/docs/reference/access-authn-authz/authentication/#configuring-the-api-server) for the API server. diff --git a/content/en/docs/reference/command-line-tools-reference/feature-gates/structured-authorization-configuration.md b/content/en/docs/reference/command-line-tools-reference/feature-gates/structured-authorization-configuration.md index cad2cbb6415c3..d2f1a47283c6a 100644 --- a/content/en/docs/reference/command-line-tools-reference/feature-gates/structured-authorization-configuration.md +++ b/content/en/docs/reference/command-line-tools-reference/feature-gates/structured-authorization-configuration.md @@ -9,6 +9,10 @@ stages: - stage: alpha defaultValue: false fromVersion: "1.29" + toVersion: "1.29" + - stage: beta + defaultValue: true + fromVersion: "1.30" --- Enable structured authorization configuration, so that cluster administrators can specify more than one [authorization webhook](/docs/reference/access-authn-authz/webhook/) diff --git a/content/en/docs/reference/command-line-tools-reference/feature-gates/translate-stream-close-websocket-requests.md b/content/en/docs/reference/command-line-tools-reference/feature-gates/translate-stream-close-websocket-requests.md index 08be9d219e2cb..95928403cb9c9 100644 --- a/content/en/docs/reference/command-line-tools-reference/feature-gates/translate-stream-close-websocket-requests.md +++ b/content/en/docs/reference/command-line-tools-reference/feature-gates/translate-stream-close-websocket-requests.md @@ -6,9 +6,9 @@ _build: render: false stages: - - stage: alpha - defaultValue: false - fromVersion: "1.29" + - stage: beta + defaultValue: true + fromVersion: "1.30" --- Allow WebSocket streaming of the remote command sub-protocol (`exec`, `cp`, `attach`) from clients requesting diff --git a/content/en/docs/reference/command-line-tools-reference/feature-gates/user-namespaces-support.md b/content/en/docs/reference/command-line-tools-reference/feature-gates/user-namespaces-support.md index 0e46c3e3158aa..7cf8240545847 100644 --- a/content/en/docs/reference/command-line-tools-reference/feature-gates/user-namespaces-support.md +++ b/content/en/docs/reference/command-line-tools-reference/feature-gates/user-namespaces-support.md @@ -6,8 +6,12 @@ _build: render: false stages: - - stage: alpha + - stage: alpha defaultValue: false fromVersion: "1.28" + toVersion: "1.29" + - stage: beta + defaultValue: false + fromVersion: "1.30" --- Enable user namespace support for Pods. diff --git a/content/en/docs/reference/command-line-tools-reference/feature-gates/validating-admission-policy.md b/content/en/docs/reference/command-line-tools-reference/feature-gates/validating-admission-policy.md index 197422115d265..497c04e0a9291 100644 --- a/content/en/docs/reference/command-line-tools-reference/feature-gates/validating-admission-policy.md +++ b/content/en/docs/reference/command-line-tools-reference/feature-gates/validating-admission-policy.md @@ -13,5 +13,9 @@ stages: - stage: beta defaultValue: false fromVersion: "1.28" + toVersion: "1.29" + - stage: stable + defaultValue: true + fromVersion: "1.30" --- Enable [ValidatingAdmissionPolicy](/docs/reference/access-authn-authz/validating-admission-policy/) support for CEL validations be used in Admission Control. diff --git a/content/en/docs/reference/command-line-tools-reference/kube-apiserver.md b/content/en/docs/reference/command-line-tools-reference/kube-apiserver.md index c4ab21a754cc7..ef8bbd8119db4 100644 --- a/content/en/docs/reference/command-line-tools-reference/kube-apiserver.md +++ b/content/en/docs/reference/command-line-tools-reference/kube-apiserver.md @@ -389,13 +389,6 @@ kube-apiserver [flags]

The API version of the authorization.k8s.io SubjectAccessReview to send to and expect from the webhook.

- ---azure-container-registry-config string - - -

Path to the file containing Azure container registry configuration information.

- - --bind-address string     Default: 0.0.0.0 @@ -470,7 +463,7 @@ kube-apiserver [flags] --disable-admission-plugins strings -

admission plugins that should be disabled although they are in the default enabled plugins list (NamespaceLifecycle, LimitRanger, ServiceAccount, TaintNodesByCondition, PodSecurity, Priority, DefaultTolerationSeconds, DefaultStorageClass, StorageObjectInUseProtection, PersistentVolumeClaimResize, RuntimeClass, CertificateApproval, CertificateSigning, ClusterTrustBundleAttest, CertificateSubjectRestriction, DefaultIngressClass, MutatingAdmissionWebhook, ValidatingAdmissionPolicy, ValidatingAdmissionWebhook, ResourceQuota). Comma-delimited list of admission plugins: AlwaysAdmit, AlwaysDeny, AlwaysPullImages, CertificateApproval, CertificateSigning, CertificateSubjectRestriction, ClusterTrustBundleAttest, DefaultIngressClass, DefaultStorageClass, DefaultTolerationSeconds, DenyServiceExternalIPs, EventRateLimit, ExtendedResourceToleration, ImagePolicyWebhook, LimitPodHardAntiAffinityTopology, LimitRanger, MutatingAdmissionWebhook, NamespaceAutoProvision, NamespaceExists, NamespaceLifecycle, NodeRestriction, OwnerReferencesPermissionEnforcement, PersistentVolumeClaimResize, PersistentVolumeLabel, PodNodeSelector, PodSecurity, PodTolerationRestriction, Priority, ResourceQuota, RuntimeClass, SecurityContextDeny, ServiceAccount, StorageObjectInUseProtection, TaintNodesByCondition, ValidatingAdmissionPolicy, ValidatingAdmissionWebhook. The order of plugins in this flag does not matter.

+

admission plugins that should be disabled although they are in the default enabled plugins list (NamespaceLifecycle, LimitRanger, ServiceAccount, TaintNodesByCondition, PodSecurity, Priority, DefaultTolerationSeconds, DefaultStorageClass, StorageObjectInUseProtection, PersistentVolumeClaimResize, RuntimeClass, CertificateApproval, CertificateSigning, ClusterTrustBundleAttest, CertificateSubjectRestriction, DefaultIngressClass, MutatingAdmissionWebhook, ValidatingAdmissionPolicy, ValidatingAdmissionWebhook, ResourceQuota). Comma-delimited list of admission plugins: AlwaysAdmit, AlwaysDeny, AlwaysPullImages, CertificateApproval, CertificateSigning, CertificateSubjectRestriction, ClusterTrustBundleAttest, DefaultIngressClass, DefaultStorageClass, DefaultTolerationSeconds, DenyServiceExternalIPs, EventRateLimit, ExtendedResourceToleration, ImagePolicyWebhook, LimitPodHardAntiAffinityTopology, LimitRanger, MutatingAdmissionWebhook, NamespaceAutoProvision, NamespaceExists, NamespaceLifecycle, NodeRestriction, OwnerReferencesPermissionEnforcement, PersistentVolumeClaimResize, PersistentVolumeLabel, PodNodeSelector, PodSecurity, PodTolerationRestriction, Priority, ResourceQuota, RuntimeClass, ServiceAccount, StorageObjectInUseProtection, TaintNodesByCondition, ValidatingAdmissionPolicy, ValidatingAdmissionWebhook. The order of plugins in this flag does not matter.

@@ -491,7 +484,7 @@ kube-apiserver [flags] --enable-admission-plugins strings -

admission plugins that should be enabled in addition to default enabled ones (NamespaceLifecycle, LimitRanger, ServiceAccount, TaintNodesByCondition, PodSecurity, Priority, DefaultTolerationSeconds, DefaultStorageClass, StorageObjectInUseProtection, PersistentVolumeClaimResize, RuntimeClass, CertificateApproval, CertificateSigning, ClusterTrustBundleAttest, CertificateSubjectRestriction, DefaultIngressClass, MutatingAdmissionWebhook, ValidatingAdmissionPolicy, ValidatingAdmissionWebhook, ResourceQuota). Comma-delimited list of admission plugins: AlwaysAdmit, AlwaysDeny, AlwaysPullImages, CertificateApproval, CertificateSigning, CertificateSubjectRestriction, ClusterTrustBundleAttest, DefaultIngressClass, DefaultStorageClass, DefaultTolerationSeconds, DenyServiceExternalIPs, EventRateLimit, ExtendedResourceToleration, ImagePolicyWebhook, LimitPodHardAntiAffinityTopology, LimitRanger, MutatingAdmissionWebhook, NamespaceAutoProvision, NamespaceExists, NamespaceLifecycle, NodeRestriction, OwnerReferencesPermissionEnforcement, PersistentVolumeClaimResize, PersistentVolumeLabel, PodNodeSelector, PodSecurity, PodTolerationRestriction, Priority, ResourceQuota, RuntimeClass, SecurityContextDeny, ServiceAccount, StorageObjectInUseProtection, TaintNodesByCondition, ValidatingAdmissionPolicy, ValidatingAdmissionWebhook. The order of plugins in this flag does not matter.

+

admission plugins that should be enabled in addition to default enabled ones (NamespaceLifecycle, LimitRanger, ServiceAccount, TaintNodesByCondition, PodSecurity, Priority, DefaultTolerationSeconds, DefaultStorageClass, StorageObjectInUseProtection, PersistentVolumeClaimResize, RuntimeClass, CertificateApproval, CertificateSigning, ClusterTrustBundleAttest, CertificateSubjectRestriction, DefaultIngressClass, MutatingAdmissionWebhook, ValidatingAdmissionPolicy, ValidatingAdmissionWebhook, ResourceQuota). Comma-delimited list of admission plugins: AlwaysAdmit, AlwaysDeny, AlwaysPullImages, CertificateApproval, CertificateSigning, CertificateSubjectRestriction, ClusterTrustBundleAttest, DefaultIngressClass, DefaultStorageClass, DefaultTolerationSeconds, DenyServiceExternalIPs, EventRateLimit, ExtendedResourceToleration, ImagePolicyWebhook, LimitPodHardAntiAffinityTopology, LimitRanger, MutatingAdmissionWebhook, NamespaceAutoProvision, NamespaceExists, NamespaceLifecycle, NodeRestriction, OwnerReferencesPermissionEnforcement, PersistentVolumeClaimResize, PersistentVolumeLabel, PodNodeSelector, PodSecurity, PodTolerationRestriction, Priority, ResourceQuota, RuntimeClass, ServiceAccount, StorageObjectInUseProtection, TaintNodesByCondition, ValidatingAdmissionPolicy, ValidatingAdmissionWebhook. The order of plugins in this flag does not matter.

@@ -638,7 +631,7 @@ kube-apiserver [flags] --feature-gates <comma-separated 'key=True|False' pairs> -

A set of key=value pairs that describe feature gates for alpha/experimental features. Options are:
APIResponseCompression=true|false (BETA - default=true)
APIServerIdentity=true|false (BETA - default=true)
APIServerTracing=true|false (BETA - default=true)
AdmissionWebhookMatchConditions=true|false (BETA - default=true)
AggregatedDiscoveryEndpoint=true|false (BETA - default=true)
AllAlpha=true|false (ALPHA - default=false)
AllBeta=true|false (BETA - default=false)
AnyVolumeDataSource=true|false (BETA - default=true)
AppArmor=true|false (BETA - default=true)
CPUManagerPolicyAlphaOptions=true|false (ALPHA - default=false)
CPUManagerPolicyBetaOptions=true|false (BETA - default=true)
CPUManagerPolicyOptions=true|false (BETA - default=true)
CRDValidationRatcheting=true|false (ALPHA - default=false)
CSIMigrationPortworx=true|false (BETA - default=false)
CSIVolumeHealth=true|false (ALPHA - default=false)
CloudControllerManagerWebhook=true|false (ALPHA - default=false)
CloudDualStackNodeIPs=true|false (BETA - default=true)
ClusterTrustBundle=true|false (ALPHA - default=false)
ClusterTrustBundleProjection=true|false (ALPHA - default=false)
ComponentSLIs=true|false (BETA - default=true)
ConsistentListFromCache=true|false (ALPHA - default=false)
ContainerCheckpoint=true|false (ALPHA - default=false)
ContextualLogging=true|false (ALPHA - default=false)
CronJobsScheduledAnnotation=true|false (BETA - default=true)
CrossNamespaceVolumeDataSource=true|false (ALPHA - default=false)
CustomCPUCFSQuotaPeriod=true|false (ALPHA - default=false)
DevicePluginCDIDevices=true|false (BETA - default=true)
DisableCloudProviders=true|false (BETA - default=true)
DisableKubeletCloudCredentialProviders=true|false (BETA - default=true)
DisableNodeKubeProxyVersion=true|false (ALPHA - default=false)
DynamicResourceAllocation=true|false (ALPHA - default=false)
ElasticIndexedJob=true|false (BETA - default=true)
EventedPLEG=true|false (BETA - default=false)
GracefulNodeShutdown=true|false (BETA - default=true)
GracefulNodeShutdownBasedOnPodPriority=true|false (BETA - default=true)
HPAContainerMetrics=true|false (BETA - default=true)
HPAScaleToZero=true|false (ALPHA - default=false)
HonorPVReclaimPolicy=true|false (ALPHA - default=false)
ImageMaximumGCAge=true|false (ALPHA - default=false)
InPlacePodVerticalScaling=true|false (ALPHA - default=false)
InTreePluginAWSUnregister=true|false (ALPHA - default=false)
InTreePluginAzureDiskUnregister=true|false (ALPHA - default=false)
InTreePluginAzureFileUnregister=true|false (ALPHA - default=false)
InTreePluginGCEUnregister=true|false (ALPHA - default=false)
InTreePluginOpenStackUnregister=true|false (ALPHA - default=false)
InTreePluginPortworxUnregister=true|false (ALPHA - default=false)
InTreePluginvSphereUnregister=true|false (ALPHA - default=false)
JobBackoffLimitPerIndex=true|false (BETA - default=true)
JobPodFailurePolicy=true|false (BETA - default=true)
JobPodReplacementPolicy=true|false (BETA - default=true)
KubeProxyDrainingTerminatingNodes=true|false (ALPHA - default=false)
KubeletCgroupDriverFromCRI=true|false (ALPHA - default=false)
KubeletInUserNamespace=true|false (ALPHA - default=false)
KubeletPodResourcesDynamicResources=true|false (ALPHA - default=false)
KubeletPodResourcesGet=true|false (ALPHA - default=false)
KubeletSeparateDiskGC=true|false (ALPHA - default=false)
KubeletTracing=true|false (BETA - default=true)
LegacyServiceAccountTokenCleanUp=true|false (BETA - default=true)
LoadBalancerIPMode=true|false (ALPHA - default=false)
LocalStorageCapacityIsolationFSQuotaMonitoring=true|false (ALPHA - default=false)
LogarithmicScaleDown=true|false (BETA - default=true)
LoggingAlphaOptions=true|false (ALPHA - default=false)
LoggingBetaOptions=true|false (BETA - default=true)
MatchLabelKeysInPodAffinity=true|false (ALPHA - default=false)
MatchLabelKeysInPodTopologySpread=true|false (BETA - default=true)
MaxUnavailableStatefulSet=true|false (ALPHA - default=false)
MemoryManager=true|false (BETA - default=true)
MemoryQoS=true|false (ALPHA - default=false)
MinDomainsInPodTopologySpread=true|false (BETA - default=true)
MultiCIDRServiceAllocator=true|false (ALPHA - default=false)
NFTablesProxyMode=true|false (ALPHA - default=false)
NewVolumeManagerReconstruction=true|false (BETA - default=true)
NodeInclusionPolicyInPodTopologySpread=true|false (BETA - default=true)
NodeLogQuery=true|false (ALPHA - default=false)
NodeSwap=true|false (BETA - default=false)
OpenAPIEnums=true|false (BETA - default=true)
PDBUnhealthyPodEvictionPolicy=true|false (BETA - default=true)
PersistentVolumeLastPhaseTransitionTime=true|false (BETA - default=true)
PodAndContainerStatsFromCRI=true|false (ALPHA - default=false)
PodDeletionCost=true|false (BETA - default=true)
PodDisruptionConditions=true|false (BETA - default=true)
PodHostIPs=true|false (BETA - default=true)
PodIndexLabel=true|false (BETA - default=true)
PodLifecycleSleepAction=true|false (ALPHA - default=false)
PodReadyToStartContainersCondition=true|false (BETA - default=true)
PodSchedulingReadiness=true|false (BETA - default=true)
ProcMountType=true|false (ALPHA - default=false)
QOSReserved=true|false (ALPHA - default=false)
RecoverVolumeExpansionFailure=true|false (ALPHA - default=false)
RotateKubeletServerCertificate=true|false (BETA - default=true)
RuntimeClassInImageCriApi=true|false (ALPHA - default=false)
SELinuxMountReadWriteOncePod=true|false (BETA - default=true)
SchedulerQueueingHints=true|false (BETA - default=false)
SecurityContextDeny=true|false (ALPHA - default=false)
SeparateTaintEvictionController=true|false (BETA - default=true)
ServiceAccountTokenJTI=true|false (ALPHA - default=false)
ServiceAccountTokenNodeBinding=true|false (ALPHA - default=false)
ServiceAccountTokenNodeBindingValidation=true|false (ALPHA - default=false)
ServiceAccountTokenPodNodeInfo=true|false (ALPHA - default=false)
SidecarContainers=true|false (BETA - default=true)
SizeMemoryBackedVolumes=true|false (BETA - default=true)
StableLoadBalancerNodeSet=true|false (BETA - default=true)
StatefulSetAutoDeletePVC=true|false (BETA - default=true)
StatefulSetStartOrdinal=true|false (BETA - default=true)
StorageVersionAPI=true|false (ALPHA - default=false)
StorageVersionHash=true|false (BETA - default=true)
StructuredAuthenticationConfiguration=true|false (ALPHA - default=false)
StructuredAuthorizationConfiguration=true|false (ALPHA - default=false)
TopologyAwareHints=true|false (BETA - default=true)
TopologyManagerPolicyAlphaOptions=true|false (ALPHA - default=false)
TopologyManagerPolicyBetaOptions=true|false (BETA - default=true)
TopologyManagerPolicyOptions=true|false (BETA - default=true)
TranslateStreamCloseWebsocketRequests=true|false (ALPHA - default=false)
UnauthenticatedHTTP2DOSMitigation=true|false (BETA - default=true)
UnknownVersionInteroperabilityProxy=true|false (ALPHA - default=false)
UserNamespacesPodSecurityStandards=true|false (ALPHA - default=false)
UserNamespacesSupport=true|false (ALPHA - default=false)
ValidatingAdmissionPolicy=true|false (BETA - default=false)
VolumeAttributesClass=true|false (ALPHA - default=false)
VolumeCapacityPriority=true|false (ALPHA - default=false)
WatchList=true|false (ALPHA - default=false)
WinDSR=true|false (ALPHA - default=false)
WinOverlay=true|false (BETA - default=true)
WindowsHostNetwork=true|false (ALPHA - default=true)
ZeroLimitedNominalConcurrencyShares=true|false (BETA - default=false)

+

A set of key=value pairs that describe feature gates for alpha/experimental features. Options are:
APIResponseCompression=true|false (BETA - default=true)
APIServerIdentity=true|false (BETA - default=true)
APIServerTracing=true|false (BETA - default=true)
APIServingWithRoutine=true|false (BETA - default=true)
AllAlpha=true|false (ALPHA - default=false)
AllBeta=true|false (BETA - default=false)
AnyVolumeDataSource=true|false (BETA - default=true)
AppArmor=true|false (BETA - default=true)
AppArmorFields=true|false (BETA - default=true)
CPUManagerPolicyAlphaOptions=true|false (ALPHA - default=false)
CPUManagerPolicyBetaOptions=true|false (BETA - default=true)
CPUManagerPolicyOptions=true|false (BETA - default=true)
CRDValidationRatcheting=true|false (BETA - default=true)
CSIMigrationPortworx=true|false (BETA - default=false)
CSIVolumeHealth=true|false (ALPHA - default=false)
CloudControllerManagerWebhook=true|false (ALPHA - default=false)
ClusterTrustBundle=true|false (ALPHA - default=false)
ClusterTrustBundleProjection=true|false (ALPHA - default=false)
ComponentSLIs=true|false (BETA - default=true)
ConsistentListFromCache=true|false (ALPHA - default=false)
ContainerCheckpoint=true|false (BETA - default=true)
ContextualLogging=true|false (BETA - default=true)
CronJobsScheduledAnnotation=true|false (BETA - default=true)
CrossNamespaceVolumeDataSource=true|false (ALPHA - default=false)
CustomCPUCFSQuotaPeriod=true|false (ALPHA - default=false)
CustomResourceFieldSelectors=true|false (ALPHA - default=false)
DevicePluginCDIDevices=true|false (BETA - default=true)
DisableCloudProviders=true|false (BETA - default=true)
DisableKubeletCloudCredentialProviders=true|false (BETA - default=true)
DisableNodeKubeProxyVersion=true|false (ALPHA - default=false)
DynamicResourceAllocation=true|false (ALPHA - default=false)
ElasticIndexedJob=true|false (BETA - default=true)
EventedPLEG=true|false (ALPHA - default=false)
GracefulNodeShutdown=true|false (BETA - default=true)
GracefulNodeShutdownBasedOnPodPriority=true|false (BETA - default=true)
HPAScaleToZero=true|false (ALPHA - default=false)
HonorPVReclaimPolicy=true|false (ALPHA - default=false)
ImageMaximumGCAge=true|false (BETA - default=true)
InPlacePodVerticalScaling=true|false (ALPHA - default=false)
InTreePluginAWSUnregister=true|false (ALPHA - default=false)
InTreePluginAzureDiskUnregister=true|false (ALPHA - default=false)
InTreePluginAzureFileUnregister=true|false (ALPHA - default=false)
InTreePluginGCEUnregister=true|false (ALPHA - default=false)
InTreePluginOpenStackUnregister=true|false (ALPHA - default=false)
InTreePluginPortworxUnregister=true|false (ALPHA - default=false)
InTreePluginvSphereUnregister=true|false (ALPHA - default=false)
InformerResourceVersion=true|false (ALPHA - default=false)
JobBackoffLimitPerIndex=true|false (BETA - default=true)
JobManagedBy=true|false (ALPHA - default=false)
JobPodFailurePolicy=true|false (BETA - default=true)
JobPodReplacementPolicy=true|false (BETA - default=true)
JobSuccessPolicy=true|false (ALPHA - default=false)
KubeProxyDrainingTerminatingNodes=true|false (BETA - default=true)
KubeletCgroupDriverFromCRI=true|false (ALPHA - default=false)
KubeletInUserNamespace=true|false (ALPHA - default=false)
KubeletPodResourcesDynamicResources=true|false (ALPHA - default=false)
KubeletPodResourcesGet=true|false (ALPHA - default=false)
KubeletSeparateDiskGC=true|false (ALPHA - default=false)
KubeletTracing=true|false (BETA - default=true)
LoadBalancerIPMode=true|false (BETA - default=true)
LocalStorageCapacityIsolationFSQuotaMonitoring=true|false (ALPHA - default=false)
LogarithmicScaleDown=true|false (BETA - default=true)
LoggingAlphaOptions=true|false (ALPHA - default=false)
LoggingBetaOptions=true|false (BETA - default=true)
MatchLabelKeysInPodAffinity=true|false (ALPHA - default=false)
MatchLabelKeysInPodTopologySpread=true|false (BETA - default=true)
MaxUnavailableStatefulSet=true|false (ALPHA - default=false)
MemoryManager=true|false (BETA - default=true)
MemoryQoS=true|false (ALPHA - default=false)
MultiCIDRServiceAllocator=true|false (ALPHA - default=false)
MutatingAdmissionPolicy=true|false (ALPHA - default=false)
NFTablesProxyMode=true|false (ALPHA - default=false)
NodeInclusionPolicyInPodTopologySpread=true|false (BETA - default=true)
NodeLogQuery=true|false (BETA - default=false)
NodeSwap=true|false (BETA - default=true)
OpenAPIEnums=true|false (BETA - default=true)
PDBUnhealthyPodEvictionPolicy=true|false (BETA - default=true)
PersistentVolumeLastPhaseTransitionTime=true|false (BETA - default=true)
PodAndContainerStatsFromCRI=true|false (ALPHA - default=false)
PodDeletionCost=true|false (BETA - default=true)
PodDisruptionConditions=true|false (BETA - default=true)
PodIndexLabel=true|false (BETA - default=true)
PodLifecycleSleepAction=true|false (BETA - default=true)
PodReadyToStartContainersCondition=true|false (BETA - default=true)
PortForwardWebsockets=true|false (ALPHA - default=false)
ProcMountType=true|false (ALPHA - default=false)
QOSReserved=true|false (ALPHA - default=false)
RecoverVolumeExpansionFailure=true|false (ALPHA - default=false)
RecursiveReadOnlyMounts=true|false (ALPHA - default=false)
RelaxedEnvironmentVariableValidation=true|false (ALPHA - default=false)
RetryGenerateName=true|false (ALPHA - default=false)
RotateKubeletServerCertificate=true|false (BETA - default=true)
RuntimeClassInImageCriApi=true|false (ALPHA - default=false)
SELinuxMount=true|false (ALPHA - default=false)
SELinuxMountReadWriteOncePod=true|false (BETA - default=true)
SchedulerQueueingHints=true|false (BETA - default=false)
SeparateCacheWatchRPC=true|false (BETA - default=true)
SeparateTaintEvictionController=true|false (BETA - default=true)
ServiceAccountTokenJTI=true|false (BETA - default=true)
ServiceAccountTokenNodeBinding=true|false (ALPHA - default=false)
ServiceAccountTokenNodeBindingValidation=true|false (BETA - default=true)
ServiceAccountTokenPodNodeInfo=true|false (BETA - default=true)
ServiceTrafficDistribution=true|false (ALPHA - default=false)
SidecarContainers=true|false (BETA - default=true)
SizeMemoryBackedVolumes=true|false (BETA - default=true)
StatefulSetAutoDeletePVC=true|false (BETA - default=true)
StatefulSetStartOrdinal=true|false (BETA - default=true)
StorageNamespaceIndex=true|false (BETA - default=true)
StorageVersionAPI=true|false (ALPHA - default=false)
StorageVersionHash=true|false (BETA - default=true)
StorageVersionMigrator=true|false (ALPHA - default=false)
StructuredAuthenticationConfiguration=true|false (BETA - default=true)
StructuredAuthorizationConfiguration=true|false (BETA - default=true)
TopologyAwareHints=true|false (BETA - default=true)
TopologyManagerPolicyAlphaOptions=true|false (ALPHA - default=false)
TopologyManagerPolicyBetaOptions=true|false (BETA - default=true)
TopologyManagerPolicyOptions=true|false (BETA - default=true)
TranslateStreamCloseWebsocketRequests=true|false (BETA - default=true)
UnauthenticatedHTTP2DOSMitigation=true|false (BETA - default=true)
UnknownVersionInteroperabilityProxy=true|false (ALPHA - default=false)
UserNamespacesPodSecurityStandards=true|false (ALPHA - default=false)
UserNamespacesSupport=true|false (BETA - default=false)
VolumeAttributesClass=true|false (ALPHA - default=false)
VolumeCapacityPriority=true|false (ALPHA - default=false)
WatchFromStorageWithoutResourceVersion=true|false (BETA - default=false)
WatchList=true|false (ALPHA - default=false)
WatchListClient=true|false (BETA - default=false)
WinDSR=true|false (ALPHA - default=false)
WinOverlay=true|false (BETA - default=true)
WindowsHostNetwork=true|false (ALPHA - default=true)

@@ -725,6 +718,20 @@ kube-apiserver [flags]

Maximum number of seconds between log flushes

+ +--log-text-info-buffer-size quantity + + +

[Alpha] In text format with split output streams, the info messages can be buffered for a while to increase performance. The default value of zero bytes disables buffering. The size can be specified as number of bytes (512), multiples of 1000 (1K), multiples of 1024 (2Ki), or powers of those (3M, 4G, 5Mi, 6Gi). Enable the LoggingAlphaOptions feature gate to use this.

+ + + +--log-text-split-stream + + +

[Alpha] In text format, write error messages to stderr and info messages to stdout. The default is to write a single stream to stdout. Enable the LoggingAlphaOptions feature gate to use this.

+ + --logging-format string     Default: "text" @@ -1058,7 +1065,7 @@ kube-apiserver [flags] --tls-cipher-suites strings -

Comma-separated list of cipher suites for the server. If omitted, the default Go cipher suites will be used.
Preferred values: TLS_AES_128_GCM_SHA256, TLS_AES_256_GCM_SHA384, TLS_CHACHA20_POLY1305_SHA256, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305, TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305, TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_RSA_WITH_AES_128_GCM_SHA256, TLS_RSA_WITH_AES_256_CBC_SHA, TLS_RSA_WITH_AES_256_GCM_SHA384.
Insecure values: TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, TLS_ECDHE_RSA_WITH_RC4_128_SHA, TLS_RSA_WITH_3DES_EDE_CBC_SHA, TLS_RSA_WITH_AES_128_CBC_SHA256, TLS_RSA_WITH_RC4_128_SHA.

+

Comma-separated list of cipher suites for the server. If omitted, the default Go cipher suites will be used.
Preferred values: TLS_AES_128_GCM_SHA256, TLS_AES_256_GCM_SHA384, TLS_CHACHA20_POLY1305_SHA256, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305, TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305, TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256.
Insecure values: TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, TLS_ECDHE_RSA_WITH_RC4_128_SHA, TLS_RSA_WITH_3DES_EDE_CBC_SHA, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_RSA_WITH_AES_128_CBC_SHA256, TLS_RSA_WITH_AES_128_GCM_SHA256, TLS_RSA_WITH_AES_256_CBC_SHA, TLS_RSA_WITH_AES_256_GCM_SHA384, TLS_RSA_WITH_RC4_128_SHA.

diff --git a/content/en/docs/reference/command-line-tools-reference/kube-controller-manager.md b/content/en/docs/reference/command-line-tools-reference/kube-controller-manager.md index 6982a31dc1d60..53f190d6c0574 100644 --- a/content/en/docs/reference/command-line-tools-reference/kube-controller-manager.md +++ b/content/en/docs/reference/command-line-tools-reference/kube-controller-manager.md @@ -127,13 +127,6 @@ kube-controller-manager [flags]

The duration to cache 'unauthorized' responses from the webhook authorizer.

- ---azure-container-registry-config string - - -

Path to the file containing Azure container registry configuration information.

- - --bind-address string     Default: 0.0.0.0 @@ -411,7 +404,7 @@ kube-controller-manager [flags] --controllers strings     Default: "*" -

A list of controllers to enable. '*' enables all on-by-default controllers, 'foo' enables the controller named 'foo', '-foo' disables the controller named 'foo'.
All controllers: bootstrap-signer-controller, certificatesigningrequest-approving-controller, certificatesigningrequest-cleaner-controller, certificatesigningrequest-signing-controller, cloud-node-lifecycle-controller, clusterrole-aggregation-controller, cronjob-controller, daemonset-controller, deployment-controller, disruption-controller, endpoints-controller, endpointslice-controller, endpointslice-mirroring-controller, ephemeral-volume-controller, garbage-collector-controller, horizontal-pod-autoscaler-controller, job-controller, legacy-serviceaccount-token-cleaner-controller, namespace-controller, node-ipam-controller, node-lifecycle-controller, node-route-controller, persistentvolume-attach-detach-controller, persistentvolume-binder-controller, persistentvolume-expander-controller, persistentvolume-protection-controller, persistentvolumeclaim-protection-controller, pod-garbage-collector-controller, replicaset-controller, replicationcontroller-controller, resourceclaim-controller, resourcequota-controller, root-ca-certificate-publisher-controller, service-cidr-controller, service-lb-controller, serviceaccount-controller, serviceaccount-token-controller, statefulset-controller, storageversion-garbage-collector-controller, taint-eviction-controller, token-cleaner-controller, ttl-after-finished-controller, ttl-controller, validatingadmissionpolicy-status-controller
Disabled-by-default controllers: bootstrap-signer-controller, token-cleaner-controller

+

A list of controllers to enable. '*' enables all on-by-default controllers, 'foo' enables the controller named 'foo', '-foo' disables the controller named 'foo'.
All controllers: bootstrap-signer-controller, certificatesigningrequest-approving-controller, certificatesigningrequest-cleaner-controller, certificatesigningrequest-signing-controller, cloud-node-lifecycle-controller, clusterrole-aggregation-controller, cronjob-controller, daemonset-controller, deployment-controller, disruption-controller, endpoints-controller, endpointslice-controller, endpointslice-mirroring-controller, ephemeral-volume-controller, garbage-collector-controller, horizontal-pod-autoscaler-controller, job-controller, legacy-serviceaccount-token-cleaner-controller, namespace-controller, node-ipam-controller, node-lifecycle-controller, node-route-controller, persistentvolume-attach-detach-controller, persistentvolume-binder-controller, persistentvolume-expander-controller, persistentvolume-protection-controller, persistentvolumeclaim-protection-controller, pod-garbage-collector-controller, replicaset-controller, replicationcontroller-controller, resourceclaim-controller, resourcequota-controller, root-ca-certificate-publisher-controller, service-cidr-controller, service-lb-controller, serviceaccount-controller, serviceaccount-token-controller, statefulset-controller, storage-version-migrator-controller, storageversion-garbage-collector-controller, taint-eviction-controller, token-cleaner-controller, ttl-after-finished-controller, ttl-controller, validatingadmissionpolicy-status-controller
Disabled-by-default controllers: bootstrap-signer-controller, token-cleaner-controller

@@ -421,6 +414,13 @@ kube-controller-manager [flags]

Disable volume attach detach reconciler sync. Disabling this may cause volumes to be mismatched with pods. Use wisely.

+ +--disable-force-detach-on-timeout + + +

Prevent force detaching volumes based on maximum unmount time and node status. If this flag is set to true, the non-graceful node shutdown feature must be used to recover from node failure. See https://k8s.io/docs/storage-disable-force-detach-on-timeout/.

+ + --disabled-metrics strings @@ -481,7 +481,7 @@ kube-controller-manager [flags] --feature-gates <comma-separated 'key=True|False' pairs> -

A set of key=value pairs that describe feature gates for alpha/experimental features. Options are:
APIResponseCompression=true|false (BETA - default=true)
APIServerIdentity=true|false (BETA - default=true)
APIServerTracing=true|false (BETA - default=true)
AdmissionWebhookMatchConditions=true|false (BETA - default=true)
AggregatedDiscoveryEndpoint=true|false (BETA - default=true)
AllAlpha=true|false (ALPHA - default=false)
AllBeta=true|false (BETA - default=false)
AnyVolumeDataSource=true|false (BETA - default=true)
AppArmor=true|false (BETA - default=true)
CPUManagerPolicyAlphaOptions=true|false (ALPHA - default=false)
CPUManagerPolicyBetaOptions=true|false (BETA - default=true)
CPUManagerPolicyOptions=true|false (BETA - default=true)
CRDValidationRatcheting=true|false (ALPHA - default=false)
CSIMigrationPortworx=true|false (BETA - default=false)
CSIVolumeHealth=true|false (ALPHA - default=false)
CloudControllerManagerWebhook=true|false (ALPHA - default=false)
CloudDualStackNodeIPs=true|false (BETA - default=true)
ClusterTrustBundle=true|false (ALPHA - default=false)
ClusterTrustBundleProjection=true|false (ALPHA - default=false)
ComponentSLIs=true|false (BETA - default=true)
ConsistentListFromCache=true|false (ALPHA - default=false)
ContainerCheckpoint=true|false (ALPHA - default=false)
ContextualLogging=true|false (ALPHA - default=false)
CronJobsScheduledAnnotation=true|false (BETA - default=true)
CrossNamespaceVolumeDataSource=true|false (ALPHA - default=false)
CustomCPUCFSQuotaPeriod=true|false (ALPHA - default=false)
DevicePluginCDIDevices=true|false (BETA - default=true)
DisableCloudProviders=true|false (BETA - default=true)
DisableKubeletCloudCredentialProviders=true|false (BETA - default=true)
DisableNodeKubeProxyVersion=true|false (ALPHA - default=false)
DynamicResourceAllocation=true|false (ALPHA - default=false)
ElasticIndexedJob=true|false (BETA - default=true)
EventedPLEG=true|false (BETA - default=false)
GracefulNodeShutdown=true|false (BETA - default=true)
GracefulNodeShutdownBasedOnPodPriority=true|false (BETA - default=true)
HPAContainerMetrics=true|false (BETA - default=true)
HPAScaleToZero=true|false (ALPHA - default=false)
HonorPVReclaimPolicy=true|false (ALPHA - default=false)
ImageMaximumGCAge=true|false (ALPHA - default=false)
InPlacePodVerticalScaling=true|false (ALPHA - default=false)
InTreePluginAWSUnregister=true|false (ALPHA - default=false)
InTreePluginAzureDiskUnregister=true|false (ALPHA - default=false)
InTreePluginAzureFileUnregister=true|false (ALPHA - default=false)
InTreePluginGCEUnregister=true|false (ALPHA - default=false)
InTreePluginOpenStackUnregister=true|false (ALPHA - default=false)
InTreePluginPortworxUnregister=true|false (ALPHA - default=false)
InTreePluginvSphereUnregister=true|false (ALPHA - default=false)
JobBackoffLimitPerIndex=true|false (BETA - default=true)
JobPodFailurePolicy=true|false (BETA - default=true)
JobPodReplacementPolicy=true|false (BETA - default=true)
KubeProxyDrainingTerminatingNodes=true|false (ALPHA - default=false)
KubeletCgroupDriverFromCRI=true|false (ALPHA - default=false)
KubeletInUserNamespace=true|false (ALPHA - default=false)
KubeletPodResourcesDynamicResources=true|false (ALPHA - default=false)
KubeletPodResourcesGet=true|false (ALPHA - default=false)
KubeletSeparateDiskGC=true|false (ALPHA - default=false)
KubeletTracing=true|false (BETA - default=true)
LegacyServiceAccountTokenCleanUp=true|false (BETA - default=true)
LoadBalancerIPMode=true|false (ALPHA - default=false)
LocalStorageCapacityIsolationFSQuotaMonitoring=true|false (ALPHA - default=false)
LogarithmicScaleDown=true|false (BETA - default=true)
LoggingAlphaOptions=true|false (ALPHA - default=false)
LoggingBetaOptions=true|false (BETA - default=true)
MatchLabelKeysInPodAffinity=true|false (ALPHA - default=false)
MatchLabelKeysInPodTopologySpread=true|false (BETA - default=true)
MaxUnavailableStatefulSet=true|false (ALPHA - default=false)
MemoryManager=true|false (BETA - default=true)
MemoryQoS=true|false (ALPHA - default=false)
MinDomainsInPodTopologySpread=true|false (BETA - default=true)
MultiCIDRServiceAllocator=true|false (ALPHA - default=false)
NFTablesProxyMode=true|false (ALPHA - default=false)
NewVolumeManagerReconstruction=true|false (BETA - default=true)
NodeInclusionPolicyInPodTopologySpread=true|false (BETA - default=true)
NodeLogQuery=true|false (ALPHA - default=false)
NodeSwap=true|false (BETA - default=false)
OpenAPIEnums=true|false (BETA - default=true)
PDBUnhealthyPodEvictionPolicy=true|false (BETA - default=true)
PersistentVolumeLastPhaseTransitionTime=true|false (BETA - default=true)
PodAndContainerStatsFromCRI=true|false (ALPHA - default=false)
PodDeletionCost=true|false (BETA - default=true)
PodDisruptionConditions=true|false (BETA - default=true)
PodHostIPs=true|false (BETA - default=true)
PodIndexLabel=true|false (BETA - default=true)
PodLifecycleSleepAction=true|false (ALPHA - default=false)
PodReadyToStartContainersCondition=true|false (BETA - default=true)
PodSchedulingReadiness=true|false (BETA - default=true)
ProcMountType=true|false (ALPHA - default=false)
QOSReserved=true|false (ALPHA - default=false)
RecoverVolumeExpansionFailure=true|false (ALPHA - default=false)
RotateKubeletServerCertificate=true|false (BETA - default=true)
RuntimeClassInImageCriApi=true|false (ALPHA - default=false)
SELinuxMountReadWriteOncePod=true|false (BETA - default=true)
SchedulerQueueingHints=true|false (BETA - default=false)
SecurityContextDeny=true|false (ALPHA - default=false)
SeparateTaintEvictionController=true|false (BETA - default=true)
ServiceAccountTokenJTI=true|false (ALPHA - default=false)
ServiceAccountTokenNodeBinding=true|false (ALPHA - default=false)
ServiceAccountTokenNodeBindingValidation=true|false (ALPHA - default=false)
ServiceAccountTokenPodNodeInfo=true|false (ALPHA - default=false)
SidecarContainers=true|false (BETA - default=true)
SizeMemoryBackedVolumes=true|false (BETA - default=true)
StableLoadBalancerNodeSet=true|false (BETA - default=true)
StatefulSetAutoDeletePVC=true|false (BETA - default=true)
StatefulSetStartOrdinal=true|false (BETA - default=true)
StorageVersionAPI=true|false (ALPHA - default=false)
StorageVersionHash=true|false (BETA - default=true)
StructuredAuthenticationConfiguration=true|false (ALPHA - default=false)
StructuredAuthorizationConfiguration=true|false (ALPHA - default=false)
TopologyAwareHints=true|false (BETA - default=true)
TopologyManagerPolicyAlphaOptions=true|false (ALPHA - default=false)
TopologyManagerPolicyBetaOptions=true|false (BETA - default=true)
TopologyManagerPolicyOptions=true|false (BETA - default=true)
TranslateStreamCloseWebsocketRequests=true|false (ALPHA - default=false)
UnauthenticatedHTTP2DOSMitigation=true|false (BETA - default=true)
UnknownVersionInteroperabilityProxy=true|false (ALPHA - default=false)
UserNamespacesPodSecurityStandards=true|false (ALPHA - default=false)
UserNamespacesSupport=true|false (ALPHA - default=false)
ValidatingAdmissionPolicy=true|false (BETA - default=false)
VolumeAttributesClass=true|false (ALPHA - default=false)
VolumeCapacityPriority=true|false (ALPHA - default=false)
WatchList=true|false (ALPHA - default=false)
WinDSR=true|false (ALPHA - default=false)
WinOverlay=true|false (BETA - default=true)
WindowsHostNetwork=true|false (ALPHA - default=true)
ZeroLimitedNominalConcurrencyShares=true|false (BETA - default=false)

+

A set of key=value pairs that describe feature gates for alpha/experimental features. Options are:
APIResponseCompression=true|false (BETA - default=true)
APIServerIdentity=true|false (BETA - default=true)
APIServerTracing=true|false (BETA - default=true)
APIServingWithRoutine=true|false (BETA - default=true)
AllAlpha=true|false (ALPHA - default=false)
AllBeta=true|false (BETA - default=false)
AnyVolumeDataSource=true|false (BETA - default=true)
AppArmor=true|false (BETA - default=true)
AppArmorFields=true|false (BETA - default=true)
CPUManagerPolicyAlphaOptions=true|false (ALPHA - default=false)
CPUManagerPolicyBetaOptions=true|false (BETA - default=true)
CPUManagerPolicyOptions=true|false (BETA - default=true)
CRDValidationRatcheting=true|false (BETA - default=true)
CSIMigrationPortworx=true|false (BETA - default=false)
CSIVolumeHealth=true|false (ALPHA - default=false)
CloudControllerManagerWebhook=true|false (ALPHA - default=false)
ClusterTrustBundle=true|false (ALPHA - default=false)
ClusterTrustBundleProjection=true|false (ALPHA - default=false)
ComponentSLIs=true|false (BETA - default=true)
ConsistentListFromCache=true|false (ALPHA - default=false)
ContainerCheckpoint=true|false (BETA - default=true)
ContextualLogging=true|false (BETA - default=true)
CronJobsScheduledAnnotation=true|false (BETA - default=true)
CrossNamespaceVolumeDataSource=true|false (ALPHA - default=false)
CustomCPUCFSQuotaPeriod=true|false (ALPHA - default=false)
CustomResourceFieldSelectors=true|false (ALPHA - default=false)
DevicePluginCDIDevices=true|false (BETA - default=true)
DisableCloudProviders=true|false (BETA - default=true)
DisableKubeletCloudCredentialProviders=true|false (BETA - default=true)
DisableNodeKubeProxyVersion=true|false (ALPHA - default=false)
DynamicResourceAllocation=true|false (ALPHA - default=false)
ElasticIndexedJob=true|false (BETA - default=true)
EventedPLEG=true|false (ALPHA - default=false)
GracefulNodeShutdown=true|false (BETA - default=true)
GracefulNodeShutdownBasedOnPodPriority=true|false (BETA - default=true)
HPAScaleToZero=true|false (ALPHA - default=false)
HonorPVReclaimPolicy=true|false (ALPHA - default=false)
ImageMaximumGCAge=true|false (BETA - default=true)
InPlacePodVerticalScaling=true|false (ALPHA - default=false)
InTreePluginAWSUnregister=true|false (ALPHA - default=false)
InTreePluginAzureDiskUnregister=true|false (ALPHA - default=false)
InTreePluginAzureFileUnregister=true|false (ALPHA - default=false)
InTreePluginGCEUnregister=true|false (ALPHA - default=false)
InTreePluginOpenStackUnregister=true|false (ALPHA - default=false)
InTreePluginPortworxUnregister=true|false (ALPHA - default=false)
InTreePluginvSphereUnregister=true|false (ALPHA - default=false)
InformerResourceVersion=true|false (ALPHA - default=false)
JobBackoffLimitPerIndex=true|false (BETA - default=true)
JobManagedBy=true|false (ALPHA - default=false)
JobPodFailurePolicy=true|false (BETA - default=true)
JobPodReplacementPolicy=true|false (BETA - default=true)
JobSuccessPolicy=true|false (ALPHA - default=false)
KubeProxyDrainingTerminatingNodes=true|false (BETA - default=true)
KubeletCgroupDriverFromCRI=true|false (ALPHA - default=false)
KubeletInUserNamespace=true|false (ALPHA - default=false)
KubeletPodResourcesDynamicResources=true|false (ALPHA - default=false)
KubeletPodResourcesGet=true|false (ALPHA - default=false)
KubeletSeparateDiskGC=true|false (ALPHA - default=false)
KubeletTracing=true|false (BETA - default=true)
LoadBalancerIPMode=true|false (BETA - default=true)
LocalStorageCapacityIsolationFSQuotaMonitoring=true|false (ALPHA - default=false)
LogarithmicScaleDown=true|false (BETA - default=true)
LoggingAlphaOptions=true|false (ALPHA - default=false)
LoggingBetaOptions=true|false (BETA - default=true)
MatchLabelKeysInPodAffinity=true|false (ALPHA - default=false)
MatchLabelKeysInPodTopologySpread=true|false (BETA - default=true)
MaxUnavailableStatefulSet=true|false (ALPHA - default=false)
MemoryManager=true|false (BETA - default=true)
MemoryQoS=true|false (ALPHA - default=false)
MultiCIDRServiceAllocator=true|false (ALPHA - default=false)
MutatingAdmissionPolicy=true|false (ALPHA - default=false)
NFTablesProxyMode=true|false (ALPHA - default=false)
NodeInclusionPolicyInPodTopologySpread=true|false (BETA - default=true)
NodeLogQuery=true|false (BETA - default=false)
NodeSwap=true|false (BETA - default=true)
OpenAPIEnums=true|false (BETA - default=true)
PDBUnhealthyPodEvictionPolicy=true|false (BETA - default=true)
PersistentVolumeLastPhaseTransitionTime=true|false (BETA - default=true)
PodAndContainerStatsFromCRI=true|false (ALPHA - default=false)
PodDeletionCost=true|false (BETA - default=true)
PodDisruptionConditions=true|false (BETA - default=true)
PodIndexLabel=true|false (BETA - default=true)
PodLifecycleSleepAction=true|false (BETA - default=true)
PodReadyToStartContainersCondition=true|false (BETA - default=true)
PortForwardWebsockets=true|false (ALPHA - default=false)
ProcMountType=true|false (ALPHA - default=false)
QOSReserved=true|false (ALPHA - default=false)
RecoverVolumeExpansionFailure=true|false (ALPHA - default=false)
RecursiveReadOnlyMounts=true|false (ALPHA - default=false)
RelaxedEnvironmentVariableValidation=true|false (ALPHA - default=false)
RetryGenerateName=true|false (ALPHA - default=false)
RotateKubeletServerCertificate=true|false (BETA - default=true)
RuntimeClassInImageCriApi=true|false (ALPHA - default=false)
SELinuxMount=true|false (ALPHA - default=false)
SELinuxMountReadWriteOncePod=true|false (BETA - default=true)
SchedulerQueueingHints=true|false (BETA - default=false)
SeparateCacheWatchRPC=true|false (BETA - default=true)
SeparateTaintEvictionController=true|false (BETA - default=true)
ServiceAccountTokenJTI=true|false (BETA - default=true)
ServiceAccountTokenNodeBinding=true|false (ALPHA - default=false)
ServiceAccountTokenNodeBindingValidation=true|false (BETA - default=true)
ServiceAccountTokenPodNodeInfo=true|false (BETA - default=true)
ServiceTrafficDistribution=true|false (ALPHA - default=false)
SidecarContainers=true|false (BETA - default=true)
SizeMemoryBackedVolumes=true|false (BETA - default=true)
StatefulSetAutoDeletePVC=true|false (BETA - default=true)
StatefulSetStartOrdinal=true|false (BETA - default=true)
StorageNamespaceIndex=true|false (BETA - default=true)
StorageVersionAPI=true|false (ALPHA - default=false)
StorageVersionHash=true|false (BETA - default=true)
StorageVersionMigrator=true|false (ALPHA - default=false)
StructuredAuthenticationConfiguration=true|false (BETA - default=true)
StructuredAuthorizationConfiguration=true|false (BETA - default=true)
TopologyAwareHints=true|false (BETA - default=true)
TopologyManagerPolicyAlphaOptions=true|false (ALPHA - default=false)
TopologyManagerPolicyBetaOptions=true|false (BETA - default=true)
TopologyManagerPolicyOptions=true|false (BETA - default=true)
TranslateStreamCloseWebsocketRequests=true|false (BETA - default=true)
UnauthenticatedHTTP2DOSMitigation=true|false (BETA - default=true)
UnknownVersionInteroperabilityProxy=true|false (ALPHA - default=false)
UserNamespacesPodSecurityStandards=true|false (ALPHA - default=false)
UserNamespacesSupport=true|false (BETA - default=false)
VolumeAttributesClass=true|false (ALPHA - default=false)
VolumeCapacityPriority=true|false (ALPHA - default=false)
WatchFromStorageWithoutResourceVersion=true|false (BETA - default=false)
WatchList=true|false (ALPHA - default=false)
WatchListClient=true|false (BETA - default=false)
WinDSR=true|false (ALPHA - default=false)
WinOverlay=true|false (BETA - default=true)
WindowsHostNetwork=true|false (ALPHA - default=true)

@@ -645,6 +645,20 @@ kube-controller-manager [flags]

Maximum number of seconds between log flushes

+ +--log-text-info-buffer-size quantity + + +

[Alpha] In text format with split output streams, the info messages can be buffered for a while to increase performance. The default value of zero bytes disables buffering. The size can be specified as number of bytes (512), multiples of 1000 (1K), multiples of 1024 (2Ki), or powers of those (3M, 4G, 5Mi, 6Gi). Enable the LoggingAlphaOptions feature gate to use this.

+ + + +--log-text-split-stream + + +

[Alpha] In text format, write error messages to stderr and info messages to stdout. The default is to write a single stream to stdout. Enable the LoggingAlphaOptions feature gate to use this.

+ + --logging-format string     Default: "text" @@ -929,7 +943,7 @@ kube-controller-manager [flags] --tls-cipher-suites strings -

Comma-separated list of cipher suites for the server. If omitted, the default Go cipher suites will be used.
Preferred values: TLS_AES_128_GCM_SHA256, TLS_AES_256_GCM_SHA384, TLS_CHACHA20_POLY1305_SHA256, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305, TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305, TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_RSA_WITH_AES_128_GCM_SHA256, TLS_RSA_WITH_AES_256_CBC_SHA, TLS_RSA_WITH_AES_256_GCM_SHA384.
Insecure values: TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, TLS_ECDHE_RSA_WITH_RC4_128_SHA, TLS_RSA_WITH_3DES_EDE_CBC_SHA, TLS_RSA_WITH_AES_128_CBC_SHA256, TLS_RSA_WITH_RC4_128_SHA.

+

Comma-separated list of cipher suites for the server. If omitted, the default Go cipher suites will be used.
Preferred values: TLS_AES_128_GCM_SHA256, TLS_AES_256_GCM_SHA384, TLS_CHACHA20_POLY1305_SHA256, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305, TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305, TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256.
Insecure values: TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, TLS_ECDHE_RSA_WITH_RC4_128_SHA, TLS_RSA_WITH_3DES_EDE_CBC_SHA, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_RSA_WITH_AES_128_CBC_SHA256, TLS_RSA_WITH_AES_128_GCM_SHA256, TLS_RSA_WITH_AES_256_CBC_SHA, TLS_RSA_WITH_AES_256_GCM_SHA384, TLS_RSA_WITH_RC4_128_SHA.

diff --git a/content/en/docs/reference/command-line-tools-reference/kube-proxy.md b/content/en/docs/reference/command-line-tools-reference/kube-proxy.md index f5c0ac0de049f..bf8811fe32abb 100644 --- a/content/en/docs/reference/command-line-tools-reference/kube-proxy.md +++ b/content/en/docs/reference/command-line-tools-reference/kube-proxy.md @@ -35,7 +35,7 @@ kube-proxy [flags] ## {{% heading "options" %}} - +
@@ -46,448 +46,448 @@ kube-proxy [flags] - + - + - + - - - - - - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + + + + + + + + + + + + + + - + - + - + - + - + - - - - - - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + diff --git a/content/en/docs/reference/command-line-tools-reference/kube-scheduler.md b/content/en/docs/reference/command-line-tools-reference/kube-scheduler.md index 13c6014ee4313..93de3487482e5 100644 --- a/content/en/docs/reference/command-line-tools-reference/kube-scheduler.md +++ b/content/en/docs/reference/command-line-tools-reference/kube-scheduler.md @@ -113,13 +113,6 @@ kube-scheduler [flags] - - - - - - - @@ -166,7 +159,7 @@ kube-scheduler [flags] - + @@ -267,6 +260,20 @@ kube-scheduler [flags] + + + + + + + + + + + + + + @@ -299,7 +306,7 @@ kube-scheduler [flags] - + @@ -369,7 +376,7 @@ kube-scheduler [flags] - + diff --git a/content/en/docs/reference/command-line-tools-reference/kubelet.md b/content/en/docs/reference/command-line-tools-reference/kubelet.md index ff53fc63b2fb4..e5ece46bbd0ae 100644 --- a/content/en/docs/reference/command-line-tools-reference/kubelet.md +++ b/content/en/docs/reference/command-line-tools-reference/kubelet.md @@ -416,7 +416,7 @@ KubeletPodResourcesGet=true|false (ALPHA - default=false)
KubeletSeparateDiskGC=true|false (ALPHA - default=false)
KubeletTracing=true|false (BETA - default=true)
LegacyServiceAccountTokenCleanUp=true|false (BETA - default=true)
-LoadBalancerIPMode=true|false (ALPHA - default=false)
+LoadBalancerIPMode=true|false (BETA - default=true)
LocalStorageCapacityIsolationFSQuotaMonitoring=true|false (ALPHA - default=false)
LogarithmicScaleDown=true|false (BETA - default=true)
LoggingAlphaOptions=true|false (ALPHA - default=false)
diff --git a/content/en/docs/reference/config-api/apiserver-admission.v1.md b/content/en/docs/reference/config-api/apiserver-admission.v1.md index 3deb8521b783b..62e8c0f62d724 100644 --- a/content/en/docs/reference/config-api/apiserver-admission.v1.md +++ b/content/en/docs/reference/config-api/apiserver-admission.v1.md @@ -152,7 +152,7 @@ requested. e.g. a patch can result in either a CREATE or UPDATE Operation.

@@ -223,7 +223,7 @@ categories are logged.

diff --git a/content/en/docs/reference/config-api/apiserver-config.v1.md b/content/en/docs/reference/config-api/apiserver-config.v1.md index c133724ec70bd..f9fab1f3fd108 100644 --- a/content/en/docs/reference/config-api/apiserver-config.v1.md +++ b/content/en/docs/reference/config-api/apiserver-config.v1.md @@ -11,6 +11,7 @@ auto_generated: true - [AdmissionConfiguration](#apiserver-config-k8s-io-v1-AdmissionConfiguration) +- [EncryptionConfiguration](#apiserver-config-k8s-io-v1-EncryptionConfiguration) ## `AdmissionConfiguration` {#apiserver-config-k8s-io-v1-AdmissionConfiguration} @@ -38,6 +39,96 @@ auto_generated: true
--add_dir_header

If true, adds the file directory to the header of the log messages

If true, adds the file directory to the header of the log messages

--alsologtostderr

log to standard error as well as files (no effect when -logtostderr=true)

log to standard error as well as files (no effect when -logtostderr=true)

--bind-address string     Default: 0.0.0.0

Overrides kube-proxy's idea of what its node's primary IP is. Note that the name is a historical artifact, and kube-proxy does not actually bind any sockets to this IP. This parameter is ignored if a config file is specified by --config.

Overrides kube-proxy's idea of what its node's primary IP is. Note that the name is a historical artifact, and kube-proxy does not actually bind any sockets to this IP. This parameter is ignored if a config file is specified by --config.

--bind-address-hard-fail

If true kube-proxy will treat failure to bind to a port as fatal and exit

--boot_id_file string     Default: "/proc/sys/kernel/random/boot_id"

Comma-separated list of files to check for boot-id. Use the first one that exists.

If true kube-proxy will treat failure to bind to a port as fatal and exit

--cleanup

If true cleanup iptables and ipvs rules and exit.

If true cleanup iptables and ipvs rules and exit.

--cluster-cidr string

The CIDR range of the pods in the cluster. (For dual-stack clusters, this can be a comma-separated dual-stack pair of CIDR ranges.). When --detect-local-mode is set to ClusterCIDR, kube-proxy will consider traffic to be local if its source IP is in this range. (Otherwise it is not used.) This parameter is ignored if a config file is specified by --config.

The CIDR range of the pods in the cluster. (For dual-stack clusters, this can be a comma-separated dual-stack pair of CIDR ranges.). When --detect-local-mode is set to ClusterCIDR, kube-proxy will consider traffic to be local if its source IP is in this range. (Otherwise it is not used.) This parameter is ignored if a config file is specified by --config.

--config string

The path to the configuration file.

The path to the configuration file.

--config-sync-period duration     Default: 15m0s

How often configuration from the apiserver is refreshed. Must be greater than 0.

How often configuration from the apiserver is refreshed. Must be greater than 0.

--conntrack-max-per-core int32     Default: 32768

Maximum number of NAT connections to track per CPU core (0 to leave the limit as-is and ignore conntrack-min).

Maximum number of NAT connections to track per CPU core (0 to leave the limit as-is and ignore conntrack-min).

--conntrack-min int32     Default: 131072

Minimum number of conntrack entries to allocate, regardless of conntrack-max-per-core (set conntrack-max-per-core=0 to leave the limit as-is).

Minimum number of conntrack entries to allocate, regardless of conntrack-max-per-core (set conntrack-max-per-core=0 to leave the limit as-is).

--conntrack-tcp-be-liberal

Enable liberal mode for tracking TCP packets by setting nf_conntrack_tcp_be_liberal to 1

Enable liberal mode for tracking TCP packets by setting nf_conntrack_tcp_be_liberal to 1

--conntrack-tcp-timeout-close-wait duration     Default: 1h0m0s

NAT timeout for TCP connections in the CLOSE_WAIT state

NAT timeout for TCP connections in the CLOSE_WAIT state

--conntrack-tcp-timeout-established duration     Default: 24h0m0s

Idle timeout for established TCP connections (0 to leave as-is)

Idle timeout for established TCP connections (0 to leave as-is)

--conntrack-udp-timeout duration

Idle timeout for UNREPLIED UDP connections (0 to leave as-is)

Idle timeout for UNREPLIED UDP connections (0 to leave as-is)

--conntrack-udp-timeout-stream duration

Idle timeout for ASSURED UDP connections (0 to leave as-is)

Idle timeout for ASSURED UDP connections (0 to leave as-is)

--detect-local-mode LocalMode

Mode to use to detect local traffic. This parameter is ignored if a config file is specified by --config.

Mode to use to detect local traffic. This parameter is ignored if a config file is specified by --config.

--feature-gates <comma-separated 'key=True|False' pairs>

A set of key=value pairs that describe feature gates for alpha/experimental features. Options are:
APIResponseCompression=true|false (BETA - default=true)
APIServerIdentity=true|false (BETA - default=true)
APIServerTracing=true|false (BETA - default=true)
AdmissionWebhookMatchConditions=true|false (BETA - default=true)
AggregatedDiscoveryEndpoint=true|false (BETA - default=true)
AllAlpha=true|false (ALPHA - default=false)
AllBeta=true|false (BETA - default=false)
AnyVolumeDataSource=true|false (BETA - default=true)
AppArmor=true|false (BETA - default=true)
CPUManagerPolicyAlphaOptions=true|false (ALPHA - default=false)
CPUManagerPolicyBetaOptions=true|false (BETA - default=true)
CPUManagerPolicyOptions=true|false (BETA - default=true)
CRDValidationRatcheting=true|false (ALPHA - default=false)
CSIMigrationPortworx=true|false (BETA - default=false)
CSIVolumeHealth=true|false (ALPHA - default=false)
CloudControllerManagerWebhook=true|false (ALPHA - default=false)
CloudDualStackNodeIPs=true|false (BETA - default=true)
ClusterTrustBundle=true|false (ALPHA - default=false)
ClusterTrustBundleProjection=true|false (ALPHA - default=false)
ComponentSLIs=true|false (BETA - default=true)
ConsistentListFromCache=true|false (ALPHA - default=false)
ContainerCheckpoint=true|false (ALPHA - default=false)
ContextualLogging=true|false (ALPHA - default=false)
CronJobsScheduledAnnotation=true|false (BETA - default=true)
CrossNamespaceVolumeDataSource=true|false (ALPHA - default=false)
CustomCPUCFSQuotaPeriod=true|false (ALPHA - default=false)
DevicePluginCDIDevices=true|false (BETA - default=true)
DisableCloudProviders=true|false (BETA - default=true)
DisableKubeletCloudCredentialProviders=true|false (BETA - default=true)
DisableNodeKubeProxyVersion=true|false (ALPHA - default=false)
DynamicResourceAllocation=true|false (ALPHA - default=false)
ElasticIndexedJob=true|false (BETA - default=true)
EventedPLEG=true|false (BETA - default=false)
GracefulNodeShutdown=true|false (BETA - default=true)
GracefulNodeShutdownBasedOnPodPriority=true|false (BETA - default=true)
HPAContainerMetrics=true|false (BETA - default=true)
HPAScaleToZero=true|false (ALPHA - default=false)
HonorPVReclaimPolicy=true|false (ALPHA - default=false)
ImageMaximumGCAge=true|false (ALPHA - default=false)
InPlacePodVerticalScaling=true|false (ALPHA - default=false)
InTreePluginAWSUnregister=true|false (ALPHA - default=false)
InTreePluginAzureDiskUnregister=true|false (ALPHA - default=false)
InTreePluginAzureFileUnregister=true|false (ALPHA - default=false)
InTreePluginGCEUnregister=true|false (ALPHA - default=false)
InTreePluginOpenStackUnregister=true|false (ALPHA - default=false)
InTreePluginPortworxUnregister=true|false (ALPHA - default=false)
InTreePluginvSphereUnregister=true|false (ALPHA - default=false)
JobBackoffLimitPerIndex=true|false (BETA - default=true)
JobPodFailurePolicy=true|false (BETA - default=true)
JobPodReplacementPolicy=true|false (BETA - default=true)
KubeProxyDrainingTerminatingNodes=true|false (ALPHA - default=false)
KubeletCgroupDriverFromCRI=true|false (ALPHA - default=false)
KubeletInUserNamespace=true|false (ALPHA - default=false)
KubeletPodResourcesDynamicResources=true|false (ALPHA - default=false)
KubeletPodResourcesGet=true|false (ALPHA - default=false)
KubeletSeparateDiskGC=true|false (ALPHA - default=false)
KubeletTracing=true|false (BETA - default=true)
LegacyServiceAccountTokenCleanUp=true|false (BETA - default=true)
LoadBalancerIPMode=true|false (ALPHA - default=false)
LocalStorageCapacityIsolationFSQuotaMonitoring=true|false (ALPHA - default=false)
LogarithmicScaleDown=true|false (BETA - default=true)
LoggingAlphaOptions=true|false (ALPHA - default=false)
LoggingBetaOptions=true|false (BETA - default=true)
MatchLabelKeysInPodAffinity=true|false (ALPHA - default=false)
MatchLabelKeysInPodTopologySpread=true|false (BETA - default=true)
MaxUnavailableStatefulSet=true|false (ALPHA - default=false)
MemoryManager=true|false (BETA - default=true)
MemoryQoS=true|false (ALPHA - default=false)
MinDomainsInPodTopologySpread=true|false (BETA - default=true)
MultiCIDRServiceAllocator=true|false (ALPHA - default=false)
NFTablesProxyMode=true|false (ALPHA - default=false)
NewVolumeManagerReconstruction=true|false (BETA - default=true)
NodeInclusionPolicyInPodTopologySpread=true|false (BETA - default=true)
NodeLogQuery=true|false (ALPHA - default=false)
NodeSwap=true|false (BETA - default=false)
OpenAPIEnums=true|false (BETA - default=true)
PDBUnhealthyPodEvictionPolicy=true|false (BETA - default=true)
PersistentVolumeLastPhaseTransitionTime=true|false (BETA - default=true)
PodAndContainerStatsFromCRI=true|false (ALPHA - default=false)
PodDeletionCost=true|false (BETA - default=true)
PodDisruptionConditions=true|false (BETA - default=true)
PodHostIPs=true|false (BETA - default=true)
PodIndexLabel=true|false (BETA - default=true)
PodLifecycleSleepAction=true|false (ALPHA - default=false)
PodReadyToStartContainersCondition=true|false (BETA - default=true)
PodSchedulingReadiness=true|false (BETA - default=true)
ProcMountType=true|false (ALPHA - default=false)
QOSReserved=true|false (ALPHA - default=false)
RecoverVolumeExpansionFailure=true|false (ALPHA - default=false)
RotateKubeletServerCertificate=true|false (BETA - default=true)
RuntimeClassInImageCriApi=true|false (ALPHA - default=false)
SELinuxMountReadWriteOncePod=true|false (BETA - default=true)
SchedulerQueueingHints=true|false (BETA - default=false)
SecurityContextDeny=true|false (ALPHA - default=false)
SeparateTaintEvictionController=true|false (BETA - default=true)
ServiceAccountTokenJTI=true|false (ALPHA - default=false)
ServiceAccountTokenNodeBinding=true|false (ALPHA - default=false)
ServiceAccountTokenNodeBindingValidation=true|false (ALPHA - default=false)
ServiceAccountTokenPodNodeInfo=true|false (ALPHA - default=false)
SidecarContainers=true|false (BETA - default=true)
SizeMemoryBackedVolumes=true|false (BETA - default=true)
StableLoadBalancerNodeSet=true|false (BETA - default=true)
StatefulSetAutoDeletePVC=true|false (BETA - default=true)
StatefulSetStartOrdinal=true|false (BETA - default=true)
StorageVersionAPI=true|false (ALPHA - default=false)
StorageVersionHash=true|false (BETA - default=true)
StructuredAuthenticationConfiguration=true|false (ALPHA - default=false)
StructuredAuthorizationConfiguration=true|false (ALPHA - default=false)
TopologyAwareHints=true|false (BETA - default=true)
TopologyManagerPolicyAlphaOptions=true|false (ALPHA - default=false)
TopologyManagerPolicyBetaOptions=true|false (BETA - default=true)
TopologyManagerPolicyOptions=true|false (BETA - default=true)
TranslateStreamCloseWebsocketRequests=true|false (ALPHA - default=false)
UnauthenticatedHTTP2DOSMitigation=true|false (BETA - default=true)
UnknownVersionInteroperabilityProxy=true|false (ALPHA - default=false)
UserNamespacesPodSecurityStandards=true|false (ALPHA - default=false)
UserNamespacesSupport=true|false (ALPHA - default=false)
ValidatingAdmissionPolicy=true|false (BETA - default=false)
VolumeAttributesClass=true|false (ALPHA - default=false)
VolumeCapacityPriority=true|false (ALPHA - default=false)
WatchList=true|false (ALPHA - default=false)
WinDSR=true|false (ALPHA - default=false)
WinOverlay=true|false (BETA - default=true)
WindowsHostNetwork=true|false (ALPHA - default=true)
ZeroLimitedNominalConcurrencyShares=true|false (BETA - default=false)
This parameter is ignored if a config file is specified by --config.

A set of key=value pairs that describe feature gates for alpha/experimental features. Options are:
APIResponseCompression=true|false (BETA - default=true)
APIServerIdentity=true|false (BETA - default=true)
APIServerTracing=true|false (BETA - default=true)
APIServingWithRoutine=true|false (BETA - default=true)
AllAlpha=true|false (ALPHA - default=false)
AllBeta=true|false (BETA - default=false)
AnyVolumeDataSource=true|false (BETA - default=true)
AppArmor=true|false (BETA - default=true)
AppArmorFields=true|false (BETA - default=true)
CPUManagerPolicyAlphaOptions=true|false (ALPHA - default=false)
CPUManagerPolicyBetaOptions=true|false (BETA - default=true)
CPUManagerPolicyOptions=true|false (BETA - default=true)
CRDValidationRatcheting=true|false (BETA - default=true)
CSIMigrationPortworx=true|false (BETA - default=false)
CSIVolumeHealth=true|false (ALPHA - default=false)
CloudControllerManagerWebhook=true|false (ALPHA - default=false)
ClusterTrustBundle=true|false (ALPHA - default=false)
ClusterTrustBundleProjection=true|false (ALPHA - default=false)
ComponentSLIs=true|false (BETA - default=true)
ConsistentListFromCache=true|false (ALPHA - default=false)
ContainerCheckpoint=true|false (BETA - default=true)
ContextualLogging=true|false (BETA - default=true)
CronJobsScheduledAnnotation=true|false (BETA - default=true)
CrossNamespaceVolumeDataSource=true|false (ALPHA - default=false)
CustomCPUCFSQuotaPeriod=true|false (ALPHA - default=false)
CustomResourceFieldSelectors=true|false (ALPHA - default=false)
DevicePluginCDIDevices=true|false (BETA - default=true)
DisableCloudProviders=true|false (BETA - default=true)
DisableKubeletCloudCredentialProviders=true|false (BETA - default=true)
DisableNodeKubeProxyVersion=true|false (ALPHA - default=false)
DynamicResourceAllocation=true|false (ALPHA - default=false)
ElasticIndexedJob=true|false (BETA - default=true)
EventedPLEG=true|false (ALPHA - default=false)
GracefulNodeShutdown=true|false (BETA - default=true)
GracefulNodeShutdownBasedOnPodPriority=true|false (BETA - default=true)
HPAScaleToZero=true|false (ALPHA - default=false)
HonorPVReclaimPolicy=true|false (ALPHA - default=false)
ImageMaximumGCAge=true|false (BETA - default=true)
InPlacePodVerticalScaling=true|false (ALPHA - default=false)
InTreePluginAWSUnregister=true|false (ALPHA - default=false)
InTreePluginAzureDiskUnregister=true|false (ALPHA - default=false)
InTreePluginAzureFileUnregister=true|false (ALPHA - default=false)
InTreePluginGCEUnregister=true|false (ALPHA - default=false)
InTreePluginOpenStackUnregister=true|false (ALPHA - default=false)
InTreePluginPortworxUnregister=true|false (ALPHA - default=false)
InTreePluginvSphereUnregister=true|false (ALPHA - default=false)
InformerResourceVersion=true|false (ALPHA - default=false)
JobBackoffLimitPerIndex=true|false (BETA - default=true)
JobManagedBy=true|false (ALPHA - default=false)
JobPodFailurePolicy=true|false (BETA - default=true)
JobPodReplacementPolicy=true|false (BETA - default=true)
JobSuccessPolicy=true|false (ALPHA - default=false)
KubeProxyDrainingTerminatingNodes=true|false (BETA - default=true)
KubeletCgroupDriverFromCRI=true|false (ALPHA - default=false)
KubeletInUserNamespace=true|false (ALPHA - default=false)
KubeletPodResourcesDynamicResources=true|false (ALPHA - default=false)
KubeletPodResourcesGet=true|false (ALPHA - default=false)
KubeletSeparateDiskGC=true|false (ALPHA - default=false)
KubeletTracing=true|false (BETA - default=true)
LoadBalancerIPMode=true|false (BETA - default=true)
LocalStorageCapacityIsolationFSQuotaMonitoring=true|false (ALPHA - default=false)
LogarithmicScaleDown=true|false (BETA - default=true)
LoggingAlphaOptions=true|false (ALPHA - default=false)
LoggingBetaOptions=true|false (BETA - default=true)
MatchLabelKeysInPodAffinity=true|false (ALPHA - default=false)
MatchLabelKeysInPodTopologySpread=true|false (BETA - default=true)
MaxUnavailableStatefulSet=true|false (ALPHA - default=false)
MemoryManager=true|false (BETA - default=true)
MemoryQoS=true|false (ALPHA - default=false)
MultiCIDRServiceAllocator=true|false (ALPHA - default=false)
MutatingAdmissionPolicy=true|false (ALPHA - default=false)
NFTablesProxyMode=true|false (ALPHA - default=false)
NodeInclusionPolicyInPodTopologySpread=true|false (BETA - default=true)
NodeLogQuery=true|false (BETA - default=false)
NodeSwap=true|false (BETA - default=true)
OpenAPIEnums=true|false (BETA - default=true)
PDBUnhealthyPodEvictionPolicy=true|false (BETA - default=true)
PersistentVolumeLastPhaseTransitionTime=true|false (BETA - default=true)
PodAndContainerStatsFromCRI=true|false (ALPHA - default=false)
PodDeletionCost=true|false (BETA - default=true)
PodDisruptionConditions=true|false (BETA - default=true)
PodIndexLabel=true|false (BETA - default=true)
PodLifecycleSleepAction=true|false (BETA - default=true)
PodReadyToStartContainersCondition=true|false (BETA - default=true)
PortForwardWebsockets=true|false (ALPHA - default=false)
ProcMountType=true|false (ALPHA - default=false)
QOSReserved=true|false (ALPHA - default=false)
RecoverVolumeExpansionFailure=true|false (ALPHA - default=false)
RecursiveReadOnlyMounts=true|false (ALPHA - default=false)
RelaxedEnvironmentVariableValidation=true|false (ALPHA - default=false)
RetryGenerateName=true|false (ALPHA - default=false)
RotateKubeletServerCertificate=true|false (BETA - default=true)
RuntimeClassInImageCriApi=true|false (ALPHA - default=false)
SELinuxMount=true|false (ALPHA - default=false)
SELinuxMountReadWriteOncePod=true|false (BETA - default=true)
SchedulerQueueingHints=true|false (BETA - default=false)
SeparateCacheWatchRPC=true|false (BETA - default=true)
SeparateTaintEvictionController=true|false (BETA - default=true)
ServiceAccountTokenJTI=true|false (BETA - default=true)
ServiceAccountTokenNodeBinding=true|false (ALPHA - default=false)
ServiceAccountTokenNodeBindingValidation=true|false (BETA - default=true)
ServiceAccountTokenPodNodeInfo=true|false (BETA - default=true)
ServiceTrafficDistribution=true|false (ALPHA - default=false)
SidecarContainers=true|false (BETA - default=true)
SizeMemoryBackedVolumes=true|false (BETA - default=true)
StatefulSetAutoDeletePVC=true|false (BETA - default=true)
StatefulSetStartOrdinal=true|false (BETA - default=true)
StorageNamespaceIndex=true|false (BETA - default=true)
StorageVersionAPI=true|false (ALPHA - default=false)
StorageVersionHash=true|false (BETA - default=true)
StorageVersionMigrator=true|false (ALPHA - default=false)
StructuredAuthenticationConfiguration=true|false (BETA - default=true)
StructuredAuthorizationConfiguration=true|false (BETA - default=true)
TopologyAwareHints=true|false (BETA - default=true)
TopologyManagerPolicyAlphaOptions=true|false (ALPHA - default=false)
TopologyManagerPolicyBetaOptions=true|false (BETA - default=true)
TopologyManagerPolicyOptions=true|false (BETA - default=true)
TranslateStreamCloseWebsocketRequests=true|false (BETA - default=true)
UnauthenticatedHTTP2DOSMitigation=true|false (BETA - default=true)
UnknownVersionInteroperabilityProxy=true|false (ALPHA - default=false)
UserNamespacesPodSecurityStandards=true|false (ALPHA - default=false)
UserNamespacesSupport=true|false (BETA - default=false)
VolumeAttributesClass=true|false (ALPHA - default=false)
VolumeCapacityPriority=true|false (ALPHA - default=false)
WatchFromStorageWithoutResourceVersion=true|false (BETA - default=false)
WatchList=true|false (ALPHA - default=false)
WatchListClient=true|false (BETA - default=false)
WinDSR=true|false (ALPHA - default=false)
WinOverlay=true|false (BETA - default=true)
WindowsHostNetwork=true|false (ALPHA - default=true)
This parameter is ignored if a config file is specified by --config.

--healthz-bind-address ipport     Default: 0.0.0.0:10256

The IP address and port for the health check server to serve on, defaulting to "0.0.0.0:10256" (if --bind-address is unset or IPv4), or "[::]:10256" (if --bind-address is IPv6). Set empty to disable. This parameter is ignored if a config file is specified by --config.

The IP address and port for the health check server to serve on, defaulting to "0.0.0.0:10256" (if --bind-address is unset or IPv4), or "[::]:10256" (if --bind-address is IPv6). Set empty to disable. This parameter is ignored if a config file is specified by --config.

-h, --help

help for kube-proxy

help for kube-proxy

--hostname-override string

If non-empty, will be used as the name of the Node that kube-proxy is running on. If unset, the node name is assumed to be the same as the node's hostname.

If non-empty, will be used as the name of the Node that kube-proxy is running on. If unset, the node name is assumed to be the same as the node's hostname.

--init-only

If true, perform any initialization steps that must be done with full root privileges, and then exit. After doing this, you can run kube-proxy again with only the CAP_NET_ADMIN capability.

If true, perform any initialization steps that must be done with full root privileges, and then exit. After doing this, you can run kube-proxy again with only the CAP_NET_ADMIN capability.

--iptables-localhost-nodeports     Default: true

If false, kube-proxy will disable the legacy behavior of allowing NodePort services to be accessed via localhost. (Applies only to iptables mode and IPv4; localhost NodePorts are never allowed with other proxy modes or with IPv6.)

If false, kube-proxy will disable the legacy behavior of allowing NodePort services to be accessed via localhost. (Applies only to iptables mode and IPv4; localhost NodePorts are never allowed with other proxy modes or with IPv6.)

--iptables-masquerade-bit int32     Default: 14

If using the iptables or ipvs proxy mode, the bit of the fwmark space to mark packets requiring SNAT with. Must be within the range [0, 31].

If using the iptables or ipvs proxy mode, the bit of the fwmark space to mark packets requiring SNAT with. Must be within the range [0, 31].

--iptables-min-sync-period duration     Default: 1s

The minimum period between iptables rule resyncs (e.g. '5s', '1m', '2h22m'). A value of 0 means every Service or EndpointSlice change will result in an immediate iptables resync.

The minimum period between iptables rule resyncs (e.g. '5s', '1m', '2h22m'). A value of 0 means every Service or EndpointSlice change will result in an immediate iptables resync.

--iptables-sync-period duration     Default: 30s

An interval (e.g. '5s', '1m', '2h22m') indicating how frequently various re-synchronizing and cleanup operations are performed. Must be greater than 0.

An interval (e.g. '5s', '1m', '2h22m') indicating how frequently various re-synchronizing and cleanup operations are performed. Must be greater than 0.

--ipvs-exclude-cidrs strings

A comma-separated list of CIDRs which the ipvs proxier should not touch when cleaning up IPVS rules.

A comma-separated list of CIDRs which the ipvs proxier should not touch when cleaning up IPVS rules.

--ipvs-min-sync-period duration

The minimum period between IPVS rule resyncs (e.g. '5s', '1m', '2h22m'). A value of 0 means every Service or EndpointSlice change will result in an immediate IPVS resync.

The minimum period between IPVS rule resyncs (e.g. '5s', '1m', '2h22m'). A value of 0 means every Service or EndpointSlice change will result in an immediate IPVS resync.

--ipvs-scheduler string

The ipvs scheduler type when proxy mode is ipvs

The ipvs scheduler type when proxy mode is ipvs

--ipvs-strict-arp

Enable strict ARP by setting arp_ignore to 1 and arp_announce to 2

Enable strict ARP by setting arp_ignore to 1 and arp_announce to 2

--ipvs-sync-period duration     Default: 30s

An interval (e.g. '5s', '1m', '2h22m') indicating how frequently various re-synchronizing and cleanup operations are performed. Must be greater than 0.

An interval (e.g. '5s', '1m', '2h22m') indicating how frequently various re-synchronizing and cleanup operations are performed. Must be greater than 0.

--ipvs-tcp-timeout duration

The timeout for idle IPVS TCP connections, 0 to leave as-is. (e.g. '5s', '1m', '2h22m').

The timeout for idle IPVS TCP connections, 0 to leave as-is. (e.g. '5s', '1m', '2h22m').

--ipvs-tcpfin-timeout duration

The timeout for IPVS TCP connections after receiving a FIN packet, 0 to leave as-is. (e.g. '5s', '1m', '2h22m').

The timeout for IPVS TCP connections after receiving a FIN packet, 0 to leave as-is. (e.g. '5s', '1m', '2h22m').

--ipvs-udp-timeout duration

The timeout for IPVS UDP packets, 0 to leave as-is. (e.g. '5s', '1m', '2h22m').

The timeout for IPVS UDP packets, 0 to leave as-is. (e.g. '5s', '1m', '2h22m').

--kube-api-burst int32     Default: 10

Burst to use while talking with kubernetes apiserver

Burst to use while talking with kubernetes apiserver

--kube-api-content-type string     Default: "application/vnd.kubernetes.protobuf"

Content type of requests sent to apiserver.

Content type of requests sent to apiserver.

--kube-api-qps float     Default: 5

QPS to use while talking with kubernetes apiserver

QPS to use while talking with kubernetes apiserver

--kubeconfig string

Path to kubeconfig file with authorization information (the master location can be overridden by the master flag).

Path to kubeconfig file with authorization information (the master location can be overridden by the master flag).

--log-flush-frequency duration     Default: 5s

Maximum number of seconds between log flushes

Maximum number of seconds between log flushes

--log-text-info-buffer-size quantity

[Alpha] In text format with split output streams, the info messages can be buffered for a while to increase performance. The default value of zero bytes disables buffering. The size can be specified as number of bytes (512), multiples of 1000 (1K), multiples of 1024 (2Ki), or powers of those (3M, 4G, 5Mi, 6Gi). Enable the LoggingAlphaOptions feature gate to use this.

--log-text-split-stream

[Alpha] In text format, write error messages to stderr and info messages to stdout. The default is to write a single stream to stdout. Enable the LoggingAlphaOptions feature gate to use this.

--log_backtrace_at <a string in the form 'file:N'>     Default: :0

when logging hits line file:N, emit a stack trace

when logging hits line file:N, emit a stack trace

--log_dir string

If non-empty, write log files in this directory (no effect when -logtostderr=true)

If non-empty, write log files in this directory (no effect when -logtostderr=true)

--log_file string

If non-empty, use this log file (no effect when -logtostderr=true)

If non-empty, use this log file (no effect when -logtostderr=true)

--log_file_max_size uint     Default: 1800

Defines the maximum size a log file can grow to (no effect when -logtostderr=true). Unit is megabytes. If the value is 0, the maximum file size is unlimited.

Defines the maximum size a log file can grow to (no effect when -logtostderr=true). Unit is megabytes. If the value is 0, the maximum file size is unlimited.

--logging-format string     Default: "text"

Sets the log format. Permitted formats: "text".

Sets the log format. Permitted formats: "text".

--logtostderr     Default: true

log to standard error instead of files

--machine_id_file string     Default: "/etc/machine-id,/var/lib/dbus/machine-id"

Comma-separated list of files to check for machine-id. Use the first one that exists.

log to standard error instead of files

--masquerade-all

If using the iptables or ipvs proxy mode, SNAT all traffic sent via Service cluster IPs. This may be required with some CNI plugins.

If using the iptables or ipvs proxy mode, SNAT all traffic sent via Service cluster IPs. This may be required with some CNI plugins.

--master string

The address of the Kubernetes API server (overrides any value in kubeconfig)

The address of the Kubernetes API server (overrides any value in kubeconfig)

--metrics-bind-address ipport     Default: 127.0.0.1:10249

The IP address and port for the metrics server to serve on, defaulting to "127.0.0.1:10249" (if --bind-address is unset or IPv4), or "[::1]:10249" (if --bind-address is IPv6). (Set to "0.0.0.0:10249" / "[::]:10249" to bind on all interfaces.) Set empty to disable. This parameter is ignored if a config file is specified by --config.

The IP address and port for the metrics server to serve on, defaulting to "127.0.0.1:10249" (if --bind-address is unset or IPv4), or "[::1]:10249" (if --bind-address is IPv6). (Set to "0.0.0.0:10249" / "[::]:10249" to bind on all interfaces.) Set empty to disable. This parameter is ignored if a config file is specified by --config.

--nodeport-addresses strings

A list of CIDR ranges that contain valid node IPs. If set, connections to NodePort services will only be accepted on node IPs in one of the indicated ranges. If unset, NodePort connections will be accepted on all local IPs. This parameter is ignored if a config file is specified by --config.

A list of CIDR ranges that contain valid node IPs. If set, connections to NodePort services will only be accepted on node IPs in one of the indicated ranges. If unset, NodePort connections will be accepted on all local IPs. This parameter is ignored if a config file is specified by --config.

--one_output

If true, only write logs to their native severity level (vs also writing to each lower severity level; no effect when -logtostderr=true)

If true, only write logs to their native severity level (vs also writing to each lower severity level; no effect when -logtostderr=true)

--oom-score-adj int32     Default: -999

The oom-score-adj value for kube-proxy process. Values must be within the range [-1000, 1000]. This parameter is ignored if a config file is specified by --config.

The oom-score-adj value for kube-proxy process. Values must be within the range [-1000, 1000]. This parameter is ignored if a config file is specified by --config.

--pod-bridge-interface string

A bridge interface name. When --detect-local-mode is set to BridgeInterface, kube-proxy will consider traffic to be local if it originates from this bridge.

A bridge interface name. When --detect-local-mode is set to BridgeInterface, kube-proxy will consider traffic to be local if it originates from this bridge.

--pod-interface-name-prefix string

An interface name prefix. When --detect-local-mode is set to InterfaceNamePrefix, kube-proxy will consider traffic to be local if it originates from any interface whose name begins with this prefix.

An interface name prefix. When --detect-local-mode is set to InterfaceNamePrefix, kube-proxy will consider traffic to be local if it originates from any interface whose name begins with this prefix.

--profiling

If true enables profiling via web interface on /debug/pprof handler. This parameter is ignored if a config file is specified by --config.

If true enables profiling via web interface on /debug/pprof handler. This parameter is ignored if a config file is specified by --config.

--proxy-mode ProxyMode

Which proxy mode to use: on Linux this can be 'iptables' (default) or 'ipvs'. On Windows the only supported value is 'kernelspace'.This parameter is ignored if a config file is specified by --config.

Which proxy mode to use: on Linux this can be 'iptables' (default) or 'ipvs'. On Windows the only supported value is 'kernelspace'.This parameter is ignored if a config file is specified by --config.

--show-hidden-metrics-for-version string

The previous version for which you want to show hidden metrics. Only the previous minor version is meaningful, other values will not be allowed. The format is <major>.<minor>, e.g.: '1.16'. The purpose of this format is make sure you have the opportunity to notice if the next release hides additional metrics, rather than being surprised when they are permanently removed in the release after that. This parameter is ignored if a config file is specified by --config.

The previous version for which you want to show hidden metrics. Only the previous minor version is meaningful, other values will not be allowed. The format is <major>.<minor>, e.g.: '1.16'. The purpose of this format is make sure you have the opportunity to notice if the next release hides additional metrics, rather than being surprised when they are permanently removed in the release after that. This parameter is ignored if a config file is specified by --config.

--skip_headers

If true, avoid header prefixes in the log messages

If true, avoid header prefixes in the log messages

--skip_log_headers

If true, avoid headers when opening log files (no effect when -logtostderr=true)

If true, avoid headers when opening log files (no effect when -logtostderr=true)

--stderrthreshold int     Default: 2

logs at or above this threshold go to stderr when writing to files and stderr (no effect when -logtostderr=true or -alsologtostderr=true)

logs at or above this threshold go to stderr when writing to files and stderr (no effect when -logtostderr=true or -alsologtostderr=true)

-v, --v int

number for the log level verbosity

number for the log level verbosity

--version version[=true]

--version, --version=raw prints version information and quits; --version=vX.Y.Z... sets the reported version

--version, --version=raw prints version information and quits; --version=vX.Y.Z... sets the reported version

--vmodule pattern=N,...

comma-separated list of pattern=N settings for file-filtered logging (only works for text log format)

comma-separated list of pattern=N settings for file-filtered logging (only works for text log format)

--write-config-to string

If set, write the default configuration values to this file and exit.

If set, write the default configuration values to this file and exit.

The duration to cache 'unauthorized' responses from the webhook authorizer.

--azure-container-registry-config string

Path to the file containing Azure container registry configuration information.

--bind-address string     Default: 0.0.0.0
--feature-gates <comma-separated 'key=True|False' pairs>

A set of key=value pairs that describe feature gates for alpha/experimental features. Options are:
APIResponseCompression=true|false (BETA - default=true)
APIServerIdentity=true|false (BETA - default=true)
APIServerTracing=true|false (BETA - default=true)
AdmissionWebhookMatchConditions=true|false (BETA - default=true)
AggregatedDiscoveryEndpoint=true|false (BETA - default=true)
AllAlpha=true|false (ALPHA - default=false)
AllBeta=true|false (BETA - default=false)
AnyVolumeDataSource=true|false (BETA - default=true)
AppArmor=true|false (BETA - default=true)
CPUManagerPolicyAlphaOptions=true|false (ALPHA - default=false)
CPUManagerPolicyBetaOptions=true|false (BETA - default=true)
CPUManagerPolicyOptions=true|false (BETA - default=true)
CRDValidationRatcheting=true|false (ALPHA - default=false)
CSIMigrationPortworx=true|false (BETA - default=false)
CSIVolumeHealth=true|false (ALPHA - default=false)
CloudControllerManagerWebhook=true|false (ALPHA - default=false)
CloudDualStackNodeIPs=true|false (BETA - default=true)
ClusterTrustBundle=true|false (ALPHA - default=false)
ClusterTrustBundleProjection=true|false (ALPHA - default=false)
ComponentSLIs=true|false (BETA - default=true)
ConsistentListFromCache=true|false (ALPHA - default=false)
ContainerCheckpoint=true|false (ALPHA - default=false)
ContextualLogging=true|false (ALPHA - default=false)
CronJobsScheduledAnnotation=true|false (BETA - default=true)
CrossNamespaceVolumeDataSource=true|false (ALPHA - default=false)
CustomCPUCFSQuotaPeriod=true|false (ALPHA - default=false)
DevicePluginCDIDevices=true|false (BETA - default=true)
DisableCloudProviders=true|false (BETA - default=true)
DisableKubeletCloudCredentialProviders=true|false (BETA - default=true)
DisableNodeKubeProxyVersion=true|false (ALPHA - default=false)
DynamicResourceAllocation=true|false (ALPHA - default=false)
ElasticIndexedJob=true|false (BETA - default=true)
EventedPLEG=true|false (BETA - default=false)
GracefulNodeShutdown=true|false (BETA - default=true)
GracefulNodeShutdownBasedOnPodPriority=true|false (BETA - default=true)
HPAContainerMetrics=true|false (BETA - default=true)
HPAScaleToZero=true|false (ALPHA - default=false)
HonorPVReclaimPolicy=true|false (ALPHA - default=false)
ImageMaximumGCAge=true|false (ALPHA - default=false)
InPlacePodVerticalScaling=true|false (ALPHA - default=false)
InTreePluginAWSUnregister=true|false (ALPHA - default=false)
InTreePluginAzureDiskUnregister=true|false (ALPHA - default=false)
InTreePluginAzureFileUnregister=true|false (ALPHA - default=false)
InTreePluginGCEUnregister=true|false (ALPHA - default=false)
InTreePluginOpenStackUnregister=true|false (ALPHA - default=false)
InTreePluginPortworxUnregister=true|false (ALPHA - default=false)
InTreePluginvSphereUnregister=true|false (ALPHA - default=false)
JobBackoffLimitPerIndex=true|false (BETA - default=true)
JobPodFailurePolicy=true|false (BETA - default=true)
JobPodReplacementPolicy=true|false (BETA - default=true)
KubeProxyDrainingTerminatingNodes=true|false (ALPHA - default=false)
KubeletCgroupDriverFromCRI=true|false (ALPHA - default=false)
KubeletInUserNamespace=true|false (ALPHA - default=false)
KubeletPodResourcesDynamicResources=true|false (ALPHA - default=false)
KubeletPodResourcesGet=true|false (ALPHA - default=false)
KubeletSeparateDiskGC=true|false (ALPHA - default=false)
KubeletTracing=true|false (BETA - default=true)
LegacyServiceAccountTokenCleanUp=true|false (BETA - default=true)
LoadBalancerIPMode=true|false (ALPHA - default=false)
LocalStorageCapacityIsolationFSQuotaMonitoring=true|false (ALPHA - default=false)
LogarithmicScaleDown=true|false (BETA - default=true)
LoggingAlphaOptions=true|false (ALPHA - default=false)
LoggingBetaOptions=true|false (BETA - default=true)
MatchLabelKeysInPodAffinity=true|false (ALPHA - default=false)
MatchLabelKeysInPodTopologySpread=true|false (BETA - default=true)
MaxUnavailableStatefulSet=true|false (ALPHA - default=false)
MemoryManager=true|false (BETA - default=true)
MemoryQoS=true|false (ALPHA - default=false)
MinDomainsInPodTopologySpread=true|false (BETA - default=true)
MultiCIDRServiceAllocator=true|false (ALPHA - default=false)
NFTablesProxyMode=true|false (ALPHA - default=false)
NewVolumeManagerReconstruction=true|false (BETA - default=true)
NodeInclusionPolicyInPodTopologySpread=true|false (BETA - default=true)
NodeLogQuery=true|false (ALPHA - default=false)
NodeSwap=true|false (BETA - default=false)
OpenAPIEnums=true|false (BETA - default=true)
PDBUnhealthyPodEvictionPolicy=true|false (BETA - default=true)
PersistentVolumeLastPhaseTransitionTime=true|false (BETA - default=true)
PodAndContainerStatsFromCRI=true|false (ALPHA - default=false)
PodDeletionCost=true|false (BETA - default=true)
PodDisruptionConditions=true|false (BETA - default=true)
PodHostIPs=true|false (BETA - default=true)
PodIndexLabel=true|false (BETA - default=true)
PodLifecycleSleepAction=true|false (ALPHA - default=false)
PodReadyToStartContainersCondition=true|false (BETA - default=true)
PodSchedulingReadiness=true|false (BETA - default=true)
ProcMountType=true|false (ALPHA - default=false)
QOSReserved=true|false (ALPHA - default=false)
RecoverVolumeExpansionFailure=true|false (ALPHA - default=false)
RotateKubeletServerCertificate=true|false (BETA - default=true)
RuntimeClassInImageCriApi=true|false (ALPHA - default=false)
SELinuxMountReadWriteOncePod=true|false (BETA - default=true)
SchedulerQueueingHints=true|false (BETA - default=false)
SecurityContextDeny=true|false (ALPHA - default=false)
SeparateTaintEvictionController=true|false (BETA - default=true)
ServiceAccountTokenJTI=true|false (ALPHA - default=false)
ServiceAccountTokenNodeBinding=true|false (ALPHA - default=false)
ServiceAccountTokenNodeBindingValidation=true|false (ALPHA - default=false)
ServiceAccountTokenPodNodeInfo=true|false (ALPHA - default=false)
SidecarContainers=true|false (BETA - default=true)
SizeMemoryBackedVolumes=true|false (BETA - default=true)
StableLoadBalancerNodeSet=true|false (BETA - default=true)
StatefulSetAutoDeletePVC=true|false (BETA - default=true)
StatefulSetStartOrdinal=true|false (BETA - default=true)
StorageVersionAPI=true|false (ALPHA - default=false)
StorageVersionHash=true|false (BETA - default=true)
StructuredAuthenticationConfiguration=true|false (ALPHA - default=false)
StructuredAuthorizationConfiguration=true|false (ALPHA - default=false)
TopologyAwareHints=true|false (BETA - default=true)
TopologyManagerPolicyAlphaOptions=true|false (ALPHA - default=false)
TopologyManagerPolicyBetaOptions=true|false (BETA - default=true)
TopologyManagerPolicyOptions=true|false (BETA - default=true)
TranslateStreamCloseWebsocketRequests=true|false (ALPHA - default=false)
UnauthenticatedHTTP2DOSMitigation=true|false (BETA - default=true)
UnknownVersionInteroperabilityProxy=true|false (ALPHA - default=false)
UserNamespacesPodSecurityStandards=true|false (ALPHA - default=false)
UserNamespacesSupport=true|false (ALPHA - default=false)
ValidatingAdmissionPolicy=true|false (BETA - default=false)
VolumeAttributesClass=true|false (ALPHA - default=false)
VolumeCapacityPriority=true|false (ALPHA - default=false)
WatchList=true|false (ALPHA - default=false)
WinDSR=true|false (ALPHA - default=false)
WinOverlay=true|false (BETA - default=true)
WindowsHostNetwork=true|false (ALPHA - default=true)
ZeroLimitedNominalConcurrencyShares=true|false (BETA - default=false)

A set of key=value pairs that describe feature gates for alpha/experimental features. Options are:
APIResponseCompression=true|false (BETA - default=true)
APIServerIdentity=true|false (BETA - default=true)
APIServerTracing=true|false (BETA - default=true)
APIServingWithRoutine=true|false (BETA - default=true)
AllAlpha=true|false (ALPHA - default=false)
AllBeta=true|false (BETA - default=false)
AnyVolumeDataSource=true|false (BETA - default=true)
AppArmor=true|false (BETA - default=true)
AppArmorFields=true|false (BETA - default=true)
CPUManagerPolicyAlphaOptions=true|false (ALPHA - default=false)
CPUManagerPolicyBetaOptions=true|false (BETA - default=true)
CPUManagerPolicyOptions=true|false (BETA - default=true)
CRDValidationRatcheting=true|false (BETA - default=true)
CSIMigrationPortworx=true|false (BETA - default=false)
CSIVolumeHealth=true|false (ALPHA - default=false)
CloudControllerManagerWebhook=true|false (ALPHA - default=false)
ClusterTrustBundle=true|false (ALPHA - default=false)
ClusterTrustBundleProjection=true|false (ALPHA - default=false)
ComponentSLIs=true|false (BETA - default=true)
ConsistentListFromCache=true|false (ALPHA - default=false)
ContainerCheckpoint=true|false (BETA - default=true)
ContextualLogging=true|false (BETA - default=true)
CronJobsScheduledAnnotation=true|false (BETA - default=true)
CrossNamespaceVolumeDataSource=true|false (ALPHA - default=false)
CustomCPUCFSQuotaPeriod=true|false (ALPHA - default=false)
CustomResourceFieldSelectors=true|false (ALPHA - default=false)
DevicePluginCDIDevices=true|false (BETA - default=true)
DisableCloudProviders=true|false (BETA - default=true)
DisableKubeletCloudCredentialProviders=true|false (BETA - default=true)
DisableNodeKubeProxyVersion=true|false (ALPHA - default=false)
DynamicResourceAllocation=true|false (ALPHA - default=false)
ElasticIndexedJob=true|false (BETA - default=true)
EventedPLEG=true|false (ALPHA - default=false)
GracefulNodeShutdown=true|false (BETA - default=true)
GracefulNodeShutdownBasedOnPodPriority=true|false (BETA - default=true)
HPAScaleToZero=true|false (ALPHA - default=false)
HonorPVReclaimPolicy=true|false (ALPHA - default=false)
ImageMaximumGCAge=true|false (BETA - default=true)
InPlacePodVerticalScaling=true|false (ALPHA - default=false)
InTreePluginAWSUnregister=true|false (ALPHA - default=false)
InTreePluginAzureDiskUnregister=true|false (ALPHA - default=false)
InTreePluginAzureFileUnregister=true|false (ALPHA - default=false)
InTreePluginGCEUnregister=true|false (ALPHA - default=false)
InTreePluginOpenStackUnregister=true|false (ALPHA - default=false)
InTreePluginPortworxUnregister=true|false (ALPHA - default=false)
InTreePluginvSphereUnregister=true|false (ALPHA - default=false)
InformerResourceVersion=true|false (ALPHA - default=false)
JobBackoffLimitPerIndex=true|false (BETA - default=true)
JobManagedBy=true|false (ALPHA - default=false)
JobPodFailurePolicy=true|false (BETA - default=true)
JobPodReplacementPolicy=true|false (BETA - default=true)
JobSuccessPolicy=true|false (ALPHA - default=false)
KubeProxyDrainingTerminatingNodes=true|false (BETA - default=true)
KubeletCgroupDriverFromCRI=true|false (ALPHA - default=false)
KubeletInUserNamespace=true|false (ALPHA - default=false)
KubeletPodResourcesDynamicResources=true|false (ALPHA - default=false)
KubeletPodResourcesGet=true|false (ALPHA - default=false)
KubeletSeparateDiskGC=true|false (ALPHA - default=false)
KubeletTracing=true|false (BETA - default=true)
LoadBalancerIPMode=true|false (BETA - default=true)
LocalStorageCapacityIsolationFSQuotaMonitoring=true|false (ALPHA - default=false)
LogarithmicScaleDown=true|false (BETA - default=true)
LoggingAlphaOptions=true|false (ALPHA - default=false)
LoggingBetaOptions=true|false (BETA - default=true)
MatchLabelKeysInPodAffinity=true|false (ALPHA - default=false)
MatchLabelKeysInPodTopologySpread=true|false (BETA - default=true)
MaxUnavailableStatefulSet=true|false (ALPHA - default=false)
MemoryManager=true|false (BETA - default=true)
MemoryQoS=true|false (ALPHA - default=false)
MultiCIDRServiceAllocator=true|false (ALPHA - default=false)
MutatingAdmissionPolicy=true|false (ALPHA - default=false)
NFTablesProxyMode=true|false (ALPHA - default=false)
NodeInclusionPolicyInPodTopologySpread=true|false (BETA - default=true)
NodeLogQuery=true|false (BETA - default=false)
NodeSwap=true|false (BETA - default=true)
OpenAPIEnums=true|false (BETA - default=true)
PDBUnhealthyPodEvictionPolicy=true|false (BETA - default=true)
PersistentVolumeLastPhaseTransitionTime=true|false (BETA - default=true)
PodAndContainerStatsFromCRI=true|false (ALPHA - default=false)
PodDeletionCost=true|false (BETA - default=true)
PodDisruptionConditions=true|false (BETA - default=true)
PodIndexLabel=true|false (BETA - default=true)
PodLifecycleSleepAction=true|false (BETA - default=true)
PodReadyToStartContainersCondition=true|false (BETA - default=true)
PortForwardWebsockets=true|false (ALPHA - default=false)
ProcMountType=true|false (ALPHA - default=false)
QOSReserved=true|false (ALPHA - default=false)
RecoverVolumeExpansionFailure=true|false (ALPHA - default=false)
RecursiveReadOnlyMounts=true|false (ALPHA - default=false)
RelaxedEnvironmentVariableValidation=true|false (ALPHA - default=false)
RetryGenerateName=true|false (ALPHA - default=false)
RotateKubeletServerCertificate=true|false (BETA - default=true)
RuntimeClassInImageCriApi=true|false (ALPHA - default=false)
SELinuxMount=true|false (ALPHA - default=false)
SELinuxMountReadWriteOncePod=true|false (BETA - default=true)
SchedulerQueueingHints=true|false (BETA - default=false)
SeparateCacheWatchRPC=true|false (BETA - default=true)
SeparateTaintEvictionController=true|false (BETA - default=true)
ServiceAccountTokenJTI=true|false (BETA - default=true)
ServiceAccountTokenNodeBinding=true|false (ALPHA - default=false)
ServiceAccountTokenNodeBindingValidation=true|false (BETA - default=true)
ServiceAccountTokenPodNodeInfo=true|false (BETA - default=true)
ServiceTrafficDistribution=true|false (ALPHA - default=false)
SidecarContainers=true|false (BETA - default=true)
SizeMemoryBackedVolumes=true|false (BETA - default=true)
StatefulSetAutoDeletePVC=true|false (BETA - default=true)
StatefulSetStartOrdinal=true|false (BETA - default=true)
StorageNamespaceIndex=true|false (BETA - default=true)
StorageVersionAPI=true|false (ALPHA - default=false)
StorageVersionHash=true|false (BETA - default=true)
StorageVersionMigrator=true|false (ALPHA - default=false)
StructuredAuthenticationConfiguration=true|false (BETA - default=true)
StructuredAuthorizationConfiguration=true|false (BETA - default=true)
TopologyAwareHints=true|false (BETA - default=true)
TopologyManagerPolicyAlphaOptions=true|false (ALPHA - default=false)
TopologyManagerPolicyBetaOptions=true|false (BETA - default=true)
TopologyManagerPolicyOptions=true|false (BETA - default=true)
TranslateStreamCloseWebsocketRequests=true|false (BETA - default=true)
UnauthenticatedHTTP2DOSMitigation=true|false (BETA - default=true)
UnknownVersionInteroperabilityProxy=true|false (ALPHA - default=false)
UserNamespacesPodSecurityStandards=true|false (ALPHA - default=false)
UserNamespacesSupport=true|false (BETA - default=false)
VolumeAttributesClass=true|false (ALPHA - default=false)
VolumeCapacityPriority=true|false (ALPHA - default=false)
WatchFromStorageWithoutResourceVersion=true|false (BETA - default=false)
WatchList=true|false (ALPHA - default=false)
WatchListClient=true|false (BETA - default=false)
WinDSR=true|false (ALPHA - default=false)
WinOverlay=true|false (BETA - default=true)
WindowsHostNetwork=true|false (ALPHA - default=true)

Maximum number of seconds between log flushes

--log-text-info-buffer-size quantity

[Alpha] In text format with split output streams, the info messages can be buffered for a while to increase performance. The default value of zero bytes disables buffering. The size can be specified as number of bytes (512), multiples of 1000 (1K), multiples of 1024 (2Ki), or powers of those (3M, 4G, 5Mi, 6Gi). Enable the LoggingAlphaOptions feature gate to use this.

--log-text-split-stream

[Alpha] In text format, write error messages to stderr and info messages to stdout. The default is to write a single stream to stdout. Enable the LoggingAlphaOptions feature gate to use this.

--logging-format string     Default: "text"
--pod-max-in-unschedulable-pods-duration duration     Default: 5m0s

DEPRECATED: the maximum time a pod can stay in unschedulablePods. If a pod stays in unschedulablePods for longer than this value, the pod will be moved from unschedulablePods to backoffQ or activeQ. This flag is deprecated and will be removed in 1.26

DEPRECATED: the maximum time a pod can stay in unschedulablePods. If a pod stays in unschedulablePods for longer than this value, the pod will be moved from unschedulablePods to backoffQ or activeQ. This flag is deprecated and will be removed in a future version.

--tls-cipher-suites strings

Comma-separated list of cipher suites for the server. If omitted, the default Go cipher suites will be used.
Preferred values: TLS_AES_128_GCM_SHA256, TLS_AES_256_GCM_SHA384, TLS_CHACHA20_POLY1305_SHA256, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305, TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305, TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_RSA_WITH_AES_128_GCM_SHA256, TLS_RSA_WITH_AES_256_CBC_SHA, TLS_RSA_WITH_AES_256_GCM_SHA384.
Insecure values: TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, TLS_ECDHE_RSA_WITH_RC4_128_SHA, TLS_RSA_WITH_3DES_EDE_CBC_SHA, TLS_RSA_WITH_AES_128_CBC_SHA256, TLS_RSA_WITH_RC4_128_SHA.

Comma-separated list of cipher suites for the server. If omitted, the default Go cipher suites will be used.
Preferred values: TLS_AES_128_GCM_SHA256, TLS_AES_256_GCM_SHA384, TLS_CHACHA20_POLY1305_SHA256, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305, TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305, TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256.
Insecure values: TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, TLS_ECDHE_RSA_WITH_RC4_128_SHA, TLS_RSA_WITH_3DES_EDE_CBC_SHA, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_RSA_WITH_AES_128_CBC_SHA256, TLS_RSA_WITH_AES_128_GCM_SHA256, TLS_RSA_WITH_AES_256_CBC_SHA, TLS_RSA_WITH_AES_256_GCM_SHA384, TLS_RSA_WITH_RC4_128_SHA.

userInfo [Required]
-authentication/v1.UserInfo +authentication/v1.UserInfo

UserInfo is information about the requesting user

@@ -226,7 +226,7 @@ This must be copied over from the corresponding AdmissionRequest.

status
-meta/v1.Status +meta/v1.Status

Result contains extra details into why an admission request was denied. diff --git a/content/en/docs/reference/config-api/apiserver-audit.v1.md b/content/en/docs/reference/config-api/apiserver-audit.v1.md index 7f9314292b94d..ec070999aed5f 100644 --- a/content/en/docs/reference/config-api/apiserver-audit.v1.md +++ b/content/en/docs/reference/config-api/apiserver-audit.v1.md @@ -71,14 +71,14 @@ For non-resource requests, this is the lower-cased HTTP method.

user [Required]
-authentication/v1.UserInfo +authentication/v1.UserInfo

Authenticated user information.

impersonatedUser
-authentication/v1.UserInfo +authentication/v1.UserInfo

Impersonated user information.

@@ -116,7 +116,7 @@ Does not apply for List-type requests, or non-resource requests.

responseStatus
-meta/v1.Status +meta/v1.Status

The response status, populated even when the ResponseObject is not a Status type. @@ -144,14 +144,14 @@ at Response Level.

requestReceivedTimestamp
-meta/v1.MicroTime +meta/v1.MicroTime

Time the request reached the apiserver.

stageTimestamp
-meta/v1.MicroTime +meta/v1.MicroTime

Time the request reached current audit stage.

@@ -188,7 +188,7 @@ should be short. Annotations are included in the Metadata level.

metadata
-meta/v1.ListMeta +meta/v1.ListMeta
No description provided.
metadata
-meta/v1.ObjectMeta +meta/v1.ObjectMeta

ObjectMeta is included for interoperability with API infrastructure.

@@ -278,7 +278,7 @@ in a rule will override the global default.

metadata
-meta/v1.ListMeta +meta/v1.ListMeta
No description provided.
+## `EncryptionConfiguration` {#apiserver-config-k8s-io-v1-EncryptionConfiguration} + + + +

EncryptionConfiguration stores the complete configuration for encryption providers. +It also allows the use of wildcards to specify the resources that should be encrypted. +Use '*.<group>' to encrypt all resources within a group or '*.*' to encrypt all resources. +'*.' can be used to encrypt all resource in the core group. '*.*' will encrypt all +resources, even custom resources that are added after API server start. +Use of wildcards that overlap within the same resource list or across multiple +entries are not allowed since part of the configuration would be ineffective. +Resource lists are processed in order, with earlier lists taking precedence.

+

Example:

+
kind: EncryptionConfiguration
+apiVersion: apiserver.config.k8s.io/v1
+resources:
+- resources:
+  - events
+  providers:
+  - identity: {}  # do not encrypt events even though *.* is specified below
+- resources:
+  - secrets
+  - configmaps
+  - pandas.awesome.bears.example
+  providers:
+  - aescbc:
+      keys:
+      - name: key1
+        secret: c2VjcmV0IGlzIHNlY3VyZQ==
+- resources:
+  - '*.apps'
+  providers:
+  - aescbc:
+      keys:
+      - name: key2
+        secret: c2VjcmV0IGlzIHNlY3VyZSwgb3IgaXMgaXQ/Cg==
+- resources:
+  - '*.*'
+  providers:
+  - aescbc:
+      keys:
+      - name: key3
+        secret: c2VjcmV0IGlzIHNlY3VyZSwgSSB0aGluaw==
+ + + + + + + + + + + + + + +
FieldDescription
apiVersion
string
apiserver.config.k8s.io/v1
kind
string
EncryptionConfiguration
resources [Required]
+[]ResourceConfiguration +
+

resources is a list containing resources, and their corresponding encryption providers.

+
+ +## `AESConfiguration` {#apiserver-config-k8s-io-v1-AESConfiguration} + + +**Appears in:** + +- [ProviderConfiguration](#apiserver-config-k8s-io-v1-ProviderConfiguration) + + +

AESConfiguration contains the API configuration for an AES transformer.

+ + + + + + + + + + + +
FieldDescription
keys [Required]
+[]Key +
+

keys is a list of keys to be used for creating the AES transformer. +Each key has to be 32 bytes long for AES-CBC and 16, 24 or 32 bytes for AES-GCM.

+
+ ## `AdmissionPluginConfiguration` {#apiserver-config-k8s-io-v1-AdmissionPluginConfiguration} @@ -80,4 +171,226 @@ configuration. If present, it will be used instead of the path to the configurat - \ No newline at end of file + +## `IdentityConfiguration` {#apiserver-config-k8s-io-v1-IdentityConfiguration} + + +**Appears in:** + +- [ProviderConfiguration](#apiserver-config-k8s-io-v1-ProviderConfiguration) + + +

IdentityConfiguration is an empty struct to allow identity transformer in provider configuration.

+ + + + +## `KMSConfiguration` {#apiserver-config-k8s-io-v1-KMSConfiguration} + + +**Appears in:** + +- [ProviderConfiguration](#apiserver-config-k8s-io-v1-ProviderConfiguration) + + +

KMSConfiguration contains the name, cache size and path to configuration file for a KMS based envelope transformer.

+ + + + + + + + + + + + + + + + + + + + + + + +
FieldDescription
apiVersion
+string +
+

apiVersion of KeyManagementService

+
name [Required]
+string +
+

name is the name of the KMS plugin to be used.

+
cachesize
+int32 +
+

cachesize is the maximum number of secrets which are cached in memory. The default value is 1000. +Set to a negative value to disable caching. This field is only allowed for KMS v1 providers.

+
endpoint [Required]
+string +
+

endpoint is the gRPC server listening address, for example "unix:///var/run/kms-provider.sock".

+
timeout
+meta/v1.Duration +
+

timeout for gRPC calls to kms-plugin (ex. 5s). The default is 3 seconds.

+
+ +## `Key` {#apiserver-config-k8s-io-v1-Key} + + +**Appears in:** + +- [AESConfiguration](#apiserver-config-k8s-io-v1-AESConfiguration) + +- [SecretboxConfiguration](#apiserver-config-k8s-io-v1-SecretboxConfiguration) + + +

Key contains name and secret of the provided key for a transformer.

+ + + + + + + + + + + + + + +
FieldDescription
name [Required]
+string +
+

name is the name of the key to be used while storing data to disk.

+
secret [Required]
+string +
+

secret is the actual key, encoded in base64.

+
+ +## `ProviderConfiguration` {#apiserver-config-k8s-io-v1-ProviderConfiguration} + + +**Appears in:** + +- [ResourceConfiguration](#apiserver-config-k8s-io-v1-ResourceConfiguration) + + +

ProviderConfiguration stores the provided configuration for an encryption provider.

+ + + + + + + + + + + + + + + + + + + + + + + +
FieldDescription
aesgcm [Required]
+AESConfiguration +
+

aesgcm is the configuration for the AES-GCM transformer.

+
aescbc [Required]
+AESConfiguration +
+

aescbc is the configuration for the AES-CBC transformer.

+
secretbox [Required]
+SecretboxConfiguration +
+

secretbox is the configuration for the Secretbox based transformer.

+
identity [Required]
+IdentityConfiguration +
+

identity is the (empty) configuration for the identity transformer.

+
kms [Required]
+KMSConfiguration +
+

kms contains the name, cache size and path to configuration file for a KMS based envelope transformer.

+
+ +## `ResourceConfiguration` {#apiserver-config-k8s-io-v1-ResourceConfiguration} + + +**Appears in:** + +- [EncryptionConfiguration](#apiserver-config-k8s-io-v1-EncryptionConfiguration) + + +

ResourceConfiguration stores per resource configuration.

+ + + + + + + + + + + + + + +
FieldDescription
resources [Required]
+[]string +
+

resources is a list of kubernetes resources which have to be encrypted. The resource names are derived from resource or resource.group of the group/version/resource. +eg: pandas.awesome.bears.example is a custom resource with 'group': awesome.bears.example, 'resource': pandas. +Use '*.*' to encrypt all resources and '*.<group>' to encrypt all resources in a specific group. +eg: '*.awesome.bears.example' will encrypt all resources in the group 'awesome.bears.example'. +eg: '*.' will encrypt all resources in the core group (such as pods, configmaps, etc).

+
providers [Required]
+[]ProviderConfiguration +
+

providers is a list of transformers to be used for reading and writing the resources to disk. +eg: aesgcm, aescbc, secretbox, identity, kms.

+
+ +## `SecretboxConfiguration` {#apiserver-config-k8s-io-v1-SecretboxConfiguration} + + +**Appears in:** + +- [ProviderConfiguration](#apiserver-config-k8s-io-v1-ProviderConfiguration) + + +

SecretboxConfiguration contains the API configuration for an Secretbox transformer.

+ + + + + + + + + + + +
FieldDescription
keys [Required]
+[]Key +
+

keys is a list of keys to be used for creating the Secretbox transformer. +Each key has to be 32 bytes long.

+
+ diff --git a/content/en/docs/reference/config-api/apiserver-config.v1alpha1.md b/content/en/docs/reference/config-api/apiserver-config.v1alpha1.md index 4207670760275..caeccf3c7f7ed 100644 --- a/content/en/docs/reference/config-api/apiserver-config.v1alpha1.md +++ b/content/en/docs/reference/config-api/apiserver-config.v1alpha1.md @@ -114,6 +114,13 @@ The specific position of JWT authenticators in relation to other authenticators is neither defined nor stable across releases. Since each JWT authenticator must have a unique issuer URL, at most one JWT authenticator will attempt to cryptographically validate the token.

+

The minimum valid JWT payload must contain the following claims: +{ +"iss": "https://issuer.example.com", +"aud": ["audience"], +"exp": 1234567890, +"<username claim>": "username" +}

@@ -238,6 +245,20 @@ configuration. If present, it will be used instead of the path to the configurat +## `AudienceMatchPolicyType` {#apiserver-k8s-io-v1alpha1-AudienceMatchPolicyType} + +(Alias of `string`) + +**Appears in:** + +- [Issuer](#apiserver-k8s-io-v1alpha1-Issuer) + + +

AudienceMatchPolicyType is a set of valid values for issuer.audienceMatchPolicy

+ + + + ## `AuthorizerConfiguration` {#apiserver-k8s-io-v1alpha1-AuthorizerConfiguration} @@ -308,7 +329,11 @@ Must not be defined when Type!=Webhook

username represents an option for the username attribute. The claim's value must be a singular string. Same as the --oidc-username-claim and --oidc-username-prefix flags. -If username.expression is set, the expression must produce a string value.

+If username.expression is set, the expression must produce a string value. +If username.expression uses 'claims.email', then 'claims.email_verified' must be used in +username.expression or extra[*].valueExpression or claimValidationRules[*].expression. +An example claim validation rule expression that matches the validation automatically +applied when username.claim is set to 'email' is 'claims.?email_verified.orValue(true)'.

In the flag based approach, the --oidc-username-claim and --oidc-username-prefix are optional. If --oidc-username-claim is not set, the default value is "sub". For the authentication config, there is no defaulting for claim or prefix. The claim and prefix must be set explicitly. For claim, if --oidc-username-claim was not set with legacy flag approach, configure username.claim="sub" in the authentication config. @@ -316,8 +341,8 @@ For prefix: (1) --oidc-username-prefix="-", no prefix was added to the username. For the same behavior using authentication config, set username.prefix="" (2) --oidc-username-prefix="" and --oidc-username-claim != "email", prefix was "<value of --oidc-issuer-url>#". For the same -behavior using authentication config, set username.prefix="#" -(3) --oidc-username-prefix="". For the same behavior using authentication config, set username.prefix=""

+behavior using authentication config, set username.prefix="<value of issuer.url>#" +(3) --oidc-username-prefix="<value>". For the same behavior using authentication config, set username.prefix="<value>"

groups
@@ -406,7 +431,7 @@ Mutually exclusive with expression.

  • 'claims' is a map of claim names to claim values. For example, a variable named 'sub' can be accessed as 'claims.sub'. -Nested claims can be accessed using dot notation, e.g. 'claims.email.verified'.
  • +Nested claims can be accessed using dot notation, e.g. 'claims.foo.bar'.

Documentation on CEL: https://kubernetes.io/docs/reference/using-api/cel/

Mutually exclusive with claim.

@@ -462,7 +487,7 @@ Must produce a boolean.

  • 'claims' is a map of claim names to claim values. For example, a variable named 'sub' can be accessed as 'claims.sub'. -Nested claims can be accessed using dot notation, e.g. 'claims.email.verified'. +Nested claims can be accessed using dot notation, e.g. 'claims.foo.bar'. Must return true for the validation to pass.

Documentation on CEL: https://kubernetes.io/docs/reference/using-api/cel/

@@ -574,7 +599,8 @@ The "master" egress selector is deprecated in favor of "controlpl key must be a domain-prefix path (e.g. example.org/foo). All characters before the first "/" must be a valid subdomain as defined by RFC 1123. All characters trailing the first "/" must be valid HTTP Path characters as defined by RFC 3986. -key must be lowercase.

+key must be lowercase. +Required to be unique.

valueExpression [Required]
@@ -589,7 +615,7 @@ Empty string values contained within a string array are filtered out.

  • 'claims' is a map of claim names to claim values. For example, a variable named 'sub' can be accessed as 'claims.sub'. -Nested claims can be accessed using dot notation, e.g. 'claims.email.verified'.
  • +Nested claims can be accessed using dot notation, e.g. 'claims.foo.bar'.

Documentation on CEL: https://kubernetes.io/docs/reference/using-api/cel/

@@ -605,7 +631,7 @@ Nested claims can be accessed using dot notation, e.g. 'claims.email.verified'.< - [JWTAuthenticator](#apiserver-k8s-io-v1alpha1-JWTAuthenticator) -

Issuer provides the configuration for a external provider specific settings.

+

Issuer provides the configuration for an external provider's specific settings.

@@ -620,8 +646,35 @@ Nested claims can be accessed using dot notation, e.g. 'claims.email.verified'.<

url points to the issuer URL in a format https://url or https://url/path. This must match the "iss" claim in the presented JWT, and the issuer returned from discovery. Same value as the --oidc-issuer-url flag. -Used to fetch discovery information unless overridden by discoveryURL. -Required to be unique. +Discovery information is fetched from "{url}/.well-known/openid-configuration" unless overridden by discoveryURL. +Required to be unique across all JWT authenticators. +Note that egress selection configuration is not used for this network connection.

+ + + + @@ -645,6 +698,29 @@ Same value as the --oidc-client-id flag (though this field supports an array). Required to be non-empty.

+ + +
discoveryURL
+string +
+

discoveryURL, if specified, overrides the URL used to fetch discovery +information instead of using "{url}/.well-known/openid-configuration". +The exact value specified is used, so "/.well-known/openid-configuration" +must be included in discoveryURL if needed.

+

The "issuer" field in the fetched discovery information must match the "issuer.url" field +in the AuthenticationConfiguration and will be used to validate the "iss" claim in the presented JWT. +This is for scenarios where the well-known and jwks endpoints are hosted at a different +location than the issuer (such as locally in the cluster).

+

Example: +A discovery url that is exposed using kubernetes service 'oidc' in namespace 'oidc-namespace' +and discovery information is available at '/.well-known/openid-configuration'. +discoveryURL: "https://oidc.oidc-namespace/.well-known/openid-configuration" +certificateAuthority is used to verify the TLS connection and the hostname on the leaf certificate +must be set to 'oidc.oidc-namespace'.

+

curl https://oidc.oidc-namespace/.well-known/openid-configuration (.discoveryURL field) +{ +issuer: "https://oidc.example.com" (.url field) +}

+

discoveryURL must be different from url. +Required to be unique across all JWT authenticators. Note that egress selection configuration is not used for this network connection.

audienceMatchPolicy
+AudienceMatchPolicyType +
+

audienceMatchPolicy defines how the "audiences" field is used to match the "aud" claim in the presented JWT. +Allowed values are:

+
    +
  1. "MatchAny" when multiple audiences are specified and
  2. +
  3. empty (or unset) or "MatchAny" when a single audience is specified.
  4. +
+
    +
  • +

    MatchAny: the "aud" claim in the presented JWT must match at least one of the entries in the "audiences" field. +For example, if "audiences" is ["foo", "bar"], the "aud" claim in the presented JWT must contain either "foo" or "bar" (and may contain both).

    +
  • +
  • +

    "": The match policy can be empty (or unset) when a single audience is specified in the "audiences" field. The "aud" claim in the presented JWT must contain the single audience (and may contain others).

    +
  • +
+

For more nuanced audience validation, use claimValidationRules. +example: claimValidationRule[].expression: 'sets.equivalent(claims.aud, ["bar", "foo", "baz"])' to require an exact match.

+
@@ -740,7 +816,7 @@ Mutually exclusive with expression.

  • 'claims' is a map of claim names to claim values. For example, a variable named 'sub' can be accessed as 'claims.sub'. -Nested claims can be accessed using dot notation, e.g. 'claims.email.verified'.
  • +Nested claims can be accessed using dot notation, e.g. 'claims.foo.bar'.

Documentation on CEL: https://kubernetes.io/docs/reference/using-api/cel/

Mutually exclusive with claim and prefix.

@@ -1126,4 +1202,4 @@ the contents would be converted to the v1 version before evaluating the CEL expr - \ No newline at end of file + diff --git a/content/en/docs/reference/config-api/apiserver-config.v1beta1.md b/content/en/docs/reference/config-api/apiserver-config.v1beta1.md index 06dfaab72291e..88c75d3fcb08b 100644 --- a/content/en/docs/reference/config-api/apiserver-config.v1beta1.md +++ b/content/en/docs/reference/config-api/apiserver-config.v1beta1.md @@ -10,6 +10,8 @@ auto_generated: true ## Resource Types +- [AuthenticationConfiguration](#apiserver-k8s-io-v1beta1-AuthenticationConfiguration) +- [AuthorizationConfiguration](#apiserver-k8s-io-v1beta1-AuthorizationConfiguration) - [EgressSelectorConfiguration](#apiserver-k8s-io-v1beta1-EgressSelectorConfiguration) - [TracingConfiguration](#apiserver-k8s-io-v1beta1-TracingConfiguration) @@ -58,6 +60,74 @@ rate, but otherwise never samples.

+## `AuthenticationConfiguration` {#apiserver-k8s-io-v1beta1-AuthenticationConfiguration} + + + +

AuthenticationConfiguration provides versioned configuration for authentication.

+ + + + + + + + + + + + + + +
FieldDescription
apiVersion
string
apiserver.k8s.io/v1beta1
kind
string
AuthenticationConfiguration
jwt [Required]
+[]JWTAuthenticator +
+

jwt is a list of authenticator to authenticate Kubernetes users using +JWT compliant tokens. The authenticator will attempt to parse a raw ID token, +verify it's been signed by the configured issuer. The public key to verify the +signature is discovered from the issuer's public endpoint using OIDC discovery. +For an incoming token, each JWT authenticator will be attempted in +the order in which it is specified in this list. Note however that +other authenticators may run before or after the JWT authenticators. +The specific position of JWT authenticators in relation to other +authenticators is neither defined nor stable across releases. Since +each JWT authenticator must have a unique issuer URL, at most one +JWT authenticator will attempt to cryptographically validate the token.

+

The minimum valid JWT payload must contain the following claims: +{ +"iss": "https://issuer.example.com", +"aud": ["audience"], +"exp": 1234567890, +"<username claim>": "username" +}

+
+ +## `AuthorizationConfiguration` {#apiserver-k8s-io-v1beta1-AuthorizationConfiguration} + + + + + + + + + + + + + + + + +
FieldDescription
apiVersion
string
apiserver.k8s.io/v1beta1
kind
string
AuthorizationConfiguration
authorizers [Required]
+[]AuthorizerConfiguration +
+

Authorizers is an ordered list of authorizers to +authorize requests against. +This is similar to the --authorization-modes kube-apiserver flag +Must be at least one.

+
+ ## `EgressSelectorConfiguration` {#apiserver-k8s-io-v1beta1-EgressSelectorConfiguration} @@ -108,6 +178,267 @@ rate, but otherwise never samples.

+## `AudienceMatchPolicyType` {#apiserver-k8s-io-v1beta1-AudienceMatchPolicyType} + +(Alias of `string`) + +**Appears in:** + +- [Issuer](#apiserver-k8s-io-v1beta1-Issuer) + + +

AudienceMatchPolicyType is a set of valid values for issuer.audienceMatchPolicy

+ + + + +## `AuthorizerConfiguration` {#apiserver-k8s-io-v1beta1-AuthorizerConfiguration} + + +**Appears in:** + +- [AuthorizationConfiguration](#apiserver-k8s-io-v1beta1-AuthorizationConfiguration) + + + + + + + + + + + + + + + + + + +
FieldDescription
type [Required]
+string +
+

Type refers to the type of the authorizer +"Webhook" is supported in the generic API server +Other API servers may support additional authorizer +types like Node, RBAC, ABAC, etc.

+
name [Required]
+string +
+

Name used to describe the webhook +This is explicitly used in monitoring machinery for metrics +Note: Names must be DNS1123 labels like myauthorizername or +subdomains like myauthorizer.example.domain +Required, with no default

+
webhook [Required]
+WebhookConfiguration +
+

Webhook defines the configuration for a Webhook authorizer +Must be defined when Type=Webhook +Must not be defined when Type!=Webhook

+
+ +## `ClaimMappings` {#apiserver-k8s-io-v1beta1-ClaimMappings} + + +**Appears in:** + +- [JWTAuthenticator](#apiserver-k8s-io-v1beta1-JWTAuthenticator) + + +

ClaimMappings provides the configuration for claim mapping

+ + + + + + + + + + + + + + + + + + + + +
FieldDescription
username [Required]
+PrefixedClaimOrExpression +
+

username represents an option for the username attribute. +The claim's value must be a singular string. +Same as the --oidc-username-claim and --oidc-username-prefix flags. +If username.expression is set, the expression must produce a string value. +If username.expression uses 'claims.email', then 'claims.email_verified' must be used in +username.expression or extra[*].valueExpression or claimValidationRules[*].expression. +An example claim validation rule expression that matches the validation automatically +applied when username.claim is set to 'email' is 'claims.?email_verified.orValue(true)'.

+

In the flag based approach, the --oidc-username-claim and --oidc-username-prefix are optional. If --oidc-username-claim is not set, +the default value is "sub". For the authentication config, there is no defaulting for claim or prefix. The claim and prefix must be set explicitly. +For claim, if --oidc-username-claim was not set with legacy flag approach, configure username.claim="sub" in the authentication config. +For prefix: +(1) --oidc-username-prefix="-", no prefix was added to the username. For the same behavior using authentication config, +set username.prefix="" +(2) --oidc-username-prefix="" and --oidc-username-claim != "email", prefix was "<value of --oidc-issuer-url>#". For the same +behavior using authentication config, set username.prefix="<value of issuer.url>#" +(3) --oidc-username-prefix="<value>". For the same behavior using authentication config, set username.prefix="<value>"

+
groups
+PrefixedClaimOrExpression +
+

groups represents an option for the groups attribute. +The claim's value must be a string or string array claim. +If groups.claim is set, the prefix must be specified (and can be the empty string). +If groups.expression is set, the expression must produce a string or string array value. +"", [], and null values are treated as the group mapping not being present.

+
uid
+ClaimOrExpression +
+

uid represents an option for the uid attribute. +Claim must be a singular string claim. +If uid.expression is set, the expression must produce a string value.

+
extra
+[]ExtraMapping +
+

extra represents an option for the extra attribute. +expression must produce a string or string array value. +If the value is empty, the extra mapping will not be present.

+

hard-coded extra key/value

+
    +
  • key: "foo" +valueExpression: "'bar'" +This will result in an extra attribute - foo: ["bar"]
  • +
+

hard-coded key, value copying claim value

+
    +
  • key: "foo" +valueExpression: "claims.some_claim" +This will result in an extra attribute - foo: [value of some_claim]
  • +
+

hard-coded key, value derived from claim value

+
    +
  • key: "admin" +valueExpression: '(has(claims.is_admin) && claims.is_admin) ? "true":""' +This will result in:
  • +
  • if is_admin claim is present and true, extra attribute - admin: ["true"]
  • +
  • if is_admin claim is present and false or is_admin claim is not present, no extra attribute will be added
  • +
+
+ +## `ClaimOrExpression` {#apiserver-k8s-io-v1beta1-ClaimOrExpression} + + +**Appears in:** + +- [ClaimMappings](#apiserver-k8s-io-v1beta1-ClaimMappings) + + +

ClaimOrExpression provides the configuration for a single claim or expression.

+ + + + + + + + + + + + + + +
FieldDescription
claim
+string +
+

claim is the JWT claim to use. +Either claim or expression must be set. +Mutually exclusive with expression.

+
expression
+string +
+

expression represents the expression which will be evaluated by CEL.

+

CEL expressions have access to the contents of the token claims, organized into CEL variable:

+
    +
  • 'claims' is a map of claim names to claim values. +For example, a variable named 'sub' can be accessed as 'claims.sub'. +Nested claims can be accessed using dot notation, e.g. 'claims.foo.bar'.
  • +
+

Documentation on CEL: https://kubernetes.io/docs/reference/using-api/cel/

+

Mutually exclusive with claim.

+
+ +## `ClaimValidationRule` {#apiserver-k8s-io-v1beta1-ClaimValidationRule} + + +**Appears in:** + +- [JWTAuthenticator](#apiserver-k8s-io-v1beta1-JWTAuthenticator) + + +

ClaimValidationRule provides the configuration for a single claim validation rule.

+ + + + + + + + + + + + + + + + + + + + +
FieldDescription
claim
+string +
+

claim is the name of a required claim. +Same as --oidc-required-claim flag. +Only string claim keys are supported. +Mutually exclusive with expression and message.

+
requiredValue
+string +
+

requiredValue is the value of a required claim. +Same as --oidc-required-claim flag. +Only string claim values are supported. +If claim is set and requiredValue is not set, the claim must be present with a value set to the empty string. +Mutually exclusive with expression and message.

+
expression
+string +
+

expression represents the expression which will be evaluated by CEL. +Must produce a boolean.

+

CEL expressions have access to the contents of the token claims, organized into CEL variable:

+
    +
  • 'claims' is a map of claim names to claim values. +For example, a variable named 'sub' can be accessed as 'claims.sub'. +Nested claims can be accessed using dot notation, e.g. 'claims.foo.bar'. +Must return true for the validation to pass.
  • +
+

Documentation on CEL: https://kubernetes.io/docs/reference/using-api/cel/

+

Mutually exclusive with claim and requiredValue.

+
message
+string +
+

message customizes the returned error message when expression returns false. +message is a literal string. +Mutually exclusive with claim and requiredValue.

+
+ ## `Connection` {#apiserver-k8s-io-v1beta1-Connection} @@ -177,6 +508,256 @@ The "master" egress selector is deprecated in favor of "controlpl +## `ExtraMapping` {#apiserver-k8s-io-v1beta1-ExtraMapping} + + +**Appears in:** + +- [ClaimMappings](#apiserver-k8s-io-v1beta1-ClaimMappings) + + +

ExtraMapping provides the configuration for a single extra mapping.

+ + + + + + + + + + + + + + +
FieldDescription
key [Required]
+string +
+

key is a string to use as the extra attribute key. +key must be a domain-prefix path (e.g. example.org/foo). All characters before the first "/" must be a valid +subdomain as defined by RFC 1123. All characters trailing the first "/" must +be valid HTTP Path characters as defined by RFC 3986. +key must be lowercase. +Required to be unique.

+
valueExpression [Required]
+string +
+

valueExpression is a CEL expression to extract extra attribute value. +valueExpression must produce a string or string array value. +"", [], and null values are treated as the extra mapping not being present. +Empty string values contained within a string array are filtered out.

+

CEL expressions have access to the contents of the token claims, organized into CEL variable:

+
    +
  • 'claims' is a map of claim names to claim values. +For example, a variable named 'sub' can be accessed as 'claims.sub'. +Nested claims can be accessed using dot notation, e.g. 'claims.foo.bar'.
  • +
+

Documentation on CEL: https://kubernetes.io/docs/reference/using-api/cel/

+
+ +## `Issuer` {#apiserver-k8s-io-v1beta1-Issuer} + + +**Appears in:** + +- [JWTAuthenticator](#apiserver-k8s-io-v1beta1-JWTAuthenticator) + + +

Issuer provides the configuration for an external provider's specific settings.

+ + + + + + + + + + + + + + + + + + + + + + + +
FieldDescription
url [Required]
+string +
+

url points to the issuer URL in a format https://url or https://url/path. +This must match the "iss" claim in the presented JWT, and the issuer returned from discovery. +Same value as the --oidc-issuer-url flag. +Discovery information is fetched from "{url}/.well-known/openid-configuration" unless overridden by discoveryURL. +Required to be unique across all JWT authenticators. +Note that egress selection configuration is not used for this network connection.

+
discoveryURL
+string +
+

discoveryURL, if specified, overrides the URL used to fetch discovery +information instead of using "{url}/.well-known/openid-configuration". +The exact value specified is used, so "/.well-known/openid-configuration" +must be included in discoveryURL if needed.

+

The "issuer" field in the fetched discovery information must match the "issuer.url" field +in the AuthenticationConfiguration and will be used to validate the "iss" claim in the presented JWT. +This is for scenarios where the well-known and jwks endpoints are hosted at a different +location than the issuer (such as locally in the cluster).

+

Example: +A discovery url that is exposed using kubernetes service 'oidc' in namespace 'oidc-namespace' +and discovery information is available at '/.well-known/openid-configuration'. +discoveryURL: "https://oidc.oidc-namespace/.well-known/openid-configuration" +certificateAuthority is used to verify the TLS connection and the hostname on the leaf certificate +must be set to 'oidc.oidc-namespace'.

+

curl https://oidc.oidc-namespace/.well-known/openid-configuration (.discoveryURL field) +{ +issuer: "https://oidc.example.com" (.url field) +}

+

discoveryURL must be different from url. +Required to be unique across all JWT authenticators. +Note that egress selection configuration is not used for this network connection.

+
certificateAuthority
+string +
+

certificateAuthority contains PEM-encoded certificate authority certificates +used to validate the connection when fetching discovery information. +If unset, the system verifier is used. +Same value as the content of the file referenced by the --oidc-ca-file flag.

+
audiences [Required]
+[]string +
+

audiences is the set of acceptable audiences the JWT must be issued to. +At least one of the entries must match the "aud" claim in presented JWTs. +Same value as the --oidc-client-id flag (though this field supports an array). +Required to be non-empty.

+
audienceMatchPolicy
+AudienceMatchPolicyType +
+

audienceMatchPolicy defines how the "audiences" field is used to match the "aud" claim in the presented JWT. +Allowed values are:

+
    +
  1. "MatchAny" when multiple audiences are specified and
  2. +
  3. empty (or unset) or "MatchAny" when a single audience is specified.
  4. +
+
    +
  • +

    MatchAny: the "aud" claim in the presented JWT must match at least one of the entries in the "audiences" field. +For example, if "audiences" is ["foo", "bar"], the "aud" claim in the presented JWT must contain either "foo" or "bar" (and may contain both).

    +
  • +
  • +

    "": The match policy can be empty (or unset) when a single audience is specified in the "audiences" field. The "aud" claim in the presented JWT must contain the single audience (and may contain others).

    +
  • +
+

For more nuanced audience validation, use claimValidationRules. +example: claimValidationRule[].expression: 'sets.equivalent(claims.aud, ["bar", "foo", "baz"])' to require an exact match.

+
+ +## `JWTAuthenticator` {#apiserver-k8s-io-v1beta1-JWTAuthenticator} + + +**Appears in:** + +- [AuthenticationConfiguration](#apiserver-k8s-io-v1beta1-AuthenticationConfiguration) + + +

JWTAuthenticator provides the configuration for a single JWT authenticator.

+ + + + + + + + + + + + + + + + + + + + +
FieldDescription
issuer [Required]
+Issuer +
+

issuer contains the basic OIDC provider connection options.

+
claimValidationRules
+[]ClaimValidationRule +
+

claimValidationRules are rules that are applied to validate token claims to authenticate users.

+
claimMappings [Required]
+ClaimMappings +
+

claimMappings points claims of a token to be treated as user attributes.

+
userValidationRules
+[]UserValidationRule +
+

userValidationRules are rules that are applied to final user before completing authentication. +These allow invariants to be applied to incoming identities such as preventing the +use of the system: prefix that is commonly used by Kubernetes components. +The validation rules are logically ANDed together and must all return true for the validation to pass.

+
+ +## `PrefixedClaimOrExpression` {#apiserver-k8s-io-v1beta1-PrefixedClaimOrExpression} + + +**Appears in:** + +- [ClaimMappings](#apiserver-k8s-io-v1beta1-ClaimMappings) + + +

PrefixedClaimOrExpression provides the configuration for a single prefixed claim or expression.

+ + + + + + + + + + + + + + + + + +
FieldDescription
claim
+string +
+

claim is the JWT claim to use. +Mutually exclusive with expression.

+
prefix
+string +
+

prefix is prepended to claim's value to prevent clashes with existing names. +prefix needs to be set if claim is set and can be the empty string. +Mutually exclusive with expression.

+
expression
+string +
+

expression represents the expression which will be evaluated by CEL.

+

CEL expressions have access to the contents of the token claims, organized into CEL variable:

+
    +
  • 'claims' is a map of claim names to claim values. +For example, a variable named 'sub' can be accessed as 'claims.sub'. +Nested claims can be accessed using dot notation, e.g. 'claims.foo.bar'.
  • +
+

Documentation on CEL: https://kubernetes.io/docs/reference/using-api/cel/

+

Mutually exclusive with claim and prefix.

+
+ ## `ProtocolType` {#apiserver-k8s-io-v1beta1-ProtocolType} (Alias of `string`) @@ -334,4 +915,224 @@ This does not use a unix:// prefix. (Eg: /etc/srv/kubernetes/konnectivity-server - \ No newline at end of file + +## `UserValidationRule` {#apiserver-k8s-io-v1beta1-UserValidationRule} + + +**Appears in:** + +- [JWTAuthenticator](#apiserver-k8s-io-v1beta1-JWTAuthenticator) + + +

UserValidationRule provides the configuration for a single user info validation rule.

+ + + + + + + + + + + + + + +
FieldDescription
expression [Required]
+string +
+

expression represents the expression which will be evaluated by CEL. +Must return true for the validation to pass.

+

CEL expressions have access to the contents of UserInfo, organized into CEL variable:

+
    +
  • 'user' - authentication.k8s.io/v1, Kind=UserInfo object +Refer to https://github.com/kubernetes/api/blob/release-1.28/authentication/v1/types.go#L105-L122 for the definition. +API documentation: https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.28/#userinfo-v1-authentication-k8s-io
  • +
+

Documentation on CEL: https://kubernetes.io/docs/reference/using-api/cel/

+
message
+string +
+

message customizes the returned error message when rule returns false. +message is a literal string.

+
+ +## `WebhookConfiguration` {#apiserver-k8s-io-v1beta1-WebhookConfiguration} + + +**Appears in:** + +- [AuthorizerConfiguration](#apiserver-k8s-io-v1beta1-AuthorizerConfiguration) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FieldDescription
authorizedTTL [Required]
+meta/v1.Duration +
+

The duration to cache 'authorized' responses from the webhook +authorizer. +Same as setting --authorization-webhook-cache-authorized-ttl flag +Default: 5m0s

+
unauthorizedTTL [Required]
+meta/v1.Duration +
+

The duration to cache 'unauthorized' responses from the webhook +authorizer. +Same as setting --authorization-webhook-cache-unauthorized-ttl flag +Default: 30s

+
timeout [Required]
+meta/v1.Duration +
+

Timeout for the webhook request +Maximum allowed value is 30s. +Required, no default value.

+
subjectAccessReviewVersion [Required]
+string +
+

The API version of the authorization.k8s.io SubjectAccessReview to +send to and expect from the webhook. +Same as setting --authorization-webhook-version flag +Valid values: v1beta1, v1 +Required, no default value

+
matchConditionSubjectAccessReviewVersion [Required]
+string +
+

MatchConditionSubjectAccessReviewVersion specifies the SubjectAccessReview +version the CEL expressions are evaluated against +Valid values: v1 +Required, no default value

+
failurePolicy [Required]
+string +
+

Controls the authorization decision when a webhook request fails to +complete or returns a malformed response or errors evaluating +matchConditions. +Valid values:

+
    +
  • NoOpinion: continue to subsequent authorizers to see if one of +them allows the request
  • +
  • Deny: reject the request without consulting subsequent authorizers +Required, with no default.
  • +
+
connectionInfo [Required]
+WebhookConnectionInfo +
+

ConnectionInfo defines how we talk to the webhook

+
matchConditions [Required]
+[]WebhookMatchCondition +
+

matchConditions is a list of conditions that must be met for a request to be sent to this +webhook. An empty list of matchConditions matches all requests. +There are a maximum of 64 match conditions allowed.

+

The exact matching logic is (in order):

+
    +
  1. If at least one matchCondition evaluates to FALSE, then the webhook is skipped.
  2. +
  3. If ALL matchConditions evaluate to TRUE, then the webhook is called.
  4. +
  5. If at least one matchCondition evaluates to an error (but none are FALSE): +
      +
    • If failurePolicy=Deny, then the webhook rejects the request
    • +
    • If failurePolicy=NoOpinion, then the error is ignored and the webhook is skipped
    • +
    +
  6. +
+
+ +## `WebhookConnectionInfo` {#apiserver-k8s-io-v1beta1-WebhookConnectionInfo} + + +**Appears in:** + +- [WebhookConfiguration](#apiserver-k8s-io-v1beta1-WebhookConfiguration) + + + + + + + + + + + + + + + +
FieldDescription
type [Required]
+string +
+

Controls how the webhook should communicate with the server. +Valid values:

+
    +
  • KubeConfigFile: use the file specified in kubeConfigFile to locate the +server.
  • +
  • InClusterConfig: use the in-cluster configuration to call the +SubjectAccessReview API hosted by kube-apiserver. This mode is not +allowed for kube-apiserver.
  • +
+
kubeConfigFile [Required]
+string +
+

Path to KubeConfigFile for connection info +Required, if connectionInfo.Type is KubeConfig

+
+ +## `WebhookMatchCondition` {#apiserver-k8s-io-v1beta1-WebhookMatchCondition} + + +**Appears in:** + +- [WebhookConfiguration](#apiserver-k8s-io-v1beta1-WebhookConfiguration) + + + + + + + + + + + + +
FieldDescription
expression [Required]
+string +
+

expression represents the expression which will be evaluated by CEL. Must evaluate to bool. +CEL expressions have access to the contents of the SubjectAccessReview in v1 version. +If version specified by subjectAccessReviewVersion in the request variable is v1beta1, +the contents would be converted to the v1 version before evaluating the CEL expression.

+

Documentation on CEL: https://kubernetes.io/docs/reference/using-api/cel/

+
+ diff --git a/content/en/docs/reference/config-api/apiserver-encryption.v1.md b/content/en/docs/reference/config-api/apiserver-encryption.v1.md deleted file mode 100644 index 30d42277e6b29..0000000000000 --- a/content/en/docs/reference/config-api/apiserver-encryption.v1.md +++ /dev/null @@ -1,327 +0,0 @@ ---- -title: kube-apiserver Encryption Configuration (v1) -content_type: tool-reference -package: apiserver.config.k8s.io/v1 -auto_generated: true ---- -

Package v1 is the v1 version of the API.

- - -## Resource Types - - -- [EncryptionConfiguration](#apiserver-config-k8s-io-v1-EncryptionConfiguration) - - -## `EncryptionConfiguration` {#apiserver-config-k8s-io-v1-EncryptionConfiguration} - - - -

EncryptionConfiguration stores the complete configuration for encryption providers. -It also allows the use of wildcards to specify the resources that should be encrypted. -Use '.' to encrypt all resources within a group or '.' to encrypt all resources. -'.' can be used to encrypt all resource in the core group. '.' will encrypt all -resources, even custom resources that are added after API server start. -Use of wildcards that overlap within the same resource list or across multiple -entries are not allowed since part of the configuration would be ineffective. -Resource lists are processed in order, with earlier lists taking precedence.

-

Example:

-
kind: EncryptionConfiguration
-apiVersion: apiserver.config.k8s.io/v1
-resources:
-- resources:
-  - events
-  providers:
-  - identity: {}  # do not encrypt events even though *.* is specified below
-- resources:
-  - secrets
-  - configmaps
-  - pandas.awesome.bears.example
-  providers:
-  - aescbc:
-      keys:
-      - name: key1
-        secret: c2VjcmV0IGlzIHNlY3VyZQ==
-- resources:
-  - '*.apps'
-  providers:
-  - aescbc:
-      keys:
-      - name: key2
-        secret: c2VjcmV0IGlzIHNlY3VyZSwgb3IgaXMgaXQ/Cg==
-- resources:
-  - '*.*'
-  providers:
-  - aescbc:
-      keys:
-      - name: key3
-        secret: c2VjcmV0IGlzIHNlY3VyZSwgSSB0aGluaw==
- - - - - - - - - - - - - - -
FieldDescription
apiVersion
string
apiserver.config.k8s.io/v1
kind
string
EncryptionConfiguration
resources [Required]
-[]ResourceConfiguration -
-

resources is a list containing resources, and their corresponding encryption providers.

-
- -## `AESConfiguration` {#apiserver-config-k8s-io-v1-AESConfiguration} - - -**Appears in:** - -- [ProviderConfiguration](#apiserver-config-k8s-io-v1-ProviderConfiguration) - - -

AESConfiguration contains the API configuration for an AES transformer.

- - - - - - - - - - - -
FieldDescription
keys [Required]
-[]Key -
-

keys is a list of keys to be used for creating the AES transformer. -Each key has to be 32 bytes long for AES-CBC and 16, 24 or 32 bytes for AES-GCM.

-
- -## `IdentityConfiguration` {#apiserver-config-k8s-io-v1-IdentityConfiguration} - - -**Appears in:** - -- [ProviderConfiguration](#apiserver-config-k8s-io-v1-ProviderConfiguration) - - -

IdentityConfiguration is an empty struct to allow identity transformer in provider configuration.

- - - - -## `KMSConfiguration` {#apiserver-config-k8s-io-v1-KMSConfiguration} - - -**Appears in:** - -- [ProviderConfiguration](#apiserver-config-k8s-io-v1-ProviderConfiguration) - - -

KMSConfiguration contains the name, cache size and path to configuration file for a KMS based envelope transformer.

- - - - - - - - - - - - - - - - - - - - - - - -
FieldDescription
apiVersion
-string -
-

apiVersion of KeyManagementService

-
name [Required]
-string -
-

name is the name of the KMS plugin to be used.

-
cachesize
-int32 -
-

cachesize is the maximum number of secrets which are cached in memory. The default value is 1000. -Set to a negative value to disable caching. This field is only allowed for KMS v1 providers.

-
endpoint [Required]
-string -
-

endpoint is the gRPC server listening address, for example "unix:///var/run/kms-provider.sock".

-
timeout
-meta/v1.Duration -
-

timeout for gRPC calls to kms-plugin (ex. 5s). The default is 3 seconds.

-
- -## `Key` {#apiserver-config-k8s-io-v1-Key} - - -**Appears in:** - -- [AESConfiguration](#apiserver-config-k8s-io-v1-AESConfiguration) - -- [SecretboxConfiguration](#apiserver-config-k8s-io-v1-SecretboxConfiguration) - - -

Key contains name and secret of the provided key for a transformer.

- - - - - - - - - - - - - - -
FieldDescription
name [Required]
-string -
-

name is the name of the key to be used while storing data to disk.

-
secret [Required]
-string -
-

secret is the actual key, encoded in base64.

-
- -## `ProviderConfiguration` {#apiserver-config-k8s-io-v1-ProviderConfiguration} - - -**Appears in:** - -- [ResourceConfiguration](#apiserver-config-k8s-io-v1-ResourceConfiguration) - - -

ProviderConfiguration stores the provided configuration for an encryption provider.

- - - - - - - - - - - - - - - - - - - - - - - -
FieldDescription
aesgcm [Required]
-AESConfiguration -
-

aesgcm is the configuration for the AES-GCM transformer.

-
aescbc [Required]
-AESConfiguration -
-

aescbc is the configuration for the AES-CBC transformer.

-
secretbox [Required]
-SecretboxConfiguration -
-

secretbox is the configuration for the Secretbox based transformer.

-
identity [Required]
-IdentityConfiguration -
-

identity is the (empty) configuration for the identity transformer.

-
kms [Required]
-KMSConfiguration -
-

kms contains the name, cache size and path to configuration file for a KMS based envelope transformer.

-
- -## `ResourceConfiguration` {#apiserver-config-k8s-io-v1-ResourceConfiguration} - - -**Appears in:** - -- [EncryptionConfiguration](#apiserver-config-k8s-io-v1-EncryptionConfiguration) - - -

ResourceConfiguration stores per resource configuration.

- - - - - - - - - - - - - - -
FieldDescription
resources [Required]
-[]string -
-

resources is a list of kubernetes resources which have to be encrypted. The resource names are derived from resource or resource.group of the group/version/resource. -eg: pandas.awesome.bears.example is a custom resource with 'group': awesome.bears.example, 'resource': pandas. -Use '.' to encrypt all resources and '.' to encrypt all resources in a specific group. -eg: '.awesome.bears.example' will encrypt all resources in the group 'awesome.bears.example'. -eg: '*.' will encrypt all resources in the core group (such as pods, configmaps, etc).

-
providers [Required]
-[]ProviderConfiguration -
-

providers is a list of transformers to be used for reading and writing the resources to disk. -eg: aesgcm, aescbc, secretbox, identity, kms.

-
- -## `SecretboxConfiguration` {#apiserver-config-k8s-io-v1-SecretboxConfiguration} - - -**Appears in:** - -- [ProviderConfiguration](#apiserver-config-k8s-io-v1-ProviderConfiguration) - - -

SecretboxConfiguration contains the API configuration for an Secretbox transformer.

- - - - - - - - - - - -
FieldDescription
keys [Required]
-[]Key -
-

keys is a list of keys to be used for creating the Secretbox transformer. -Each key has to be 32 bytes long.

-
- \ No newline at end of file diff --git a/content/en/docs/reference/config-api/client-authentication.v1.md b/content/en/docs/reference/config-api/client-authentication.v1.md index e49be08c93dc6..5b0f460be5170 100644 --- a/content/en/docs/reference/config-api/client-authentication.v1.md +++ b/content/en/docs/reference/config-api/client-authentication.v1.md @@ -205,7 +205,7 @@ itself should at least be protected via file permissions.

expirationTimestamp
-meta/v1.Time +meta/v1.Time

ExpirationTimestamp indicates a time when the provided credentials expire.

diff --git a/content/en/docs/reference/config-api/client-authentication.v1beta1.md b/content/en/docs/reference/config-api/client-authentication.v1beta1.md index cd60d94c56480..e787539df7dff 100644 --- a/content/en/docs/reference/config-api/client-authentication.v1beta1.md +++ b/content/en/docs/reference/config-api/client-authentication.v1beta1.md @@ -205,7 +205,7 @@ itself should at least be protected via file permissions.

expirationTimestamp
-meta/v1.Time +meta/v1.Time

ExpirationTimestamp indicates a time when the provided credentials expire.

diff --git a/content/en/docs/reference/config-api/imagepolicy.v1alpha1.md b/content/en/docs/reference/config-api/imagepolicy.v1alpha1.md index d03ab7479629e..c93f3bcb4a1fd 100644 --- a/content/en/docs/reference/config-api/imagepolicy.v1alpha1.md +++ b/content/en/docs/reference/config-api/imagepolicy.v1alpha1.md @@ -28,7 +28,7 @@ auto_generated: true metadata
-meta/v1.ObjectMeta +meta/v1.ObjectMeta

Standard object's metadata. diff --git a/content/en/docs/reference/config-api/kube-controller-manager-config.v1alpha1.md b/content/en/docs/reference/config-api/kube-controller-manager-config.v1alpha1.md index d63e35f68a973..6988671969c32 100644 --- a/content/en/docs/reference/config-api/kube-controller-manager-config.v1alpha1.md +++ b/content/en/docs/reference/config-api/kube-controller-manager-config.v1alpha1.md @@ -769,7 +769,16 @@ This flag enables or disables reconcile. Is false by default, and thus enabled.

ReconcilerSyncLoopPeriod is the amount of time the reconciler sync states loop -wait between successive executions. Is set to 5 sec by default.

+wait between successive executions. Is set to 60 sec by default.

+ + +disableForceDetachOnTimeout [Required]
+bool + + +

DisableForceDetachOnTimeout disables force detach when the maximum unmount +time is exceeded. Is false by default, and thus force detach on unmount is +enabled.

diff --git a/content/en/docs/reference/config-api/kube-scheduler-config.v1.md b/content/en/docs/reference/config-api/kube-scheduler-config.v1.md index 886523e82e4b8..428f43f43dacd 100644 --- a/content/en/docs/reference/config-api/kube-scheduler-config.v1.md +++ b/content/en/docs/reference/config-api/kube-scheduler-config.v1.md @@ -396,7 +396,7 @@ Defaults to false.

addedAffinity
-core/v1.NodeAffinity +core/v1.NodeAffinity

AddedAffinity is applied to all Pods additionally to the NodeAffinity @@ -495,7 +495,7 @@ The default strategy is LeastAllocated with an equal "cpu" and "m defaultConstraints
-[]core/v1.TopologySpreadConstraint +[]core/v1.TopologySpreadConstraint

DefaultConstraints defines topology spread constraints to be applied to diff --git a/content/en/docs/reference/config-api/kubeadm-config.v1beta3.md b/content/en/docs/reference/config-api/kubeadm-config.v1beta3.md index bb4cec56503a7..2bca31da93069 100644 --- a/content/en/docs/reference/config-api/kubeadm-config.v1beta3.md +++ b/content/en/docs/reference/config-api/kubeadm-config.v1beta3.md @@ -307,7 +307,7 @@ for, so other administrators can know its purpose.

expires
-meta/v1.Time +meta/v1.Time

expires specifies the timestamp when this token expires. Defaults to being set @@ -1038,7 +1038,7 @@ file from which to load cluster information.

pathType
-core/v1.HostPathType +core/v1.HostPathType

pathType is the type of the hostPath.

@@ -1262,7 +1262,7 @@ This information will be annotated to the Node API object, for later re-use.

taints [Required]
-[]core/v1.Taint +[]core/v1.Taint

taints specifies the taints the Node API object should be registered with. @@ -1294,7 +1294,7 @@ Value all ignores errors from all checks.

imagePullPolicy
-core/v1.PullPolicy +core/v1.PullPolicy

imagePullPolicy specifies the policy for image pulling during kubeadm "init" and diff --git a/content/en/docs/reference/config-api/kubeadm-config.v1beta4.md b/content/en/docs/reference/config-api/kubeadm-config.v1beta4.md index c194ccacd1280..67ed2f8fb45db 100644 --- a/content/en/docs/reference/config-api/kubeadm-config.v1beta4.md +++ b/content/en/docs/reference/config-api/kubeadm-config.v1beta4.md @@ -10,8 +10,7 @@ This version improves on the v1beta3 format by fixing some minor issues and addi

A list of changes since v1beta3:

  • TODO https://github.com/kubernetes/kubeadm/issues/2890
  • -
  • Support custom environment variables in control plane components under -ClusterConfiguration. +
  • Support custom environment variables in control plane components under ClusterConfiguration. Use APIServer.ExtraEnvs, ControllerManager.ExtraEnvs, Scheduler.ExtraEnvs, Etcd.Local.ExtraEnvs.
  • The ResetConfiguration API type is now supported in v1beta4. @@ -21,12 +20,20 @@ Users are able to reset a node by passing a --config file to that support duplicates. The change applies to ClusterConfiguration - APIServer.ExtraArgs, ControllerManager.ExtraArgs, Scheduler.ExtraArgs. Also to NodeRegistrationOptions.KubeletExtraArgs.
  • Add ClusterConfiguration.EncryptionAlgorithm that can be used to set the asymmetric -encryption algorithm used for this cluster's keys and certificates. Can be "RSA" -(default algorithm, key size is 2048) or "ECDSA" (uses the P-256 elliptic curve).
  • +encryption algorithm used for this cluster's keys and certificates. Can be one of +"RSA-2048" (default), "RSA-3072", "RSA-4096" or "ECDSA-P256".
  • Add ClusterConfiguration.DNS.Disabled and ClusterConfiguration.Proxy.Disabled that can be used to disable the CoreDNS and kube-proxy addons during cluster initialization. Skipping the related addons phases, during cluster creation will set the same fields to false.
  • +
  • Add the NodeRegistration.ImagePullSerial field in 'InitConfigurationandJoinConfiguration`, which +can be used to control if kubeadm pulls images serially or in parallel.
  • +
  • The UpgradeConfiguration kubeadm API is now supported in v1beta4 when passing +--config to kubeadm upgrade subcommands. Usage of component configuration for kubelet and kube-proxy, +InitConfiguration and ClusterConfiguration is deprecated and will be ignored when passing --config to +upgrade subcommands.
  • +
  • Add a Timeouts structure to InitConfiguration, JoinConfiguration, ResetConfiguration and UpgradeConfiguration +that can be used to configure various timeouts.

Migration from old kubeadm config versions

    @@ -300,6 +307,7 @@ node only (e.g. the node ip).

    - [InitConfiguration](#kubeadm-k8s-io-v1beta4-InitConfiguration) - [JoinConfiguration](#kubeadm-k8s-io-v1beta4-JoinConfiguration) - [ResetConfiguration](#kubeadm-k8s-io-v1beta4-ResetConfiguration) +- [UpgradeConfiguration](#kubeadm-k8s-io-v1beta4-UpgradeConfiguration) @@ -347,7 +355,7 @@ for, so other administrators can know its purpose.

    expires
    -meta/v1.Time +meta/v1.Time

    expires specifies the timestamp when this token expires. Defaults to being set @@ -448,7 +456,7 @@ of view and as an authentication method for the node in the bootstrap phase of string -

    ontrolPlaneEndpoint sets a stable IP address or DNS name for the control plane; +

    controlPlaneEndpoint sets a stable IP address or DNS name for the control plane; It can be a valid IP address or a RFC-1123 DNS subdomain, both with optional TCP port. In case the controlPlaneEndpoint is not specified, the advertiseAddress + bindPort are used; in case the controlPlaneEndpoint is specified but without a TCP port, @@ -591,7 +599,7 @@ to the cluster.

    localAPIEndpoint represents the endpoint of the API server instance that's deployed on this control plane node. In HA setups, this differs from ClusterConfiguration.controlPlaneEndpoint -in the sense that ontrolPlaneEndpoint is the global endpoint for the cluster, which then +in the sense that controlPlaneEndpoint is the global endpoint for the cluster, which then loadbalances the requests to each individual API server. This configuration object lets you customize what IP/DNS name and port the local API server advertises it's accessible on. By default, kubeadm tries to auto-detect the IP of the default @@ -730,7 +738,7 @@ during the reset process.

    string -

    certificatesDir specifies the directory where the certificates are stored. +

    certificatesDir specifies the directory where the certificates are stored. If specified, it will be cleaned during the reset process.

    @@ -779,6 +787,59 @@ The list of phases can be obtained with the kubeadm reset phase --help +## `UpgradeConfiguration` {#kubeadm-k8s-io-v1beta4-UpgradeConfiguration} + + + +

    UpgradeConfiguration contains a list of options that are specific to kubeadm upgrade subcommands.

    + + + + + + + + + + + + + + + + + + + + + + + + + + +
    FieldDescription
    apiVersion
    string
    kubeadm.k8s.io/v1beta4
    kind
    string
    UpgradeConfiguration
    apply
    +UpgradeApplyConfiguration +
    +

    apply holds a list of options that are specific to the kubeadm upgrade apply command.

    +
    diff
    +UpgradeDiffConfiguration +
    +

    diff holds a list of options that are specific to the kubeadm upgrade diff command.

    +
    node
    +UpgradeNodeConfiguration +
    +

    node holds a list of options that are specific to the kubeadm upgrade node command.

    +
    plan
    +UpgradePlanConfiguration +
    +

    plan holds a list of options that are specific to the kubeadm upgrade plan command.

    +
    timeouts
    +Timeouts +
    +

    timeouts holds various timeouts that apply to kubeadm commands.

    +
    + ## `APIEndpoint` {#kubeadm-k8s-io-v1beta4-APIEndpoint} @@ -1113,7 +1174,7 @@ does not contain any other authentication information.

    EnvVar [Required]
    -core/v1.EnvVar +core/v1.EnvVar (Members of EnvVar are embedded into this type.) No description provided. @@ -1280,7 +1341,7 @@ file from which to load cluster information.

    pathType
    -core/v1.HostPathType +core/v1.HostPathType

    pathType is the type of the hostPath.

    @@ -1515,7 +1576,7 @@ This information will be annotated to the Node API object, for later re-use.

    taints [Required]
    -[]core/v1.Taint +[]core/v1.Taint

    taints specifies the taints the Node API object should be registered with. @@ -1548,7 +1609,7 @@ Value 'all' ignores errors from all checks.

    imagePullPolicy
    -core/v1.PullPolicy +core/v1.PullPolicy

    imagePullPolicy specifies the policy for image pulling during kubeadm init and @@ -1570,6 +1631,10 @@ images if not present on the host.

    - [JoinConfiguration](#kubeadm-k8s-io-v1beta4-JoinConfiguration) +- [UpgradeApplyConfiguration](#kubeadm-k8s-io-v1beta4-UpgradeApplyConfiguration) + +- [UpgradeNodeConfiguration](#kubeadm-k8s-io-v1beta4-UpgradeNodeConfiguration) +

    Patches contains options related to applying patches to components deployed by kubeadm.

    @@ -1622,4 +1687,352 @@ first alpha-numerically.

    + +## `Timeouts` {#kubeadm-k8s-io-v1beta4-Timeouts} + + +**Appears in:** + +- [UpgradeConfiguration](#kubeadm-k8s-io-v1beta4-UpgradeConfiguration) + + +

    Timeouts holds various timeouts that apply to kubeadm commands.

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    FieldDescription
    controlPlaneComponentHealthCheck
    +meta/v1.Duration +
    +

    controlPlaneComponentHealthCheck is the amount of time to wait for a control plane +component, such as the API server, to be healthy during kubeadm init and kubeadm join. +Default: 4m

    +
    kubeletHealthCheck
    +meta/v1.Duration +
    +

    kubeletHealthCheck is the amount of time to wait for the kubelet to be healthy +during kubeadm init and kubeadm join. +Default: 4m

    +
    kubernetesAPICall
    +meta/v1.Duration +
    +

    kubernetesAPICall is the amount of time to wait for the kubeadm client to complete a request to +the API server. This applies to all types of methods (GET, POST, etc). +Default: 1m

    +
    etcdAPICall
    +meta/v1.Duration +
    +

    etcdAPICall is the amount of time to wait for the kubeadm etcd client to complete a request to +the etcd cluster. +Default: 2m

    +
    tlsBootstrap
    +meta/v1.Duration +
    +

    tlsBootstrap is the amount of time to wait for the kubelet to complete TLS bootstrap +for a joining node. +Default: 5m

    +
    discovery
    +meta/v1.Duration +
    +

    discovery is the amount of time to wait for kubeadm to validate the API server identity +for a joining node. +Default: 5m

    +
    upgradeManifests [Required]
    +meta/v1.Duration +
    +

    upgradeManifests is the timeout for upgradring static Pod manifests +Default: 5m

    +
    + +## `UpgradeApplyConfiguration` {#kubeadm-k8s-io-v1beta4-UpgradeApplyConfiguration} + + +**Appears in:** + +- [UpgradeConfiguration](#kubeadm-k8s-io-v1beta4-UpgradeConfiguration) + + +

    UpgradeApplyConfiguration contains a list of configurable options which are specific to the "kubeadm upgrade apply" command.

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    FieldDescription
    kubernetesVersion
    +string +
    +

    kubernetesVersion is the target version of the control plane.

    +
    allowExperimentalUpgrades
    +bool +
    +

    allowExperimentalUpgrades instructs kubeadm to show unstable versions of Kubernetes as an upgrade +alternative and allows upgrading to an alpha/beta/release candidate version of Kubernetes. +Default: false

    +
    allowRCUpgrades
    +bool +
    +

    Enable allowRCUpgrades will show release candidate versions of Kubernetes as an upgrade alternative and +allows upgrading to a release candidate version of Kubernetes.

    +
    certificateRenewal
    +bool +
    +

    certificateRenewal instructs kubeadm to execute certificate renewal during upgrades. +Defaults to true.

    +
    dryRun
    +bool +
    +

    dryRun tells if the dry run mode is enabled, don't apply any change if it is and just output +what would be done.

    +
    etcdUpgrade
    +bool +
    +

    etcdUpgrade instructs kubeadm to execute etcd upgrade during upgrades. +Defaults to true.

    +
    forceUpgrade
    +bool +
    +

    forceUpgrade flag instructs kubeadm to upgrade the cluster without prompting for confirmation.

    +
    ignorePreflightErrors
    +[]string +
    +

    ignorePreflightErrors provides a slice of pre-flight errors to be ignored during the upgrade process, +e.g. 'IsPrivilegedUser,Swap'. Value 'all' ignores errors from all checks.

    +
    patches
    +Patches +
    +

    patches contains options related to applying patches to components deployed by kubeadm during "kubeadm upgrade".

    +
    printConfig
    +bool +
    +

    printConfig specifies whether the configuration file that will be used in the upgrade should be printed or not.

    +
    SkipPhases [Required]
    +[]string +
    +

    skipPhases is a list of phases to skip during command execution. +NOTE: This field is currently ignored for "kubeadm upgrade apply", but in the future it will be supported.

    +
    + +## `UpgradeDiffConfiguration` {#kubeadm-k8s-io-v1beta4-UpgradeDiffConfiguration} + + +**Appears in:** + +- [UpgradeConfiguration](#kubeadm-k8s-io-v1beta4-UpgradeConfiguration) + + +

    UpgradeDiffConfiguration contains a list of configurable options which are specific to the "kubeadm upgrade diff" command.

    + + + + + + + + + + + + + + +
    FieldDescription
    kubernetesVersion
    +string +
    +

    kubernetesVersion is the target version of the control plane.

    +
    contextLines
    +int +
    +

    diffContextLines is the number of lines of context in the diff.

    +
    + +## `UpgradeNodeConfiguration` {#kubeadm-k8s-io-v1beta4-UpgradeNodeConfiguration} + + +**Appears in:** + +- [UpgradeConfiguration](#kubeadm-k8s-io-v1beta4-UpgradeConfiguration) + + +

    UpgradeNodeConfiguration contains a list of configurable options which are specific to the "kubeadm upgrade node" command.

    + + + + + + + + + + + + + + + + + + + + + + + + + + +
    FieldDescription
    certificateRenewal
    +bool +
    +

    certificateRenewal instructs kubeadm to execute certificate renewal during upgrades. +Defaults to true.

    +
    dryRun
    +bool +
    +

    dryRun tells if the dry run mode is enabled, don't apply any change if it is and just output what would be done.

    +
    etcdUpgrade
    +bool +
    +

    etcdUpgrade instructs kubeadm to execute etcd upgrade during upgrades. +Defaults to true.

    +
    ignorePreflightErrors
    +[]string +
    +

    ignorePreflightErrors provides a slice of pre-flight errors to be ignored during the upgrade process, +e.g. 'IsPrivilegedUser,Swap'. Value 'all' ignores errors from all checks.

    +
    skipPhases
    +[]string +
    +

    skipPhases is a list of phases to skip during command execution. +The list of phases can be obtained with the kubeadm upgrade node phase --help command.

    +
    patches
    +Patches +
    +

    patches contains options related to applying patches to components deployed by kubeadm during kubeadm upgrade.

    +
    + +## `UpgradePlanConfiguration` {#kubeadm-k8s-io-v1beta4-UpgradePlanConfiguration} + + +**Appears in:** + +- [UpgradeConfiguration](#kubeadm-k8s-io-v1beta4-UpgradeConfiguration) + + +

    UpgradePlanConfiguration contains a list of configurable options which are specific to the "kubeadm upgrade plan" command.

    + + + + + + + + + + + + + + + + + + + + + + + + + + +
    FieldDescription
    kubernetesVersion [Required]
    +string +
    +

    kubernetesVersion is the target version of the control plane.

    +
    allowExperimentalUpgrades
    +bool +
    +

    allowExperimentalUpgrades instructs kubeadm to show unstable versions of Kubernetes as an upgrade +alternative and allows upgrading to an alpha/beta/release candidate version of Kubernetes. +Default: false

    +
    allowRCUpgrades
    +bool +
    +

    Enable allowRCUpgrades will show release candidate versions of Kubernetes as an upgrade alternative and +allows upgrading to a release candidate version of Kubernetes.

    +
    dryRun
    +bool +
    +

    dryRun tells if the dry run mode is enabled, don't apply any change if it is and just output what would be done.

    +
    ignorePreflightErrors
    +[]string +
    +

    ignorePreflightErrors provides a slice of pre-flight errors to be ignored during the upgrade process, +e.g. 'IsPrivilegedUser,Swap'. Value 'all' ignores errors from all checks.

    +
    printConfig
    +bool +
    +

    printConfig specifies whether the configuration file that will be used in the upgrade should be printed or not.

    +
    \ No newline at end of file diff --git a/content/en/docs/reference/config-api/kubelet-config.v1.md b/content/en/docs/reference/config-api/kubelet-config.v1.md index 83dbc993f1993..7de3e195a95a4 100644 --- a/content/en/docs/reference/config-api/kubelet-config.v1.md +++ b/content/en/docs/reference/config-api/kubelet-config.v1.md @@ -80,9 +80,9 @@ to provide credentials. Images are expected to contain the registry domain and URL path.

    Each entry in matchImages is a pattern which can optionally contain a port and a path. Globs can be used in the domain, but not in the port or the path. Globs are supported -as subdomains like '.k8s.io' or 'k8s..io', and top-level-domains such as 'k8s.'. -Matching partial subdomains like 'app.k8s.io' is also supported. Each glob can only match -a single subdomain segment, so *.io does not match *.k8s.io.

    +as subdomains like '*.k8s.io' or 'k8s.*.io', and top-level-domains such as 'k8s.*'. +Matching partial subdomains like 'app*.k8s.io' is also supported. Each glob can only match +a single subdomain segment, so '*.io' does not match '*.k8s.io'.

    A match exists between an image and a matchImage when all of the below are true:

    • Both contain the same number of domain parts and each part matches.
    • @@ -92,9 +92,9 @@ a single subdomain segment, so *.io does not match *.k8s.io.

      Example values of matchImages:

      • 123456789.dkr.ecr.us-east-1.amazonaws.com
      • -
      • *.azurecr.io
      • +
      • *.azurecr.io
      • gcr.io
      • -
      • ..registry.io
      • +
      • *.*.registry.io
      • registry.io:8080/path
      @@ -168,4 +168,4 @@ credential plugin.

      - \ No newline at end of file + diff --git a/content/en/docs/reference/config-api/kubelet-config.v1beta1.md b/content/en/docs/reference/config-api/kubelet-config.v1beta1.md index 2975657ccfd19..1abe592ff380e 100644 --- a/content/en/docs/reference/config-api/kubelet-config.v1beta1.md +++ b/content/en/docs/reference/config-api/kubelet-config.v1beta1.md @@ -32,6 +32,14 @@ auto_generated: true +text [Required]
      +TextOptions + + +

      [Alpha] Text contains options for logging format "text". +Only available when the LoggingAlphaOptions feature gate is enabled.

      + + json [Required]
      JSONOptions @@ -59,24 +67,11 @@ Only available when the LoggingAlphaOptions feature gate is enabled.

      -splitStream [Required]
      -bool - - -

      [Alpha] SplitStream redirects error messages to stderr while -info messages go to stdout, with buffering. The default is to write -both to stdout, without buffering. Only available when -the LoggingAlphaOptions feature gate is enabled.

      - - -infoBufferSize [Required]
      -k8s.io/apimachinery/pkg/api/resource.QuantityValue - - -

      [Alpha] InfoBufferSize sets the size of the info stream when -using split streams. The default is zero, which disables buffering. -Only available when the LoggingAlphaOptions feature gate is enabled.

      +OutputRoutingOptions [Required]
      +OutputRoutingOptions +(Members of OutputRoutingOptions are embedded into this type.) + No description provided. @@ -186,6 +181,71 @@ certain global defaults.

      +## `OutputRoutingOptions` {#OutputRoutingOptions} + + +**Appears in:** + +- [JSONOptions](#JSONOptions) + +- [TextOptions](#TextOptions) + + +

      OutputRoutingOptions contains options that are supported by both "text" and "json".

      + + + + + + + + + + + + + + +
      FieldDescription
      splitStream [Required]
      +bool +
      +

      [Alpha] SplitStream redirects error messages to stderr while +info messages go to stdout, with buffering. The default is to write +both to stdout, without buffering. Only available when +the LoggingAlphaOptions feature gate is enabled.

      +
      infoBufferSize [Required]
      +k8s.io/apimachinery/pkg/api/resource.QuantityValue +
      +

      [Alpha] InfoBufferSize sets the size of the info stream when +using split streams. The default is zero, which disables buffering. +Only available when the LoggingAlphaOptions feature gate is enabled.

      +
      + +## `TextOptions` {#TextOptions} + + +**Appears in:** + +- [FormatOptions](#FormatOptions) + + +

      TextOptions contains options for logging format "text".

      + + + + + + + + + + + +
      FieldDescription
      OutputRoutingOptions [Required]
      +OutputRoutingOptions +
      (Members of OutputRoutingOptions are embedded into this type.) + No description provided.
      + ## `TimeOrMetaDuration` {#TimeOrMetaDuration} @@ -352,6 +412,16 @@ run, or the path to a single static pod file. Default: ""

      +podLogsDir
      +string + + +

      podLogsDir is a custom root directory path kubelet will use to place pod's log files. +Default: "/var/log/pods/" +Note: it is not recommended to use the temp folder as a log directory as it may cause +unexpected behavior in many places.

      + + syncFrequency
      meta/v1.Duration @@ -449,7 +519,7 @@ Default: ""

      tlsCipherSuites is the list of allowed cipher suites for the server. Note that TLS 1.3 ciphersuites are not configurable. -Values are from tls package constants (https://pkg.go.dev/crypto/tls#pkg-constants). +Values are from tls package constants (https://golang.org/pkg/crypto/tls/#pkg-constants). Default: nil

      @@ -458,7 +528,7 @@ Default: nil

      tlsMinVersion is the minimum TLS version supported. -Values are from tls package constants (https://pkg.go.dev/crypto/tls#pkg-constants). +Values are from tls package constants (https://golang.org/pkg/crypto/tls/#pkg-constants). Default: ""

      @@ -1176,6 +1246,27 @@ be present for a container. Default: 5

      +containerLogMaxWorkers
      +int32 + + +

      ContainerLogMaxWorkers specifies the maximum number of concurrent workers to spawn +for performing the log rotate operations. Set this count to 1 for disabling the +concurrent log rotation workflows +Default: 1

      + + +containerLogMonitorInterval
      +meta/v1.Duration + + +

      ContainerLogMonitorInterval specifies the duration at which the container logs are monitored +for performing the log rotate operation. This defaults to 10 * time.Seconds. But can be +customized to a smaller value based on the log generation rate and the size required to be +rotated against +Default: 10s

      + + configMapAndSecretChangeDetectionStrategy
      ResourceChangeDetectionStrategy @@ -1416,7 +1507,7 @@ Also, avoid specifying:

    • Duplicates, the same NUMA node, and memory type, but with a different value.
    • zero limits for any memory type.
    • NUMAs nodes IDs that do not exist under the machine.
    • -
    • memory types except for memory and hugepages-
    • +
    • memory types except for memory and hugepages-<size>
    • Default: nil

      @@ -1458,7 +1549,7 @@ Default: 0.9

      registerWithTaints
      -[]core/v1.Taint +[]core/v1.Taint

      registerWithTaints are an array of taints to add to a node object when @@ -1538,7 +1629,7 @@ It exists in the kubeletconfig API group because it is classified as a versioned source
      -core/v1.NodeConfigSource +core/v1.NodeConfigSource

      source is the source that we are serializing.

      @@ -1584,9 +1675,9 @@ to provide credentials. Images are expected to contain the registry domain and URL path.

      Each entry in matchImages is a pattern which can optionally contain a port and a path. Globs can be used in the domain, but not in the port or the path. Globs are supported -as subdomains like '.k8s.io' or 'k8s..io', and top-level-domains such as 'k8s.'. -Matching partial subdomains like 'app.k8s.io' is also supported. Each glob can only match -a single subdomain segment, so *.io does not match *.k8s.io.

      +as subdomains like '*.k8s.io' or 'k8s.*.io', and top-level-domains such as 'k8s.*'. +Matching partial subdomains like 'app*.k8s.io' is also supported. Each glob can only match +a single subdomain segment, so '*.io' does not match '*.k8s.io'.

      A match exists between an image and a matchImage when all of the below are true:

      • Both contain the same number of domain parts and each part matches.
      • @@ -1596,9 +1687,9 @@ a single subdomain segment, so *.io does not match *.k8s.io.

        Example values of matchImages:

        • 123456789.dkr.ecr.us-east-1.amazonaws.com
        • -
        • *.azurecr.io
        • +
        • *.azurecr.io
        • gcr.io
        • -
        • ..registry.io
        • +
        • *.*.registry.io
        • registry.io:8080/path
        @@ -1899,7 +1990,7 @@ and groups corresponding to the Organization in the client certificate.

        No description provided. limits [Required]
        -core/v1.ResourceList +core/v1.ResourceList No description provided. @@ -1926,8 +2017,8 @@ and groups corresponding to the Organization in the client certificate.

        swapBehavior configures swap memory available to container workloads. May be one of -"", "LimitedSwap": workload combined memory and swap usage cannot exceed pod memory limit -"UnlimitedSwap": workloads can use unlimited swap, up to the allocatable limit.

        +"", "NoSwap": workloads can not use swap, default option. +"LimitedSwap": workload swap usage is limited. The swap limit is proportionate to the container's memory request.

        @@ -1980,4 +2071,4 @@ managers (secret, configmap) are discovering object changes.

        - \ No newline at end of file + diff --git a/content/en/docs/reference/config-api/kubelet-credentialprovider.v1.md b/content/en/docs/reference/config-api/kubelet-credentialprovider.v1.md index 8575b92303461..4ad907614e0a2 100644 --- a/content/en/docs/reference/config-api/kubelet-credentialprovider.v1.md +++ b/content/en/docs/reference/config-api/kubelet-credentialprovider.v1.md @@ -88,9 +88,9 @@ should be valid for all images that match against this key. A plugin should set this field to null if no valid credentials can be returned for the requested image.

        Each key in the map is a pattern which can optionally contain a port and a path. Globs can be used in the domain, but not in the port or the path. Globs are supported -as subdomains like '.k8s.io' or 'k8s..io', and top-level-domains such as 'k8s.'. -Matching partial subdomains like 'app.k8s.io' is also supported. Each glob can only match -a single subdomain segment, so *.io does not match *.k8s.io.

        +as subdomains like '*.k8s.io' or 'k8s.*.io', and top-level-domains such as 'k8s.*'. +Matching partial subdomains like 'app*.k8s.io' is also supported. Each glob can only match +a single subdomain segment, so '*.io' does not match '*.k8s.io'.

        The kubelet will match images against the key when all of the below are true:

        • Both contain the same number of domain parts and each part matches.
        • @@ -107,9 +107,9 @@ stopping after the first successfully authenticated pull.

          Example keys:

          • 123456789.dkr.ecr.us-east-1.amazonaws.com
          • -
          • *.azurecr.io
          • +
          • *.azurecr.io
          • gcr.io
          • -
          • ..registry.io
          • +
          • *.*.registry.io
          • registry.io:8080/path
          @@ -165,4 +165,4 @@ An empty password is valid.

          - \ No newline at end of file + diff --git a/content/en/docs/reference/glossary/immutable-infrastructure.md b/content/en/docs/reference/glossary/immutable-infrastructure.md new file mode 100644 index 0000000000000..b0af309dad352 --- /dev/null +++ b/content/en/docs/reference/glossary/immutable-infrastructure.md @@ -0,0 +1,26 @@ +--- +title: Immutable Infrastructure +id: immutable-infrastructure +date: 2024-03-25 +full_link: +short_description: > + Immutable Infrastructure refers to computer infrastructure (virtual machines, containers, network appliances) that cannot be changed once deployed + +aka: +tags: +- architecture +--- + Immutable Infrastructure refers to computer infrastructure (virtual machines, containers, network appliances) that cannot be changed once deployed. + + + +Immutability can be enforced by an automated process that overwrites unauthorized changes or through a system that won’t allow changes in the first place. +{{< glossary_tooltip text="Containers" term_id="container" >}} are a good example of immutable infrastructure because persistent changes to containers +can only be made by creating a new version of the container or recreating the existing container from its image. + +By preventing or identifying unauthorized changes, immutable infrastructures make it easier to identify and mitigate security risks. +Operating such a system becomes a lot more straightforward because administrators can make assumptions about it. +After all, they know no one made mistakes or changes they forgot to communicate. +Immutable infrastructure goes hand-in-hand with infrastructure as code where all automation needed +to create infrastructure is stored in version control (such as Git). +This combination of immutability and version control means that there is a durable audit log of every authorized change to a system. diff --git a/content/en/docs/reference/glossary/index.md b/content/en/docs/reference/glossary/index.md index 29bd54bd21d36..1a0312369bd04 100644 --- a/content/en/docs/reference/glossary/index.md +++ b/content/en/docs/reference/glossary/index.md @@ -5,6 +5,7 @@ approvers: title: Glossary layout: glossary noedit: true +body_class: glossary default_active_tag: fundamental weight: 5 card: diff --git a/content/en/docs/reference/glossary/init-container.md b/content/en/docs/reference/glossary/init-container.md index a999042e3056f..591e534a1ca60 100644 --- a/content/en/docs/reference/glossary/init-container.md +++ b/content/en/docs/reference/glossary/init-container.md @@ -2,10 +2,9 @@ title: Init Container id: init-container date: 2018-04-12 -full_link: +full_link: /docs/concepts/workloads/pods/init-containers/ short_description: > One or more initialization containers that must run to completion before any app containers run. - aka: tags: - fundamental @@ -15,3 +14,7 @@ tags: Initialization (init) containers are like regular app containers, with one difference: init containers must run to completion before any app containers can start. Init containers run in series: each init container must run to completion before the next init container begins. + +Unlike {{< glossary_tooltip text="sidecar containers" term_id="sidecar-container" >}}, init containers do not remain running after Pod startup. + +For more information, read [init containers](/docs/concepts/workloads/pods/init-containers/). diff --git a/content/en/docs/reference/glossary/priority-class.md b/content/en/docs/reference/glossary/priority-class.md new file mode 100644 index 0000000000000..612a43449be90 --- /dev/null +++ b/content/en/docs/reference/glossary/priority-class.md @@ -0,0 +1,20 @@ +--- +title: PriorityClass +id: priority-class +date: 2024-03-19 +full_link: /docs/concepts/scheduling-eviction/pod-priority-preemption/#priorityclass +short_description: > + A mapping from a class name to the scheduling priority that a Pod should have. +aka: +tags: +- core-object +--- +A PriorityClass is a named class for the scheduling priority that should be assigned to a Pod +in that class. + + + +A [PriorityClass](/docs/concepts/scheduling-eviction/pod-priority-preemption/#how-to-use-priority-and-preemption) +is a non-namespaced object mapping a name to an integer priority, used for a Pod. The name is +specified in the `metadata.name` field, and the priority value in the `value` field. Priorities range from +-2147483648 to 1000000000 inclusive. Higher values indicate higher priority. diff --git a/content/en/docs/reference/glossary/sidecar-container.md b/content/en/docs/reference/glossary/sidecar-container.md new file mode 100644 index 0000000000000..97faa10153216 --- /dev/null +++ b/content/en/docs/reference/glossary/sidecar-container.md @@ -0,0 +1,20 @@ +--- +title: Sidecar Container +id: sidecar-container +date: 2018-04-12 +full_link: +short_description: > + An auxilliary container that stays running throughout the lifecycle of a Pod. +full_link: /docs/concepts/workloads/pods/sidecar-containers/ +tags: +- fundamental +--- + One or more {{< glossary_tooltip text="containers" term_id="container" >}} that are typically started before any app containers run. + + + +Sidecar containers are like regular app containers, but with a different purpose: the sidecar provides a Pod-local service to the main app container. +Unlike {{< glossary_tooltip text="init containers" term_id="init-container" >}}, sidecar containers +continue running after Pod startup. + +Read [Sidecar containers](/docs/concepts/workloads/pods/sidecar-containers/) for more information. diff --git a/content/en/docs/reference/kubectl/generated/kubectl.md b/content/en/docs/reference/kubectl/generated/kubectl.md index 2a34e7fa4fa34..249aa872103cb 100644 --- a/content/en/docs/reference/kubectl/generated/kubectl.md +++ b/content/en/docs/reference/kubectl/generated/kubectl.md @@ -59,13 +59,6 @@ kubectl [flags]

          UID to impersonate for the operation.

          - ---azure-container-registry-config string - - -

          Path to the file containing Azure container registry configuration information.

          - - --cache-dir string     Default: "$HOME/.kube/cache" diff --git a/content/en/docs/reference/kubectl/generated/kubectl_annotate/_index.md b/content/en/docs/reference/kubectl/generated/kubectl_annotate/_index.md index 611b30178b336..f053a41eef968 100644 --- a/content/en/docs/reference/kubectl/generated/kubectl_annotate/_index.md +++ b/content/en/docs/reference/kubectl/generated/kubectl_annotate/_index.md @@ -228,13 +228,6 @@ kubectl annotate [--overwrite] (-f FILENAME | TYPE NAME) KEY_1=VAL_1 ... KEY_N=V

          UID to impersonate for the operation.

          - ---azure-container-registry-config string - - -

          Path to the file containing Azure container registry configuration information.

          - - --cache-dir string     Default: "$HOME/.kube/cache" diff --git a/content/en/docs/reference/kubectl/generated/kubectl_api-resources/_index.md b/content/en/docs/reference/kubectl/generated/kubectl_api-resources/_index.md index 7457dc8d34b5f..7966d689fac4a 100644 --- a/content/en/docs/reference/kubectl/generated/kubectl_api-resources/_index.md +++ b/content/en/docs/reference/kubectl/generated/kubectl_api-resources/_index.md @@ -157,13 +157,6 @@ kubectl api-resources [flags]

          UID to impersonate for the operation.

          - ---azure-container-registry-config string - - -

          Path to the file containing Azure container registry configuration information.

          - - --cache-dir string     Default: "$HOME/.kube/cache" diff --git a/content/en/docs/reference/kubectl/generated/kubectl_api-versions/_index.md b/content/en/docs/reference/kubectl/generated/kubectl_api-versions/_index.md index 3c63eb25052bb..edd70ee137d94 100644 --- a/content/en/docs/reference/kubectl/generated/kubectl_api-versions/_index.md +++ b/content/en/docs/reference/kubectl/generated/kubectl_api-versions/_index.md @@ -86,13 +86,6 @@ kubectl api-versions

          UID to impersonate for the operation.

          - ---azure-container-registry-config string - - -

          Path to the file containing Azure container registry configuration information.

          - - --cache-dir string     Default: "$HOME/.kube/cache" diff --git a/content/en/docs/reference/kubectl/generated/kubectl_apply/_index.md b/content/en/docs/reference/kubectl/generated/kubectl_apply/_index.md index 15587371c62b9..3a695679cdc99 100644 --- a/content/en/docs/reference/kubectl/generated/kubectl_apply/_index.md +++ b/content/en/docs/reference/kubectl/generated/kubectl_apply/_index.md @@ -267,13 +267,6 @@ kubectl apply (-f FILENAME | -k DIRECTORY)

          UID to impersonate for the operation.

          - ---azure-container-registry-config string - - -

          Path to the file containing Azure container registry configuration information.

          - - --cache-dir string     Default: "$HOME/.kube/cache" diff --git a/content/en/docs/reference/kubectl/generated/kubectl_apply/kubectl_apply_edit-last-applied.md b/content/en/docs/reference/kubectl/generated/kubectl_apply/kubectl_apply_edit-last-applied.md index 2e12d98d0f5a9..4dee3ca50cd25 100644 --- a/content/en/docs/reference/kubectl/generated/kubectl_apply/kubectl_apply_edit-last-applied.md +++ b/content/en/docs/reference/kubectl/generated/kubectl_apply/kubectl_apply_edit-last-applied.md @@ -166,13 +166,6 @@ kubectl apply edit-last-applied (RESOURCE/NAME | -f FILENAME)

          UID to impersonate for the operation.

          - ---azure-container-registry-config string - - -

          Path to the file containing Azure container registry configuration information.

          - - --cache-dir string     Default: "$HOME/.kube/cache" diff --git a/content/en/docs/reference/kubectl/generated/kubectl_apply/kubectl_apply_set-last-applied.md b/content/en/docs/reference/kubectl/generated/kubectl_apply/kubectl_apply_set-last-applied.md index 6dc2da4e29494..75df869a4c855 100644 --- a/content/en/docs/reference/kubectl/generated/kubectl_apply/kubectl_apply_set-last-applied.md +++ b/content/en/docs/reference/kubectl/generated/kubectl_apply/kubectl_apply_set-last-applied.md @@ -140,13 +140,6 @@ kubectl apply set-last-applied -f FILENAME

          UID to impersonate for the operation.

          - ---azure-container-registry-config string - - -

          Path to the file containing Azure container registry configuration information.

          - - --cache-dir string     Default: "$HOME/.kube/cache" diff --git a/content/en/docs/reference/kubectl/generated/kubectl_apply/kubectl_apply_view-last-applied.md b/content/en/docs/reference/kubectl/generated/kubectl_apply/kubectl_apply_view-last-applied.md index c3a138d68c53c..f5819c7d58e42 100644 --- a/content/en/docs/reference/kubectl/generated/kubectl_apply/kubectl_apply_view-last-applied.md +++ b/content/en/docs/reference/kubectl/generated/kubectl_apply/kubectl_apply_view-last-applied.md @@ -132,13 +132,6 @@ kubectl apply view-last-applied (TYPE [NAME | -l label] | TYPE/NAME | -f FILENAM

          UID to impersonate for the operation.

          - ---azure-container-registry-config string - - -

          Path to the file containing Azure container registry configuration information.

          - - --cache-dir string     Default: "$HOME/.kube/cache" diff --git a/content/en/docs/reference/kubectl/generated/kubectl_attach/_index.md b/content/en/docs/reference/kubectl/generated/kubectl_attach/_index.md index de53451202a34..9a69031dfd2b5 100644 --- a/content/en/docs/reference/kubectl/generated/kubectl_attach/_index.md +++ b/content/en/docs/reference/kubectl/generated/kubectl_attach/_index.md @@ -132,13 +132,6 @@ kubectl attach (POD | TYPE/NAME) -c CONTAINER

          UID to impersonate for the operation.

          - ---azure-container-registry-config string - - -

          Path to the file containing Azure container registry configuration information.

          - - --cache-dir string     Default: "$HOME/.kube/cache" diff --git a/content/en/docs/reference/kubectl/generated/kubectl_auth/_index.md b/content/en/docs/reference/kubectl/generated/kubectl_auth/_index.md index 0885909fd4408..7173c4bee1f5f 100644 --- a/content/en/docs/reference/kubectl/generated/kubectl_auth/_index.md +++ b/content/en/docs/reference/kubectl/generated/kubectl_auth/_index.md @@ -79,13 +79,6 @@ kubectl auth [flags]

          UID to impersonate for the operation.

          - ---azure-container-registry-config string - - -

          Path to the file containing Azure container registry configuration information.

          - - --cache-dir string     Default: "$HOME/.kube/cache" diff --git a/content/en/docs/reference/kubectl/generated/kubectl_auth/kubectl_auth_can-i.md b/content/en/docs/reference/kubectl/generated/kubectl_auth/kubectl_auth_can-i.md index 283efb27d402f..b1c063440bdd7 100644 --- a/content/en/docs/reference/kubectl/generated/kubectl_auth/kubectl_auth_can-i.md +++ b/content/en/docs/reference/kubectl/generated/kubectl_auth/kubectl_auth_can-i.md @@ -145,13 +145,6 @@ kubectl auth can-i VERB [TYPE | TYPE/NAME | NONRESOURCEURL]

          UID to impersonate for the operation.

          - ---azure-container-registry-config string - - -

          Path to the file containing Azure container registry configuration information.

          - - --cache-dir string     Default: "$HOME/.kube/cache" diff --git a/content/en/docs/reference/kubectl/generated/kubectl_auth/kubectl_auth_reconcile.md b/content/en/docs/reference/kubectl/generated/kubectl_auth/kubectl_auth_reconcile.md index 88dc2cd8476f4..2bd7a1acc3bf5 100644 --- a/content/en/docs/reference/kubectl/generated/kubectl_auth/kubectl_auth_reconcile.md +++ b/content/en/docs/reference/kubectl/generated/kubectl_auth/kubectl_auth_reconcile.md @@ -163,13 +163,6 @@ kubectl auth reconcile -f FILENAME

          UID to impersonate for the operation.

          - ---azure-container-registry-config string - - -

          Path to the file containing Azure container registry configuration information.

          - - --cache-dir string     Default: "$HOME/.kube/cache" diff --git a/content/en/docs/reference/kubectl/generated/kubectl_auth/kubectl_auth_whoami.md b/content/en/docs/reference/kubectl/generated/kubectl_auth/kubectl_auth_whoami.md index 8080079a9cb15..1d87c7e8486e8 100644 --- a/content/en/docs/reference/kubectl/generated/kubectl_auth/kubectl_auth_whoami.md +++ b/content/en/docs/reference/kubectl/generated/kubectl_auth/kubectl_auth_whoami.md @@ -120,13 +120,6 @@ kubectl auth whoami

          UID to impersonate for the operation.

          - ---azure-container-registry-config string - - -

          Path to the file containing Azure container registry configuration information.

          - - --cache-dir string     Default: "$HOME/.kube/cache" diff --git a/content/en/docs/reference/kubectl/generated/kubectl_autoscale/_index.md b/content/en/docs/reference/kubectl/generated/kubectl_autoscale/_index.md index 1d4906cbbf851..503e775e1da8f 100644 --- a/content/en/docs/reference/kubectl/generated/kubectl_autoscale/_index.md +++ b/content/en/docs/reference/kubectl/generated/kubectl_autoscale/_index.md @@ -189,13 +189,6 @@ kubectl autoscale (-f FILENAME | TYPE NAME | TYPE/NAME) [--min=MINPODS] --max=MA

          UID to impersonate for the operation.

          - ---azure-container-registry-config string - - -

          Path to the file containing Azure container registry configuration information.

          - - --cache-dir string     Default: "$HOME/.kube/cache" diff --git a/content/en/docs/reference/kubectl/generated/kubectl_certificate/_index.md b/content/en/docs/reference/kubectl/generated/kubectl_certificate/_index.md index 7270dded9262b..43292d61606fe 100644 --- a/content/en/docs/reference/kubectl/generated/kubectl_certificate/_index.md +++ b/content/en/docs/reference/kubectl/generated/kubectl_certificate/_index.md @@ -79,13 +79,6 @@ kubectl certificate SUBCOMMAND

          UID to impersonate for the operation.

          - ---azure-container-registry-config string - - -

          Path to the file containing Azure container registry configuration information.

          - - --cache-dir string     Default: "$HOME/.kube/cache" diff --git a/content/en/docs/reference/kubectl/generated/kubectl_certificate/kubectl_certificate_approve.md b/content/en/docs/reference/kubectl/generated/kubectl_certificate/kubectl_certificate_approve.md index 628a001aba272..3c741798db7bd 100644 --- a/content/en/docs/reference/kubectl/generated/kubectl_certificate/kubectl_certificate_approve.md +++ b/content/en/docs/reference/kubectl/generated/kubectl_certificate/kubectl_certificate_approve.md @@ -145,13 +145,6 @@ kubectl certificate approve (-f FILENAME | NAME)

          UID to impersonate for the operation.

          - ---azure-container-registry-config string - - -

          Path to the file containing Azure container registry configuration information.

          - - --cache-dir string     Default: "$HOME/.kube/cache" diff --git a/content/en/docs/reference/kubectl/generated/kubectl_certificate/kubectl_certificate_deny.md b/content/en/docs/reference/kubectl/generated/kubectl_certificate/kubectl_certificate_deny.md index a119682f851df..9b138d52b2aa3 100644 --- a/content/en/docs/reference/kubectl/generated/kubectl_certificate/kubectl_certificate_deny.md +++ b/content/en/docs/reference/kubectl/generated/kubectl_certificate/kubectl_certificate_deny.md @@ -143,13 +143,6 @@ kubectl certificate deny (-f FILENAME | NAME)

          UID to impersonate for the operation.

          - ---azure-container-registry-config string - - -

          Path to the file containing Azure container registry configuration information.

          - - --cache-dir string     Default: "$HOME/.kube/cache" diff --git a/content/en/docs/reference/kubectl/generated/kubectl_cluster-info/_index.md b/content/en/docs/reference/kubectl/generated/kubectl_cluster-info/_index.md index acc42af2f9cdc..ce7afb8167d7d 100644 --- a/content/en/docs/reference/kubectl/generated/kubectl_cluster-info/_index.md +++ b/content/en/docs/reference/kubectl/generated/kubectl_cluster-info/_index.md @@ -86,13 +86,6 @@ kubectl cluster-info [flags]

          UID to impersonate for the operation.

          - ---azure-container-registry-config string - - -

          Path to the file containing Azure container registry configuration information.

          - - --cache-dir string     Default: "$HOME/.kube/cache" diff --git a/content/en/docs/reference/kubectl/generated/kubectl_cluster-info/kubectl_cluster-info_dump.md b/content/en/docs/reference/kubectl/generated/kubectl_cluster-info/kubectl_cluster-info_dump.md index 3b680b06d9bbc..6c0e3e6d6e56b 100644 --- a/content/en/docs/reference/kubectl/generated/kubectl_cluster-info/kubectl_cluster-info_dump.md +++ b/content/en/docs/reference/kubectl/generated/kubectl_cluster-info/kubectl_cluster-info_dump.md @@ -152,13 +152,6 @@ kubectl cluster-info dump [flags]

          UID to impersonate for the operation.

          - ---azure-container-registry-config string - - -

          Path to the file containing Azure container registry configuration information.

          - - --cache-dir string     Default: "$HOME/.kube/cache" diff --git a/content/en/docs/reference/kubectl/generated/kubectl_completion/_index.md b/content/en/docs/reference/kubectl/generated/kubectl_completion/_index.md index 82b20219a75f7..d2def578a5574 100644 --- a/content/en/docs/reference/kubectl/generated/kubectl_completion/_index.md +++ b/content/en/docs/reference/kubectl/generated/kubectl_completion/_index.md @@ -143,13 +143,6 @@ kubectl completion SHELL

          UID to impersonate for the operation.

          - ---azure-container-registry-config string - - -

          Path to the file containing Azure container registry configuration information.

          - - --cache-dir string     Default: "$HOME/.kube/cache" diff --git a/content/en/docs/reference/kubectl/generated/kubectl_config/_index.md b/content/en/docs/reference/kubectl/generated/kubectl_config/_index.md index c4976676426b5..7b52f4e718c92 100644 --- a/content/en/docs/reference/kubectl/generated/kubectl_config/_index.md +++ b/content/en/docs/reference/kubectl/generated/kubectl_config/_index.md @@ -92,13 +92,6 @@ kubectl config SUBCOMMAND

          UID to impersonate for the operation.

          - ---azure-container-registry-config string - - -

          Path to the file containing Azure container registry configuration information.

          - - --cache-dir string     Default: "$HOME/.kube/cache" diff --git a/content/en/docs/reference/kubectl/generated/kubectl_config/kubectl_config_current-context.md b/content/en/docs/reference/kubectl/generated/kubectl_config/kubectl_config_current-context.md index b095a52cfaa39..7c54644ee3c66 100644 --- a/content/en/docs/reference/kubectl/generated/kubectl_config/kubectl_config_current-context.md +++ b/content/en/docs/reference/kubectl/generated/kubectl_config/kubectl_config_current-context.md @@ -85,13 +85,6 @@ kubectl config current-context [flags]

          UID to impersonate for the operation.

          - ---azure-container-registry-config string - - -

          Path to the file containing Azure container registry configuration information.

          - - --cache-dir string     Default: "$HOME/.kube/cache" diff --git a/content/en/docs/reference/kubectl/generated/kubectl_config/kubectl_config_delete-cluster.md b/content/en/docs/reference/kubectl/generated/kubectl_config/kubectl_config_delete-cluster.md index 343865f278a4e..dbcf5453c82a0 100644 --- a/content/en/docs/reference/kubectl/generated/kubectl_config/kubectl_config_delete-cluster.md +++ b/content/en/docs/reference/kubectl/generated/kubectl_config/kubectl_config_delete-cluster.md @@ -85,13 +85,6 @@ kubectl config delete-cluster NAME

          UID to impersonate for the operation.

          - ---azure-container-registry-config string - - -

          Path to the file containing Azure container registry configuration information.

          - - --cache-dir string     Default: "$HOME/.kube/cache" diff --git a/content/en/docs/reference/kubectl/generated/kubectl_config/kubectl_config_delete-context.md b/content/en/docs/reference/kubectl/generated/kubectl_config/kubectl_config_delete-context.md index 0743778a8ecdc..681cf5ee2a8d8 100644 --- a/content/en/docs/reference/kubectl/generated/kubectl_config/kubectl_config_delete-context.md +++ b/content/en/docs/reference/kubectl/generated/kubectl_config/kubectl_config_delete-context.md @@ -85,13 +85,6 @@ kubectl config delete-context NAME

          UID to impersonate for the operation.

          - ---azure-container-registry-config string - - -

          Path to the file containing Azure container registry configuration information.

          - - --cache-dir string     Default: "$HOME/.kube/cache" diff --git a/content/en/docs/reference/kubectl/generated/kubectl_config/kubectl_config_delete-user.md b/content/en/docs/reference/kubectl/generated/kubectl_config/kubectl_config_delete-user.md index 22e2d3adc49ce..0c3ad34edb25d 100644 --- a/content/en/docs/reference/kubectl/generated/kubectl_config/kubectl_config_delete-user.md +++ b/content/en/docs/reference/kubectl/generated/kubectl_config/kubectl_config_delete-user.md @@ -85,13 +85,6 @@ kubectl config delete-user NAME

          UID to impersonate for the operation.

          - ---azure-container-registry-config string - - -

          Path to the file containing Azure container registry configuration information.

          - - --cache-dir string     Default: "$HOME/.kube/cache" diff --git a/content/en/docs/reference/kubectl/generated/kubectl_config/kubectl_config_get-clusters.md b/content/en/docs/reference/kubectl/generated/kubectl_config/kubectl_config_get-clusters.md index ba61e2fdabbf8..3bbf1a18126e3 100644 --- a/content/en/docs/reference/kubectl/generated/kubectl_config/kubectl_config_get-clusters.md +++ b/content/en/docs/reference/kubectl/generated/kubectl_config/kubectl_config_get-clusters.md @@ -85,13 +85,6 @@ kubectl config get-clusters [flags]

          UID to impersonate for the operation.

          - ---azure-container-registry-config string - - -

          Path to the file containing Azure container registry configuration information.

          - - --cache-dir string     Default: "$HOME/.kube/cache" diff --git a/content/en/docs/reference/kubectl/generated/kubectl_config/kubectl_config_get-contexts.md b/content/en/docs/reference/kubectl/generated/kubectl_config/kubectl_config_get-contexts.md index 2019c2860aa8d..9f6a668f49280 100644 --- a/content/en/docs/reference/kubectl/generated/kubectl_config/kubectl_config_get-contexts.md +++ b/content/en/docs/reference/kubectl/generated/kubectl_config/kubectl_config_get-contexts.md @@ -102,13 +102,6 @@ kubectl config get-contexts [(-o|--output=)name)]

          UID to impersonate for the operation.

          - ---azure-container-registry-config string - - -

          Path to the file containing Azure container registry configuration information.

          - - --cache-dir string     Default: "$HOME/.kube/cache" diff --git a/content/en/docs/reference/kubectl/generated/kubectl_config/kubectl_config_get-users.md b/content/en/docs/reference/kubectl/generated/kubectl_config/kubectl_config_get-users.md index d6682c5a41f7a..3c778f447a41a 100644 --- a/content/en/docs/reference/kubectl/generated/kubectl_config/kubectl_config_get-users.md +++ b/content/en/docs/reference/kubectl/generated/kubectl_config/kubectl_config_get-users.md @@ -85,13 +85,6 @@ kubectl config get-users [flags]

          UID to impersonate for the operation.

          - ---azure-container-registry-config string - - -

          Path to the file containing Azure container registry configuration information.

          - - --cache-dir string     Default: "$HOME/.kube/cache" diff --git a/content/en/docs/reference/kubectl/generated/kubectl_config/kubectl_config_rename-context.md b/content/en/docs/reference/kubectl/generated/kubectl_config/kubectl_config_rename-context.md index 3bf5c5125911b..23c7125da3fa0 100644 --- a/content/en/docs/reference/kubectl/generated/kubectl_config/kubectl_config_rename-context.md +++ b/content/en/docs/reference/kubectl/generated/kubectl_config/kubectl_config_rename-context.md @@ -91,13 +91,6 @@ kubectl config rename-context CONTEXT_NAME NEW_NAME

          UID to impersonate for the operation.

          - ---azure-container-registry-config string - - -

          Path to the file containing Azure container registry configuration information.

          - - --cache-dir string     Default: "$HOME/.kube/cache" diff --git a/content/en/docs/reference/kubectl/generated/kubectl_config/kubectl_config_set-cluster.md b/content/en/docs/reference/kubectl/generated/kubectl_config/kubectl_config_set-cluster.md index c2d3205bf9b63..f19d49f3ac2f6 100644 --- a/content/en/docs/reference/kubectl/generated/kubectl_config/kubectl_config_set-cluster.md +++ b/content/en/docs/reference/kubectl/generated/kubectl_config/kubectl_config_set-cluster.md @@ -141,13 +141,6 @@ kubectl config set-cluster NAME [--server=server] [--certificate-authority=path/

          UID to impersonate for the operation.

          - ---azure-container-registry-config string - - -

          Path to the file containing Azure container registry configuration information.

          - - --cache-dir string     Default: "$HOME/.kube/cache" diff --git a/content/en/docs/reference/kubectl/generated/kubectl_config/kubectl_config_set-context.md b/content/en/docs/reference/kubectl/generated/kubectl_config/kubectl_config_set-context.md index 3085248376b57..3a02d8313644f 100644 --- a/content/en/docs/reference/kubectl/generated/kubectl_config/kubectl_config_set-context.md +++ b/content/en/docs/reference/kubectl/generated/kubectl_config/kubectl_config_set-context.md @@ -115,13 +115,6 @@ kubectl config set-context [NAME | --current] [--cluster=cluster_nickname] [--us

          UID to impersonate for the operation.

          - ---azure-container-registry-config string - - -

          Path to the file containing Azure container registry configuration information.

          - - --cache-dir string     Default: "$HOME/.kube/cache" diff --git a/content/en/docs/reference/kubectl/generated/kubectl_config/kubectl_config_set-credentials.md b/content/en/docs/reference/kubectl/generated/kubectl_config/kubectl_config_set-credentials.md index 330bbfd65617c..598ac94f63674 100644 --- a/content/en/docs/reference/kubectl/generated/kubectl_config/kubectl_config_set-credentials.md +++ b/content/en/docs/reference/kubectl/generated/kubectl_config/kubectl_config_set-credentials.md @@ -65,6 +65,9 @@ kubectl config set-credentials NAME [--client-certificate=path/to/certfile] [--c # Enable new exec auth plugin for the "cluster-admin" entry kubectl config set-credentials cluster-admin --exec-command=/path/to/the/executable --exec-api-version=client.authentication.k8s.io/v1beta1 + # Enable new exec auth plugin for the "cluster-admin" entry with interactive mode + kubectl config set-credentials cluster-admin --exec-command=/path/to/the/executable --exec-api-version=client.authentication.k8s.io/v1beta1 --exec-interactive-mode=Never + # Define new exec auth plugin arguments for the "cluster-admin" entry kubectl config set-credentials cluster-admin --exec-arg=arg1 --exec-arg=arg2 @@ -147,6 +150,20 @@ kubectl config set-credentials NAME [--client-certificate=path/to/certfile] [--c

          'key=value' environment values for the exec credential plugin

          + +--exec-interactive-mode string + + +

          InteractiveMode of the exec credentials plugin for the user entry in kubeconfig

          + + + +--exec-provide-cluster-info tristate[=true] + + +

          ProvideClusterInfo of the exec credentials plugin for the user entry in kubeconfig

          + + -h, --help @@ -210,13 +227,6 @@ kubectl config set-credentials NAME [--client-certificate=path/to/certfile] [--c

          UID to impersonate for the operation.

          - ---azure-container-registry-config string - - -

          Path to the file containing Azure container registry configuration information.

          - - --cache-dir string     Default: "$HOME/.kube/cache" diff --git a/content/en/docs/reference/kubectl/generated/kubectl_config/kubectl_config_set.md b/content/en/docs/reference/kubectl/generated/kubectl_config/kubectl_config_set.md index 895a27d126ebc..fc3c8a05b75cd 100644 --- a/content/en/docs/reference/kubectl/generated/kubectl_config/kubectl_config_set.md +++ b/content/en/docs/reference/kubectl/generated/kubectl_config/kubectl_config_set.md @@ -107,13 +107,6 @@ kubectl config set PROPERTY_NAME PROPERTY_VALUE

          UID to impersonate for the operation.

          - ---azure-container-registry-config string - - -

          Path to the file containing Azure container registry configuration information.

          - - --cache-dir string     Default: "$HOME/.kube/cache" diff --git a/content/en/docs/reference/kubectl/generated/kubectl_config/kubectl_config_unset.md b/content/en/docs/reference/kubectl/generated/kubectl_config/kubectl_config_unset.md index 7fdc0f4fb58aa..bd4038ff8f3dc 100644 --- a/content/en/docs/reference/kubectl/generated/kubectl_config/kubectl_config_unset.md +++ b/content/en/docs/reference/kubectl/generated/kubectl_config/kubectl_config_unset.md @@ -90,13 +90,6 @@ kubectl config unset PROPERTY_NAME

          UID to impersonate for the operation.

          - ---azure-container-registry-config string - - -

          Path to the file containing Azure container registry configuration information.

          - - --cache-dir string     Default: "$HOME/.kube/cache" diff --git a/content/en/docs/reference/kubectl/generated/kubectl_config/kubectl_config_use-context.md b/content/en/docs/reference/kubectl/generated/kubectl_config/kubectl_config_use-context.md index 7e194a0a6348b..1ac0cae808099 100644 --- a/content/en/docs/reference/kubectl/generated/kubectl_config/kubectl_config_use-context.md +++ b/content/en/docs/reference/kubectl/generated/kubectl_config/kubectl_config_use-context.md @@ -85,13 +85,6 @@ kubectl config use-context CONTEXT_NAME

          UID to impersonate for the operation.

          - ---azure-container-registry-config string - - -

          Path to the file containing Azure container registry configuration information.

          - - --cache-dir string     Default: "$HOME/.kube/cache" diff --git a/content/en/docs/reference/kubectl/generated/kubectl_config/kubectl_config_view.md b/content/en/docs/reference/kubectl/generated/kubectl_config/kubectl_config_view.md index e9f2cc9e0bd48..4bbd33461decd 100644 --- a/content/en/docs/reference/kubectl/generated/kubectl_config/kubectl_config_view.md +++ b/content/en/docs/reference/kubectl/generated/kubectl_config/kubectl_config_view.md @@ -149,13 +149,6 @@ kubectl config view [flags]

          UID to impersonate for the operation.

          - ---azure-container-registry-config string - - -

          Path to the file containing Azure container registry configuration information.

          - - --cache-dir string     Default: "$HOME/.kube/cache" diff --git a/content/en/docs/reference/kubectl/generated/kubectl_cordon/_index.md b/content/en/docs/reference/kubectl/generated/kubectl_cordon/_index.md index f973b3727c5eb..953f6c3b0c704 100644 --- a/content/en/docs/reference/kubectl/generated/kubectl_cordon/_index.md +++ b/content/en/docs/reference/kubectl/generated/kubectl_cordon/_index.md @@ -100,13 +100,6 @@ kubectl cordon NODE

          UID to impersonate for the operation.

          - ---azure-container-registry-config string - - -

          Path to the file containing Azure container registry configuration information.

          - - --cache-dir string     Default: "$HOME/.kube/cache" diff --git a/content/en/docs/reference/kubectl/generated/kubectl_cp/_index.md b/content/en/docs/reference/kubectl/generated/kubectl_cp/_index.md index c9a8b908d3782..ebaf754ce62ed 100644 --- a/content/en/docs/reference/kubectl/generated/kubectl_cp/_index.md +++ b/content/en/docs/reference/kubectl/generated/kubectl_cp/_index.md @@ -129,13 +129,6 @@ kubectl cp

          UID to impersonate for the operation.

          - ---azure-container-registry-config string - - -

          Path to the file containing Azure container registry configuration information.

          - - --cache-dir string     Default: "$HOME/.kube/cache" diff --git a/content/en/docs/reference/kubectl/generated/kubectl_create/_index.md b/content/en/docs/reference/kubectl/generated/kubectl_create/_index.md index 6fd9e8a1627eb..20f9d44d5bbf6 100644 --- a/content/en/docs/reference/kubectl/generated/kubectl_create/_index.md +++ b/content/en/docs/reference/kubectl/generated/kubectl_create/_index.md @@ -199,13 +199,6 @@ kubectl create -f FILENAME

          UID to impersonate for the operation.

          - ---azure-container-registry-config string - - -

          Path to the file containing Azure container registry configuration information.

          - - --cache-dir string     Default: "$HOME/.kube/cache" diff --git a/content/en/docs/reference/kubectl/generated/kubectl_create/kubectl_create_clusterrole.md b/content/en/docs/reference/kubectl/generated/kubectl_create/kubectl_create_clusterrole.md index 53261d91eda23..4c7c2475719ce 100644 --- a/content/en/docs/reference/kubectl/generated/kubectl_create/kubectl_create_clusterrole.md +++ b/content/en/docs/reference/kubectl/generated/kubectl_create/kubectl_create_clusterrole.md @@ -191,13 +191,6 @@ kubectl create clusterrole NAME --verb=verb --resource=resource.group [--resourc

          UID to impersonate for the operation.

          - ---azure-container-registry-config string - - -

          Path to the file containing Azure container registry configuration information.

          - - --cache-dir string     Default: "$HOME/.kube/cache" diff --git a/content/en/docs/reference/kubectl/generated/kubectl_create/kubectl_create_clusterrolebinding.md b/content/en/docs/reference/kubectl/generated/kubectl_create/kubectl_create_clusterrolebinding.md index c2840acf411ed..37f0a232a9cc0 100644 --- a/content/en/docs/reference/kubectl/generated/kubectl_create/kubectl_create_clusterrolebinding.md +++ b/content/en/docs/reference/kubectl/generated/kubectl_create/kubectl_create_clusterrolebinding.md @@ -169,13 +169,6 @@ kubectl create clusterrolebinding NAME --clusterrole=NAME [--user=username] [--g

          UID to impersonate for the operation.

          - ---azure-container-registry-config string - - -

          Path to the file containing Azure container registry configuration information.

          - - --cache-dir string     Default: "$HOME/.kube/cache" diff --git a/content/en/docs/reference/kubectl/generated/kubectl_create/kubectl_create_configmap.md b/content/en/docs/reference/kubectl/generated/kubectl_create/kubectl_create_configmap.md index 94916db2e85df..6994faa236d72 100644 --- a/content/en/docs/reference/kubectl/generated/kubectl_create/kubectl_create_configmap.md +++ b/content/en/docs/reference/kubectl/generated/kubectl_create/kubectl_create_configmap.md @@ -187,13 +187,6 @@ kubectl create configmap NAME [--from-file=[key=]source] [--from-literal=key1=va

          UID to impersonate for the operation.

          - ---azure-container-registry-config string - - -

          Path to the file containing Azure container registry configuration information.

          - - --cache-dir string     Default: "$HOME/.kube/cache" diff --git a/content/en/docs/reference/kubectl/generated/kubectl_create/kubectl_create_cronjob.md b/content/en/docs/reference/kubectl/generated/kubectl_create/kubectl_create_cronjob.md index 489499e81c92e..619593cb9e933 100644 --- a/content/en/docs/reference/kubectl/generated/kubectl_create/kubectl_create_cronjob.md +++ b/content/en/docs/reference/kubectl/generated/kubectl_create/kubectl_create_cronjob.md @@ -165,13 +165,6 @@ kubectl create cronjob NAME --image=image --schedule='0/5 * * * ?' -- [COMMAND]

          UID to impersonate for the operation.

          - ---azure-container-registry-config string - - -

          Path to the file containing Azure container registry configuration information.

          - - --cache-dir string     Default: "$HOME/.kube/cache" diff --git a/content/en/docs/reference/kubectl/generated/kubectl_create/kubectl_create_deployment.md b/content/en/docs/reference/kubectl/generated/kubectl_create/kubectl_create_deployment.md index b0171a66419be..af7f0ddf8ce62 100644 --- a/content/en/docs/reference/kubectl/generated/kubectl_create/kubectl_create_deployment.md +++ b/content/en/docs/reference/kubectl/generated/kubectl_create/kubectl_create_deployment.md @@ -41,6 +41,9 @@ kubectl create deployment NAME --image=image -- [COMMAND] [args...] # Create a deployment named my-dep that runs the busybox image and expose port 5701 kubectl create deployment my-dep --image=busybox --port=5701 + + # Create a deployment named my-dep that runs multiple containers + kubectl create deployment my-dep --image=busybox:latest --image=ubuntu:latest --image=nginx ``` ## {{% heading "options" %}} @@ -84,7 +87,7 @@ kubectl create deployment NAME --image=image -- [COMMAND] [args...] --image strings -

          Image names to run.

          +

          Image names to run. A deployment can have multiple images set for multi-container pod.

          @@ -98,7 +101,7 @@ kubectl create deployment NAME --image=image -- [COMMAND] [args...] --port int32     Default: -1 -

          The port that this container exposes.

          +

          The containerPort that this deployment exposes.

          @@ -171,13 +174,6 @@ kubectl create deployment NAME --image=image -- [COMMAND] [args...]

          UID to impersonate for the operation.

          - ---azure-container-registry-config string - - -

          Path to the file containing Azure container registry configuration information.

          - - --cache-dir string     Default: "$HOME/.kube/cache" diff --git a/content/en/docs/reference/kubectl/generated/kubectl_create/kubectl_create_ingress.md b/content/en/docs/reference/kubectl/generated/kubectl_create/kubectl_create_ingress.md index d5e807c152cf3..686c48e554f92 100644 --- a/content/en/docs/reference/kubectl/generated/kubectl_create/kubectl_create_ingress.md +++ b/content/en/docs/reference/kubectl/generated/kubectl_create/kubectl_create_ingress.md @@ -202,13 +202,6 @@ kubectl create ingress NAME --rule=host/path=service:port[,tls[=secret]]

          UID to impersonate for the operation.

          - ---azure-container-registry-config string - - -

          Path to the file containing Azure container registry configuration information.

          - - --cache-dir string     Default: "$HOME/.kube/cache" diff --git a/content/en/docs/reference/kubectl/generated/kubectl_create/kubectl_create_job.md b/content/en/docs/reference/kubectl/generated/kubectl_create/kubectl_create_job.md index f482be5e55123..e338ac6071820 100644 --- a/content/en/docs/reference/kubectl/generated/kubectl_create/kubectl_create_job.md +++ b/content/en/docs/reference/kubectl/generated/kubectl_create/kubectl_create_job.md @@ -161,13 +161,6 @@ kubectl create job NAME --image=image [--from=cronjob/name] -- [COMMAND] [args..

          UID to impersonate for the operation.

          - ---azure-container-registry-config string - - -

          Path to the file containing Azure container registry configuration information.

          - - --cache-dir string     Default: "$HOME/.kube/cache" diff --git a/content/en/docs/reference/kubectl/generated/kubectl_create/kubectl_create_namespace.md b/content/en/docs/reference/kubectl/generated/kubectl_create/kubectl_create_namespace.md index eb3262ddfde7f..fd1d72b59c873 100644 --- a/content/en/docs/reference/kubectl/generated/kubectl_create/kubectl_create_namespace.md +++ b/content/en/docs/reference/kubectl/generated/kubectl_create/kubectl_create_namespace.md @@ -141,13 +141,6 @@ kubectl create namespace NAME [--dry-run=server|client|none]

          UID to impersonate for the operation.

          - ---azure-container-registry-config string - - -

          Path to the file containing Azure container registry configuration information.

          - - --cache-dir string     Default: "$HOME/.kube/cache" diff --git a/content/en/docs/reference/kubectl/generated/kubectl_create/kubectl_create_poddisruptionbudget.md b/content/en/docs/reference/kubectl/generated/kubectl_create/kubectl_create_poddisruptionbudget.md index aac007bc876ff..50625aebd3e16 100644 --- a/content/en/docs/reference/kubectl/generated/kubectl_create/kubectl_create_poddisruptionbudget.md +++ b/content/en/docs/reference/kubectl/generated/kubectl_create/kubectl_create_poddisruptionbudget.md @@ -167,13 +167,6 @@ kubectl create poddisruptionbudget NAME --selector=SELECTOR --min-available=N [-

          UID to impersonate for the operation.

          - ---azure-container-registry-config string - - -

          Path to the file containing Azure container registry configuration information.

          - - --cache-dir string     Default: "$HOME/.kube/cache" diff --git a/content/en/docs/reference/kubectl/generated/kubectl_create/kubectl_create_priorityclass.md b/content/en/docs/reference/kubectl/generated/kubectl_create/kubectl_create_priorityclass.md index a953b44eef9a2..0b835221cb6f5 100644 --- a/content/en/docs/reference/kubectl/generated/kubectl_create/kubectl_create_priorityclass.md +++ b/content/en/docs/reference/kubectl/generated/kubectl_create/kubectl_create_priorityclass.md @@ -175,13 +175,6 @@ kubectl create priorityclass NAME --value=VALUE --global-default=BOOL [--dry-run

          UID to impersonate for the operation.

          - ---azure-container-registry-config string - - -

          Path to the file containing Azure container registry configuration information.

          - - --cache-dir string     Default: "$HOME/.kube/cache" diff --git a/content/en/docs/reference/kubectl/generated/kubectl_create/kubectl_create_quota.md b/content/en/docs/reference/kubectl/generated/kubectl_create/kubectl_create_quota.md index 15f59f82b3a28..befd71a1e63d0 100644 --- a/content/en/docs/reference/kubectl/generated/kubectl_create/kubectl_create_quota.md +++ b/content/en/docs/reference/kubectl/generated/kubectl_create/kubectl_create_quota.md @@ -158,13 +158,6 @@ kubectl create quota NAME [--hard=key1=value1,key2=value2] [--scopes=Scope1,Scop

          UID to impersonate for the operation.

          - ---azure-container-registry-config string - - -

          Path to the file containing Azure container registry configuration information.

          - - --cache-dir string     Default: "$HOME/.kube/cache" diff --git a/content/en/docs/reference/kubectl/generated/kubectl_create/kubectl_create_role.md b/content/en/docs/reference/kubectl/generated/kubectl_create/kubectl_create_role.md index 43fcfccaa5ebb..c58fe5ba406bb 100644 --- a/content/en/docs/reference/kubectl/generated/kubectl_create/kubectl_create_role.md +++ b/content/en/docs/reference/kubectl/generated/kubectl_create/kubectl_create_role.md @@ -171,13 +171,6 @@ kubectl create role NAME --verb=verb --resource=resource.group/subresource [--re

          UID to impersonate for the operation.

          - ---azure-container-registry-config string - - -

          Path to the file containing Azure container registry configuration information.

          - - --cache-dir string     Default: "$HOME/.kube/cache" diff --git a/content/en/docs/reference/kubectl/generated/kubectl_create/kubectl_create_rolebinding.md b/content/en/docs/reference/kubectl/generated/kubectl_create/kubectl_create_rolebinding.md index 6e52b10d83770..a4b324292b6d3 100644 --- a/content/en/docs/reference/kubectl/generated/kubectl_create/kubectl_create_rolebinding.md +++ b/content/en/docs/reference/kubectl/generated/kubectl_create/kubectl_create_rolebinding.md @@ -179,13 +179,6 @@ kubectl create rolebinding NAME --clusterrole=NAME|--role=NAME [--user=username]

          UID to impersonate for the operation.

          - ---azure-container-registry-config string - - -

          Path to the file containing Azure container registry configuration information.

          - - --cache-dir string     Default: "$HOME/.kube/cache" diff --git a/content/en/docs/reference/kubectl/generated/kubectl_create/kubectl_create_secret.md b/content/en/docs/reference/kubectl/generated/kubectl_create/kubectl_create_secret.md index 2fadccd843be2..e2fa5e3da12bb 100644 --- a/content/en/docs/reference/kubectl/generated/kubectl_create/kubectl_create_secret.md +++ b/content/en/docs/reference/kubectl/generated/kubectl_create/kubectl_create_secret.md @@ -84,13 +84,6 @@ kubectl create secret (docker-registry | generic | tls)

          UID to impersonate for the operation.

          - ---azure-container-registry-config string - - -

          Path to the file containing Azure container registry configuration information.

          - - --cache-dir string     Default: "$HOME/.kube/cache" diff --git a/content/en/docs/reference/kubectl/generated/kubectl_create/kubectl_create_secret_docker-registry.md b/content/en/docs/reference/kubectl/generated/kubectl_create/kubectl_create_secret_docker-registry.md index 2bc16aff5cf37..3df895ad30732 100644 --- a/content/en/docs/reference/kubectl/generated/kubectl_create/kubectl_create_secret_docker-registry.md +++ b/content/en/docs/reference/kubectl/generated/kubectl_create/kubectl_create_secret_docker-registry.md @@ -197,13 +197,6 @@ kubectl create secret docker-registry NAME --docker-username=user --docker-passw

          UID to impersonate for the operation.

          - ---azure-container-registry-config string - - -

          Path to the file containing Azure container registry configuration information.

          - - --cache-dir string     Default: "$HOME/.kube/cache" diff --git a/content/en/docs/reference/kubectl/generated/kubectl_create/kubectl_create_secret_generic.md b/content/en/docs/reference/kubectl/generated/kubectl_create/kubectl_create_secret_generic.md index 1bc568a77f575..29bb108872a19 100644 --- a/content/en/docs/reference/kubectl/generated/kubectl_create/kubectl_create_secret_generic.md +++ b/content/en/docs/reference/kubectl/generated/kubectl_create/kubectl_create_secret_generic.md @@ -194,13 +194,6 @@ kubectl create secret generic NAME [--type=string] [--from-file=[key=]source] [-

          UID to impersonate for the operation.

          - ---azure-container-registry-config string - - -

          Path to the file containing Azure container registry configuration information.

          - - --cache-dir string     Default: "$HOME/.kube/cache" diff --git a/content/en/docs/reference/kubectl/generated/kubectl_create/kubectl_create_secret_tls.md b/content/en/docs/reference/kubectl/generated/kubectl_create/kubectl_create_secret_tls.md index 10d582d9e2909..778254efcd7b4 100644 --- a/content/en/docs/reference/kubectl/generated/kubectl_create/kubectl_create_secret_tls.md +++ b/content/en/docs/reference/kubectl/generated/kubectl_create/kubectl_create_secret_tls.md @@ -33,7 +33,7 @@ kubectl create secret tls NAME --cert=path/to/cert/file --key=path/to/key/file [ ``` # Create a new TLS secret named tls-secret with the given key pair - kubectl create secret tls tls-secret --cert=path/to/tls.cert --key=path/to/tls.key + kubectl create secret tls tls-secret --cert=path/to/tls.crt --key=path/to/tls.key ``` ## {{% heading "options" %}} @@ -164,13 +164,6 @@ kubectl create secret tls NAME --cert=path/to/cert/file --key=path/to/key/file [

          UID to impersonate for the operation.

          - ---azure-container-registry-config string - - -

          Path to the file containing Azure container registry configuration information.

          - - --cache-dir string     Default: "$HOME/.kube/cache" diff --git a/content/en/docs/reference/kubectl/generated/kubectl_create/kubectl_create_service.md b/content/en/docs/reference/kubectl/generated/kubectl_create/kubectl_create_service.md index 31bc14b9b8a05..ba9c2317ab0e8 100644 --- a/content/en/docs/reference/kubectl/generated/kubectl_create/kubectl_create_service.md +++ b/content/en/docs/reference/kubectl/generated/kubectl_create/kubectl_create_service.md @@ -78,13 +78,6 @@ kubectl create service [flags]

          UID to impersonate for the operation.

          - ---azure-container-registry-config string - - -

          Path to the file containing Azure container registry configuration information.

          - - --cache-dir string     Default: "$HOME/.kube/cache" diff --git a/content/en/docs/reference/kubectl/generated/kubectl_create/kubectl_create_service_clusterip.md b/content/en/docs/reference/kubectl/generated/kubectl_create/kubectl_create_service_clusterip.md index df28894007972..07e25810cedd2 100644 --- a/content/en/docs/reference/kubectl/generated/kubectl_create/kubectl_create_service_clusterip.md +++ b/content/en/docs/reference/kubectl/generated/kubectl_create/kubectl_create_service_clusterip.md @@ -158,13 +158,6 @@ kubectl create service clusterip NAME [--tcp=:] [--dry-run=ser

          UID to impersonate for the operation.

          - ---azure-container-registry-config string - - -

          Path to the file containing Azure container registry configuration information.

          - - --cache-dir string     Default: "$HOME/.kube/cache" diff --git a/content/en/docs/reference/kubectl/generated/kubectl_create/kubectl_create_service_externalname.md b/content/en/docs/reference/kubectl/generated/kubectl_create/kubectl_create_service_externalname.md index 879045effcf59..147e5b25e9ed2 100644 --- a/content/en/docs/reference/kubectl/generated/kubectl_create/kubectl_create_service_externalname.md +++ b/content/en/docs/reference/kubectl/generated/kubectl_create/kubectl_create_service_externalname.md @@ -157,13 +157,6 @@ kubectl create service externalname NAME --external-name external.name [--dry-ru

          UID to impersonate for the operation.

          - ---azure-container-registry-config string - - -

          Path to the file containing Azure container registry configuration information.

          - - --cache-dir string     Default: "$HOME/.kube/cache" diff --git a/content/en/docs/reference/kubectl/generated/kubectl_create/kubectl_create_service_loadbalancer.md b/content/en/docs/reference/kubectl/generated/kubectl_create/kubectl_create_service_loadbalancer.md index a2e4181db2c91..722736e66a94d 100644 --- a/content/en/docs/reference/kubectl/generated/kubectl_create/kubectl_create_service_loadbalancer.md +++ b/content/en/docs/reference/kubectl/generated/kubectl_create/kubectl_create_service_loadbalancer.md @@ -148,13 +148,6 @@ kubectl create service loadbalancer NAME [--tcp=port:targetPort] [--dry-run=serv

          UID to impersonate for the operation.

          - ---azure-container-registry-config string - - -

          Path to the file containing Azure container registry configuration information.

          - - --cache-dir string     Default: "$HOME/.kube/cache" diff --git a/content/en/docs/reference/kubectl/generated/kubectl_create/kubectl_create_service_nodeport.md b/content/en/docs/reference/kubectl/generated/kubectl_create/kubectl_create_service_nodeport.md index c391ceaf11ecf..7acceeebcc55e 100644 --- a/content/en/docs/reference/kubectl/generated/kubectl_create/kubectl_create_service_nodeport.md +++ b/content/en/docs/reference/kubectl/generated/kubectl_create/kubectl_create_service_nodeport.md @@ -155,13 +155,6 @@ kubectl create service nodeport NAME [--tcp=port:targetPort] [--dry-run=server|c

          UID to impersonate for the operation.

          - ---azure-container-registry-config string - - -

          Path to the file containing Azure container registry configuration information.

          - - --cache-dir string     Default: "$HOME/.kube/cache" diff --git a/content/en/docs/reference/kubectl/generated/kubectl_create/kubectl_create_serviceaccount.md b/content/en/docs/reference/kubectl/generated/kubectl_create/kubectl_create_serviceaccount.md index 8b06bb62623d5..51121a3f56161 100644 --- a/content/en/docs/reference/kubectl/generated/kubectl_create/kubectl_create_serviceaccount.md +++ b/content/en/docs/reference/kubectl/generated/kubectl_create/kubectl_create_serviceaccount.md @@ -141,13 +141,6 @@ kubectl create serviceaccount NAME [--dry-run=server|client|none]

          UID to impersonate for the operation.

          - ---azure-container-registry-config string - - -

          Path to the file containing Azure container registry configuration information.

          - - --cache-dir string     Default: "$HOME/.kube/cache" diff --git a/content/en/docs/reference/kubectl/generated/kubectl_create/kubectl_create_token.md b/content/en/docs/reference/kubectl/generated/kubectl_create/kubectl_create_token.md index 5711599ac326f..8ece743b2e887 100644 --- a/content/en/docs/reference/kubectl/generated/kubectl_create/kubectl_create_token.md +++ b/content/en/docs/reference/kubectl/generated/kubectl_create/kubectl_create_token.md @@ -97,7 +97,7 @@ kubectl create token SERVICE_ACCOUNT_NAME --duration duration -

          Requested lifetime of the issued token. If not set, the lifetime will be determined by the server automatically. The server may return a token with a longer or shorter lifetime.

          +

          Requested lifetime of the issued token. If not set or if set to 0, the lifetime will be determined by the server automatically. The server may return a token with a longer or shorter lifetime.

          @@ -163,13 +163,6 @@ kubectl create token SERVICE_ACCOUNT_NAME

          UID to impersonate for the operation.

          - ---azure-container-registry-config string - - -

          Path to the file containing Azure container registry configuration information.

          - - --cache-dir string     Default: "$HOME/.kube/cache" diff --git a/content/en/docs/reference/kubectl/generated/kubectl_debug/_index.md b/content/en/docs/reference/kubectl/generated/kubectl_debug/_index.md index ccb3acbaa15b2..d1f7b0ecafc92 100644 --- a/content/en/docs/reference/kubectl/generated/kubectl_debug/_index.md +++ b/content/en/docs/reference/kubectl/generated/kubectl_debug/_index.md @@ -142,7 +142,7 @@ kubectl debug (POD | TYPE[[.VERSION].GROUP]/NAME) [ -- COMMAND [args...] ] --profile string     Default: "legacy" -

          Debugging profile. Options are "legacy", "general", "baseline", "netadmin", or "restricted".

          +

          Options are "legacy", "general", "baseline", "netadmin", "restricted" or "sysadmin".

          @@ -236,13 +236,6 @@ kubectl debug (POD | TYPE[[.VERSION].GROUP]/NAME) [ -- COMMAND [args...] ]

          UID to impersonate for the operation.

          - ---azure-container-registry-config string - - -

          Path to the file containing Azure container registry configuration information.

          - - --cache-dir string     Default: "$HOME/.kube/cache" diff --git a/content/en/docs/reference/kubectl/generated/kubectl_delete/_index.md b/content/en/docs/reference/kubectl/generated/kubectl_delete/_index.md index 4ba71656d1fc1..7484870752bec 100644 --- a/content/en/docs/reference/kubectl/generated/kubectl_delete/_index.md +++ b/content/en/docs/reference/kubectl/generated/kubectl_delete/_index.md @@ -152,7 +152,7 @@ kubectl delete ([-f FILENAME] | [-k DIRECTORY] | TYPE [(NAME | -l label | --all) -i, --interactive -

          If true, delete resource only when user confirms. This flag is in Alpha.

          +

          If true, delete resource only when user confirms.

          @@ -246,13 +246,6 @@ kubectl delete ([-f FILENAME] | [-k DIRECTORY] | TYPE [(NAME | -l label | --all)

          UID to impersonate for the operation.

          - ---azure-container-registry-config string - - -

          Path to the file containing Azure container registry configuration information.

          - - --cache-dir string     Default: "$HOME/.kube/cache" diff --git a/content/en/docs/reference/kubectl/generated/kubectl_describe/_index.md b/content/en/docs/reference/kubectl/generated/kubectl_describe/_index.md index 5d63c7e9e5986..a2438003f1cdb 100644 --- a/content/en/docs/reference/kubectl/generated/kubectl_describe/_index.md +++ b/content/en/docs/reference/kubectl/generated/kubectl_describe/_index.md @@ -159,13 +159,6 @@ kubectl describe (-f FILENAME | TYPE [NAME_PREFIX | -l label] | TYPE/NAME)

          UID to impersonate for the operation.

          - ---azure-container-registry-config string - - -

          Path to the file containing Azure container registry configuration information.

          - - --cache-dir string     Default: "$HOME/.kube/cache" diff --git a/content/en/docs/reference/kubectl/generated/kubectl_diff/_index.md b/content/en/docs/reference/kubectl/generated/kubectl_diff/_index.md index 3cce8f607c9a9..b559a6bb762e1 100644 --- a/content/en/docs/reference/kubectl/generated/kubectl_diff/_index.md +++ b/content/en/docs/reference/kubectl/generated/kubectl_diff/_index.md @@ -110,7 +110,7 @@ kubectl diff -f FILENAME --prune-allowlist strings -

          Overwrite the default whitelist with <group/version/kind> for --prune

          +

          Overwrite the default allowlist with <group/version/kind> for --prune

          @@ -176,13 +176,6 @@ kubectl diff -f FILENAME

          UID to impersonate for the operation.

          - ---azure-container-registry-config string - - -

          Path to the file containing Azure container registry configuration information.

          - - --cache-dir string     Default: "$HOME/.kube/cache" diff --git a/content/en/docs/reference/kubectl/generated/kubectl_drain/_index.md b/content/en/docs/reference/kubectl/generated/kubectl_drain/_index.md index f871858a38af7..9e0cc89fbab6a 100644 --- a/content/en/docs/reference/kubectl/generated/kubectl_drain/_index.md +++ b/content/en/docs/reference/kubectl/generated/kubectl_drain/_index.md @@ -174,13 +174,6 @@ kubectl drain NODE

          UID to impersonate for the operation.

          - ---azure-container-registry-config string - - -

          Path to the file containing Azure container registry configuration information.

          - - --cache-dir string     Default: "$HOME/.kube/cache" diff --git a/content/en/docs/reference/kubectl/generated/kubectl_edit/_index.md b/content/en/docs/reference/kubectl/generated/kubectl_edit/_index.md index 9e66d63ed4f95..1885496ee044d 100644 --- a/content/en/docs/reference/kubectl/generated/kubectl_edit/_index.md +++ b/content/en/docs/reference/kubectl/generated/kubectl_edit/_index.md @@ -201,13 +201,6 @@ kubectl edit (RESOURCE/NAME | -f FILENAME)

          UID to impersonate for the operation.

          - ---azure-container-registry-config string - - -

          Path to the file containing Azure container registry configuration information.

          - - --cache-dir string     Default: "$HOME/.kube/cache" diff --git a/content/en/docs/reference/kubectl/generated/kubectl_events/_index.md b/content/en/docs/reference/kubectl/generated/kubectl_events/_index.md index 878ce52141465..959c4f6c67f41 100644 --- a/content/en/docs/reference/kubectl/generated/kubectl_events/_index.md +++ b/content/en/docs/reference/kubectl/generated/kubectl_events/_index.md @@ -170,13 +170,6 @@ kubectl events [(-o|--output=)json|yaml|name|go-template|go-template-file|templa

          UID to impersonate for the operation.

          - ---azure-container-registry-config string - - -

          Path to the file containing Azure container registry configuration information.

          - - --cache-dir string     Default: "$HOME/.kube/cache" diff --git a/content/en/docs/reference/kubectl/generated/kubectl_exec/_index.md b/content/en/docs/reference/kubectl/generated/kubectl_exec/_index.md index 24716e8fe7fc5..55964d0bd09bb 100644 --- a/content/en/docs/reference/kubectl/generated/kubectl_exec/_index.md +++ b/content/en/docs/reference/kubectl/generated/kubectl_exec/_index.md @@ -148,13 +148,6 @@ kubectl exec (POD | TYPE/NAME) [-c CONTAINER] [flags] -- COMMAND [args...]

          UID to impersonate for the operation.

          - ---azure-container-registry-config string - - -

          Path to the file containing Azure container registry configuration information.

          - - --cache-dir string     Default: "$HOME/.kube/cache" diff --git a/content/en/docs/reference/kubectl/generated/kubectl_explain/_index.md b/content/en/docs/reference/kubectl/generated/kubectl_explain/_index.md index 75acae550e64b..0e1d0ad84063b 100644 --- a/content/en/docs/reference/kubectl/generated/kubectl_explain/_index.md +++ b/content/en/docs/reference/kubectl/generated/kubectl_explain/_index.md @@ -127,13 +127,6 @@ kubectl explain TYPE [--recursive=FALSE|TRUE] [--api-version=api-version-group]

          UID to impersonate for the operation.

          - ---azure-container-registry-config string - - -

          Path to the file containing Azure container registry configuration information.

          - - --cache-dir string     Default: "$HOME/.kube/cache" diff --git a/content/en/docs/reference/kubectl/generated/kubectl_expose/_index.md b/content/en/docs/reference/kubectl/generated/kubectl_expose/_index.md index f3ff17a938b98..fc5813cc6df98 100644 --- a/content/en/docs/reference/kubectl/generated/kubectl_expose/_index.md +++ b/content/en/docs/reference/kubectl/generated/kubectl_expose/_index.md @@ -271,13 +271,6 @@ kubectl expose (-f FILENAME | TYPE NAME) [--port=port] [--protocol=TCP|UDP|SCTP]

          UID to impersonate for the operation.

          - ---azure-container-registry-config string - - -

          Path to the file containing Azure container registry configuration information.

          - - --cache-dir string     Default: "$HOME/.kube/cache" diff --git a/content/en/docs/reference/kubectl/generated/kubectl_get/_index.md b/content/en/docs/reference/kubectl/generated/kubectl_get/_index.md index 71d27912a237a..ab909ada995d7 100644 --- a/content/en/docs/reference/kubectl/generated/kubectl_get/_index.md +++ b/content/en/docs/reference/kubectl/generated/kubectl_get/_index.md @@ -286,13 +286,6 @@ kubectl get [(-o|--output=)json|yaml|name|go-template|go-template-file|template|

          UID to impersonate for the operation.

          - ---azure-container-registry-config string - - -

          Path to the file containing Azure container registry configuration information.

          - - --cache-dir string     Default: "$HOME/.kube/cache" diff --git a/content/en/docs/reference/kubectl/generated/kubectl_kustomize/_index.md b/content/en/docs/reference/kubectl/generated/kubectl_kustomize/_index.md index 3cb4256a6398d..6c07094fc6e8e 100644 --- a/content/en/docs/reference/kubectl/generated/kubectl_kustomize/_index.md +++ b/content/en/docs/reference/kubectl/generated/kubectl_kustomize/_index.md @@ -162,13 +162,6 @@ kubectl kustomize DIR [flags]

          UID to impersonate for the operation.

          - ---azure-container-registry-config string - - -

          Path to the file containing Azure container registry configuration information.

          - - --cache-dir string     Default: "$HOME/.kube/cache" diff --git a/content/en/docs/reference/kubectl/generated/kubectl_label/_index.md b/content/en/docs/reference/kubectl/generated/kubectl_label/_index.md index 33277f5219f8a..639e188f4d9c8 100644 --- a/content/en/docs/reference/kubectl/generated/kubectl_label/_index.md +++ b/content/en/docs/reference/kubectl/generated/kubectl_label/_index.md @@ -226,13 +226,6 @@ kubectl label [--overwrite] (-f FILENAME | TYPE NAME) KEY_1=VAL_1 ... KEY_N=VAL_

          UID to impersonate for the operation.

          - ---azure-container-registry-config string - - -

          Path to the file containing Azure container registry configuration information.

          - - --cache-dir string     Default: "$HOME/.kube/cache" diff --git a/content/en/docs/reference/kubectl/generated/kubectl_logs/_index.md b/content/en/docs/reference/kubectl/generated/kubectl_logs/_index.md index 61b0bc120e2dc..17bec0c220409 100644 --- a/content/en/docs/reference/kubectl/generated/kubectl_logs/_index.md +++ b/content/en/docs/reference/kubectl/generated/kubectl_logs/_index.md @@ -221,13 +221,6 @@ kubectl logs [-f] [-p] (POD | TYPE/NAME) [-c CONTAINER]

          UID to impersonate for the operation.

          - ---azure-container-registry-config string - - -

          Path to the file containing Azure container registry configuration information.

          - - --cache-dir string     Default: "$HOME/.kube/cache" diff --git a/content/en/docs/reference/kubectl/generated/kubectl_options/_index.md b/content/en/docs/reference/kubectl/generated/kubectl_options/_index.md index 300222b012afd..0eff960cf54a2 100644 --- a/content/en/docs/reference/kubectl/generated/kubectl_options/_index.md +++ b/content/en/docs/reference/kubectl/generated/kubectl_options/_index.md @@ -86,13 +86,6 @@ kubectl options [flags]

          UID to impersonate for the operation.

          - ---azure-container-registry-config string - - -

          Path to the file containing Azure container registry configuration information.

          - - --cache-dir string     Default: "$HOME/.kube/cache" diff --git a/content/en/docs/reference/kubectl/generated/kubectl_patch/_index.md b/content/en/docs/reference/kubectl/generated/kubectl_patch/_index.md index c818e1d8de149..5c37c3c329d78 100644 --- a/content/en/docs/reference/kubectl/generated/kubectl_patch/_index.md +++ b/content/en/docs/reference/kubectl/generated/kubectl_patch/_index.md @@ -203,13 +203,6 @@ kubectl patch (-f FILENAME | TYPE NAME) [-p PATCH|--patch-file FILE]

          UID to impersonate for the operation.

          - ---azure-container-registry-config string - - -

          Path to the file containing Azure container registry configuration information.

          - - --cache-dir string     Default: "$HOME/.kube/cache" diff --git a/content/en/docs/reference/kubectl/generated/kubectl_plugin/_index.md b/content/en/docs/reference/kubectl/generated/kubectl_plugin/_index.md index 499a1cfbb6ed8..d78a7ea22021d 100644 --- a/content/en/docs/reference/kubectl/generated/kubectl_plugin/_index.md +++ b/content/en/docs/reference/kubectl/generated/kubectl_plugin/_index.md @@ -83,13 +83,6 @@ kubectl plugin [flags]

          UID to impersonate for the operation.

          - ---azure-container-registry-config string - - -

          Path to the file containing Azure container registry configuration information.

          - - --cache-dir string     Default: "$HOME/.kube/cache" diff --git a/content/en/docs/reference/kubectl/generated/kubectl_plugin/kubectl_plugin_list.md b/content/en/docs/reference/kubectl/generated/kubectl_plugin/kubectl_plugin_list.md index d91443d3465d0..483b881b630d6 100644 --- a/content/en/docs/reference/kubectl/generated/kubectl_plugin/kubectl_plugin_list.md +++ b/content/en/docs/reference/kubectl/generated/kubectl_plugin/kubectl_plugin_list.md @@ -94,13 +94,6 @@ kubectl plugin list [flags]

          UID to impersonate for the operation.

          - ---azure-container-registry-config string - - -

          Path to the file containing Azure container registry configuration information.

          - - --cache-dir string     Default: "$HOME/.kube/cache" diff --git a/content/en/docs/reference/kubectl/generated/kubectl_port-forward/_index.md b/content/en/docs/reference/kubectl/generated/kubectl_port-forward/_index.md index af464b467a1dc..77a1584882094 100644 --- a/content/en/docs/reference/kubectl/generated/kubectl_port-forward/_index.md +++ b/content/en/docs/reference/kubectl/generated/kubectl_port-forward/_index.md @@ -122,13 +122,6 @@ kubectl port-forward TYPE/NAME [options] [LOCAL_PORT:]REMOTE_PORT [...[LOCAL_POR

          UID to impersonate for the operation.

          - ---azure-container-registry-config string - - -

          Path to the file containing Azure container registry configuration information.

          - - --cache-dir string     Default: "$HOME/.kube/cache" diff --git a/content/en/docs/reference/kubectl/generated/kubectl_proxy/_index.md b/content/en/docs/reference/kubectl/generated/kubectl_proxy/_index.md index 8d6e95e6f3ca4..ba4e90f2b7a35 100644 --- a/content/en/docs/reference/kubectl/generated/kubectl_proxy/_index.md +++ b/content/en/docs/reference/kubectl/generated/kubectl_proxy/_index.md @@ -196,13 +196,6 @@ kubectl proxy [--port=PORT] [--www=static-dir] [--www-prefix=prefix] [--api-pref

          UID to impersonate for the operation.

          - ---azure-container-registry-config string - - -

          Path to the file containing Azure container registry configuration information.

          - - --cache-dir string     Default: "$HOME/.kube/cache" diff --git a/content/en/docs/reference/kubectl/generated/kubectl_replace/_index.md b/content/en/docs/reference/kubectl/generated/kubectl_replace/_index.md index bfa8a29fd9ff9..a079657972376 100644 --- a/content/en/docs/reference/kubectl/generated/kubectl_replace/_index.md +++ b/content/en/docs/reference/kubectl/generated/kubectl_replace/_index.md @@ -225,13 +225,6 @@ kubectl replace -f FILENAME

          UID to impersonate for the operation.

          - ---azure-container-registry-config string - - -

          Path to the file containing Azure container registry configuration information.

          - - --cache-dir string     Default: "$HOME/.kube/cache" diff --git a/content/en/docs/reference/kubectl/generated/kubectl_rollout/_index.md b/content/en/docs/reference/kubectl/generated/kubectl_rollout/_index.md index f722514062947..8ab152817da89 100644 --- a/content/en/docs/reference/kubectl/generated/kubectl_rollout/_index.md +++ b/content/en/docs/reference/kubectl/generated/kubectl_rollout/_index.md @@ -101,13 +101,6 @@ kubectl rollout SUBCOMMAND

          UID to impersonate for the operation.

          - ---azure-container-registry-config string - - -

          Path to the file containing Azure container registry configuration information.

          - - --cache-dir string     Default: "$HOME/.kube/cache" diff --git a/content/en/docs/reference/kubectl/generated/kubectl_rollout/kubectl_rollout_history.md b/content/en/docs/reference/kubectl/generated/kubectl_rollout/kubectl_rollout_history.md index 3e491ef2fd7f4..7637acfc408cc 100644 --- a/content/en/docs/reference/kubectl/generated/kubectl_rollout/kubectl_rollout_history.md +++ b/content/en/docs/reference/kubectl/generated/kubectl_rollout/kubectl_rollout_history.md @@ -151,13 +151,6 @@ kubectl rollout history (TYPE NAME | TYPE/NAME) [flags]

          UID to impersonate for the operation.

          - ---azure-container-registry-config string - - -

          Path to the file containing Azure container registry configuration information.

          - - --cache-dir string     Default: "$HOME/.kube/cache" diff --git a/content/en/docs/reference/kubectl/generated/kubectl_rollout/kubectl_rollout_pause.md b/content/en/docs/reference/kubectl/generated/kubectl_rollout/kubectl_rollout_pause.md index 81cd8fb1caffb..e091e896427fb 100644 --- a/content/en/docs/reference/kubectl/generated/kubectl_rollout/kubectl_rollout_pause.md +++ b/content/en/docs/reference/kubectl/generated/kubectl_rollout/kubectl_rollout_pause.md @@ -152,13 +152,6 @@ kubectl rollout pause RESOURCE

          UID to impersonate for the operation.

          - ---azure-container-registry-config string - - -

          Path to the file containing Azure container registry configuration information.

          - - --cache-dir string     Default: "$HOME/.kube/cache" diff --git a/content/en/docs/reference/kubectl/generated/kubectl_rollout/kubectl_rollout_restart.md b/content/en/docs/reference/kubectl/generated/kubectl_rollout/kubectl_rollout_restart.md index 71e7aaf53dbd9..33e5a80efe73b 100644 --- a/content/en/docs/reference/kubectl/generated/kubectl_rollout/kubectl_rollout_restart.md +++ b/content/en/docs/reference/kubectl/generated/kubectl_rollout/kubectl_rollout_restart.md @@ -159,13 +159,6 @@ kubectl rollout restart RESOURCE

          UID to impersonate for the operation.

          - ---azure-container-registry-config string - - -

          Path to the file containing Azure container registry configuration information.

          - - --cache-dir string     Default: "$HOME/.kube/cache" diff --git a/content/en/docs/reference/kubectl/generated/kubectl_rollout/kubectl_rollout_resume.md b/content/en/docs/reference/kubectl/generated/kubectl_rollout/kubectl_rollout_resume.md index 6ef7bb29a3276..51d2ed0b8d795 100644 --- a/content/en/docs/reference/kubectl/generated/kubectl_rollout/kubectl_rollout_resume.md +++ b/content/en/docs/reference/kubectl/generated/kubectl_rollout/kubectl_rollout_resume.md @@ -150,13 +150,6 @@ kubectl rollout resume RESOURCE

          UID to impersonate for the operation.

          - ---azure-container-registry-config string - - -

          Path to the file containing Azure container registry configuration information.

          - - --cache-dir string     Default: "$HOME/.kube/cache" diff --git a/content/en/docs/reference/kubectl/generated/kubectl_rollout/kubectl_rollout_status.md b/content/en/docs/reference/kubectl/generated/kubectl_rollout/kubectl_rollout_status.md index 5d2367623237b..b377de1342552 100644 --- a/content/en/docs/reference/kubectl/generated/kubectl_rollout/kubectl_rollout_status.md +++ b/content/en/docs/reference/kubectl/generated/kubectl_rollout/kubectl_rollout_status.md @@ -136,13 +136,6 @@ kubectl rollout status (TYPE NAME | TYPE/NAME) [flags]

          UID to impersonate for the operation.

          - ---azure-container-registry-config string - - -

          Path to the file containing Azure container registry configuration information.

          - - --cache-dir string     Default: "$HOME/.kube/cache" diff --git a/content/en/docs/reference/kubectl/generated/kubectl_rollout/kubectl_rollout_undo.md b/content/en/docs/reference/kubectl/generated/kubectl_rollout/kubectl_rollout_undo.md index a7d607003b68d..8c86db01cbaec 100644 --- a/content/en/docs/reference/kubectl/generated/kubectl_rollout/kubectl_rollout_undo.md +++ b/content/en/docs/reference/kubectl/generated/kubectl_rollout/kubectl_rollout_undo.md @@ -161,13 +161,6 @@ kubectl rollout undo (TYPE NAME | TYPE/NAME) [flags]

          UID to impersonate for the operation.

          - ---azure-container-registry-config string - - -

          Path to the file containing Azure container registry configuration information.

          - - --cache-dir string     Default: "$HOME/.kube/cache" diff --git a/content/en/docs/reference/kubectl/generated/kubectl_run/_index.md b/content/en/docs/reference/kubectl/generated/kubectl_run/_index.md index 63c7ac1b75263..a5649ada608af 100644 --- a/content/en/docs/reference/kubectl/generated/kubectl_run/_index.md +++ b/content/en/docs/reference/kubectl/generated/kubectl_run/_index.md @@ -292,13 +292,6 @@ kubectl run NAME --image=image [--env="key=value"] [--port=port] [--dry-run=serv

          UID to impersonate for the operation.

          - ---azure-container-registry-config string - - -

          Path to the file containing Azure container registry configuration information.

          - - --cache-dir string     Default: "$HOME/.kube/cache" diff --git a/content/en/docs/reference/kubectl/generated/kubectl_scale/_index.md b/content/en/docs/reference/kubectl/generated/kubectl_scale/_index.md index 8c620e7d38916..7b176c7e6a59d 100644 --- a/content/en/docs/reference/kubectl/generated/kubectl_scale/_index.md +++ b/content/en/docs/reference/kubectl/generated/kubectl_scale/_index.md @@ -200,13 +200,6 @@ kubectl scale [--resource-version=version] [--current-replicas=count] --replicas

          UID to impersonate for the operation.

          - ---azure-container-registry-config string - - -

          Path to the file containing Azure container registry configuration information.

          - - --cache-dir string     Default: "$HOME/.kube/cache" diff --git a/content/en/docs/reference/kubectl/generated/kubectl_set/_index.md b/content/en/docs/reference/kubectl/generated/kubectl_set/_index.md index 464fe8b53aa6b..b44e768f10b19 100644 --- a/content/en/docs/reference/kubectl/generated/kubectl_set/_index.md +++ b/content/en/docs/reference/kubectl/generated/kubectl_set/_index.md @@ -81,13 +81,6 @@ kubectl set SUBCOMMAND

          UID to impersonate for the operation.

          - ---azure-container-registry-config string - - -

          Path to the file containing Azure container registry configuration information.

          - - --cache-dir string     Default: "$HOME/.kube/cache" diff --git a/content/en/docs/reference/kubectl/generated/kubectl_set/kubectl_set_env.md b/content/en/docs/reference/kubectl/generated/kubectl_set/kubectl_set_env.md index e3407bf103cd9..b34ccac2c932b 100644 --- a/content/en/docs/reference/kubectl/generated/kubectl_set/kubectl_set_env.md +++ b/content/en/docs/reference/kubectl/generated/kubectl_set/kubectl_set_env.md @@ -264,13 +264,6 @@ kubectl set env RESOURCE/NAME KEY_1=VAL_1 ... KEY_N=VAL_N

          UID to impersonate for the operation.

          - ---azure-container-registry-config string - - -

          Path to the file containing Azure container registry configuration information.

          - - --cache-dir string     Default: "$HOME/.kube/cache" diff --git a/content/en/docs/reference/kubectl/generated/kubectl_set/kubectl_set_image.md b/content/en/docs/reference/kubectl/generated/kubectl_set/kubectl_set_image.md index 126169bdacc0e..ad18bf32391bd 100644 --- a/content/en/docs/reference/kubectl/generated/kubectl_set/kubectl_set_image.md +++ b/content/en/docs/reference/kubectl/generated/kubectl_set/kubectl_set_image.md @@ -182,13 +182,6 @@ kubectl set image (-f FILENAME | TYPE NAME) CONTAINER_NAME_1=CONTAINER_IMAGE_1 .

          UID to impersonate for the operation.

          - ---azure-container-registry-config string - - -

          Path to the file containing Azure container registry configuration information.

          - - --cache-dir string     Default: "$HOME/.kube/cache" diff --git a/content/en/docs/reference/kubectl/generated/kubectl_set/kubectl_set_resources.md b/content/en/docs/reference/kubectl/generated/kubectl_set/kubectl_set_resources.md index 876bdb5f79466..9560080394597 100644 --- a/content/en/docs/reference/kubectl/generated/kubectl_set/kubectl_set_resources.md +++ b/content/en/docs/reference/kubectl/generated/kubectl_set/kubectl_set_resources.md @@ -203,13 +203,6 @@ kubectl set resources (-f FILENAME | TYPE NAME) ([--limits=LIMITS & --requests=

          UID to impersonate for the operation.

          - ---azure-container-registry-config string - - -

          Path to the file containing Azure container registry configuration information.

          - - --cache-dir string     Default: "$HOME/.kube/cache" diff --git a/content/en/docs/reference/kubectl/generated/kubectl_set/kubectl_set_selector.md b/content/en/docs/reference/kubectl/generated/kubectl_set/kubectl_set_selector.md index 22b93938c18c7..54b5a86b72ddb 100644 --- a/content/en/docs/reference/kubectl/generated/kubectl_set/kubectl_set_selector.md +++ b/content/en/docs/reference/kubectl/generated/kubectl_set/kubectl_set_selector.md @@ -165,13 +165,6 @@ kubectl set selector (-f FILENAME | TYPE NAME) EXPRESSIONS [--resource-version=v

          UID to impersonate for the operation.

          - ---azure-container-registry-config string - - -

          Path to the file containing Azure container registry configuration information.

          - - --cache-dir string     Default: "$HOME/.kube/cache" diff --git a/content/en/docs/reference/kubectl/generated/kubectl_set/kubectl_set_serviceaccount.md b/content/en/docs/reference/kubectl/generated/kubectl_set/kubectl_set_serviceaccount.md index 0077649dc3fe1..f4c6394475a15 100644 --- a/content/en/docs/reference/kubectl/generated/kubectl_set/kubectl_set_serviceaccount.md +++ b/content/en/docs/reference/kubectl/generated/kubectl_set/kubectl_set_serviceaccount.md @@ -169,13 +169,6 @@ kubectl set serviceaccount (-f FILENAME | TYPE NAME) SERVICE_ACCOUNT

          UID to impersonate for the operation.

          - ---azure-container-registry-config string - - -

          Path to the file containing Azure container registry configuration information.

          - - --cache-dir string     Default: "$HOME/.kube/cache" diff --git a/content/en/docs/reference/kubectl/generated/kubectl_set/kubectl_set_subject.md b/content/en/docs/reference/kubectl/generated/kubectl_set/kubectl_set_subject.md index 4bb9e1807c2da..b4886977c7663 100644 --- a/content/en/docs/reference/kubectl/generated/kubectl_set/kubectl_set_subject.md +++ b/content/en/docs/reference/kubectl/generated/kubectl_set/kubectl_set_subject.md @@ -196,13 +196,6 @@ kubectl set subject (-f FILENAME | TYPE NAME) [--user=username] [--group=groupna

          UID to impersonate for the operation.

          - ---azure-container-registry-config string - - -

          Path to the file containing Azure container registry configuration information.

          - - --cache-dir string     Default: "$HOME/.kube/cache" diff --git a/content/en/docs/reference/kubectl/generated/kubectl_taint/_index.md b/content/en/docs/reference/kubectl/generated/kubectl_taint/_index.md index 81fabb002ce1e..e60838c5d9ab5 100644 --- a/content/en/docs/reference/kubectl/generated/kubectl_taint/_index.md +++ b/content/en/docs/reference/kubectl/generated/kubectl_taint/_index.md @@ -176,13 +176,6 @@ kubectl taint NODE NAME KEY_1=VAL_1:TAINT_EFFECT_1 ... KEY_N=VAL_N:TAINT_EFFECT_

          UID to impersonate for the operation.

          - ---azure-container-registry-config string - - -

          Path to the file containing Azure container registry configuration information.

          - - --cache-dir string     Default: "$HOME/.kube/cache" diff --git a/content/en/docs/reference/kubectl/generated/kubectl_top/_index.md b/content/en/docs/reference/kubectl/generated/kubectl_top/_index.md index 79c0ec6b9211e..9fc9c86c06023 100644 --- a/content/en/docs/reference/kubectl/generated/kubectl_top/_index.md +++ b/content/en/docs/reference/kubectl/generated/kubectl_top/_index.md @@ -83,13 +83,6 @@ kubectl top [flags]

          UID to impersonate for the operation.

          - ---azure-container-registry-config string - - -

          Path to the file containing Azure container registry configuration information.

          - - --cache-dir string     Default: "$HOME/.kube/cache" diff --git a/content/en/docs/reference/kubectl/generated/kubectl_top/kubectl_top_node.md b/content/en/docs/reference/kubectl/generated/kubectl_top/kubectl_top_node.md index 4fa3234b20a36..729fa04921b63 100644 --- a/content/en/docs/reference/kubectl/generated/kubectl_top/kubectl_top_node.md +++ b/content/en/docs/reference/kubectl/generated/kubectl_top/kubectl_top_node.md @@ -125,13 +125,6 @@ kubectl top node [NAME | -l label]

          UID to impersonate for the operation.

          - ---azure-container-registry-config string - - -

          Path to the file containing Azure container registry configuration information.

          - - --cache-dir string     Default: "$HOME/.kube/cache" diff --git a/content/en/docs/reference/kubectl/generated/kubectl_top/kubectl_top_pod.md b/content/en/docs/reference/kubectl/generated/kubectl_top/kubectl_top_pod.md index 1d2809c1a586e..42aff6fa19f41 100644 --- a/content/en/docs/reference/kubectl/generated/kubectl_top/kubectl_top_pod.md +++ b/content/en/docs/reference/kubectl/generated/kubectl_top/kubectl_top_pod.md @@ -154,13 +154,6 @@ kubectl top pod [NAME | -l label]

          UID to impersonate for the operation.

          - ---azure-container-registry-config string - - -

          Path to the file containing Azure container registry configuration information.

          - - --cache-dir string     Default: "$HOME/.kube/cache" diff --git a/content/en/docs/reference/kubectl/generated/kubectl_uncordon/_index.md b/content/en/docs/reference/kubectl/generated/kubectl_uncordon/_index.md index e476068de58c5..b19b0be756808 100644 --- a/content/en/docs/reference/kubectl/generated/kubectl_uncordon/_index.md +++ b/content/en/docs/reference/kubectl/generated/kubectl_uncordon/_index.md @@ -100,13 +100,6 @@ kubectl uncordon NODE

          UID to impersonate for the operation.

          - ---azure-container-registry-config string - - -

          Path to the file containing Azure container registry configuration information.

          - - --cache-dir string     Default: "$HOME/.kube/cache" diff --git a/content/en/docs/reference/kubectl/generated/kubectl_version/_index.md b/content/en/docs/reference/kubectl/generated/kubectl_version/_index.md index 53020be62130f..6f549c289df6d 100644 --- a/content/en/docs/reference/kubectl/generated/kubectl_version/_index.md +++ b/content/en/docs/reference/kubectl/generated/kubectl_version/_index.md @@ -100,13 +100,6 @@ kubectl version [flags]

          UID to impersonate for the operation.

          - ---azure-container-registry-config string - - -

          Path to the file containing Azure container registry configuration information.

          - - --cache-dir string     Default: "$HOME/.kube/cache" diff --git a/content/en/docs/reference/kubectl/generated/kubectl_wait/_index.md b/content/en/docs/reference/kubectl/generated/kubectl_wait/_index.md index fa385b6018ca4..3ef3d4ef527e5 100644 --- a/content/en/docs/reference/kubectl/generated/kubectl_wait/_index.md +++ b/content/en/docs/reference/kubectl/generated/kubectl_wait/_index.md @@ -199,13 +199,6 @@ kubectl wait ([-f FILENAME] | resource.group/resource.name | resource.group [(-l

          UID to impersonate for the operation.

          - ---azure-container-registry-config string - - -

          Path to the file containing Azure container registry configuration information.

          - - --cache-dir string     Default: "$HOME/.kube/cache" diff --git a/content/en/docs/reference/kubectl/introduction.md b/content/en/docs/reference/kubectl/introduction.md new file mode 100644 index 0000000000000..ac0aff2b590d6 --- /dev/null +++ b/content/en/docs/reference/kubectl/introduction.md @@ -0,0 +1,71 @@ +--- +title: "Introduction To Kubectl" +content_type: concept +weight: 1 +--- + +Kubectl is the Kubernetes cli version of a swiss army knife, and can do many things. + +While this Book is focused on using Kubectl to declaratively manage Applications in Kubernetes, it +also covers other Kubectl functions. + +## Command Families + +Most Kubectl commands typically fall into one of a few categories: + +| Type | Used For | Description | +|----------------------------------------|----------------------------|----------------------------------------------------| +| Declarative Resource Management | Deployment and Operations (e.g. GitOps) | Declaratively manage Kubernetes Workloads using Resource Config | +| Imperative Resource Management | Development Only | Run commands to manage Kubernetes Workloads using Command Line arguments and flags | +| Printing Workload State | Debugging | Print information about Workloads | +| Interacting with Containers | Debugging | Exec, Attach, Cp, Logs | +| Cluster Management | Cluster Ops | Drain and Cordon Nodes | + +## Declarative Application Management + +The preferred approach for managing Resources is through +declarative files called Resource Config used with the Kubectl *Apply* command. +This command reads a local (or remote) file structure and modifies cluster state to +reflect the declared intent. + +{{< alert color="success" title="Apply" >}} +Apply is the preferred mechanism for managing Resources in a Kubernetes cluster. +{{< /alert >}} + +## Printing state about Workloads + +Users will need to view Workload state. + +- Printing summarize state and information about Resources +- Printing complete state and information about Resources +- Printing specific fields from Resources +- Query Resources matching labels + +## Debugging Workloads + +Kubectl supports debugging by providing commands for: + +- Printing Container logs +- Printing cluster events +- Exec or attaching to a Container +- Copying files from Containers in the cluster to a user's filesystem + +## Cluster Management + +On occasion, users may need to perform operations to the Nodes of cluster. Kubectl supports +commands to drain Workloads from a Node so that it can be decommission or debugged. + +## Porcelain + +Users may find using Resource Config overly verbose for *Development* and prefer to work with +the cluster *imperatively* with a shell-like workflow. Kubectl offers porcelain commands for +generating and modifying Resources. + +- Generating + creating Resources such as Deployments, StatefulSets, Services, ConfigMaps, etc +- Setting fields on Resources +- Editing (live) Resources in a text editor + +{{< alert color="warning" title="Porcelain For Dev Only" >}} +Porcelain commands are time saving for experimenting with workloads in a dev cluster, but shouldn't +be used for production. +{{< /alert >}} diff --git a/content/en/docs/reference/kubectl/kubectl.md b/content/en/docs/reference/kubectl/kubectl.md index 80377dce33e70..c09a05dfccc4b 100644 --- a/content/en/docs/reference/kubectl/kubectl.md +++ b/content/en/docs/reference/kubectl/kubectl.md @@ -6,12 +6,11 @@ weight: 30 ## {{% heading "synopsis" %}} - kubectl controls the Kubernetes cluster manager. - Find more information at: https://kubernetes.io/docs/reference/kubectl/overview/ +Find more information in [Command line tool](/docs/reference/kubectl/) (`kubectl`). -``` +```shell kubectl [flags] ``` @@ -210,7 +209,7 @@ kubectl [flags] --one-output -If true, only write logs to their native severity level (vs also writing to each lower severity level +If true, only write logs to their native severity level (vs also writing to each lower severity level) @@ -351,7 +350,13 @@ kubectl [flags] When set to false, turns off extra HTTP headers detailing invoked kubectl command (Kubernetes version v1.22 or later) - + +KUBECTL_DEBUG_CUSTOM_PROFILE + + +When set to true, custom flag will be enabled in kubectl debug. This flag is used to customize the pre-defined profiles. + + KUBECTL_EXPLAIN_OPENAPIV3 @@ -369,6 +374,14 @@ kubectl [flags] + +KUBECTL_PORT_FORWARD_WEBSOCKETS + + +When set to true, the kubectl port-forward command will attempt to stream using the websockets protocol. If the upgrade to websockets fails, the commands will fallback to use the current SPDY protocol. + + + KUBECTL_REMOTE_COMMAND_WEBSOCKETS @@ -382,47 +395,50 @@ kubectl [flags] ## {{% heading "seealso" %}} -* [kubectl annotate](/docs/reference/generated/kubectl/kubectl-commands#annotate) - Update the annotations on a resource -* [kubectl api-resources](/docs/reference/generated/kubectl/kubectl-commands#api-resources) - Print the supported API resources on the server -* [kubectl api-versions](/docs/reference/generated/kubectl/kubectl-commands#api-versions) - Print the supported API versions on the server, in the form of "group/version" -* [kubectl apply](/docs/reference/generated/kubectl/kubectl-commands#apply) - Apply a configuration to a resource by filename or stdin -* [kubectl attach](/docs/reference/generated/kubectl/kubectl-commands#attach) - Attach to a running container -* [kubectl auth](/docs/reference/generated/kubectl/kubectl-commands#auth) - Inspect authorization -* [kubectl autoscale](/docs/reference/generated/kubectl/kubectl-commands#autoscale) - Auto-scale a Deployment, ReplicaSet, or ReplicationController -* [kubectl certificate](/docs/reference/generated/kubectl/kubectl-commands#certificate) - Modify certificate resources. -* [kubectl cluster-info](/docs/reference/generated/kubectl/kubectl-commands#cluster-info) - Display cluster info -* [kubectl completion](/docs/reference/generated/kubectl/kubectl-commands#completion) - Output shell completion code for the specified shell (bash or zsh) -* [kubectl config](/docs/reference/generated/kubectl/kubectl-commands#config) - Modify kubeconfig files -* [kubectl cordon](/docs/reference/generated/kubectl/kubectl-commands#cordon) - Mark node as unschedulable -* [kubectl cp](/docs/reference/generated/kubectl/kubectl-commands#cp) - Copy files and directories to and from containers. -* [kubectl create](/docs/reference/generated/kubectl/kubectl-commands#create) - Create a resource from a file or from stdin. -* [kubectl debug](/docs/reference/generated/kubectl/kubectl-commands#debug) - Create debugging sessions for troubleshooting workloads and nodes -* [kubectl delete](/docs/reference/generated/kubectl/kubectl-commands#delete) - Delete resources by filenames, stdin, resources and names, or by resources and label selector -* [kubectl describe](/docs/reference/generated/kubectl/kubectl-commands#describe) - Show details of a specific resource or group of resources -* [kubectl diff](/docs/reference/generated/kubectl/kubectl-commands#diff) - Diff live version against would-be applied version -* [kubectl drain](/docs/reference/generated/kubectl/kubectl-commands#drain) - Drain node in preparation for maintenance -* [kubectl edit](/docs/reference/generated/kubectl/kubectl-commands#edit) - Edit a resource on the server -* [kubectl events](/docs/reference/generated/kubectl/kubectl-commands#events) - List events -* [kubectl exec](/docs/reference/generated/kubectl/kubectl-commands#exec) - Execute a command in a container -* [kubectl explain](/docs/reference/generated/kubectl/kubectl-commands#explain) - Documentation of resources -* [kubectl expose](/docs/reference/generated/kubectl/kubectl-commands#expose) - Take a replication controller, service, deployment or pod and expose it as a new Kubernetes Service -* [kubectl get](/docs/reference/generated/kubectl/kubectl-commands#get) - Display one or many resources -* [kubectl kustomize](/docs/reference/generated/kubectl/kubectl-commands#kustomize) - Build a kustomization target from a directory or a remote url. -* [kubectl label](/docs/reference/generated/kubectl/kubectl-commands#label) - Update the labels on a resource -* [kubectl logs](/docs/reference/generated/kubectl/kubectl-commands#logs) - Print the logs for a container in a pod -* [kubectl options](/docs/reference/generated/kubectl/kubectl-commands#options) - Print the list of flags inherited by all commands -* [kubectl patch](/docs/reference/generated/kubectl/kubectl-commands#patch) - Update field(s) of a resource -* [kubectl plugin](/docs/reference/generated/kubectl/kubectl-commands#plugin) - Provides utilities for interacting with plugins. -* [kubectl port-forward](/docs/reference/generated/kubectl/kubectl-commands#port-forward) - Forward one or more local ports to a pod -* [kubectl proxy](/docs/reference/generated/kubectl/kubectl-commands#proxy) - Run a proxy to the Kubernetes API server -* [kubectl replace](/docs/reference/generated/kubectl/kubectl-commands#replace) - Replace a resource by filename or stdin -* [kubectl rollout](/docs/reference/generated/kubectl/kubectl-commands#rollout) - Manage the rollout of a resource -* [kubectl run](/docs/reference/generated/kubectl/kubectl-commands#run) - Run a particular image on the cluster -* [kubectl scale](/docs/reference/generated/kubectl/kubectl-commands#scale) - Set a new size for a Deployment, ReplicaSet or Replication Controller -* [kubectl set](/docs/reference/generated/kubectl/kubectl-commands#set) - Set specific features on objects -* [kubectl taint](/docs/reference/generated/kubectl/kubectl-commands#taint) - Update the taints on one or more nodes -* [kubectl top](/docs/reference/generated/kubectl/kubectl-commands#top) - Display Resource (CPU/Memory/Storage) usage. -* [kubectl uncordon](/docs/reference/generated/kubectl/kubectl-commands#uncordon) - Mark node as schedulable -* [kubectl version](/docs/reference/generated/kubectl/kubectl-commands#version) - Print the client and server version information -* [kubectl wait](/docs/reference/generated/kubectl/kubectl-commands#wait) - Experimental: Wait for a specific condition on one or many resources. - +* [kubectl annotate](/docs/reference/kubectl/generated/kubectl_annotate/) - Update the annotations on a resource +* [kubectl api-resources](/docs/reference/kubectl/generated/kubectl_api-resources/) - Print the supported API resources on the server +* [kubectl api-versions](/docs/reference/kubectl/generated/kubectl_api-versions/) - Print the supported API versions on the server, + in the form of "group/version" +* [kubectl apply](/docs/reference/kubectl/generated/kubectl_apply/) - Apply a configuration to a resource by filename or stdin +* [kubectl attach](/docs/reference/kubectl/generated/kubectl_attach/) - Attach to a running container +* [kubectl auth](/docs/reference/kubectl/generated/kubectl_auth/) - Inspect authorization +* [kubectl autoscale](/docs/reference/kubectl/generated/kubectl_autoscale/) - Auto-scale a Deployment, ReplicaSet, or ReplicationController +* [kubectl certificate](/docs/reference/kubectl/generated/kubectl_certificate/) - Modify certificate resources. +* [kubectl cluster-info](/docs/reference/kubectl/generated/kubectl_cluster-info/) - Display cluster info +* [kubectl completion](/docs/reference/kubectl/generated/kubectl_completion/) - Output shell completion code for the specified shell (bash or zsh) +* [kubectl config](/docs/reference/kubectl/generated/kubectl_config/) - Modify kubeconfig files +* [kubectl cordon](/docs/reference/kubectl/generated/kubectl_cordon/) - Mark node as unschedulable +* [kubectl cp](/docs/reference/kubectl/generated/kubectl_cp/) - Copy files and directories to and from containers. +* [kubectl create](/docs/reference/kubectl/generated/kubectl_create/) - Create a resource from a file or from stdin. +* [kubectl debug](/docs/reference/kubectl/generated/kubectl_debug/) - Create debugging sessions for troubleshooting workloads and nodes +* [kubectl delete](/docs/reference/kubectl/generated/kubectl_delete/) - Delete resources by filenames, + stdin, resources and names, or by resources and label selector +* [kubectl describe](/docs/reference/kubectl/generated/kubectl_describe/) - Show details of a specific resource or group of resources +* [kubectl diff](/docs/reference/kubectl/generated/kubectl_diff/) - Diff live version against would-be applied version +* [kubectl drain](/docs/reference/kubectl/generated/kubectl_drain/) - Drain node in preparation for maintenance +* [kubectl edit](/docs/reference/kubectl/generated/kubectl_edit/) - Edit a resource on the server +* [kubectl events](/docs/reference/kubectl/generated/kubectl_events/) - List events +* [kubectl exec](/docs/reference/kubectl/generated/kubectl_exec/) - Execute a command in a container +* [kubectl explain](/docs/reference/kubectl/generated/kubectl_explain/) - Documentation of resources +* [kubectl expose](/docs/reference/kubectl/generated/kubectl_expose/) - Take a replication controller, + service, deployment or pod and expose it as a new Kubernetes Service +* [kubectl get](/docs/reference/kubectl/generated/kubectl_get/) - Display one or many resources +* [kubectl kustomize](/docs/reference/kubectl/generated/kubectl_kustomize/) - Build a kustomization + target from a directory or a remote url. +* [kubectl label](/docs/reference/kubectl/generated/kubectl_label/) - Update the labels on a resource +* [kubectl logs](/docs/reference/kubectl/generated/kubectl_logs/) - Print the logs for a container in a pod +* [kubectl options](/docs/reference/kubectl/generated/kubectl_options/) - Print the list of flags inherited by all commands +* [kubectl patch](/docs/reference/kubectl/generated/kubectl_patch/) - Update field(s) of a resource +* [kubectl plugin](/docs/reference/kubectl/generated/kubectl_plugin/) - Provides utilities for interacting with plugins. +* [kubectl port-forward](/docs/reference/kubectl/generated/kubectl_port-forward/) - Forward one or more local ports to a pod +* [kubectl proxy](/docs/reference/kubectl/generated/kubectl_proxy/) - Run a proxy to the Kubernetes API server +* [kubectl replace](/docs/reference/kubectl/generated/kubectl_replace/) - Replace a resource by filename or stdin +* [kubectl rollout](/docs/reference/kubectl/generated/kubectl_rollout/) - Manage the rollout of a resource +* [kubectl run](/docs/reference/kubectl/generated/kubectl_run/) - Run a particular image on the cluster +* [kubectl scale](/docs/reference/kubectl/generated/kubectl_scale/) - Set a new size for a Deployment, ReplicaSet or Replication Controller +* [kubectl set](/docs/reference/kubectl/generated/kubectl_set/) - Set specific features on objects +* [kubectl taint](/docs/reference/kubectl/generated/kubectl_taint/) - Update the taints on one or more nodes +* [kubectl top](/docs/reference/kubectl/generated/kubectl_top/) - Display Resource (CPU/Memory/Storage) usage. +* [kubectl uncordon](/docs/reference/kubectl/generated/kubectl_uncordon/) - Mark node as schedulable +* [kubectl version](/docs/reference/kubectl/generated/kubectl_version/) - Print the client and server version information +* [kubectl wait](/docs/reference/kubectl/generated/kubectl_wait/) - Experimental: Wait for a specific condition on one or many resources. diff --git a/content/en/docs/reference/kubectl/quick-reference.md b/content/en/docs/reference/kubectl/quick-reference.md index d0140aebf2aa0..c0f0dc37b2088 100644 --- a/content/en/docs/reference/kubectl/quick-reference.md +++ b/content/en/docs/reference/kubectl/quick-reference.md @@ -45,10 +45,12 @@ echo '[[ $commands[kubectl] ]] && source <(kubectl completion zsh)' >> ~/.zshrc ### FISH -Require kubectl version 1.23 or above. +{{< note >}} +Requires kubectl version 1.23 or above. +{{< /note >}} ```bash -echo 'kubectl completion fish | source' >> ~/.config/fish/config.fish # add kubectl autocompletion permanently to your fish shell +echo 'kubectl completion fish | source' > ~/.config/fish/completions/kubectl.fish && source ~/.config/fish/completions/kubectl.fish ``` ### A note on `--all-namespaces` @@ -71,12 +73,19 @@ KUBECONFIG=~/.kube/config:~/.kube/kubconfig2 kubectl config view +# Show merged kubeconfig settings and raw certificate data and exposed secrets +kubectl config view --raw + # get the password for the e2e user kubectl config view -o jsonpath='{.users[?(@.name == "e2e")].user.password}' +# get the certificate for the e2e user +kubectl config view --raw -o jsonpath='{.users[?(.name == "e2e")].user.client-certificate-data}' | base64 -d + kubectl config view -o jsonpath='{.users[].name}' # display the first user kubectl config view -o jsonpath='{.users[*].name}' # get a list of users kubectl config get-contexts # display list of contexts +kubectl config get-contexts -o name # get all context names kubectl config current-context # display the current-context kubectl config use-context my-cluster-name # set the default context to my-cluster-name @@ -112,11 +121,11 @@ Kubernetes manifests can be defined in YAML or JSON. The file extension `.yaml`, `.yml`, and `.json` can be used. ```bash -kubectl apply -f ./my-manifest.yaml # create resource(s) -kubectl apply -f ./my1.yaml -f ./my2.yaml # create from multiple files -kubectl apply -f ./dir # create resource(s) in all manifest files in dir -kubectl apply -f https://git.io/vPieo # create resource(s) from url -kubectl create deployment nginx --image=nginx # start a single instance of nginx +kubectl apply -f ./my-manifest.yaml # create resource(s) +kubectl apply -f ./my1.yaml -f ./my2.yaml # create from multiple files +kubectl apply -f ./dir # create resource(s) in all manifest files in dir +kubectl apply -f https://example.com/manifest.yaml # create resource(s) from url (Note: this is an example domain and does not contain a valid manifest) +kubectl create deployment nginx --image=nginx # start a single instance of nginx # create a Job which prints "Hello World" kubectl create job hello --image=busybox:1.28 -- echo "Hello World" @@ -287,7 +296,7 @@ kubectl label pods my-pod new-label=awesome # Add a Label kubectl label pods my-pod new-label- # Remove a label kubectl label pods my-pod new-label=new-value --overwrite # Overwrite an existing value kubectl annotate pods my-pod icon-url=http://goo.gl/XXBTWq # Add an annotation -kubectl annotate pods my-pod icon- # Remove annotation +kubectl annotate pods my-pod icon-url- # Remove annotation kubectl autoscale deployment foo --min=2 --max=10 # Auto scale a deployment "foo" ``` @@ -364,6 +373,9 @@ kubectl port-forward my-pod 5000:6000 # Listen on port 5000 on the kubectl exec my-pod -- ls / # Run command in existing pod (1 container case) kubectl exec --stdin --tty my-pod -- /bin/sh # Interactive shell access to a running pod (1 container case) kubectl exec my-pod -c my-container -- ls / # Run command in existing pod (multi-container case) +kubectl debug my-pod -it --image=busybox:1.28 # Create an interactive debugging session witin existing pod and immediately attach to it +kubectl debug node/my-node -it --image=busybox:1.28 # Create an interactive debugging session on a node and immediately attach to it +kubectl top pod # Show metrics for all pods in the default namespace kubectl top pod POD_NAME --containers # Show metrics for a given pod and its containers kubectl top pod POD_NAME --sort-by=cpu # Show metrics for a given pod and sort it by 'cpu' or 'memory' ``` @@ -404,6 +416,7 @@ kubectl exec deploy/my-deployment -- ls # run command in first kubectl cordon my-node # Mark my-node as unschedulable kubectl drain my-node # Drain my-node in preparation for maintenance kubectl uncordon my-node # Mark my-node as schedulable +kubectl top node # Show metrics for all nodes kubectl top node my-node # Show metrics for a given node kubectl cluster-info # Display addresses of the master and services kubectl cluster-info dump # Dump current cluster state to stdout diff --git a/content/en/docs/reference/kubernetes-api/common-parameters/common-parameters.md b/content/en/docs/reference/kubernetes-api/common-parameters/common-parameters.md index 95a8f5dd37c56..6c4c643f80bdd 100644 --- a/content/en/docs/reference/kubernetes-api/common-parameters/common-parameters.md +++ b/content/en/docs/reference/kubernetes-api/common-parameters/common-parameters.md @@ -60,7 +60,7 @@ When present, indicates that modifications should not be persisted. An invalid o ## fieldManager {#fieldManager} -fieldManager is a name associated with the actor or entity that is making these changes. The value must be less than or 128 characters long, and only contain printable characters, as defined by https://golang.org/pkg/unicode/#IsPrint. +fieldManager is a name associated with the actor or entity that is making these changes. The value must be less than or 128 characters long, and only contain printable characters, as defined by https://pkg.go.dev/unicode#IsPrint.
          diff --git a/content/en/docs/reference/labels-annotations-taints/_index.md b/content/en/docs/reference/labels-annotations-taints/_index.md index 7c12db03205aa..fc057b132dc95 100644 --- a/content/en/docs/reference/labels-annotations-taints/_index.md +++ b/content/en/docs/reference/labels-annotations-taints/_index.md @@ -54,7 +54,7 @@ Type: Label Example: `app.kubernetes.io/created-by: "controller-manager"` -Used on: All Objects (typically used on[workload resources](/docs/reference/kubernetes-api/workload-resources/)). +Used on: All Objects (typically used on [workload resources](/docs/reference/kubernetes-api/workload-resources/)). The controller/user who created this resource. @@ -300,7 +300,7 @@ which is used by Kustomize and similar third-party tools. For example, Kustomize removes objects with this annotation from its final build output. -### container.apparmor.security.beta.kubernetes.io/* (beta) {#container-apparmor-security-beta-kubernetes-io} +### container.apparmor.security.beta.kubernetes.io/* (deprecated) {#container-apparmor-security-beta-kubernetes-io} Type: Annotation @@ -309,7 +309,7 @@ Example: `container.apparmor.security.beta.kubernetes.io/my-container: my-custom Used on: Pods This annotation allows you to specify the AppArmor security profile for a container within a -Kubernetes pod. +Kubernetes pod. As of Kubernetes v1.30, this should be set with the `appArmorProfile` field instead. To learn more, see the [AppArmor](/docs/tutorials/security/apparmor/) tutorial. The tutorial illustrates using AppArmor to restrict a container's abilities and access. @@ -1001,9 +1001,10 @@ Type: Label Example: `service.kubernetes.io/headless: ""` -Used on: Service +Used on: Endpoints The control plane adds this label to an Endpoints object when the owning Service is headless. +To learn more, read [Headless Services](/docs/concepts/services-networking/service/#headless-services). ### service.kubernetes.io/topology-aware-hints (deprecated) {#servicekubernetesiotopology-aware-hints} @@ -1105,19 +1106,17 @@ Example: `kubernetes.io/legacy-token-invalid-since: 2023-10-27` Used on: Secret The control plane automatically adds this label to auto-generated Secrets that -have the type `kubernetes.io/service-account-token`, provided that you have the -`LegacyServiceAccountTokenCleanUp` [feature gate](/docs/reference/command-line-tools-reference/feature-gates/) -enabled. Kubernetes {{< skew currentVersion >}} enables that behavior by default. -This label marks the Secret-based token as invalid for authentication. The value -of this label records the date (ISO 8601 format, UTC time zone) when the control -plane detects that the auto-generated Secret has not been used for a specified -duration (defaults to one year). +have the type `kubernetes.io/service-account-token`. This label marks the +Secret-based token as invalid for authentication. The value of this label +records the date (ISO 8601 format, UTC time zone) when the control plane detects +that the auto-generated Secret has not been used for a specified duration +(defaults to one year). ### endpointslice.kubernetes.io/managed-by {#endpointslicekubernetesiomanaged-by} Type: Label -Example: `endpointslice.kubernetes.io/managed-by: "controller"` +Example: `endpointslice.kubernetes.io/managed-by: endpointslice-controller.k8s.io` Used on: EndpointSlices @@ -1294,6 +1293,18 @@ has been truncated to 1000. If the number of backend endpoints falls below 1000, the control plane removes this annotation. +### endpoints.kubernetes.io/last-change-trigger-time + +Type: Annotation + +Example: `endpoints.kubernetes.io/last-change-trigger-time: "2023-07-20T04:45:21Z"` + +Used on: Endpoints + +This annotation set to an [Endpoints](/docs/concepts/services-networking/service/#endpoints) object that +represents the timestamp (The timestamp is stored in RFC 3339 date-time string format. For example, '2018-10-22T19:32:52.1Z'). This is timestamp +of the last change in some Pod or Service object, that triggered the change to the Endpoints object. + ### control-plane.alpha.kubernetes.io/leader (deprecated) {#control-plane-alpha-kubernetes-io-leader} Type: Annotation @@ -2060,6 +2071,25 @@ on an existing Service object. See the AWS documentation on this topic for more details. {{< /caution >}} +### service.beta.kubernetes.io/azure-load-balancer-disable-tcp-reset (deprecated) {#service-beta-kubernetes-azure-load-balancer-disble-tcp-reset} + +Example: `service.beta.kubernetes.io/azure-load-balancer-disable-tcp-reset: "false"` + +Used on: Service + +This annotation only works for Azure standard load balancer backed service. +This annotation is used on the Service to specify whether the load balancer +should disable or enable TCP reset on idle timeout. If enabled, it helps +applications to behave more predictably, to detect the termination of a connection, +remove expired connections and initiate new connections. +You can set the value to be either true or false. + +See [Load Balancer TCP Reset](https://learn.microsoft.com/en-gb/azure/load-balancer/load-balancer-tcp-reset) for more information. + +{{< note >}} +This annotation is deprecated. +{{< /note >}} + ### pod-security.kubernetes.io/enforce Type: Label @@ -2255,7 +2285,8 @@ Starting in v1.16, this annotation was removed in favor of - [`pod-security.kubernetes.io/audit-violations`](/docs/reference/labels-annotations-taints/audit-annotations/#pod-security-kubernetes-io-audit-violations) - [`pod-security.kubernetes.io/enforce-policy`](/docs/reference/labels-annotations-taints/audit-annotations/#pod-security-kubernetes-io-enforce-policy) - [`pod-security.kubernetes.io/exempt`](/docs/reference/labels-annotations-taints/audit-annotations/#pod-security-kubernetes-io-exempt) - +- [`validation.policy.admission.k8s.io/validation_failure`](/docs/reference/labels-annotations-taints/audit-annotations/#validation-policy-admission-k8s-io-validation-failure) + See more details on [Audit Annotations](/docs/reference/labels-annotations-taints/audit-annotations/). ## kubeadm diff --git a/content/en/docs/reference/networking/ports-and-protocols.md b/content/en/docs/reference/networking/ports-and-protocols.md index 2e716e4d46fd9..388a50f519240 100644 --- a/content/en/docs/reference/networking/ports-and-protocols.md +++ b/content/en/docs/reference/networking/ports-and-protocols.md @@ -27,6 +27,7 @@ etcd cluster externally or on custom ports. | Protocol | Direction | Port Range | Purpose | Used By | |----------|-----------|-------------|-----------------------|-------------------------| | TCP | Inbound | 10250 | Kubelet API | Self, Control plane | +| TCP | Inbound | 10256 | kube-proxy | Self, Load balancers | | TCP | Inbound | 30000-32767 | NodePort Services† | All | † Default port range for [NodePort Services](/docs/concepts/services-networking/service/). diff --git a/content/en/docs/reference/networking/virtual-ips.md b/content/en/docs/reference/networking/virtual-ips.md index 862458009f81d..269c41654133f 100644 --- a/content/en/docs/reference/networking/virtual-ips.md +++ b/content/en/docs/reference/networking/virtual-ips.md @@ -488,6 +488,67 @@ route to ready node-local endpoints. If the traffic policy is `Local` and there are no node-local endpoints, the kube-proxy does not forward any traffic for the relevant Service. +If `Cluster` is specified all nodes are eligible load balancing targets _as long as_ +the node is not being deleted and kube-proxy is healthy. In this mode: load balancer +health checks are configured to target the service proxy's readiness port and path. +In the case of kube-proxy this evaluates to: `${NODE_IP}:10256/healthz`. kube-proxy +will return either an HTTP code 200 or 503. kube-proxy's load balancer health check +endpoint returns 200 if: + +1. kube-proxy is healthy, meaning: + - it's able to progress programming the network and isn't timing out while doing + so (the timeout is defined to be: **2 × `iptables.syncPeriod`**); and +2. the node is not being deleted (there is no deletion timestamp set for the Node). + +The reason why kube-proxy returns 503 and marks the node as not +eligible when it's being deleted, is because kube-proxy supports connection +draining for terminating nodes. A couple of important things occur from the point +of view of a Kubernetes-managed load balancer when a node _is being_ / _is_ deleted. + +While deleting: + +* kube-proxy will start failing its readiness probe and essentially mark the + node as not eligible for load balancer traffic. The load balancer health + check failing causes load balancers which support connection draining to + allow existing connections to terminate, and block new connections from + establishing. + +When deleted: + +* The service controller in the Kubernetes cloud controller manager removes the + node from the referenced set of eligible targets. Removing any instance from + the load balancer's set of backend targets immediately terminates all + connections. This is also the reason kube-proxy first fails the health check + while the node is deleting. + +It's important to note for Kubernetes vendors that if any vendor configures the +kube-proxy readiness probe as a liveness probe: that kube-proxy will start +restarting continuously when a node is deleting until it has been fully deleted. +kube-proxy exposes a `/livez` path which, as opposed to the `/healthz` one, does +**not** consider the Node's deleting state and only its progress programming the +network. `/livez` is therefore the recommended path for anyone looking to define +a livenessProbe for kube-proxy. + +Users deploying kube-proxy can inspect both the readiness / liveness state by +evaluating the metrics: `proxy_livez_total` / `proxy_healthz_total`. Both +metrics publish two series, one with the 200 label and one with the 503 one. + +For `Local` Services: kube-proxy will return 200 if + +1. kube-proxy is healthy/ready, and +2. has a local endpoint on the node in question. + +Node deletion does **not** have an impact on kube-proxy's return +code for what concerns load balancer health checks. The reason for this is: +deleting nodes could end up causing an ingress outage should all endpoints +simultaneously be running on said nodes. + +The Kubernetes project recommends that cloud provider integration code +configures load balancer health checks that target the service proxy's healthz +port. If you are using or implementing your own virtual IP implementation, +that people can use instead of kube-proxy, you should set up a similar health +checking port with logic that matches the kube-proxy implementation. + ### Traffic to terminating endpoints {{< feature-state for_k8s_version="v1.28" state="stable" >}} @@ -513,6 +574,96 @@ those terminating Pods. By the time the Pod completes termination, the external should have seen the node's health check failing and fully removed the node from the backend pool. +## Traffic Distribution + +{{< feature-state feature_gate_name="ServiceTrafficDistribution" >}} + +The `spec.trafficDistribution` field within a Kubernetes Service allows you to +express preferences for how traffic should be routed to Service endpoints. +Implementations like kube-proxy use the `spec.trafficDistribution` field as a +guideline. The behavior associated with a given preference may subtly differ +between implementations. + +`PreferClose` with kube-proxy +: For kube-proxy, this means prioritizing sending traffic to endpoints within + the same zone as the client. The EndpointSlice controller updates + EndpointSlices with `hints` to communicate this preference, which kube-proxy + then uses for routing decisions. If a client's zone does not have any + available endpoints, traffic will be routed cluster-wide for that client. + +In the absence of any value for `trafficDistribution`, the default routing +strategy for kube-proxy is to distribute traffic to any endpoint in the cluster. + +### Comparison with `service.kubernetes.io/topology-mode: Auto` + +The `trafficDistribution` field with `PreferClose` and the +`service.kubernetes.io/topology-mode: Auto` annotation both aim to prioritize +same-zone traffic. However, there are key differences in their approaches: + +* `service.kubernetes.io/topology-mode: Auto`: Attempts to distribute traffic + proportionally across zones based on allocatable CPU resources. This heuristic + includes safeguards (such as the [fallback + behavior](/docs/concepts/services-networking/topology-aware-routing/#three-or-more-endpoints-per-zone) + for small numbers of endpoints) and could lead to the feature being disabled + in certain scenarios for load-balancing reasons. This approach sacrifices some + predictability in favor of potential load balancing. + +* `trafficDistribution: PreferClose`: This approach aims to be slightly simpler + and more predictable: "If there are endpoints in the zone, they will receive + all traffic for that zone, if there are no endpoints in a zone, the traffic + will be distributed to other zones". While the approach may offer more + predictability, it does mean that you are in control of managing a [potential + overload](#considerations-for-using-traffic-distribution-control). + +If the `service.kubernetes.io/topology-mode` annotation is set to `Auto`, it +will take precedence over `trafficDistribution`. (The annotation may be deprecated +in the future in favour of the `trafficDistribution` field). + +### Interaction with Traffic Policies + +When compared to the `trafficDistribution` field, the traffic policy fields +(`externalTrafficPolicy` and `internalTrafficPolicy`) are meant to offer a +stricter traffic locality requirements. Here's how `trafficDistribution` +interacts with them: + +* Precedence of Traffic Policies: For a given Service, if a traffic policy + (`externalTrafficPolicy` or `internalTrafficPolicy`) is set to `Local`, it + takes precedence over `trafficDistribution: PreferClose` for the corresponding + traffic type (external or internal, respectively). + +* `trafficDistribution` Influence: For a given Service, if a traffic policy + (`externalTrafficPolicy` or `internalTrafficPolicy`) is set to `Cluster` (the + default), or if the fields are not set, then `trafficDistribution: + PreferClose` guides the routing behavior for the corresponding traffic type + (external or internal, respectively). This means that an attempt will be made + to route traffic to an endpoint that is in the same zone as the client. + +### Considerations for using traffic distribution control + +* **Increased Probability of Overloaded Endpoints:** The `PreferClose` + heuristic will attempt to route traffic to the closest healthy endpoints + instead of spreading that traffic evenly across all endpoints. If you do not + have a sufficient number of endpoints within a zone, they may become + overloaded. This is especially likely if incoming traffic is not + proportionally distributed across zones. To mitigate this, consider the + following strategies: + + * [Pod Topology Spread + Constraints](/docs/concepts/scheduling-eviction/topology-spread-constraints/): + Use Pod Topology Spread Constraints to distribute your pods more evenly + across zones. + + * Zone-specific Deployments: If you expect to see skewed traffic patterns, + create a separate Deployment for each zone. This approach allows the + separate workloads to scale independently. There are also workload + management addons available from the ecosystem, outside the Kubernetes + project itself, that can help here. + +* **Implementation-specific behavior:** Each dataplane implementation may handle + this field slightly differently. If you're using an implementation other than + kube-proxy, refer the documentation specific to that implementation to + understand how this field is being handled. + ## {{% heading "whatsnext" %}} To learn more about Services, diff --git a/content/en/docs/reference/node/_index.md b/content/en/docs/reference/node/_index.md index 881761f64eab9..64a41edb61176 100644 --- a/content/en/docs/reference/node/_index.md +++ b/content/en/docs/reference/node/_index.md @@ -9,6 +9,10 @@ This section contains the following reference topics about nodes: * the kubelet's [checkpoint API](/docs/reference/node/kubelet-checkpoint-api/) * a list of [Articles on dockershim Removal and on Using CRI-compatible Runtimes](/docs/reference/node/topics-on-dockershim-and-cri-compatible-runtimes/) +* [Kubelet Device Manager API Versions](/docs/reference/node/device-plugin-api-versions) + +* [Node Labels Populated By The Kubelet](/docs/reference/node/node-labels) + * [Node `.status` information](/docs/reference/node/node-status/) You can also read node reference details from elsewhere in the @@ -16,4 +20,4 @@ Kubernetes documentation, including: * [Node Metrics Data](/docs/reference/instrumentation/node-metrics). -* [CRI Pod & Container Metrics](/docs/reference/instrumentation/cri-pod-container-metrics). \ No newline at end of file +* [CRI Pod & Container Metrics](/docs/reference/instrumentation/cri-pod-container-metrics). diff --git a/content/en/docs/reference/node/kubelet-config-directory-merging.md b/content/en/docs/reference/node/kubelet-config-directory-merging.md new file mode 100644 index 0000000000000..99ed1bc631203 --- /dev/null +++ b/content/en/docs/reference/node/kubelet-config-directory-merging.md @@ -0,0 +1,155 @@ +--- +content_type: "reference" +title: Kubelet Configuration Directory Merging +weight: 50 +--- + +When using the kubelet's `--config-dir` flag to specify a drop-in directory for +configuration, there is some specific behavior on how different types are +merged. + +Here are some examples of how different data types behave during configuration merging: + +### Structure Fields +There are two types of structure fields in a YAML structure: singular (or a +scalar type) and embedded (structures that contain scalar types). +The configuration merging process handles the overriding of singular and embedded struct fields to create a resulting kubelet configuration. + +For instance, you may want a baseline kubelet configuration for all nodes, but you may want to customize the `address` and `authorization` fields. +This can be done as follows: + +Main kubelet configuration file contents: +```yaml +apiVersion: kubelet.config.k8s.io/v1beta1 +kind: KubeletConfiguration +port: 20250 +authorization: + mode: Webhook + webhook: + cacheAuthorizedTTL: "5m" + cacheUnauthorizedTTL: "30s" +serializeImagePulls: false +address: "192.168.0.1" +``` + +Contents of a file in `--config-dir` directory: +```yaml +apiVersion: kubelet.config.k8s.io/v1beta1 +kind: KubeletConfiguration +authorization: + mode: AlwaysAllow + webhook: + cacheAuthorizedTTL: "8m" + cacheUnauthorizedTTL: "45s" +address: "192.168.0.8" +``` + +The resulting configuration will be as follows: +```yaml +apiVersion: kubelet.config.k8s.io/v1beta1 +kind: KubeletConfiguration +port: 20250 +serializeImagePulls: false +authorization: + mode: AlwaysAllow + webhook: + cacheAuthorizedTTL: "8m" + cacheUnauthorizedTTL: "45s" +address: "192.168.0.8" +``` + +### Lists +You can overide the slices/lists values of the kubelet configuration. +However, the entire list gets overridden during the merging process. +For example, you can override the `clusterDNS` list as follows: + +Main kubelet configuration file contents: +```yaml +apiVersion: kubelet.config.k8s.io/v1beta1 +kind: KubeletConfiguration +port: 20250 +serializeImagePulls: false +clusterDNS: + - "192.168.0.9" + - "192.168.0.8" +``` + +Contents of a file in `--config-dir` directory: +```yaml +apiVersion: kubelet.config.k8s.io/v1beta1 +kind: KubeletConfiguration +clusterDNS: + - "192.168.0.2" + - "192.168.0.3" + - "192.168.0.5" +``` + +The resulting configuration will be as follows: +```yaml +apiVersion: kubelet.config.k8s.io/v1beta1 +kind: KubeletConfiguration +port: 20250 +serializeImagePulls: false +clusterDNS: + - "192.168.0.2" + - "192.168.0.3" + - "192.168.0.5" +``` + +### Maps, including Nested Structures + +Individual fields in maps, regardless of their value types (boolean, string, etc.), can be selectively overridden. +However, for `map[string][]string`, the entire list associated with a specific field gets overridden. +Let's understand this better with an example, particularly on fields like `featureGates` and `staticPodURLHeader`: + +Main kubelet configuration file contents: +```yaml +apiVersion: kubelet.config.k8s.io/v1beta1 +kind: KubeletConfiguration +port: 20250 +serializeImagePulls: false +featureGates: + AllAlpha: false + MemoryQoS: true +staticPodURLHeader: + kubelet-api-support: + - "Authorization: 234APSDFA" + - "X-Custom-Header: 123" + custom-static-pod: + - "Authorization: 223EWRWER" + - "X-Custom-Header: 456" +``` + +Contents of a file in `--config-dir` directory: +```yaml +apiVersion: kubelet.config.k8s.io/v1beta1 +kind: KubeletConfiguration +featureGates: + MemoryQoS: false + KubeletTracing: true + DynamicResourceAllocation: true +staticPodURLHeader: + custom-static-pod: + - "Authorization: 223EWRWER" + - "X-Custom-Header: 345" +``` + +The resulting configuration will be as follows: +```yaml +apiVersion: kubelet.config.k8s.io/v1beta1 +kind: KubeletConfiguration +port: 20250 +serializeImagePulls: false +featureGates: + AllAlpha: false + MemoryQoS: false + KubeletTracing: true + DynamicResourceAllocation: true +staticPodURLHeader: + kubelet-api-support: + - "Authorization: 234APSDFA" + - "X-Custom-Header: 123" + custom-static-pod: + - "Authorization: 223EWRWER" + - "X-Custom-Header: 345" +``` diff --git a/content/en/docs/reference/node/topics-on-dockershim-and-cri-compatible-runtimes.md b/content/en/docs/reference/node/topics-on-dockershim-and-cri-compatible-runtimes.md index 8d2e26c1e981e..b56f2af9f378d 100644 --- a/content/en/docs/reference/node/topics-on-dockershim-and-cri-compatible-runtimes.md +++ b/content/en/docs/reference/node/topics-on-dockershim-and-cri-compatible-runtimes.md @@ -48,6 +48,6 @@ You can provide feedback via the GitHub issue [**Dockershim removal feedback & i * Mirantis blog: [The Future of Dockershim is cri-dockerd](https://www.mirantis.com/blog/the-future-of-dockershim-is-cri-dockerd/) (published 2021/04/21) -* Mirantis: [Mirantis/cri-dockerd](https://github.com/Mirantis/cri-dockerd) Git repository (on GitHub) +* Mirantis: [Mirantis/cri-dockerd](https://mirantis.github.io/cri-dockerd/) Official Documentation * Tripwire: [How Dockershim’s Forthcoming Deprecation Affects Your Kubernetes](https://www.tripwire.com/state-of-security/security-data-protection/cloud/how-dockershim-forthcoming-deprecation-affects-your-kubernetes/) (published 2021/07/01) diff --git a/content/en/docs/reference/setup-tools/kubeadm/generated/kubeadm_certs_check-expiration.md b/content/en/docs/reference/setup-tools/kubeadm/generated/kubeadm_certs_check-expiration.md index a96fb3648aafc..1a1803ca41f2c 100644 --- a/content/en/docs/reference/setup-tools/kubeadm/generated/kubeadm_certs_check-expiration.md +++ b/content/en/docs/reference/setup-tools/kubeadm/generated/kubeadm_certs_check-expiration.md @@ -30,6 +30,13 @@ kubeadm certs check-expiration [flags] + +--allow-missing-template-keys     Default: true + + +

          If true, ignore any errors in templates when a field or map key is missing in the template. Only applies to golang and jsonpath output formats.

          + + --cert-dir string     Default: "/etc/kubernetes/pki" @@ -44,6 +51,13 @@ kubeadm certs check-expiration [flags]

          Path to a kubeadm configuration file.

          + +-o, --experimental-output string     Default: "text" + + +

          Output format. One of: text|json|yaml|go-template|go-template-file|template|templatefile|jsonpath|jsonpath-as-json|jsonpath-file.

          + + -h, --help @@ -58,6 +72,13 @@ kubeadm certs check-expiration [flags]

          The kubeconfig file to use when talking to the cluster. If the flag is not set, a set of standard locations can be searched for an existing kubeconfig file.

          + +--show-managed-fields + + +

          If true, keep the managedFields when printing objects in JSON or YAML format.

          + + diff --git a/content/en/docs/reference/setup-tools/kubeadm/generated/kubeadm_config_images_list.md b/content/en/docs/reference/setup-tools/kubeadm/generated/kubeadm_config_images_list.md index 416d92bc86ec9..def9c409b1aa3 100644 --- a/content/en/docs/reference/setup-tools/kubeadm/generated/kubeadm_config_images_list.md +++ b/content/en/docs/reference/setup-tools/kubeadm/generated/kubeadm_config_images_list.md @@ -55,7 +55,7 @@ kubeadm config images list [flags] --feature-gates string -

          A set of key=value pairs that describe feature gates for various features. Options are:
          EtcdLearnerMode=true|false (BETA - default=true)
          PublicKeysECDSA=true|false (DEPRECATED - default=false)
          RootlessControlPlane=true|false (ALPHA - default=false)
          UpgradeAddonsBeforeControlPlane=true|false (DEPRECATED - default=false)

          +

          A set of key=value pairs that describe feature gates for various features. Options are:
          EtcdLearnerMode=true|false (BETA - default=true)
          PublicKeysECDSA=true|false (DEPRECATED - default=false)
          RootlessControlPlane=true|false (ALPHA - default=false)
          UpgradeAddonsBeforeControlPlane=true|false (DEPRECATED - default=false)
          WaitForAllControlPlaneComponents=true|false (ALPHA - default=false)

          diff --git a/content/en/docs/reference/setup-tools/kubeadm/generated/kubeadm_config_images_pull.md b/content/en/docs/reference/setup-tools/kubeadm/generated/kubeadm_config_images_pull.md index 9ef9b05e8f523..3534a4556428f 100644 --- a/content/en/docs/reference/setup-tools/kubeadm/generated/kubeadm_config_images_pull.md +++ b/content/en/docs/reference/setup-tools/kubeadm/generated/kubeadm_config_images_pull.md @@ -48,7 +48,7 @@ kubeadm config images pull [flags] --feature-gates string -

          A set of key=value pairs that describe feature gates for various features. Options are:
          EtcdLearnerMode=true|false (BETA - default=true)
          PublicKeysECDSA=true|false (DEPRECATED - default=false)
          RootlessControlPlane=true|false (ALPHA - default=false)
          UpgradeAddonsBeforeControlPlane=true|false (DEPRECATED - default=false)

          +

          A set of key=value pairs that describe feature gates for various features. Options are:
          EtcdLearnerMode=true|false (BETA - default=true)
          PublicKeysECDSA=true|false (DEPRECATED - default=false)
          RootlessControlPlane=true|false (ALPHA - default=false)
          UpgradeAddonsBeforeControlPlane=true|false (DEPRECATED - default=false)
          WaitForAllControlPlaneComponents=true|false (ALPHA - default=false)

          diff --git a/content/en/docs/reference/setup-tools/kubeadm/generated/kubeadm_config_validate.md b/content/en/docs/reference/setup-tools/kubeadm/generated/kubeadm_config_validate.md index 69a92868c27de..9a65b7e6930da 100644 --- a/content/en/docs/reference/setup-tools/kubeadm/generated/kubeadm_config_validate.md +++ b/content/en/docs/reference/setup-tools/kubeadm/generated/kubeadm_config_validate.md @@ -18,7 +18,7 @@ Read a file containing the kubeadm configuration API and report any validation p This command lets you validate a kubeadm configuration API file and report any warnings and errors. If there are no errors the exit status will be zero, otherwise it will be non-zero. -Any unmarshalling problems such as unknown API fields will trigger errors. Unknown API versions and +Any unmarshaling problems such as unknown API fields will trigger errors. Unknown API versions and fields with invalid values will also trigger errors. Any other errors or warnings may be reported depending on contents of the input file. diff --git a/content/en/docs/reference/setup-tools/kubeadm/generated/kubeadm_init.md b/content/en/docs/reference/setup-tools/kubeadm/generated/kubeadm_init.md index d554cdd0d7103..538f802c7fb2e 100644 --- a/content/en/docs/reference/setup-tools/kubeadm/generated/kubeadm_init.md +++ b/content/en/docs/reference/setup-tools/kubeadm/generated/kubeadm_init.md @@ -140,7 +140,7 @@ kubeadm init [flags] --feature-gates string -

          A set of key=value pairs that describe feature gates for various features. Options are:
          EtcdLearnerMode=true|false (BETA - default=true)
          PublicKeysECDSA=true|false (DEPRECATED - default=false)
          RootlessControlPlane=true|false (ALPHA - default=false)
          UpgradeAddonsBeforeControlPlane=true|false (DEPRECATED - default=false)

          +

          A set of key=value pairs that describe feature gates for various features. Options are:
          EtcdLearnerMode=true|false (BETA - default=true)
          PublicKeysECDSA=true|false (DEPRECATED - default=false)
          RootlessControlPlane=true|false (ALPHA - default=false)
          UpgradeAddonsBeforeControlPlane=true|false (DEPRECATED - default=false)
          WaitForAllControlPlaneComponents=true|false (ALPHA - default=false)

          diff --git a/content/en/docs/reference/setup-tools/kubeadm/generated/kubeadm_init_phase_addon_all.md b/content/en/docs/reference/setup-tools/kubeadm/generated/kubeadm_init_phase_addon_all.md index 9856fbb338ee4..4b08bcf5f87d1 100644 --- a/content/en/docs/reference/setup-tools/kubeadm/generated/kubeadm_init_phase_addon_all.md +++ b/content/en/docs/reference/setup-tools/kubeadm/generated/kubeadm_init_phase_addon_all.md @@ -69,7 +69,7 @@ kubeadm init phase addon all [flags] --feature-gates string -

          A set of key=value pairs that describe feature gates for various features. Options are:
          EtcdLearnerMode=true|false (BETA - default=true)
          PublicKeysECDSA=true|false (DEPRECATED - default=false)
          RootlessControlPlane=true|false (ALPHA - default=false)
          UpgradeAddonsBeforeControlPlane=true|false (DEPRECATED - default=false)

          +

          A set of key=value pairs that describe feature gates for various features. Options are:
          EtcdLearnerMode=true|false (BETA - default=true)
          PublicKeysECDSA=true|false (DEPRECATED - default=false)
          RootlessControlPlane=true|false (ALPHA - default=false)
          UpgradeAddonsBeforeControlPlane=true|false (DEPRECATED - default=false)
          WaitForAllControlPlaneComponents=true|false (ALPHA - default=false)

          diff --git a/content/en/docs/reference/setup-tools/kubeadm/generated/kubeadm_init_phase_addon_coredns.md b/content/en/docs/reference/setup-tools/kubeadm/generated/kubeadm_init_phase_addon_coredns.md index aa9b25aa74635..b3811cf5c61e4 100644 --- a/content/en/docs/reference/setup-tools/kubeadm/generated/kubeadm_init_phase_addon_coredns.md +++ b/content/en/docs/reference/setup-tools/kubeadm/generated/kubeadm_init_phase_addon_coredns.md @@ -48,7 +48,7 @@ kubeadm init phase addon coredns [flags] --feature-gates string -

          A set of key=value pairs that describe feature gates for various features. Options are:
          EtcdLearnerMode=true|false (BETA - default=true)
          PublicKeysECDSA=true|false (DEPRECATED - default=false)
          RootlessControlPlane=true|false (ALPHA - default=false)
          UpgradeAddonsBeforeControlPlane=true|false (DEPRECATED - default=false)

          +

          A set of key=value pairs that describe feature gates for various features. Options are:
          EtcdLearnerMode=true|false (BETA - default=true)
          PublicKeysECDSA=true|false (DEPRECATED - default=false)
          RootlessControlPlane=true|false (ALPHA - default=false)
          UpgradeAddonsBeforeControlPlane=true|false (DEPRECATED - default=false)
          WaitForAllControlPlaneComponents=true|false (ALPHA - default=false)

          diff --git a/content/en/docs/reference/setup-tools/kubeadm/generated/kubeadm_init_phase_control-plane_all.md b/content/en/docs/reference/setup-tools/kubeadm/generated/kubeadm_init_phase_control-plane_all.md index 2c86f8622c4ba..ff8784a15a84a 100644 --- a/content/en/docs/reference/setup-tools/kubeadm/generated/kubeadm_init_phase_control-plane_all.md +++ b/content/en/docs/reference/setup-tools/kubeadm/generated/kubeadm_init_phase_control-plane_all.md @@ -101,7 +101,7 @@ kubeadm init phase control-plane all [flags] --feature-gates string -

          A set of key=value pairs that describe feature gates for various features. Options are:
          EtcdLearnerMode=true|false (BETA - default=true)
          PublicKeysECDSA=true|false (DEPRECATED - default=false)
          RootlessControlPlane=true|false (ALPHA - default=false)
          UpgradeAddonsBeforeControlPlane=true|false (DEPRECATED - default=false)

          +

          A set of key=value pairs that describe feature gates for various features. Options are:
          EtcdLearnerMode=true|false (BETA - default=true)
          PublicKeysECDSA=true|false (DEPRECATED - default=false)
          RootlessControlPlane=true|false (ALPHA - default=false)
          UpgradeAddonsBeforeControlPlane=true|false (DEPRECATED - default=false)
          WaitForAllControlPlaneComponents=true|false (ALPHA - default=false)

          diff --git a/content/en/docs/reference/setup-tools/kubeadm/generated/kubeadm_init_phase_control-plane_apiserver.md b/content/en/docs/reference/setup-tools/kubeadm/generated/kubeadm_init_phase_control-plane_apiserver.md index c38bd787a8542..862608294c26f 100644 --- a/content/en/docs/reference/setup-tools/kubeadm/generated/kubeadm_init_phase_control-plane_apiserver.md +++ b/content/en/docs/reference/setup-tools/kubeadm/generated/kubeadm_init_phase_control-plane_apiserver.md @@ -83,7 +83,7 @@ kubeadm init phase control-plane apiserver [flags] --feature-gates string -

          A set of key=value pairs that describe feature gates for various features. Options are:
          EtcdLearnerMode=true|false (BETA - default=true)
          PublicKeysECDSA=true|false (DEPRECATED - default=false)
          RootlessControlPlane=true|false (ALPHA - default=false)
          UpgradeAddonsBeforeControlPlane=true|false (DEPRECATED - default=false)

          +

          A set of key=value pairs that describe feature gates for various features. Options are:
          EtcdLearnerMode=true|false (BETA - default=true)
          PublicKeysECDSA=true|false (DEPRECATED - default=false)
          RootlessControlPlane=true|false (ALPHA - default=false)
          UpgradeAddonsBeforeControlPlane=true|false (DEPRECATED - default=false)
          WaitForAllControlPlaneComponents=true|false (ALPHA - default=false)

          diff --git a/content/en/docs/reference/setup-tools/kubeadm/generated/kubeadm_join.md b/content/en/docs/reference/setup-tools/kubeadm/generated/kubeadm_join.md index d1bff7d0c1824..0f29c5473a595 100644 --- a/content/en/docs/reference/setup-tools/kubeadm/generated/kubeadm_join.md +++ b/content/en/docs/reference/setup-tools/kubeadm/generated/kubeadm_join.md @@ -73,6 +73,7 @@ control-plane-join Join a machine as a control plane instance /etcd Add a new local etcd member /update-status Register the new control-plane node into the ClusterStatus maintained in the kubeadm-config ConfigMap (DEPRECATED) /mark-control-plane Mark a node as a control-plane +wait-control-plane EXPERIMENTAL: Wait for the control plane to start ``` diff --git a/content/en/docs/reference/setup-tools/kubeadm/generated/kubeadm_join_phase_wait-control-plane.md b/content/en/docs/reference/setup-tools/kubeadm/generated/kubeadm_join_phase_wait-control-plane.md new file mode 100644 index 0000000000000..cbdf65f75d62a --- /dev/null +++ b/content/en/docs/reference/setup-tools/kubeadm/generated/kubeadm_join_phase_wait-control-plane.md @@ -0,0 +1,65 @@ + + + +EXPERIMENTAL: Wait for the control plane to start + +### Synopsis + + +EXPERIMENTAL: Wait for the control plane to start + +``` +kubeadm join phase wait-control-plane [flags] +``` + +### Options + + ++++ + + + + + + + + + + +
          -h, --help

          help for wait-control-plane

          + + + +### Options inherited from parent commands + + ++++ + + + + + + + + + + +
          --rootfs string

          [EXPERIMENTAL] The path to the 'real' host root filesystem.

          + + + diff --git a/content/en/docs/reference/setup-tools/kubeadm/generated/kubeadm_upgrade_apply.md b/content/en/docs/reference/setup-tools/kubeadm/generated/kubeadm_upgrade_apply.md index 8d257715149a8..1a30145ae6e5b 100644 --- a/content/en/docs/reference/setup-tools/kubeadm/generated/kubeadm_upgrade_apply.md +++ b/content/en/docs/reference/setup-tools/kubeadm/generated/kubeadm_upgrade_apply.md @@ -76,7 +76,7 @@ kubeadm upgrade apply [version] --feature-gates string -

          A set of key=value pairs that describe feature gates for various features. Options are:
          EtcdLearnerMode=true|false (BETA - default=true)
          PublicKeysECDSA=true|false (DEPRECATED - default=false)
          RootlessControlPlane=true|false (ALPHA - default=false)
          UpgradeAddonsBeforeControlPlane=true|false (DEPRECATED - default=false)

          +

          A set of key=value pairs that describe feature gates for various features. Options are:
          EtcdLearnerMode=true|false (BETA - default=true)
          PublicKeysECDSA=true|false (DEPRECATED - default=false)
          RootlessControlPlane=true|false (ALPHA - default=false)
          UpgradeAddonsBeforeControlPlane=true|false (DEPRECATED - default=false)
          WaitForAllControlPlaneComponents=true|false (ALPHA - default=false)

          diff --git a/content/en/docs/reference/setup-tools/kubeadm/generated/kubeadm_upgrade_node.md b/content/en/docs/reference/setup-tools/kubeadm/generated/kubeadm_upgrade_node.md index 1ee54c4ee3721..ffa9d94e3f801 100644 --- a/content/en/docs/reference/setup-tools/kubeadm/generated/kubeadm_upgrade_node.md +++ b/content/en/docs/reference/setup-tools/kubeadm/generated/kubeadm_upgrade_node.md @@ -45,6 +45,13 @@ kubeadm upgrade node [flags]

          Perform the renewal of certificates used by component changed during upgrades.

          + +--config string + + +

          Path to a kubeadm configuration file.

          + + --dry-run diff --git a/content/en/docs/reference/setup-tools/kubeadm/generated/kubeadm_upgrade_plan.md b/content/en/docs/reference/setup-tools/kubeadm/generated/kubeadm_upgrade_plan.md index a2f1de2ee3efa..09fbdbb19408a 100644 --- a/content/en/docs/reference/setup-tools/kubeadm/generated/kubeadm_upgrade_plan.md +++ b/content/en/docs/reference/setup-tools/kubeadm/generated/kubeadm_upgrade_plan.md @@ -10,12 +10,12 @@ guide. You can file document formatting bugs against the --> -Check which versions are available to upgrade to and validate whether your current cluster is upgradeable. To skip the internet check, pass in the optional [version] parameter +Check which versions are available to upgrade to and validate whether your current cluster is upgradeable. ### Synopsis -Check which versions are available to upgrade to and validate whether your current cluster is upgradeable. To skip the internet check, pass in the optional [version] parameter +Check which versions are available to upgrade to and validate whether your current cluster is upgradeable. This command can only run on the control plane nodes where the kubeconfig file "admin.conf" exists. To skip the internet check, pass in the optional [version] parameter. ``` kubeadm upgrade plan [version] [flags] @@ -37,6 +37,13 @@ kubeadm upgrade plan [version] [flags]

          Show unstable versions of Kubernetes as an upgrade alternative and allow upgrading to an alpha/beta/release candidate versions of Kubernetes.

          + +--allow-missing-template-keys     Default: true + + +

          If true, ignore any errors in templates when a field or map key is missing in the template. Only applies to golang and jsonpath output formats.

          + + --allow-release-candidate-upgrades @@ -51,11 +58,18 @@ kubeadm upgrade plan [version] [flags]

          Path to a kubeadm configuration file.

          + +-o, --experimental-output string     Default: "text" + + +

          Output format. One of: text|json|yaml|go-template|go-template-file|template|templatefile|jsonpath|jsonpath-as-json|jsonpath-file.

          + + --feature-gates string -

          A set of key=value pairs that describe feature gates for various features. Options are:
          EtcdLearnerMode=true|false (BETA - default=true)
          PublicKeysECDSA=true|false (DEPRECATED - default=false)
          RootlessControlPlane=true|false (ALPHA - default=false)
          UpgradeAddonsBeforeControlPlane=true|false (DEPRECATED - default=false)

          +

          A set of key=value pairs that describe feature gates for various features. Options are:
          EtcdLearnerMode=true|false (BETA - default=true)
          PublicKeysECDSA=true|false (DEPRECATED - default=false)
          RootlessControlPlane=true|false (ALPHA - default=false)
          UpgradeAddonsBeforeControlPlane=true|false (DEPRECATED - default=false)
          WaitForAllControlPlaneComponents=true|false (ALPHA - default=false)

          @@ -79,13 +93,6 @@ kubeadm upgrade plan [version] [flags]

          The kubeconfig file to use when talking to the cluster. If the flag is not set, a set of standard locations can be searched for an existing kubeconfig file.

          - --o, --output string     Default: "text" - - -

          EXPERIMENTAL: Output format. One of: text|json|yaml.

          - - --print-config diff --git a/content/en/docs/reference/setup-tools/kubeadm/implementation-details.md b/content/en/docs/reference/setup-tools/kubeadm/implementation-details.md index 33463afb8cad8..97494f69a5a2e 100644 --- a/content/en/docs/reference/setup-tools/kubeadm/implementation-details.md +++ b/content/en/docs/reference/setup-tools/kubeadm/implementation-details.md @@ -109,8 +109,6 @@ The user can skip specific preflight checks or all of them with the `--ignore-pr - [warning] if firewalld is active - [error] if API server bindPort or ports 10250/10251/10252 are used - [Error] if `/etc/kubernetes/manifest` folder already exists and it is not empty -- [Error] if `/proc/sys/net/bridge/bridge-nf-call-iptables` file does not exist/does not contain 1 -- [Error] if advertise address is ipv6 and `/proc/sys/net/bridge/bridge-nf-call-ip6tables` does not exist/does not contain 1. - [Error] if swap is on - [Error] if `conntrack`, `ip`, `iptables`, `mount`, `nsenter` commands are not present in the command path - [warning] if `ebtables`, `ethtool`, `socat`, `tc`, `touch`, `crictl` commands are not present in the command path diff --git a/content/en/docs/reference/setup-tools/kubeadm/kubeadm-init.md b/content/en/docs/reference/setup-tools/kubeadm/kubeadm-init.md index 0fbeb13e93040..2caa94d6764a1 100644 --- a/content/en/docs/reference/setup-tools/kubeadm/kubeadm-init.md +++ b/content/en/docs/reference/setup-tools/kubeadm/kubeadm-init.md @@ -1,7 +1,4 @@ --- -reviewers: -- luxas -- jbeda title: kubeadm init content_type: concept weight: 20 @@ -161,6 +158,7 @@ Feature | Default | Alpha | Beta | GA `EtcdLearnerMode` | `true` | 1.27 | 1.29 | - `PublicKeysECDSA` | `false` | 1.19 | - | - `RootlessControlPlane` | `false` | 1.22 | - | - +`WaitForAllControlPlaneComponents` | `false` | 1.30 | - | - {{< /table >}} {{< note >}} @@ -184,6 +182,16 @@ for `kube-apiserver`, `kube-controller-manager`, `kube-scheduler` and `etcd` to If the flag is not set, those components run as root. You can change the value of this feature gate before you upgrade to a newer version of Kubernetes. +`WaitForAllControlPlaneComponents` +: With this feature gate enabled kubeadm will wait for all control plane components (kube-apiserver, +kube-controller-manager, kube-scheduler) on a control plane node to report status 200 on their `/healthz` +endpoints. These checks are performed on `https://127.0.0.1:PORT/healthz`, where `PORT` is taken from +`--secure-port` of a component. If you specify custom `--secure-port` values in the kubeadm configuration +they will be respected. Without the feature gate enabled, kubeadm will only wait for the kube-apiserver +on a control plane node to become ready. The wait process starts right after the kubelet on the host +is started by kubeadm. You are advised to enable this feature gate in case you wish to observe a ready +state from all control plane components during the `kubeadm init` or `kubeadm join` command execution. + List of deprecated feature gates: {{< table caption="kubeadm deprecated feature gates" >}} diff --git a/content/en/docs/reference/setup-tools/kubeadm/kubeadm-join.md b/content/en/docs/reference/setup-tools/kubeadm/kubeadm-join.md index 1c6e0789cf20c..a2ca3e2050564 100644 --- a/content/en/docs/reference/setup-tools/kubeadm/kubeadm-join.md +++ b/content/en/docs/reference/setup-tools/kubeadm/kubeadm-join.md @@ -191,8 +191,10 @@ and CSR approval for a new node: 2. Modify the resulted `kubelet.conf` manually to adjust the cluster name and the server endpoint, or run `kubeadm kubeconfig user --config` (it accepts `InitConfiguration`). -If your cluster does not have the `ca.key` file, you must sign the embedded certificates in -the `kubelet.conf` externally. +If your cluster does not have the `ca.key` file, you must sign the embedded certificates in +the `kubelet.conf` externally. For additional information, see +[PKI certificates and requirements](/docs/setup/best-practices/certificates/) and +[Certificate Management with kubeadm](/docs/tasks/administer-cluster/kubeadm/kubeadm-certs/#external-ca-mode). 1. Copy the resulting `kubelet.conf` to `/etc/kubernetes/kubelet.conf` on the new node. 2. Execute `kubeadm join` with the flag diff --git a/content/en/docs/reference/setup-tools/kubeadm/kubeadm-reset.md b/content/en/docs/reference/setup-tools/kubeadm/kubeadm-reset.md index 9a5f9b29fde69..944d0accaa880 100644 --- a/content/en/docs/reference/setup-tools/kubeadm/kubeadm-reset.md +++ b/content/en/docs/reference/setup-tools/kubeadm/kubeadm-reset.md @@ -34,6 +34,17 @@ etcdctl del "" --prefix See the [etcd documentation](https://github.com/coreos/etcd/tree/master/etcdctl) for more information. +### Graceful kube-apiserver shutdown + +If you have your `kube-apiserver` configured with the `--shutdown-delay-duration` flag, +you can run the following commands to attempt a graceful shutdown for the running API server Pod, +before you run `kubeadm reset`: + +```bash +yq eval -i '.spec.containers[0].command = []' /etc/kubernetes/manifests/kube-apiserver.yaml +timeout 60 sh -c 'while pgrep kube-apiserver >/dev/null; do sleep 1; done' || true +``` + ## {{% heading "whatsnext" %}} * [kubeadm init](/docs/reference/setup-tools/kubeadm/kubeadm-init/) to bootstrap a Kubernetes control-plane node diff --git a/content/en/docs/reference/using-api/api-concepts.md b/content/en/docs/reference/using-api/api-concepts.md index 3e50fabb94313..acd54e8030fd2 100644 --- a/content/en/docs/reference/using-api/api-concepts.md +++ b/content/en/docs/reference/using-api/api-concepts.md @@ -229,7 +229,7 @@ the API server will send any `BOOKMARK` event even when requested. ## Streaming lists -{{< feature-state for_k8s_version="v1.27" state="alpha" >}} +{{< feature-state feature_gate_name="WatchList" >}} On large clusters, retrieving the collection of some resource types may result in a significant increase of resource usage (primarily RAM) on the control plane. @@ -287,7 +287,7 @@ Content-Type: application/json ## Response compression -{{< feature-state for_k8s_version="v1.16" state="beta" >}} +{{< feature-state feature_gate_name="APIResponseCompression" >}} `APIResponseCompression` is an option that allows the API server to compress the responses for **get** and **list** requests, reducing the network bandwidth and improving the performance of large-scale clusters. @@ -317,7 +317,7 @@ The `content-encoding` header indicates that the response is compressed with `gz ## Retrieving large results sets in chunks -{{< feature-state for_k8s_version="v1.29" state="stable" >}} +{{< feature-state feature_gate_name="APIListChunking" >}} On large clusters, retrieving the collection of some resource types may result in very large responses that can impact the server and client. For instance, a cluster @@ -349,7 +349,7 @@ of time (by default 5 minutes) and return a `410 Gone` if more results cannot be returned. In this case, the client will need to start from the beginning or omit the `limit` parameter. -For example, if there are 1,253 pods on the cluster and you wants to receive chunks +For example, if there are 1,253 pods on the cluster and you want to receive chunks of 500 pods at a time, request those chunks as follows: 1. List all of the pods on a cluster, retrieving up to 500 pods each time. @@ -787,7 +787,7 @@ These situations are: ### Validation for unrecognized or duplicate fields {#setting-the-field-validation-level} -{{< feature-state for_k8s_version="v1.27" state="stable" >}} +{{< feature-state feature_gate_name="ServerSideFieldValidation" >}} From 1.25 onward, unrecognized or duplicate fields in an object are detected via validation on the server when you use HTTP verbs that can submit data (`POST`, `PUT`, and `PATCH`). Possible levels of @@ -846,7 +846,7 @@ a boolean flag. ## Dry-run - {{< feature-state for_k8s_version="v1.18" state="stable" >}} +{{< feature-state feature_gate_name="DryRun" >}} When you use HTTP verbs that can modify resources (`POST`, `PUT`, `PATCH`, and `DELETE`), you can submit your request in a _dry run_ mode. Dry run mode helps to diff --git a/content/en/docs/reference/using-api/cel.md b/content/en/docs/reference/using-api/cel.md index 5c94a0cf952cc..fd6460ea78172 100644 --- a/content/en/docs/reference/using-api/cel.md +++ b/content/en/docs/reference/using-api/cel.md @@ -55,37 +55,33 @@ Example CEL expressions: | `has(self.expired) && self.created + self.ttl < self.expired` | Validate that 'expired' date is after a 'create' date plus a 'ttl' duration | | `self.health.startsWith('ok')` | Validate a 'health' string field has the prefix 'ok' | | `self.widgets.exists(w, w.key == 'x' && w.foo < 10)` | Validate that the 'foo' property of a listMap item with a key 'x' is less than 10 | -| `type(self) == string ? self == '99%' : self == 42` | Validate an int-or-string field for both the int and string cases | +| `type(self) == string ? self == '99%' : self == 42` | Validate an int-or-string field for both the int and string cases | | `self.metadata.name == 'singleton'` | Validate that an object's name matches a specific value (making it a singleton) | | `self.set1.all(e, !(e in self.set2))` | Validate that two listSets are disjoint | | `self.names.size() == self.details.size() && self.names.all(n, n in self.details)` | Validate the 'details' map is keyed by the items in the 'names' listSet | +| `self.details.all(key, key.matches('^[a-zA-Z]*$')` | Validate the keys of the 'details' map | +| `self.details.all(key, self.details[key].matches('^[a-zA-Z]*$')` | Validate the values of the 'details' map | {{< /table >}} ## CEL options, language features, and libraries CEL is configured with the following options, libraries and language features, introduced at the specified Kubernetes versions: -| CEL option, library or language feature | Included | Availablity | -| --------------------------------------------------- | --------------------------------------------------------------------------------------------------------------- | -------------------------- | -| [Standard macros](stdmacros) | `has`, `all`, `exists`, `exists_one`, `map`, `filter` | All Kubernetes versions | -| [Standard functions](stdlib) | See [official list of standard definitions](stdlib) | All Kubernetes versions | -| [Homogeneous Aggregate Literals](opt1) | | All Kubernetes versions | -| [Default UTC Time Zone](opt2) | | All Kubernetes versions | -| [Eagerly Validate Declarations](opt3) | | All Kubernetes versions | -| [extended strings library](stringsgodoc), Version 1 | `charAt`, `indexOf`, `lastIndexOf`, `lowerAscii`, `upperAscii`, `replace`, `split`, `join`, `substring`, `trim` | All Kubernetes versions | -| Kubernetes list library | See [Kubernetes list library](#kubernetes-list-library) | All Kubernetes versions | -| Kubernetes regex library | See [Kubernetes regex library](#kubernetes-regex-library) | All Kubernetes versions | -| Kubernetes URL library | See [Kubernetes URL library](#kubernetes-url-library) | All Kubernetes versions | -| Kubernetes authorizer library | See [Kubernetes authorizer library](#kubernetes-authorizer-library) | All Kubernetes versions | - -[stdmacros]: https://github.com/google/cel-spec/blob/v0.7.0/doc/langdef.md#macros -[stdlib]: https://github.com/google/cel-spec/blob/master/doc/langdef.md#list-of-standard-definitions -[stringsgodoc]: https://pkg.go.dev/github.com/google/cel-go/ext#Strings -[opt1]: https://pkg.go.dev/github.com/google/cel-go@v0.17.4/cel#HomogeneousAggregateLiterals -[opt2]: https://pkg.go.dev/github.com/google/cel-go@v0.17.4/cel#DefaultUTCTimeZone -[opt3]: https://pkg.go.dev/github.com/google/cel-go@v0.17.4/cel#EagerlyValidateDeclarations -[opt4]: https://pkg.go.dev/github.com/google/cel-go@v0.17.4/cel#OptionalTypes -[opt5]: https://pkg.go.dev/github.com/google/cel-go@v0.17.4/cel#CrossTypeNumericComparisons +| CEL option, library or language feature | Included | Availablity | +|------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------|---------------------------| +| [Standard macros](https://github.com/google/cel-spec/blob/v0.7.0/doc/langdef.md#macros) | `has`, `all`, `exists`, `exists_one`, `map`, `filter` | All Kubernetes versions | +| [Standard functions](https://github.com/google/cel-spec/blob/master/doc/langdef.md#list-of-standard-definitions) | See [official list of standard definitions](https://github.com/google/cel-spec/blob/master/doc/langdef.md#list-of-standard-definitions) | All Kubernetes versions | +| [Homogeneous Aggregate Literals](https://pkg.go.dev/github.com/google/cel-go@v0.17.4/cel#HomogeneousAggregateLiterals) | | All Kubernetes versions | +| [Default UTC Time Zone](https://pkg.go.dev/github.com/google/cel-go@v0.17.4/cel#DefaultUTCTimeZone) | | All Kubernetes versions | +| [Eagerly Validate Declarations](https://pkg.go.dev/github.com/google/cel-go@v0.17.4/cel#EagerlyValidateDeclarations) | | All Kubernetes versions | +| [extended strings library](https://pkg.go.dev/github.com/google/cel-go/ext#Strings), Version 1 | `charAt`, `indexOf`, `lastIndexOf`, `lowerAscii`, `upperAscii`, `replace`, `split`, `join`, `substring`, `trim` | All Kubernetes versions | +| Kubernetes list library | See [Kubernetes list library](#kubernetes-list-library) | All Kubernetes versions | +| Kubernetes regex library | See [Kubernetes regex library](#kubernetes-regex-library) | All Kubernetes versions | +| Kubernetes URL library | See [Kubernetes URL library](#kubernetes-url-library) | All Kubernetes versions | +| Kubernetes authorizer library | See [Kubernetes authorizer library](#kubernetes-authorizer-library) | All Kubernetes versions | +| Kubernetes quantity library | See [Kubernetes quantity library](#kubernetes-quantity-library) | Kubernetes versions 1.29+ | +| CEL optional types | See [CEL optional types](https://pkg.go.dev/github.com/google/cel-go@v0.17.4/cel#OptionalTypes) | Kubernetes versions 1.29+ | +| CEL CrossTypeNumericComparisons | See [CEL CrossTypeNumericComparisons](https://pkg.go.dev/github.com/google/cel-go@v0.17.4/cel#CrossTypeNumericComparisons) | Kubernetes versions 1.29+ | CEL functions, features and language settings support Kubernetes control plane rollbacks. For example, _CEL Optional Values_ was introduced at Kubernetes 1.29 @@ -207,6 +203,50 @@ To perform an authorization check for a service account: See the [Kubernetes Authz library](https://pkg.go.dev/k8s.io/apiserver/pkg/cel/library#Authz) godoc for more information. +### Kubernetes quantity library + +Kubernetes 1.28 adds support for manipulating quantity strings (ex 1.5G, 512k, 20Mi) + +- `isQuantity(string)` checks if a string is a valid Quantity according to [Kubernetes' + resource.Quantity](https://pkg.go.dev/k8s.io/apimachinery/pkg/api/resource#Quantity). +- `quantity(string) Quantity` converts a string to a Quantity or results in an error if the + string is not a valid quantity. + +Once parsed via the `quantity` function, the resulting Quantity object has the +following library of member functions: + +{{< table caption="Available member functions of a Quantity" >}} +| Member Function | CEL Return Value | Description | +|-------------------------------|-------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `isInteger()` | bool | returns true if and only if asInteger is safe to call without an error | +| `asInteger()` | int | returns a representation of the current value as an int64 if possible or results in an error if conversion would result in overflow or loss of precision. | +| `asApproximateFloat()` | float | returns a float64 representation of the quantity which may lose precision. If the value of the quantity is outside the range of a float64 +Inf/-Inf will be returned. | +| `sign()` | int | Returns `1` if the quantity is positive, `-1` if it is negative. `0` if it is zero | +| `add()` | Quantity | Returns sum of two quantities | +| `add()` | Quantity | Returns sum of quantity and an integer | +| `sub()` | Quantity | Returns difference between two quantities | +| `sub()` | Quantity | Returns difference between a quantity and an integer | +| `isLessThan()` | bool | Returns true if and only if the receiver is less than the operand | +| `isGreaterThan()` | bool | Returns true if and only if the receiver is greater than the operand | +| `compareTo()` | int | Compares receiver to operand and returns 0 if they are equal, 1 if the receiver is greater, or -1 if the receiver is less than the operand | +{{< /table >}} + +Examples: + +{{< table caption="Examples of CEL expressions using URL library functions" >}} +| CEL Expression | Purpose | +|---------------------------------------------------------------------------|-------------------------------------------------------| +| `quantity("500000G").isInteger()` | Test if conversion to integer would throw an error | +| `quantity("50k").asInteger()` | Precise conversion to integer | +| `quantity("9999999999999999999999999999999999999G").asApproximateFloat()` | Lossy conversion to float | +| `quantity("50k").add("20k")` | Add two quantities | +| `quantity("50k").sub(20000)` | Subtract an integer from a quantity | +| `quantity("50k").add(20).sub(quantity("100k")).sub(-50000)` | Chain adding and subtracting integers and quantities | +| `quantity("200M").compareTo(quantity("0.2G"))` | Compare two quantities | +| `quantity("150Mi").isGreaterThan(quantity("100Mi"))` | Test if a quantity is greater than the receiver | +| `quantity("50M").isLessThan(quantity("100M"))` | Test if a quantity is less than the receiver | +{{< /table >}} + ## Type checking CEL is a [gradually typed language](https://github.com/google/cel-spec/blob/master/doc/langdef.md#gradual-type-checking). diff --git a/content/en/docs/reference/using-api/deprecation-guide.md b/content/en/docs/reference/using-api/deprecation-guide.md index d2382cc3f38dc..88ebd1a589c2a 100644 --- a/content/en/docs/reference/using-api/deprecation-guide.md +++ b/content/en/docs/reference/using-api/deprecation-guide.md @@ -78,7 +78,8 @@ The **autoscaling/v2beta2** API version of HorizontalPodAutoscaler is no longer * Migrate manifests and API clients to use the **autoscaling/v2** API version, available since v1.23. * All existing persisted objects are accessible via the new API - +* Notable changes: + * `targetAverageUtilization` is replaced with `target.averageUtilization` and `target.type: Utilization`. See [Autoscaling on multiple metrics and custom metrics](/docs/tasks/run-application/horizontal-pod-autoscale-walkthrough/#autoscaling-on-multiple-metrics-and-custom-metrics). ### v1.25 The **v1.25** release stopped serving the following deprecated API versions: @@ -130,6 +131,8 @@ The **autoscaling/v2beta1** API version of HorizontalPodAutoscaler is no longer * Migrate manifests and API clients to use the **autoscaling/v2** API version, available since v1.23. * All existing persisted objects are accessible via the new API +* Notable changes: + * `targetAverageUtilization` is replaced with `target.averageUtilization` and `target.type: Utilization`. See [Autoscaling on multiple metrics and custom metrics](/docs/tasks/run-application/horizontal-pod-autoscale-walkthrough/#autoscaling-on-multiple-metrics-and-custom-metrics). #### PodDisruptionBudget {#poddisruptionbudget-v125} diff --git a/content/en/docs/reference/using-api/server-side-apply.md b/content/en/docs/reference/using-api/server-side-apply.md index 7db7120b7be79..4b8ea9134edc3 100644 --- a/content/en/docs/reference/using-api/server-side-apply.md +++ b/content/en/docs/reference/using-api/server-side-apply.md @@ -11,7 +11,7 @@ weight: 25 -{{< feature-state for_k8s_version="v1.22" state="stable" >}} +{{< feature-state feature_gate_name="ServerSideApply" >}} Kubernetes supports multiple appliers collaborating to manage the fields of a single [object](/docs/concepts/overview/working-with-objects/). @@ -196,7 +196,9 @@ as [YAML](https://yaml.org/), with the media type `application/apply-patch+yaml` Whether you are submitting JSON data or YAML data, use `application/apply-patch+yaml` as the `Content-Type` header value. -All JSON documents are valid YAML. +All JSON documents are valid YAML. However, Kubernetes has a bug where it uses a YAML +parser that does not fully implement the YAML specification. Some JSON escapes may +not be recognized. {{< /note >}} The serialization is the same as for Kubernetes objects, with the exception that diff --git a/content/en/docs/setup/best-practices/cluster-large.md b/content/en/docs/setup/best-practices/cluster-large.md index 808a1c47510a3..f5f4292b44c3a 100644 --- a/content/en/docs/setup/best-practices/cluster-large.md +++ b/content/en/docs/setup/best-practices/cluster-large.md @@ -121,9 +121,7 @@ Learn more about [Vertical Pod Autoscaler](https://github.com/kubernetes/autosca and how you can use it to scale cluster components, including cluster-critical addons. -* The [cluster autoscaler](https://github.com/kubernetes/autoscaler/tree/master/cluster-autoscaler#readme) -integrates with a number of cloud providers to help you run the right number of -nodes for the level of resource demand in your cluster. +* Read about [cluster autoscaling](/docs/concepts/cluster-administration/cluster-autoscaling/) * The [addon resizer](https://github.com/kubernetes/autoscaler/tree/master/addon-resizer#readme) helps you in resizing the addons automatically as your cluster's scale changes. diff --git a/content/en/docs/setup/best-practices/multiple-zones.md b/content/en/docs/setup/best-practices/multiple-zones.md index 3bce1669372fe..f9ff827946783 100644 --- a/content/en/docs/setup/best-practices/multiple-zones.md +++ b/content/en/docs/setup/best-practices/multiple-zones.md @@ -95,13 +95,16 @@ such as Deployment, StatefulSet, or Job. ## Storage access for zones -When persistent volumes are created, the `PersistentVolumeLabel` -[admission controller](/docs/reference/access-authn-authz/admission-controllers/) -automatically adds zone labels to any PersistentVolumes that are linked to a specific -zone. The {{< glossary_tooltip text="scheduler" term_id="kube-scheduler" >}} then ensures, +When persistent volumes are created, Kubernetes automatically adds zone labels +to any PersistentVolumes that are linked to a specific zone. +The {{< glossary_tooltip text="scheduler" term_id="kube-scheduler" >}} then ensures, through its `NoVolumeZoneConflict` predicate, that pods which claim a given PersistentVolume are only placed into the same zone as that volume. +Please note that the method of adding zone labels can depend on your +cloud provider and the storage provisioner you’re using. Always refer to the specific +documentation for your environment to ensure correct configuration. + You can specify a {{< glossary_tooltip text="StorageClass" term_id="storage-class" >}} for PersistentVolumeClaims that specifies the failure domains (zones) that the storage in that class may use. diff --git a/content/en/docs/setup/production-environment/_index.md b/content/en/docs/setup/production-environment/_index.md index 7aeb4eb1919bf..02332ca4e0e98 100644 --- a/content/en/docs/setup/production-environment/_index.md +++ b/content/en/docs/setup/production-environment/_index.md @@ -183,15 +183,9 @@ simply as *nodes*). to help determine how many nodes you need, based on the number of pods and containers you need to run. If you are managing nodes yourself, this can mean purchasing and installing your own physical equipment. -- *Autoscale nodes*: Most cloud providers support - [Cluster Autoscaler](https://github.com/kubernetes/autoscaler/tree/master/cluster-autoscaler#readme) - to replace unhealthy nodes or grow and shrink the number of nodes as demand requires. See the - [Frequently Asked Questions](https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/FAQ.md) - for how the autoscaler works and - [Deployment](https://github.com/kubernetes/autoscaler/tree/master/cluster-autoscaler#deployment) - for how it is implemented by different cloud providers. For on-premises, there - are some virtualization platforms that can be scripted to spin up new nodes - based on demand. +- *Autoscale nodes*: Read [Cluster Autoscaling](/docs/concepts/cluster-administration/cluster-autoscaling) to learn about the + tools available to automatically manage your nodes and the capacity they + provide. - *Set up node health checks*: For important workloads, you want to make sure that the nodes and pods running on those nodes are healthy. Using the [Node Problem Detector](/docs/tasks/debug/debug-cluster/monitor-node-health/) diff --git a/content/en/docs/setup/production-environment/container-runtimes.md b/content/en/docs/setup/production-environment/container-runtimes.md index ddd32a11c7dc9..4154042e533cf 100644 --- a/content/en/docs/setup/production-environment/container-runtimes.md +++ b/content/en/docs/setup/production-environment/container-runtimes.md @@ -47,50 +47,33 @@ check the documentation for that version. ## Install and configure prerequisites -The following steps apply common settings for Kubernetes nodes on Linux. +### Network configuration -You can skip a particular setting if you're certain you don't need it. +By default, the Linux kernel does not allow IPv4 packets to be routed +between interfaces. Most Kubernetes cluster networking implementations +will change this setting (if needed), but some might expect the +administrator to do it for them. (Some might also expect other sysctl +parameters to be set, kernel modules to be loaded, etc; consult the +documentation for your specific network implementation.) -For more information, see -[Network Plugin Requirements](/docs/concepts/extend-kubernetes/compute-storage-net/network-plugins/#network-plugin-requirements) -or the documentation for your specific container runtime. +### Enable IPv4 packet forwarding {#prerequisite-ipv4-forwarding-optional} -### Forwarding IPv4 and letting iptables see bridged traffic - -Execute the below mentioned instructions: +To manually enable IPv4 packet forwarding: ```bash -cat <}} These instructions assume that you are using the -[`cri-dockerd`](https://github.com/Mirantis/cri-dockerd) adapter to integrate +[`cri-dockerd`](https://mirantis.github.io/cri-dockerd/) adapter to integrate Docker Engine with Kubernetes. {{< /note >}} 1. On each of your nodes, install Docker for your Linux distribution as per [Install Docker Engine](https://docs.docker.com/engine/install/#server). -2. Install [`cri-dockerd`](https://github.com/Mirantis/cri-dockerd), following - the instructions in that source code repository. +2. Install [`cri-dockerd`](https://mirantis.github.io/cri-dockerd/usage/install), following the directions in the install section of the documentation. For `cri-dockerd`, the CRI socket is `/run/cri-dockerd.sock` by default. @@ -343,7 +325,7 @@ For `cri-dockerd`, the CRI socket is `/run/cri-dockerd.sock` by default. available container runtime that was formerly known as Docker Enterprise Edition. You can use Mirantis Container Runtime with Kubernetes using the open source -[`cri-dockerd`](https://github.com/Mirantis/cri-dockerd) component, included with MCR. +[`cri-dockerd`](https://mirantis.github.io/cri-dockerd/) component, included with MCR. To learn more about how to install Mirantis Container Runtime, visit [MCR Deployment Guide](https://docs.mirantis.com/mcr/20.10/install.html). diff --git a/content/en/docs/setup/production-environment/tools/kubeadm/create-cluster-kubeadm.md b/content/en/docs/setup/production-environment/tools/kubeadm/create-cluster-kubeadm.md index f59427dde0fe2..a2078c77fc4b6 100644 --- a/content/en/docs/setup/production-environment/tools/kubeadm/create-cluster-kubeadm.md +++ b/content/en/docs/setup/production-environment/tools/kubeadm/create-cluster-kubeadm.md @@ -333,7 +333,10 @@ support [Network Policy](/docs/concepts/services-networking/network-policies/). See a list of add-ons that implement the [Kubernetes networking model](/docs/concepts/cluster-administration/networking/#how-to-implement-the-kubernetes-network-model). -You can install a Pod network add-on with the following command on the + +Please refer to the [Installing Addons](/docs/concepts/cluster-administration/addons/#networking-and-network-policy) +page for a non-exhaustive list of networking addons supported by Kubernetes. +You can install a Pod network add-on with the following command on the control-plane node or a node that has the kubeconfig credentials: ```bash @@ -380,6 +383,14 @@ This will remove the `node-role.kubernetes.io/control-plane:NoSchedule` taint from any nodes that have it, including the control plane nodes, meaning that the scheduler will then be able to schedule Pods everywhere. +Additionally, you can execute the following command to remove the +[`node.kubernetes.io/exclude-from-external-load-balancers`](/docs/reference/labels-annotations-taints/#node-kubernetes-io-exclude-from-external-load-balancers) label +from the control plane node, which excludes it from the list of backend servers: + +```bash +kubectl label nodes --all node.kubernetes.io/exclude-from-external-load-balancers- +``` + ### Joining your nodes {#join-nodes} The nodes are where your workloads (containers and Pods, etc) run. To add new nodes to your cluster do the following for each machine: @@ -557,37 +568,6 @@ reference documentation for more information about this subcommand and its options. - - - -## What's next {#whats-next} - -* Verify that your cluster is running properly with [Sonobuoy](https://github.com/heptio/sonobuoy) -* See [Upgrading kubeadm clusters](/docs/tasks/administer-cluster/kubeadm/kubeadm-upgrade/) - for details about upgrading your cluster using `kubeadm`. -* Learn about advanced `kubeadm` usage in the [kubeadm reference documentation](/docs/reference/setup-tools/kubeadm/) -* Learn more about Kubernetes [concepts](/docs/concepts/) and [`kubectl`](/docs/reference/kubectl/). -* See the [Cluster Networking](/docs/concepts/cluster-administration/networking/) page for a bigger list - of Pod network add-ons. -* See the [list of add-ons](/docs/concepts/cluster-administration/addons/) to - explore other add-ons, including tools for logging, monitoring, network policy, visualization & - control of your Kubernetes cluster. -* Configure how your cluster handles logs for cluster events and from - applications running in Pods. - See [Logging Architecture](/docs/concepts/cluster-administration/logging/) for - an overview of what is involved. - -### Feedback {#feedback} - -* For bugs, visit the [kubeadm GitHub issue tracker](https://github.com/kubernetes/kubeadm/issues) -* For support, visit the - [#kubeadm](https://kubernetes.slack.com/messages/kubeadm/) Slack channel -* General SIG Cluster Lifecycle development Slack channel: - [#sig-cluster-lifecycle](https://kubernetes.slack.com/messages/sig-cluster-lifecycle/) -* SIG Cluster Lifecycle [SIG information](https://github.com/kubernetes/community/tree/master/sig-cluster-lifecycle#readme) -* SIG Cluster Lifecycle mailing list: - [kubernetes-sig-cluster-lifecycle](https://groups.google.com/forum/#!forum/kubernetes-sig-cluster-lifecycle) - ## Version skew policy {#version-skew-policy} While kubeadm allows version skew against some components that it manages, it is recommended that you @@ -608,8 +588,8 @@ Example: ### kubeadm's skew against the kubelet -Similarly to the Kubernetes version, kubeadm can be used with a kubelet version that is the same -version as kubeadm or one version older. +Similarly to the Kubernetes version, kubeadm can be used with a kubelet version that is +the same version as kubeadm or three versions older. Example: * kubeadm is at {{< skew currentVersion >}} @@ -675,3 +655,33 @@ supports your chosen platform. If you are running into difficulties with kubeadm, please consult our [troubleshooting docs](/docs/setup/production-environment/tools/kubeadm/troubleshooting-kubeadm/). + + + +## What's next {#whats-next} + +* Verify that your cluster is running properly with [Sonobuoy](https://github.com/heptio/sonobuoy) +* See [Upgrading kubeadm clusters](/docs/tasks/administer-cluster/kubeadm/kubeadm-upgrade/) + for details about upgrading your cluster using `kubeadm`. +* Learn about advanced `kubeadm` usage in the [kubeadm reference documentation](/docs/reference/setup-tools/kubeadm/) +* Learn more about Kubernetes [concepts](/docs/concepts/) and [`kubectl`](/docs/reference/kubectl/). +* See the [Cluster Networking](/docs/concepts/cluster-administration/networking/) page for a bigger list + of Pod network add-ons. +* See the [list of add-ons](/docs/concepts/cluster-administration/addons/) to + explore other add-ons, including tools for logging, monitoring, network policy, visualization & + control of your Kubernetes cluster. +* Configure how your cluster handles logs for cluster events and from + applications running in Pods. + See [Logging Architecture](/docs/concepts/cluster-administration/logging/) for + an overview of what is involved. + +### Feedback {#feedback} + +* For bugs, visit the [kubeadm GitHub issue tracker](https://github.com/kubernetes/kubeadm/issues) +* For support, visit the + [#kubeadm](https://kubernetes.slack.com/messages/kubeadm/) Slack channel +* General SIG Cluster Lifecycle development Slack channel: + [#sig-cluster-lifecycle](https://kubernetes.slack.com/messages/sig-cluster-lifecycle/) +* SIG Cluster Lifecycle [SIG information](https://github.com/kubernetes/community/tree/master/sig-cluster-lifecycle#readme) +* SIG Cluster Lifecycle mailing list: + [kubernetes-sig-cluster-lifecycle](https://groups.google.com/forum/#!forum/kubernetes-sig-cluster-lifecycle) diff --git a/content/en/docs/setup/production-environment/tools/kubeadm/install-kubeadm.md b/content/en/docs/setup/production-environment/tools/kubeadm/install-kubeadm.md index d9113725097b7..59b4c8be17649 100644 --- a/content/en/docs/setup/production-environment/tools/kubeadm/install-kubeadm.md +++ b/content/en/docs/setup/production-environment/tools/kubeadm/install-kubeadm.md @@ -62,10 +62,10 @@ route, we recommend you add IP route(s) so Kubernetes cluster addresses go via t These [required ports](/docs/reference/networking/ports-and-protocols/) need to be open in order for Kubernetes components to communicate with each other. -You can use tools like netcat to check if a port is open. For example: +You can use tools like [netcat](https://netcat.sourceforge.net) to check if a port is open. For example: ```shell -nc 127.0.0.1 6443 +nc 127.0.0.1 6443 -v ``` The pod network plugin you use may also require certain ports to be @@ -93,7 +93,7 @@ for more information. {{< note >}} Docker Engine does not implement the [CRI](/docs/concepts/architecture/cri/) which is a requirement for a container runtime to work with Kubernetes. -For that reason, an additional service [cri-dockerd](https://github.com/Mirantis/cri-dockerd) +For that reason, an additional service [cri-dockerd](https://mirantis.github.io/cri-dockerd/) has to be installed. cri-dockerd is a project based on the legacy built-in Docker Engine support that was [removed](/dockershim) from the kubelet in version 1.24. {{< /note >}} @@ -161,14 +161,14 @@ For more information on version skews, see: {{< note >}} There's a dedicated package repository for each Kubernetes minor version. If you want to install -a minor version other than {{< skew currentVersion >}}, please see the installation guide for +a minor version other than v{{< skew currentVersion >}}, please see the installation guide for your desired minor version. {{< /note >}} {{< tabs name="k8s_install" >}} {{% tab name="Debian-based distributions" %}} -These instructions are for Kubernetes {{< skew currentVersion >}}. +These instructions are for Kubernetes v{{< skew currentVersion >}}. 1. Update the `apt` package index and install packages needed to use the Kubernetes `apt` repository: @@ -182,13 +182,13 @@ These instructions are for Kubernetes {{< skew currentVersion >}}. The same signing key is used for all repositories so you can disregard the version in the URL: ```shell - # If the folder `/etc/apt/keyrings` does not exist, it should be created before the curl command, read the note below. + # If the directory `/etc/apt/keyrings` does not exist, it should be created before the curl command, read the note below. # sudo mkdir -p -m 755 /etc/apt/keyrings curl -fsSL https://pkgs.k8s.io/core:/stable:/{{< param "version" >}}/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg ``` - + {{< note >}} -In releases older than Debian 12 and Ubuntu 22.04, folder `/etc/apt/keyrings` does not exist by default, and it should be created before the curl command. +In releases older than Debian 12 and Ubuntu 22.04, directory `/etc/apt/keyrings` does not exist by default, and it should be created before the curl command. {{< /note >}} 3. Add the appropriate Kubernetes `apt` repository. Please note that this repository have packages @@ -210,6 +210,12 @@ In releases older than Debian 12 and Ubuntu 22.04, folder `/etc/apt/keyrings` do sudo apt-mark hold kubelet kubeadm kubectl ``` +5. (Optional) Enable the kubelet service before running kubeadm: + + ```shell + sudo systemctl enable --now kubelet + ``` + {{% /tab %}} {{% tab name="Red Hat-based distributions" %}} @@ -255,10 +261,15 @@ settings that are not supported by kubeadm. EOF ``` -3. Install kubelet, kubeadm and kubectl, and enable kubelet to ensure it's automatically started on startup: +3. Install kubelet, kubeadm and kubectl: ```shell sudo yum install -y kubelet kubeadm kubectl --disableexcludes=kubernetes + ``` + +4. (Optional) Enable the kubelet service before running kubeadm: + + ```shell sudo systemctl enable --now kubelet ``` @@ -294,7 +305,7 @@ ARCH="amd64" curl -L "https://github.com/kubernetes-sigs/cri-tools/releases/download/${CRICTL_VERSION}/crictl-${CRICTL_VERSION}-linux-${ARCH}.tar.gz" | sudo tar -C $DOWNLOAD_DIR -xz ``` -Install `kubeadm`, `kubelet`, `kubectl` and add a `kubelet` systemd service: +Install `kubeadm`, `kubelet` and add a `kubelet` systemd service: ```bash RELEASE="$(curl -sSL https://dl.k8s.io/release/stable.txt)" @@ -304,9 +315,9 @@ sudo curl -L --remote-name-all https://dl.k8s.io/release/${RELEASE}/bin/linux/${ sudo chmod +x {kubeadm,kubelet} RELEASE_VERSION="v0.16.2" -curl -sSL "https://raw.githubusercontent.com/kubernetes/release/${RELEASE_VERSION}/cmd/krel/templates/latest/kubelet/kubelet.service" | sed "s:/usr/bin:${DOWNLOAD_DIR}:g" | sudo tee /etc/systemd/system/kubelet.service -sudo mkdir -p /etc/systemd/system/kubelet.service.d -curl -sSL "https://raw.githubusercontent.com/kubernetes/release/${RELEASE_VERSION}/cmd/krel/templates/latest/kubeadm/10-kubeadm.conf" | sed "s:/usr/bin:${DOWNLOAD_DIR}:g" | sudo tee /etc/systemd/system/kubelet.service.d/10-kubeadm.conf +curl -sSL "https://raw.githubusercontent.com/kubernetes/release/${RELEASE_VERSION}/cmd/krel/templates/latest/kubelet/kubelet.service" | sed "s:/usr/bin:${DOWNLOAD_DIR}:g" | sudo tee /usr/lib/systemd/system/kubelet.service +sudo mkdir -p /usr/lib/systemd/system/kubelet.service.d +curl -sSL "https://raw.githubusercontent.com/kubernetes/release/${RELEASE_VERSION}/cmd/krel/templates/latest/kubeadm/10-kubeadm.conf" | sed "s:/usr/bin:${DOWNLOAD_DIR}:g" | sudo tee /usr/lib/systemd/system/kubelet.service.d/10-kubeadm.conf ``` {{< note >}} @@ -316,10 +327,10 @@ that do not include `glibc` by default. Install `kubectl` by following the instructions on [Install Tools page](/docs/tasks/tools/#kubectl). -Enable and start `kubelet`: +Optionally, enable the kubelet service before running kubeadm: ```bash -systemctl enable --now kubelet +sudo systemctl enable --now kubelet ``` {{< note >}} diff --git a/content/en/docs/setup/production-environment/tools/kubeadm/kubelet-integration.md b/content/en/docs/setup/production-environment/tools/kubeadm/kubelet-integration.md index 3e91058180b13..864900f8e047b 100644 --- a/content/en/docs/setup/production-environment/tools/kubeadm/kubelet-integration.md +++ b/content/en/docs/setup/production-environment/tools/kubeadm/kubelet-integration.md @@ -163,9 +163,16 @@ Note that the kubeadm CLI command never touches this drop-in file. This configuration file installed by the `kubeadm` [package](https://github.com/kubernetes/release/blob/cd53840/cmd/krel/templates/latest/kubeadm/10-kubeadm.conf) is written to -`/etc/systemd/system/kubelet.service.d/10-kubeadm.conf` and is used by systemd. +`/usr/lib/systemd/system/kubelet.service.d/10-kubeadm.conf` and is used by systemd. It augments the basic -[`kubelet.service`](https://github.com/kubernetes/release/blob/cd53840/cmd/krel/templates/latest/kubelet/kubelet.service): +[`kubelet.service`](https://github.com/kubernetes/release/blob/cd53840/cmd/krel/templates/latest/kubelet/kubelet.service). + +If you want to override that further, you can make a directory `/etc/systemd/system/kubelet.service.d/` +(not `/usr/lib/systemd/system/kubelet.service.d/`) and put your own customizations into a file there. +For example, you might add a new local file `/etc/systemd/system/kubelet.service.d/local-overrides.conf` +to override the unit settings configured by `kubeadm`. + +Here is what you are likely to find in `/usr/lib/systemd/system/kubelet.service.d/10-kubeadm.conf`: {{< note >}} The contents below are just an example. If you don't want to use a package manager diff --git a/content/en/docs/setup/production-environment/tools/kubeadm/troubleshooting-kubeadm.md b/content/en/docs/setup/production-environment/tools/kubeadm/troubleshooting-kubeadm.md index abd3f3e0e4968..64a4ce2286897 100644 --- a/content/en/docs/setup/production-environment/tools/kubeadm/troubleshooting-kubeadm.md +++ b/content/en/docs/setup/production-environment/tools/kubeadm/troubleshooting-kubeadm.md @@ -213,7 +213,7 @@ in kube-apiserver logs. To fix the issue you must follow these steps: `kubeadm kubeconfig user --org system:nodes --client-name system:node:$NODE > kubelet.conf`. `$NODE` must be set to the name of the existing failed node in the cluster. Modify the resulted `kubelet.conf` manually to adjust the cluster name and server endpoint, - or pass `kubeconfig user --config` (it accepts `InitConfiguration`). If your cluster does not have + or pass `kubeconfig user --config` (see [Generating kubeconfig files for additional users](/docs/tasks/administer-cluster/kubeadm/kubeadm-certs/#kubeconfig-additional-users)). If your cluster does not have the `ca.key` you must sign the embedded certificates in the `kubelet.conf` externally. 1. Copy this resulted `kubelet.conf` to `/etc/kubernetes/kubelet.conf` on the failed node. 1. Restart the kubelet (`systemctl restart kubelet`) on the failed node and wait for diff --git a/content/en/docs/tasks/access-application-cluster/ingress-minikube.md b/content/en/docs/tasks/access-application-cluster/ingress-minikube.md index c250347d423dc..4dd9882d186dd 100644 --- a/content/en/docs/tasks/access-application-cluster/ingress-minikube.md +++ b/content/en/docs/tasks/access-application-cluster/ingress-minikube.md @@ -20,6 +20,13 @@ This page shows you how to set up a simple Ingress which routes requests to Serv This tutorial assumes that you are using `minikube` to run a local Kubernetes cluster. Visit [Install tools](/docs/tasks/tools/#minikube) to learn how to install `minikube`. +{{< note >}} +This tutorial uses a container that requires the AMD64 architecture. +If you are using minikube on a computer with a different CPU architecture, +you could try using minikube with a driver that can emulate AMD64. +For example, the Docker Desktop driver can do this. +{{< /note >}} + {{< include "task-tutorial-prereqs.md" >}} {{< version-check >}} If you are using an older Kubernetes version, switch to the documentation for that version. @@ -70,6 +77,21 @@ If you haven't already set up a cluster locally, run `minikube start` to create ```none deployment.apps/web created ``` + + Verify that the Deployment is in a Ready state: + + ```shell + kubectl get deployment web + ``` + + The output should be similar to: + + ```none + NAME READY UP-TO-DATE AVAILABLE AGE + web 1/1 1 1 53s + ``` + + 1. Expose the Deployment: @@ -96,22 +118,40 @@ If you haven't already set up a cluster locally, run `minikube start` to create web NodePort 10.104.133.249 8080:31637/TCP 12m ``` -1. Visit the Service via NodePort: +1. Visit the Service via NodePort, using the [`minikube service`](https://minikube.sigs.k8s.io/docs/handbook/accessing/#using-minikube-service-with-tunnel) command. Follow the instructions for your platform: + {{< tabs name="minikube_service" >}} + {{% tab name="Linux" %}} + ```shell minikube service web --url ``` - The output is similar to: - ```none http://172.17.0.15:31637 ``` - + Invoke the URL obtained in the output of the previous step: ```shell curl http://172.17.0.15:31637 ``` - + {{% /tab %}} + {{% tab name="MacOS" %}} + ```shell + # The command must be run in a separate terminal. + minikube service web --url + ``` + The output is similar to: + ```none + http://127.0.0.1:62445 + ! Because you are using a Docker driver on darwin, the terminal needs to be open to run it. + ``` + From a different terminal, invoke the URL obtained in the output of the previous step: + ```shell + curl http://127.0.0.1:62445 + ``` + {{% /tab %}} + {{< /tabs >}} +
          The output is similar to: ```none @@ -162,12 +202,46 @@ The following manifest defines an Ingress that sends traffic to your Service via ``` -1. Verify that the Ingress controller is directing traffic: +1. Verify that the Ingress controller is directing traffic, by following the instructions for your platform: + + {{< note >}} + The network is limited if using the Docker driver on MacOS (Darwin) and the Node IP is not reachable directly. To get ingress to work you’ll need to open a new terminal and run `minikube tunnel`. + `sudo` permission is required for it, so provide the password when prompted. + {{< /note >}} + + + {{< tabs name="ingress" >}} + {{% tab name="Linux" %}} ```shell curl --resolve "hello-world.info:80:$( minikube ip )" -i http://hello-world.info ``` + {{% /tab %}} + {{% tab name="MacOS" %}} + + ```shell + minikube tunnel + ``` + The output is similar to: + + ```none + Tunnel successfully started + + NOTE: Please do not close this terminal as this process must stay alive for the tunnel to be accessible ... + + The service/ingress example-ingress requires privileged ports to be exposed: [80 443] + sudo permission will be asked for it. + Starting tunnel for service example-ingress. + ``` + From within a new terminal, invoke the following command: + ```shell + curl --resolve "hello-world.info:80:127.0.0.1" -i http://hello-world.info + ``` + + {{% /tab %}} + {{< /tabs >}} +
          You should see: ```none @@ -176,25 +250,36 @@ The following manifest defines an Ingress that sends traffic to your Service via Hostname: web-55b8c6998d-8k564 ``` - You can also visit `hello-world.info` from your browser. +1. Optionally, you can also visit `hello-world.info` from your browser. - * **Optionally** - Look up the external IP address as reported by minikube: - ```shell - minikube ip - ``` - - Add line similar to the following one to the bottom of the `/etc/hosts` file on + Add a line to the bottom of the `/etc/hosts` file on your computer (you will need administrator access): - ```none - 172.17.0.15 hello-world.info - ``` - - {{< note >}} - Change the IP address to match the output from `minikube ip`. - {{< /note >}} + {{< tabs name="hosts" >}} + {{% tab name="Linux" %}} + Look up the external IP address as reported by minikube + ```none + minikube ip + ``` +
          + ```none + 172.17.0.15 hello-world.info + ``` + + {{< note >}} + Change the IP address to match the output from `minikube ip`. + {{< /note >}} + {{% /tab %}} + {{% tab name="MacOS" %}} + ```none + 127.0.0.1 hello-world.info + ``` + {{% /tab %}} + {{< /tabs >}} + +
          + After you make this change, your web browser sends requests for `hello-world.info` URLs to Minikube. @@ -211,6 +296,18 @@ The following manifest defines an Ingress that sends traffic to your Service via ```none deployment.apps/web2 created ``` + Verify that the Deployment is in a Ready state: + + ```shell + kubectl get deployment web2 + ``` + + The output should be similar to: + + ```none + NAME READY UP-TO-DATE AVAILABLE AGE + web2 1/1 1 1 16s + ``` 1. Expose the second Deployment: @@ -255,9 +352,38 @@ The following manifest defines an Ingress that sends traffic to your Service via 1. Access the 1st version of the Hello World app. + {{< tabs name="ingress2-v1" >}} + {{% tab name="Linux" %}} + ```shell curl --resolve "hello-world.info:80:$( minikube ip )" -i http://hello-world.info ``` + {{% /tab %}} + {{% tab name="MacOS" %}} + + ```shell + minikube tunnel + ``` + The output is similar to: + + ```none + Tunnel successfully started + + NOTE: Please do not close this terminal as this process must stay alive for the tunnel to be accessible ... + + The service/ingress example-ingress requires privileged ports to be exposed: [80 443] + sudo permission will be asked for it. + Starting tunnel for service example-ingress. + ``` + + From within a new terminal, invoke the following command: + ```shell + curl --resolve "hello-world.info:80:127.0.0.1" -i http://hello-world.info + ``` + + {{% /tab %}} + {{< /tabs >}} +
          The output is similar to: @@ -269,9 +395,37 @@ The following manifest defines an Ingress that sends traffic to your Service via 1. Access the 2nd version of the Hello World app. + {{< tabs name="ingress2-v2" >}} + {{% tab name="Linux" %}} + ```shell curl --resolve "hello-world.info:80:$( minikube ip )" -i http://hello-world.info/v2 ``` + {{% /tab %}} + {{% tab name="MacOS" %}} + + ```shell + minikube tunnel + ``` + The output is similar to: + + ```none + Tunnel successfully started + + NOTE: Please do not close this terminal as this process must stay alive for the tunnel to be accessible ... + + The service/ingress example-ingress requires privileged ports to be exposed: [80 443] + sudo permission will be asked for it. + Starting tunnel for service example-ingress. + ``` + + From within a new terminal, invoke the following command: + ```shell + curl --resolve "hello-world.info:80:127.0.0.1" -i http://hello-world.info/v2 + ``` + + {{% /tab %}} + {{< /tabs >}} The output is similar to: diff --git a/content/en/docs/tasks/access-application-cluster/port-forward-access-application-cluster.md b/content/en/docs/tasks/access-application-cluster/port-forward-access-application-cluster.md index 3b2648f9437e7..d31585a1a9781 100644 --- a/content/en/docs/tasks/access-application-cluster/port-forward-access-application-cluster.md +++ b/content/en/docs/tasks/access-application-cluster/port-forward-access-application-cluster.md @@ -110,7 +110,7 @@ for database debugging. 27017 ``` - 27017 is the TCP port allocated to MongoDB on the internet. + 27017 is the official TCP port for MongoDB. ## Forward a local port to a port on the Pod diff --git a/content/en/docs/tasks/access-application-cluster/service-access-application-cluster.md b/content/en/docs/tasks/access-application-cluster/service-access-application-cluster.md index 92f715b818753..9effb1e2f785e 100644 --- a/content/en/docs/tasks/access-application-cluster/service-access-application-cluster.md +++ b/content/en/docs/tasks/access-application-cluster/service-access-application-cluster.md @@ -87,7 +87,7 @@ Here is the configuration file for the application Deployment: Events: ``` - Make a note of the NodePort value for the service. For example, + Make a note of the NodePort value for the Service. For example, in the preceding output, the NodePort value is 31496. 1. List the pods that are running the Hello World application: diff --git a/content/en/docs/tasks/access-application-cluster/web-ui-dashboard.md b/content/en/docs/tasks/access-application-cluster/web-ui-dashboard.md index 16cc1abf021d0..148e20f93fc9b 100644 --- a/content/en/docs/tasks/access-application-cluster/web-ui-dashboard.md +++ b/content/en/docs/tasks/access-application-cluster/web-ui-dashboard.md @@ -34,10 +34,18 @@ Dashboard also provides information on the state of Kubernetes resources in your ## Deploying the Dashboard UI +{{< note >}} +Kubernetes Dashboard supports only Helm-based installation currently as it is faster +and gives us better control over all dependencies required by Dashboard to run. +{{< /note >}} + The Dashboard UI is not deployed by default. To deploy it, run the following command: -``` -kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.7.0/aio/deploy/recommended.yaml +```shell +# Add kubernetes-dashboard repository +helm repo add kubernetes-dashboard https://kubernetes.github.io/dashboard/ +# Deploy a Helm Release named "kubernetes-dashboard" using the kubernetes-dashboard chart +helm upgrade --install kubernetes-dashboard kubernetes-dashboard/kubernetes-dashboard --create-namespace --namespace kubernetes-dashboard ``` ## Accessing the Dashboard UI diff --git a/content/en/docs/tasks/administer-cluster/configure-upgrade-etcd.md b/content/en/docs/tasks/administer-cluster/configure-upgrade-etcd.md index 1f9b7fc998150..af577fba3df3d 100644 --- a/content/en/docs/tasks/administer-cluster/configure-upgrade-etcd.md +++ b/content/en/docs/tasks/administer-cluster/configure-upgrade-etcd.md @@ -15,9 +15,9 @@ weight: 270 ## {{% heading "prerequisites" %}} You need to have a Kubernetes cluster, and the kubectl command-line tool must -be configured to communicate with your cluster. It is recommended to run this -task on a cluster with at least two nodes that are not acting as control plane -nodes . If you do not already have a cluster, you can create one by using +be configured to communicate with your cluster. It is recommended to follow this +guide on a cluster with at least two nodes that are not acting as control plane +nodes. If you do not already have a cluster, you can create one by using [minikube](https://minikube.sigs.k8s.io/docs/tutorials/multi_node/). @@ -57,7 +57,7 @@ This section covers starting a single-node and multi-node etcd cluster. ### Single-node etcd cluster -Use a single-node etcd cluster only for testing purpose. +Use a single-node etcd cluster only for testing purposes. 1. Run the following: @@ -144,8 +144,8 @@ ETCDCTL_API=3 etcdctl --endpoints 10.2.0.9:2379 \ ### Limiting access of etcd clusters -After configuring secure communication, restrict the access of etcd cluster to -only the Kubernetes API servers. Use TLS authentication to do so. +After configuring secure communication, restrict the access of the etcd cluster to +only the Kubernetes API servers using TLS authentication. For example, consider key pairs `k8sclient.key` and `k8sclient.cert` that are trusted by the CA `etcd.ca`. When etcd is configured with `--client-cert-auth` @@ -160,9 +160,7 @@ flags `--etcd-certfile=k8sclient.cert`, `--etcd-keyfile=k8sclient.key` and `--etcd-cafile=ca.cert`. {{< note >}} -etcd authentication is not currently supported by Kubernetes. For more -information, see the related issue -[Support Basic Auth for Etcd v2](https://github.com/kubernetes/kubernetes/issues/23398). +etcd authentication is not planned for Kubernetes. {{< /note >}} ## Replacing a failed etcd member @@ -203,9 +201,9 @@ replace it with `member4=http://10.0.0.4`. etcd. 1. Stop the etcd server on the broken node. It is possible that other - clients besides the Kubernetes API server is causing traffic to etcd + clients besides the Kubernetes API server are causing traffic to etcd and it is desirable to stop all traffic to prevent writes to the data - dir. + directory. 1. Remove the failed member: @@ -256,10 +254,10 @@ For more information on cluster reconfiguration, see ## Backing up an etcd cluster -All Kubernetes objects are stored on etcd. Periodically backing up the etcd +All Kubernetes objects are stored in etcd. Periodically backing up the etcd cluster data is important to recover Kubernetes clusters under disaster scenarios, such as losing all control plane nodes. The snapshot file contains -all the Kubernetes states and critical information. In order to keep the +all the Kubernetes state and critical information. In order to keep the sensitive Kubernetes data safe, encrypt the snapshot files. Backing up an etcd cluster can be accomplished in two ways: etcd built-in @@ -267,14 +265,14 @@ snapshot and volume snapshot. ### Built-in snapshot -etcd supports built-in snapshot. A snapshot may either be taken from a live +etcd supports built-in snapshot. A snapshot may either be created from a live member with the `etcdctl snapshot save` command or by copying the `member/snap/db` file from an etcd [data directory](https://etcd.io/docs/current/op-guide/configuration/#--data-dir) -that is not currently used by an etcd process. Taking the snapshot will +that is not currently used by an etcd process. Creating the snapshot will not affect the performance of the member. -Below is an example for taking a snapshot of the keyspace served by +Below is an example for creating a snapshot of the keyspace served by `$ENDPOINT` to the file `snapshot.db`: ```shell @@ -298,19 +296,19 @@ ETCDCTL_API=3 etcdctl --write-out=table snapshot status snapshot.db ### Volume snapshot If etcd is running on a storage volume that supports backup, such as Amazon -Elastic Block Store, back up etcd data by taking a snapshot of the storage +Elastic Block Store, back up etcd data by creating a snapshot of the storage volume. ### Snapshot using etcdctl options -We can also take the snapshot using various options given by etcdctl. For example +We can also create the snapshot using various options given by etcdctl. For example: ```shell ETCDCTL_API=3 etcdctl -h ``` -will list various options available from etcdctl. For example, you can take a snapshot by specifying -the endpoint, certificates etc as shown below: +will list various options available from etcdctl. For example, you can create a snapshot by specifying +the endpoint, certificates and key as shown below: ```shell ETCDCTL_API=3 etcdctl --endpoints=https://127.0.0.1:2379 \ @@ -324,7 +322,7 @@ where `trusted-ca-file`, `cert-file` and `key-file` can be obtained from the des Scaling out etcd clusters increases availability by trading off performance. Scaling does not increase cluster performance nor capability. A general rule is not to scale out or in etcd clusters. Do not configure any auto scaling -groups for etcd clusters. It is highly recommended to always run a static +groups for etcd clusters. It is strongly recommended to always run a static five-member etcd cluster for production Kubernetes clusters at any officially supported scale. @@ -337,7 +335,7 @@ for information on how to add members into an existing cluster. etcd supports restoring from snapshots that are taken from an etcd process of the [major.minor](http://semver.org/) version. Restoring a version from a -different patch version of etcd also is supported. A restore operation is +different patch version of etcd is also supported. A restore operation is employed to recover the data of a failed cluster. Before starting the restore operation, a snapshot file must be present. It can @@ -358,12 +356,12 @@ export ETCDCTL_API=3 etcdctl --data-dir snapshot restore snapshot.db ``` -If `` is the same folder as before, delete it and stop etcd process before restoring the cluster. Else change etcd configuration and restart the etcd process after restoration to make it use the new data directory. +If `` is the same folder as before, delete it and stop the etcd process before restoring the cluster. Otherwise, change etcd configuration and restart the etcd process after restoration to have it use the new data directory. For more information and examples on restoring a cluster from a snapshot file, see [etcd disaster recovery documentation](https://etcd.io/docs/current/op-guide/recovery/#restoring-a-cluster). -If the access URLs of the restored cluster is changed from the previous +If the access URLs of the restored cluster are changed from the previous cluster, the Kubernetes API server must be reconfigured accordingly. In this case, restart Kubernetes API servers with the flag `--etcd-servers=$NEW_ETCD_CLUSTER` instead of the flag @@ -408,9 +406,9 @@ For more details on etcd maintenance, please refer to the [etcd maintenance](htt {{% thirdparty-content single="true" %}} {{< note >}} -Defragmentation is an expensive operation, so it should be executed as infrequent +Defragmentation is an expensive operation, so it should be executed as infrequently as possible. On the other hand, it's also necessary to make sure any etcd member -will not run out of the storage quota. The Kubernetes project recommends that when +will not exceed the storage quota. The Kubernetes project recommends that when you perform defragmentation, you use a tool such as [etcd-defrag](https://github.com/ahrtr/etcd-defrag). You can also run the defragmentation tool as a Kubernetes CronJob, to make sure that diff --git a/content/en/docs/tasks/administer-cluster/decrypt-data.md b/content/en/docs/tasks/administer-cluster/decrypt-data.md index 2bf9b11f5648e..0278125cc3323 100644 --- a/content/en/docs/tasks/administer-cluster/decrypt-data.md +++ b/content/en/docs/tasks/administer-cluster/decrypt-data.md @@ -163,4 +163,4 @@ Make sure that you use the same encryption configuration on each control plane h ## {{% heading "whatsnext" %}} -* Learn more about the [EncryptionConfiguration configuration API (v1)](/docs/reference/config-api/apiserver-encryption.v1/). +* Learn more about the [EncryptionConfiguration configuration API (v1)](/docs/reference/config-api/apiserver-config.v1/). diff --git a/content/en/docs/tasks/administer-cluster/encrypt-data.md b/content/en/docs/tasks/administer-cluster/encrypt-data.md index d113cdd836a28..78d92d7fbcaca 100644 --- a/content/en/docs/tasks/administer-cluster/encrypt-data.md +++ b/content/en/docs/tasks/administer-cluster/encrypt-data.md @@ -168,19 +168,31 @@ encrypt all resources, even custom resources that are added after API server sta since part of the configuration would be ineffective. The `resources` list's processing order and precedence are determined by the order it's listed in the configuration. {{< /note >}} -Opting out of encryption for specific resources while wildcard is enabled can be achieved by adding a new -`resources` array item with the resource name, followed by the `providers` array item with the `identity` provider. -For example, if '`*.*`' is enabled and you want to opt-out encryption for the `events` resource, add a new item -to the `resources` array with `events` as the resource name, followed by the providers array item with `identity`. -The new item should look like this: +If you have a wildcard covering resources and want to opt out of at-rest encryption for a particular kind +of resource, you achieve that by adding a separate `resources` array item with the name of the resource that +you want to exempt, followed by a `providers` array item where you specify the `identity` provider. You add +this item to the list so that it appears earlier than the configuration where you do specify encryption +(a provider that is not `identity`). + +For example, if '`*.*`' is enabled and you want to opt out of encryption for Events and ConfigMaps, add a +new **earlier** item to the `resources`, followed by the providers array item with `identity` as the +provider. The more specific entry must come before the wildcard entry. + +The new item would look similar to: ```yaml -- resources: - - events - providers: - - identity: {} + ... + - resources: + - configmaps. # specifically from the core API group, + # because of trailing "." + - events + providers: + - identity: {} + # and then other entries in resources ``` -Ensure that the new item is listed before the wildcard '`*.*`' item in the resources array to give it precedence. + +Ensure that the exemption is listed _before_ the wildcard '`*.*`' item in the resources array +to give it precedence. For more detailed information about the `EncryptionConfiguration` struct, please refer to the [encryption configuration API](/docs/reference/config-api/apiserver-encryption.v1/). @@ -703,4 +715,4 @@ To allow automatic reloading, configure the API server to run with: ## {{% heading "whatsnext" %}} * Read about [decrypting data that are already stored at rest](/docs/tasks/administer-cluster/decrypt-data/) -* Learn more about the [EncryptionConfiguration configuration API (v1)](/docs/reference/config-api/apiserver-encryption.v1/). +* Learn more about the [EncryptionConfiguration configuration API (v1)](/docs/reference/config-api/apiserver-config.v1/). diff --git a/content/en/docs/tasks/administer-cluster/kubeadm/kubeadm-certs.md b/content/en/docs/tasks/administer-cluster/kubeadm/kubeadm-certs.md index df93d79c4687c..623e528aa80d6 100644 --- a/content/en/docs/tasks/administer-cluster/kubeadm/kubeadm-certs.md +++ b/content/en/docs/tasks/administer-cluster/kubeadm/kubeadm-certs.md @@ -46,8 +46,46 @@ CA key on disk. Instead, run the controller-manager standalone with `--controllers=csrsigner` and point to the CA certificate and key. -[PKI certificates and requirements](/docs/setup/best-practices/certificates/) includes guidance on -setting up a cluster to use an external CA. +There are various ways to prepare the component credentials when using external CA mode. + +### Manual preparation of component credentials + +[PKI certificates and requirements](/docs/setup/best-practices/certificates/) includes information +on how to prepare all the required by kubeadm component credentials manually. + +### Preparation of credentials by signing CSRs generated by kubeadm + +kubeadm can [generate CSR files](#signing-csr) that you can sign manually with tools like +`openssl` and your external CA. These CSR files will include all the specification for credentials +that components deployed by kubeadm require. + +### Automated preparation of component credentials by using kubeadm phases + +Alternatively, it is possible to use kubeadm phase commands to automate this process. + +- Go to a host that you want to prepare as a kubeadm control plane node with external CA. +- Copy the external CA files `ca.crt` and `ca.key` that you have into `/etc/kubernetes/pki` on the node. +- Prepare a temporary [kubeadm configuration file](/docs/reference/setup-tools/kubeadm/kubeadm-init/#config-file) +called `config.yaml` that can be used with `kubeadm init`. Make sure that this file includes +any relevant cluster wide or host-specific information that could be included in certificates, such as, +`ClusterConfiguration.controlPlaneEndpoint`, `ClusterConfiguration.certSANs` and `InitConfiguration.APIEndpoint`. +- On the same host execute the commands `kubeadm init phase kubeconfig all --config config.yaml` and +`kubeadm init phase certs all --config config.yaml`. This will generate all required kubeconfig +files and certificates under `/etc/kubernetes/` and its `pki` sub directory. +- Inspect the generated files. Delete `/etc/kubernetes/pki/ca.key`, delete or move to a safe location +the file `/etc/kubernetes/super-admin.conf`. +- On nodes where `kubeadm join` will be called also delete `/etc/kubernetes/kubelet.conf`. +This file is only required on the first node where `kubeadm init` will be called. +- Note that some files such `pki/sa.*`, `pki/front-proxy-ca.*` and `pki/etc/ca.*` are +shared between control plane nodes, You can generate them once and +[distribute them manually](/docs/setup/production-environment/tools/kubeadm/high-availability/#manual-certs) +to nodes where `kubeadm join` will be called, or you can use the +[`--upload-certs`](/docs/setup/production-environment/tools/kubeadm/high-availability/#stacked-control-plane-and-etcd-nodes) +functionality of `kubeadm init` and `--certificate-key` of `kubeadm join` to automate this distribution. + +Once the credentials are prepared on all nodes, call `kubeadm init` and `kubeadm join` for these nodes to +join the cluster. kubeadm will use the existing kubeconfig and certificate files under `/etc/kubernetes/` +and its `pki` sub directory. ## Check certificate expiration diff --git a/content/en/docs/tasks/administer-cluster/kubeadm/kubeadm-upgrade.md b/content/en/docs/tasks/administer-cluster/kubeadm/kubeadm-upgrade.md index 09f43dd6341dc..daa7a141e6e72 100644 --- a/content/en/docs/tasks/administer-cluster/kubeadm/kubeadm-upgrade.md +++ b/content/en/docs/tasks/administer-cluster/kubeadm/kubeadm-upgrade.md @@ -43,7 +43,7 @@ The upgrade workflow at high level is the following: they could be running CoreDNS Pods or other critical workloads. For more information see [Draining nodes](/docs/tasks/administer-cluster/safely-drain-node/). - The Kubernetes project recommends that you match your kubelet and kubeadm versions. - You can instead use an a version of kubelet that is older than kubeadm, provided it is within the + You can instead use a version of kubelet that is older than kubeadm, provided it is within the range of supported versions. For more details, please visit [kubeadm's skew against the kubelet](/docs/setup/production-environment/tools/kubeadm/create-cluster-kubeadm/#kubeadm-s-skew-against-the-kubelet). - All containers are restarted after upgrade, because the container spec hash value is changed. @@ -54,11 +54,28 @@ The upgrade workflow at high level is the following: with the purpose of reconfiguring the cluster is not recommended and can have unexpected results. Follow the steps in [Reconfiguring a kubeadm cluster](/docs/tasks/administer-cluster/kubeadm/kubeadm-reconfigure) instead. +### Considerations when upgrading etcd + +Because the `kube-apiserver` static pod is running at all times (even if you +have drained the node), when you perform a kubeadm upgrade which includes an +etcd upgrade, in-flight requests to the server will stall while the new etcd +static pod is restarting. As a workaround, it is possible to actively stop the +`kube-apiserver` process a few seconds before starting the `kubeadm upgrade +apply` command. This permits to complete in-flight requests and close existing +connections, and minimizes the consequence of the etcd downtime. This can be +done as follows on control plane nodes: + +```shell +killall -s SIGTERM kube-apiserver # trigger a graceful kube-apiserver shutdown +sleep 20 # wait a little bit to permit completing in-flight requests +kubeadm upgrade ... # execute a kubeadm upgrade command +``` + ## Changing the package repository -If you're using the community-owned package repositories (`pkgs.k8s.io`), you need to +If you're using the community-owned package repositories (`pkgs.k8s.io`), you need to enable the package repository for the desired Kubernetes minor release. This is explained in [Changing the Kubernetes package repository](/docs/tasks/administer-cluster/kubeadm/change-package-repository/) document. @@ -75,8 +92,8 @@ Find the latest patch release for Kubernetes {{< skew currentVersion >}} using t ```shell # Find the latest {{< skew currentVersion >}} version in the list. # It should look like {{< skew currentVersion >}}.x-*, where x is the latest patch. -apt update -apt-cache madison kubeadm +sudo apt update +sudo apt-cache madison kubeadm ``` {{% /tab %}} @@ -85,7 +102,7 @@ apt-cache madison kubeadm ```shell # Find the latest {{< skew currentVersion >}} version in the list. # It should look like {{< skew currentVersion >}}.x-*, where x is the latest patch. -yum list --showduplicates kubeadm --disableexcludes=kubernetes +sudo yum list --showduplicates kubeadm --disableexcludes=kubernetes ``` {{% /tab %}} @@ -107,9 +124,9 @@ Pick a control plane node that you wish to upgrade first. It must have the `/etc ```shell # replace x in {{< skew currentVersion >}}.x-* with the latest patch version - apt-mark unhold kubeadm && \ - apt-get update && apt-get install -y kubeadm='{{< skew currentVersion >}}.x-*' && \ - apt-mark hold kubeadm + sudo apt-mark unhold kubeadm && \ + sudo apt-get update && sudo apt-get install -y kubeadm='{{< skew currentVersion >}}.x-*' && \ + sudo apt-mark hold kubeadm ``` {{% /tab %}} @@ -117,7 +134,7 @@ Pick a control plane node that you wish to upgrade first. It must have the `/etc ```shell # replace x in {{< skew currentVersion >}}.x-* with the latest patch version - yum install -y kubeadm-'{{< skew currentVersion >}}.x-*' --disableexcludes=kubernetes + sudo yum install -y kubeadm-'{{< skew currentVersion >}}.x-*' --disableexcludes=kubernetes ``` {{% /tab %}} @@ -132,7 +149,7 @@ Pick a control plane node that you wish to upgrade first. It must have the `/etc 1. Verify the upgrade plan: ```shell - kubeadm upgrade plan + sudo kubeadm upgrade plan ``` This command checks that your cluster can be upgraded, and fetches the versions you can upgrade to. @@ -221,9 +238,9 @@ kubectl drain --ignore-daemonsets ```shell # replace x in {{< skew currentVersion >}}.x-* with the latest patch version - apt-mark unhold kubelet kubectl && \ - apt-get update && apt-get install -y kubelet='{{< skew currentVersion >}}.x-*' kubectl='{{< skew currentVersion >}}.x-*' && \ - apt-mark hold kubelet kubectl + sudo apt-mark unhold kubelet kubectl && \ + sudo apt-get update && sudo apt-get install -y kubelet='{{< skew currentVersion >}}.x-*' kubectl='{{< skew currentVersion >}}.x-*' && \ + sudo apt-mark hold kubelet kubectl ``` {{% /tab %}} @@ -231,7 +248,7 @@ kubectl drain --ignore-daemonsets ```shell # replace x in {{< skew currentVersion >}}.x-* with the latest patch version - yum install -y kubelet-'{{< skew currentVersion >}}.x-*' kubectl-'{{< skew currentVersion >}}.x-*' --disableexcludes=kubernetes + sudo yum install -y kubelet-'{{< skew currentVersion >}}.x-*' kubectl-'{{< skew currentVersion >}}.x-*' --disableexcludes=kubernetes ``` {{% /tab %}} @@ -279,7 +296,7 @@ The `STATUS` column should show `Ready` for all your nodes, and the version numb If `kubeadm upgrade` fails and does not roll back, for example because of an unexpected shutdown during execution, you can run `kubeadm upgrade` again. This command is idempotent and eventually makes sure that the actual state is the desired state you declare. -To recover from a bad state, you can also run `kubeadm upgrade apply --force` without changing the version that your cluster is running. +To recover from a bad state, you can also run `sudo kubeadm upgrade apply --force` without changing the version that your cluster is running. During upgrade kubeadm writes the following backup folders under `/etc/kubernetes/tmp`: @@ -320,4 +337,4 @@ and post-upgrade manifest file for a certain component, a backup file for it wil `kubeadm upgrade node` does the following on worker nodes: - Fetches the kubeadm `ClusterConfiguration` from the cluster. -- Upgrades the kubelet configuration for this node. +- Upgrades the kubelet configuration for this node. \ No newline at end of file diff --git a/content/en/docs/tasks/administer-cluster/kubeadm/upgrading-linux-nodes.md b/content/en/docs/tasks/administer-cluster/kubeadm/upgrading-linux-nodes.md index e61c6f3d2b134..d53682b572a3e 100644 --- a/content/en/docs/tasks/administer-cluster/kubeadm/upgrading-linux-nodes.md +++ b/content/en/docs/tasks/administer-cluster/kubeadm/upgrading-linux-nodes.md @@ -10,7 +10,7 @@ This page explains how to upgrade a Linux Worker Nodes created with kubeadm. ## {{% heading "prerequisites" %}} -{{< include "task-tutorial-prereqs.md" >}} {{< version-check >}} +{{< include "task-tutorial-prereqs-node-upgrade.md" >}} {{< version-check >}} * Familiarize yourself with [the process for upgrading the rest of your kubeadm cluster](/docs/tasks/administer-cluster/kubeadm/kubeadm-upgrade). You will want to upgrade the control plane nodes before upgrading your Linux Worker nodes. @@ -36,15 +36,15 @@ Upgrade kubeadm: {{% tab name="Ubuntu, Debian or HypriotOS" %}} ```shell # replace x in {{< skew currentVersion >}}.x-* with the latest patch version -apt-mark unhold kubeadm && \ -apt-get update && apt-get install -y kubeadm='{{< skew currentVersion >}}.x-*' && \ -apt-mark hold kubeadm +sudo apt-mark unhold kubeadm && \ +sudo apt-get update && sudo apt-get install -y kubeadm='{{< skew currentVersion >}}.x-*' && \ +sudo apt-mark hold kubeadm ``` {{% /tab %}} {{% tab name="CentOS, RHEL or Fedora" %}} ```shell # replace x in {{< skew currentVersion >}}.x-* with the latest patch version -yum install -y kubeadm-'{{< skew currentVersion >}}.x-*' --disableexcludes=kubernetes +sudo yum install -y kubeadm-'{{< skew currentVersion >}}.x-*' --disableexcludes=kubernetes ``` {{% /tab %}} {{< /tabs >}} @@ -75,15 +75,15 @@ kubectl drain --ignore-daemonsets {{% tab name="Ubuntu, Debian or HypriotOS" %}} ```shell # replace x in {{< skew currentVersion >}}.x-* with the latest patch version - apt-mark unhold kubelet kubectl && \ - apt-get update && apt-get install -y kubelet='{{< skew currentVersion >}}.x-*' kubectl='{{< skew currentVersion >}}.x-*' && \ - apt-mark hold kubelet kubectl + sudo apt-mark unhold kubelet kubectl && \ + sudo apt-get update && sudo apt-get install -y kubelet='{{< skew currentVersion >}}.x-*' kubectl='{{< skew currentVersion >}}.x-*' && \ + sudo apt-mark hold kubelet kubectl ``` {{% /tab %}} {{% tab name="CentOS, RHEL or Fedora" %}} ```shell # replace x in {{< skew currentVersion >}}.x-* with the latest patch version - yum install -y kubelet-'{{< skew currentVersion >}}.x-*' kubectl-'{{< skew currentVersion >}}.x-*' --disableexcludes=kubernetes + sudo yum install -y kubelet-'{{< skew currentVersion >}}.x-*' kubectl-'{{< skew currentVersion >}}.x-*' --disableexcludes=kubernetes ``` {{% /tab %}} {{< /tabs >}} diff --git a/content/en/docs/tasks/administer-cluster/kubeadm/upgrading-windows-nodes.md b/content/en/docs/tasks/administer-cluster/kubeadm/upgrading-windows-nodes.md index e80b1e3287e92..b0ff422160892 100644 --- a/content/en/docs/tasks/administer-cluster/kubeadm/upgrading-windows-nodes.md +++ b/content/en/docs/tasks/administer-cluster/kubeadm/upgrading-windows-nodes.md @@ -13,7 +13,7 @@ This page explains how to upgrade a Windows node created with kubeadm. ## {{% heading "prerequisites" %}} -{{< include "task-tutorial-prereqs.md" >}} {{< version-check >}} +{{< include "task-tutorial-prereqs-node-upgrade.md" >}} {{< version-check >}} * Familiarize yourself with [the process for upgrading the rest of your kubeadm cluster](/docs/tasks/administer-cluster/kubeadm/kubeadm-upgrade). You will want to upgrade the control plane nodes before upgrading your Windows nodes. diff --git a/content/en/docs/tasks/administer-cluster/kubelet-config-file.md b/content/en/docs/tasks/administer-cluster/kubelet-config-file.md index 815f9f70c3aec..4b7da012098e1 100644 --- a/content/en/docs/tasks/administer-cluster/kubelet-config-file.md +++ b/content/en/docs/tasks/administer-cluster/kubelet-config-file.md @@ -7,6 +7,16 @@ content_type: task weight: 330 --- +## {{% heading "prerequisites" %}} + +Some steps in this page use the `jq` tool. If you don't have `jq`, you can +install it via your operating system's software sources, or fetch it from +[https://jqlang.github.io/jq/](https://jqlang.github.io/jq/). + +Some steps also involve installing `curl`, which can be installed via your +operating system's software sources. + + A subset of the kubelet's configuration parameters may be @@ -86,46 +96,195 @@ In the above example, this version is `kubelet.config.k8s.io/v1beta1`. ## Drop-in directory for kubelet configuration files {#kubelet-conf-d} -As of Kubernetes v1.28.0, the kubelet has been extended to support a drop-in configuration directory. The location of it can be specified with -`--config-dir` flag, and it defaults to `""`, or disabled, by default. +{{}} -You can only set `--config-dir` if you set the environment variable `KUBELET_CONFIG_DROPIN_DIR_ALPHA` for the kubelet process (the value of that variable does not matter). -For Kubernetes v{{< skew currentVersion >}}, the kubelet returns an error if you specify `--config-dir` without that variable set, and startup fails. -You cannot specify the drop-in configuration directory using the kubelet configuration file; only the CLI argument `--config-dir` can set it. +You can specify a drop-in configuration directory for the kubelet. By default, the kubelet does not look +for drop-in configuration files anywhere - you must specify a path. +For example: `--config-dir=/etc/kubernetes/kubelet.conf.d` + +For Kubernetes v1.28 to v1.29, you can only specify `--config-dir` if you also set +the environment variable `KUBELET_CONFIG_DROPIN_DIR_ALPHA` for the kubelet process (the value +of that variable does not matter). -One can use the kubelet configuration directory in a similar way to the kubelet config file. {{< note >}} -The suffix of a valid kubelet drop-in configuration file must be `.conf`. For instance: `99-kubelet-address.conf` +The suffix of a valid kubelet drop-in configuration file **must** be `.conf`. For instance: `99-kubelet-address.conf` {{< /note >}} -For instance, you may want a baseline kubelet configuration for all nodes, but you may want to customize the `address` field. This can be done as follows: +The kubelet processes files in its config drop-in directory by sorting the **entire file name** alphanumerically. +For instance, `00-kubelet.conf` is processed first, and then overridden with a file named `01-kubelet.conf`. -Main kubelet configuration file contents: -```yaml -apiVersion: kubelet.config.k8s.io/v1beta1 -kind: KubeletConfiguration -port: 20250 -serializeImagePulls: false -evictionHard: - memory.available: "200Mi" -``` +These files may contain partial configurations and might not be valid config files by themselves. +Validation is only performed on the final resulting configuration structure +stored internally in the kubelet. +This offers you flexibility in how you manage and combine kubelet configuration that comes from different sources. +However, it's important to note that the behavior varies based on the data type of the configuration fields. -Contents of a file in `--config-dir` directory: -```yaml -apiVersion: kubelet.config.k8s.io/v1beta1 -kind: KubeletConfiguration -address: "192.168.0.8" -``` +Different data types in the kubelet configuration structure merge differently. +See the [reference +document](/docs/reference/node/kubelet-config-directory-merging.md) for more +information. + +### Kubelet configuration merging order On startup, the kubelet merges configuration from: -* Command line arguments (lowest precedence). -* the kubelet configuration +* Feature gates specified over the command line (lowest precedence). +* The kubelet configuration. * Drop-in configuration files, according to sort order. -* Feature gates specified over the command line (highest precedence). +* Command line arguments excluding feature gates (highest precedence). + +{{< note >}} +The config drop-in dir mechanism for the kubelet is similar but different from how the `kubeadm` tool allows you to patch configuration. +The `kubeadm` tool uses a specific [patching strategy](/docs/setup/production-environment/tools/kubeadm/control-plane-flags/#patches) for its configuration, +whereas the only patch strategy for kubelet configuration drop-in files is `replace`. The kubelet determines the order of merges based on sorting the **suffixes** alphanumerically, +and replaces every field present in a higher priority file. +{{< /note >}} + +## Viewing the kubelet configuration + +Since the configuration could now be spread over multiple files with this feature, if someone wants to inspect the final actuated configuration, +they can follow these steps to inspect the kubelet configuration: + +1. Start a proxy server using [`kubectl proxy`](/docs/reference/kubectl/generated/kubectl-commands#proxy) in your terminal. -This produces the same outcome as if you used the [single configuration file](#create-the-config-file) used in the earlier example. +```bash +kubectl proxy +``` + +Which gives output like: + +```bash +Starting to serve on 127.0.0.1:8001 + +``` +2. Open another terminal window and use `curl` to fetch the kubelet configuration. +Replace `` with the actual name of your node: + +```bash +curl -X GET http://127.0.0.1:8001/api/v1/nodes//proxy/configz | jq . +``` +```bash +{ + "kubeletconfig": { + "enableServer": true, + "staticPodPath": "/var/run/kubernetes/static-pods", + "syncFrequency": "1m0s", + "fileCheckFrequency": "20s", + "httpCheckFrequency": "20s", + "address": "192.168.1.16", + "port": 10250, + "readOnlyPort": 10255, + "tlsCertFile": "/var/lib/kubelet/pki/kubelet.crt", + "tlsPrivateKeyFile": "/var/lib/kubelet/pki/kubelet.key", + "rotateCertificates": true, + "authentication": { + "x509": { + "clientCAFile": "/var/run/kubernetes/client-ca.crt" + }, + "webhook": { + "enabled": true, + "cacheTTL": "2m0s" + }, + "anonymous": { + "enabled": true + } + }, + "authorization": { + "mode": "AlwaysAllow", + "webhook": { + "cacheAuthorizedTTL": "5m0s", + "cacheUnauthorizedTTL": "30s" + } + }, + "registryPullQPS": 5, + "registryBurst": 10, + "eventRecordQPS": 50, + "eventBurst": 100, + "enableDebuggingHandlers": true, + "healthzPort": 10248, + "healthzBindAddress": "127.0.0.1", + "oomScoreAdj": -999, + "clusterDomain": "cluster.local", + "clusterDNS": [ + "10.0.0.10" + ], + "streamingConnectionIdleTimeout": "4h0m0s", + "nodeStatusUpdateFrequency": "10s", + "nodeStatusReportFrequency": "5m0s", + "nodeLeaseDurationSeconds": 40, + "imageMinimumGCAge": "2m0s", + "imageMaximumGCAge": "0s", + "imageGCHighThresholdPercent": 85, + "imageGCLowThresholdPercent": 80, + "volumeStatsAggPeriod": "1m0s", + "cgroupsPerQOS": true, + "cgroupDriver": "systemd", + "cpuManagerPolicy": "none", + "cpuManagerReconcilePeriod": "10s", + "memoryManagerPolicy": "None", + "topologyManagerPolicy": "none", + "topologyManagerScope": "container", + "runtimeRequestTimeout": "2m0s", + "hairpinMode": "promiscuous-bridge", + "maxPods": 110, + "podPidsLimit": -1, + "resolvConf": "/run/systemd/resolve/resolv.conf", + "cpuCFSQuota": true, + "cpuCFSQuotaPeriod": "100ms", + "nodeStatusMaxImages": 50, + "maxOpenFiles": 1000000, + "contentType": "application/vnd.kubernetes.protobuf", + "kubeAPIQPS": 50, + "kubeAPIBurst": 100, + "serializeImagePulls": true, + "evictionHard": { + "imagefs.available": "15%", + "memory.available": "100Mi", + "nodefs.available": "10%", + "nodefs.inodesFree": "5%" + }, + "evictionPressureTransitionPeriod": "1m0s", + "enableControllerAttachDetach": true, + "makeIPTablesUtilChains": true, + "iptablesMasqueradeBit": 14, + "iptablesDropBit": 15, + "featureGates": { + "AllAlpha": false + }, + "failSwapOn": false, + "memorySwap": {}, + "containerLogMaxSize": "10Mi", + "containerLogMaxFiles": 5, + "configMapAndSecretChangeDetectionStrategy": "Watch", + "enforceNodeAllocatable": [ + "pods" + ], + "volumePluginDir": "/usr/libexec/kubernetes/kubelet-plugins/volume/exec/", + "logging": { + "format": "text", + "flushFrequency": "5s", + "verbosity": 3, + "options": { + "json": { + "infoBufferSize": "0" + } + } + }, + "enableSystemLogHandler": true, + "enableSystemLogQuery": false, + "shutdownGracePeriod": "0s", + "shutdownGracePeriodCriticalPods": "0s", + "enableProfilingHandler": true, + "enableDebugFlagsHandler": true, + "seccompDefault": false, + "memoryThrottlingFactor": 0.9, + "registerNode": true, + "localStorageCapacityIsolation": true, + "containerRuntimeEndpoint": "unix:///var/run/crio/crio.sock" + } +} +``` @@ -133,4 +292,6 @@ This produces the same outcome as if you used the [single configuration file](#c - Learn more about kubelet configuration by checking the [`KubeletConfiguration`](/docs/reference/config-api/kubelet-config.v1beta1/) - reference. \ No newline at end of file + reference. +- Learn more about kubelet configuration merging in the + [reference document](/docs/reference/node/kubelet-config-directory-merging.md). \ No newline at end of file diff --git a/content/en/docs/tasks/administer-cluster/memory-manager.md b/content/en/docs/tasks/administer-cluster/memory-manager.md index b64adede0e67f..459acb54112b7 100644 --- a/content/en/docs/tasks/administer-cluster/memory-manager.md +++ b/content/en/docs/tasks/administer-cluster/memory-manager.md @@ -12,7 +12,7 @@ weight: 410 -{{< feature-state state="beta" for_k8s_version="v1.22" >}} +{{< feature-state feature_gate_name="MemoryManager" >}} The Kubernetes *Memory Manager* enables the feature of guaranteed memory (and hugepages) allocation for pods in the `Guaranteed` {{< glossary_tooltip text="QoS class" term_id="qos-class" >}}. diff --git a/content/en/docs/tasks/administer-cluster/migrating-from-dockershim/migrate-dockershim-dockerd.md b/content/en/docs/tasks/administer-cluster/migrating-from-dockershim/migrate-dockershim-dockerd.md index a4adb12234622..652d2d2724c8b 100644 --- a/content/en/docs/tasks/administer-cluster/migrating-from-dockershim/migrate-dockershim-dockerd.md +++ b/content/en/docs/tasks/administer-cluster/migrating-from-dockershim/migrate-dockershim-dockerd.md @@ -47,7 +47,7 @@ to `cri-dockerd`. ## {{% heading "prerequisites" %}} -* [`cri-dockerd`](https://github.com/mirantis/cri-dockerd#build-and-install) +* [`cri-dockerd`](https://mirantis.github.io/cri-dockerd/usage/install) installed and started on each node. * A [network plugin](/docs/concepts/extend-kubernetes/compute-storage-net/network-plugins/). diff --git a/content/en/docs/tasks/administer-cluster/network-policy-provider/weave-network-policy.md b/content/en/docs/tasks/administer-cluster/network-policy-provider/weave-network-policy.md index 631d3e6ba5718..1b5aa70ad9e22 100644 --- a/content/en/docs/tasks/administer-cluster/network-policy-provider/weave-network-policy.md +++ b/content/en/docs/tasks/administer-cluster/network-policy-provider/weave-network-policy.md @@ -19,10 +19,10 @@ You need to have a Kubernetes cluster. Follow the ## Install the Weave Net addon -Follow the [Integrating Kubernetes via the Addon](https://www.weave.works/docs/net/latest/kubernetes/kube-addon/) guide. +Follow the [Integrating Kubernetes via the Addon](https://github.com/weaveworks/weave/blob/master/site/kubernetes/kube-addon.md#-installation) guide. The Weave Net addon for Kubernetes comes with a -[Network Policy Controller](https://www.weave.works/docs/net/latest/kubernetes/kube-addon/#npc) +[Network Policy Controller](https://github.com/weaveworks/weave/blob/master/site/kubernetes/kube-addon.md#network-policy) that automatically monitors Kubernetes for any NetworkPolicy annotations on all namespaces and configures `iptables` rules to allow or block traffic as directed by the policies. diff --git a/content/en/docs/tasks/administer-cluster/switch-to-evented-pleg.md b/content/en/docs/tasks/administer-cluster/switch-to-evented-pleg.md index d56ffb6963057..f213016490862 100644 --- a/content/en/docs/tasks/administer-cluster/switch-to-evented-pleg.md +++ b/content/en/docs/tasks/administer-cluster/switch-to-evented-pleg.md @@ -5,7 +5,7 @@ content_type: task weight: 90 --- -{{< feature-state for_k8s_version="v1.27" state="beta" >}} +{{< feature-state feature_gate_name="EventedPLEG" >}} diff --git a/content/en/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes.md b/content/en/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes.md index 4d0b744d7d206..97c11177fcc5a 100644 --- a/content/en/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes.md +++ b/content/en/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes.md @@ -140,7 +140,7 @@ liveness-exec 1/1 Running 1 1m ## Define a liveness HTTP request Another kind of liveness probe uses an HTTP GET request. Here is the configuration -file for a Pod that runs a container based on the `registry.k8s.io/liveness` image. +file for a Pod that runs a container based on the `registry.k8s.io/e2e-test-images/agnhost` image. {{% code_sample file="pods/probe/http-liveness.yaml" %}} @@ -294,7 +294,6 @@ For example: ports: - name: liveness-port containerPort: 8080 - hostPort: 8080 livenessProbe: httpGet: @@ -318,7 +317,6 @@ So, the previous example would become: ports: - name: liveness-port containerPort: 8080 - hostPort: 8080 livenessProbe: httpGet: @@ -542,7 +540,6 @@ spec: ports: - name: liveness-port containerPort: 8080 - hostPort: 8080 livenessProbe: httpGet: diff --git a/content/en/docs/tasks/configure-pod-container/configure-pod-configmap.md b/content/en/docs/tasks/configure-pod-container/configure-pod-configmap.md index 1eb409389fed9..7a0802e6c3ef1 100644 --- a/content/en/docs/tasks/configure-pod-container/configure-pod-configmap.md +++ b/content/en/docs/tasks/configure-pod-container/configure-pod-configmap.md @@ -918,3 +918,4 @@ or move it into the trash can / deleted files location. * Follow a real world example of [Configuring Redis using a ConfigMap](/docs/tutorials/configuration/configure-redis-using-configmap/). +* Follow an example of [Updating configuration via a ConfigMap](/docs/tutorials/configuration/updating-configuration-via-a-configmap/). diff --git a/content/en/docs/tasks/configure-pod-container/resize-container-resources.md b/content/en/docs/tasks/configure-pod-container/resize-container-resources.md index c6a479b1685d4..8390605fd267d 100644 --- a/content/en/docs/tasks/configure-pod-container/resize-container-resources.md +++ b/content/en/docs/tasks/configure-pod-container/resize-container-resources.md @@ -8,7 +8,7 @@ min-kubernetes-server-version: 1.27 -{{< feature-state state="alpha" for_k8s_version="v1.27" >}} +{{< feature-state feature_gate_name="InPlacePodVerticalScaling" >}} This page assumes that you are familiar with [Quality of Service](/docs/tasks/configure-pod-container/quality-service-pod/) for Kubernetes Pods. @@ -18,6 +18,12 @@ of a running pod without restarting the pod or its containers. A Kubernetes node allocates resources for a pod based on its `requests`, and restricts the pod's resource usage based on the `limits` specified in the pod's containers. +Changing the resource allocation for a running Pod requires the +`InPlacePodVerticalScaling` [feature gate](/docs/reference/command-line-tools-reference/feature-gates/) +to be enabled. The alternative is to delete the Pod and let the +[workload controller](/docs/concepts/workloads/controllers/) make a replacement Pod +that has a different resource requirement. + For in-place resize of pod resources: - Container's resource `requests` and `limits` are _mutable_ for CPU and memory resources. @@ -45,6 +51,8 @@ For in-place resize of pod resources: {{< include "task-tutorial-prereqs.md" >}} {{< version-check >}} +The `InPlacePodVerticalScaling` [feature gate](/docs/reference/command-line-tools-reference/feature-gates/) must be enabled +for your control plane and for all nodes in your cluster. ## Container Resize Policies @@ -170,8 +178,8 @@ spec: ## Updating the pod's resources -Let's say the CPU requirements have increased, and 0.8 CPU is now desired. This -is typically determined, and may be programmatically applied, by an entity such as +Let's say the CPU requirements have increased, and 0.8 CPU is now desired. This may +be specified manually, or determined and programmatically applied by an entity such as [VerticalPodAutoscaler](https://github.com/kubernetes/autoscaler/tree/master/vertical-pod-autoscaler#readme) (VPA). {{< note >}} diff --git a/content/en/docs/tasks/configure-pod-container/security-context.md b/content/en/docs/tasks/configure-pod-container/security-context.md index 67f40e884ceba..b176d20df51c5 100644 --- a/content/en/docs/tasks/configure-pod-container/security-context.md +++ b/content/en/docs/tasks/configure-pod-container/security-context.md @@ -440,7 +440,17 @@ To assign SELinux labels, the SELinux security module must be loaded on the host ### Efficient SELinux volume relabeling -{{< feature-state for_k8s_version="v1.27" state="beta" >}} +{{< feature-state feature_gate_name="SELinuxMountReadWriteOncePod" >}} + +{{< note >}} +Kubernetes v1.27 introduced an early limited form of this behavior that was only applicable +to volumes (and PersistentVolumeClaims) using the `ReadWriteOncePod` access mode. + +As an alpha feature, you can enable the `SELinuxMount` +[feature gate](/docs/reference/command-line-tools-reference/feature-gates/) to widen that +performance improvement to other kinds of PersistentVolumeClaims, as explained in detail +below. +{{< /note >}} By default, the container runtime recursively assigns SELinux label to all files on all Pod volumes. To speed up this process, Kubernetes can change the @@ -451,7 +461,9 @@ To benefit from this speedup, all these conditions must be met: * The [feature gates](/docs/reference/command-line-tools-reference/feature-gates/) `ReadWriteOncePod` and `SELinuxMountReadWriteOncePod` must be enabled. -* Pod must use PersistentVolumeClaim with `accessModes: ["ReadWriteOncePod"]`. +* Pod must use PersistentVolumeClaim with applicable `accessModes` and [feature gates](/docs/reference/command-line-tools-reference/feature-gates/): + * Either the volume has `accessModes: ["ReadWriteOncePod"]`, and feature gate `SELinuxMountReadWriteOncePod` is enabled. + * Or the volume can use any other access modes and both feature gates `SELinuxMountReadWriteOncePod` and `SELinuxMount` must be enabled. * Pod (or all its Containers that use the PersistentVolumeClaim) must have `seLinuxOptions` set. * The corresponding PersistentVolume must be either: @@ -465,13 +477,56 @@ runtime recursively changes the SELinux label for all inodes (files and directo in the volume. The more files and directories in the volume, the longer that relabelling takes. +## Managing access to the `/proc` filesystem {#proc-access} + +{{< feature-state feature_gate_name="ProcMountType" >}} + +For runtimes that follow the OCI runtime specification, containers default to running in a mode where +there are multiple paths that are both masked and read-only. +The result of this is the container has these paths present inside the container's mount namespace, and they can function similarly to if +the container was an isolated host, but the container process cannot write to +them. The list of masked and read-only paths are as follows: + +- Masked Paths: + - `/proc/asound` + - `/proc/acpi` + - `/proc/kcore` + - `/proc/keys` + - `/proc/latency_stats` + - `/proc/timer_list` + - `/proc/timer_stats` + - `/proc/sched_debug` + - `/proc/scsi` + - `/sys/firmware` + +- Read-Only Paths: + - `/proc/bus` + - `/proc/fs` + - `/proc/irq` + - `/proc/sys` + - `/proc/sysrq-trigger` + + +For some Pods, you might want to bypass that default masking of paths. +The most common context for wanting this is if you are trying to run containers within +a Kubernetes container (within a pod). + +The `securityContext` field `procMount` allows a user to request a container's `/proc` +be `Unmasked`, or be mounted as read-write by the container process. This also +applies to `/sys/firmware` which is not in `/proc`. + +```yaml +... +securityContext: + procMount: Unmasked +``` + {{< note >}} - -If you are running Kubernetes v1.25, refer to the v1.25 version of this task page: -[Configure a Security Context for a Pod or Container](https://v1-25.docs.kubernetes.io/docs/tasks/configure-pod-container/security-context/) (v1.25). -There is an important note in that documentation about a situation where the kubelet -can lose track of volume labels after restart. This deficiency has been fixed -in Kubernetes 1.26. +Setting `procMount` to Unmasked requires the `spec.hostUsers` value in the pod +spec to be `false`. In other words: a container that wishes to have an Unmasked +`/proc` or unmasked `/sys` must also be in a +[user namespace](/docs/concepts/workloads/pods/user-namespaces/). +Kubernetes v1.12 to v1.29 did not enforce that requirement. {{< /note >}} ## Discussion @@ -520,3 +575,7 @@ kubectl delete pod security-context-demo-4 * For more information about security mechanisms in Linux, see [Overview of Linux Kernel Security Features](https://www.linux.com/learn/overview-linux-kernel-security-features) (Note: Some information is out of date) +* Read about [User Namespaces](/docs/concepts/workloads/pods/user-namespaces/) + for Linux pods. +* [Masked Paths in the OCI Runtime + Specification](https://github.com/opencontainers/runtime-spec/blob/f66aad47309/config-linux.md#masked-paths) \ No newline at end of file diff --git a/content/en/docs/tasks/configure-pod-container/user-namespaces.md b/content/en/docs/tasks/configure-pod-container/user-namespaces.md index f25d0f0da39b9..9b531775fc73e 100644 --- a/content/en/docs/tasks/configure-pod-container/user-namespaces.md +++ b/content/en/docs/tasks/configure-pod-container/user-namespaces.md @@ -7,7 +7,7 @@ min-kubernetes-server-version: v1.25 --- -{{< feature-state for_k8s_version="v1.25" state="alpha" >}} +{{< feature-state feature_gate_name="UserNamespacesSupport" >}} This page shows how to configure a user namespace for pods. This allows you to isolate the user running inside the container from the one in the host. @@ -57,10 +57,6 @@ If you have a mixture of nodes and only some of the nodes provide user namespace Pods, you also need to ensure that the user namespace Pods are [scheduled](/docs/concepts/scheduling-eviction/assign-pod-node/) to suitable nodes. -Please note that **if your container runtime doesn't support user namespaces, the -`hostUsers` field in the pod spec will be silently ignored and the pod will be -created without user namespaces.** - ## Run a Pod that uses a user namespace {#create-pod} @@ -82,27 +78,42 @@ to `false`. For example: kubectl attach -it userns bash ``` -And run the command. The output is similar to this: +Run this command: -```none +```shell readlink /proc/self/ns/user +``` + +The output is similar to: + +```shell user:[4026531837] +``` + +Also run: + +```shell cat /proc/self/uid_map -0 0 4294967295 ``` -Then, open a shell in the host and run the same command. +The output is similar to: +```shell +0 833617920 65536 +``` + +Then, open a shell in the host and run the same commands. + +The `readlink` command shows the user namespace the process is running in. It +should be different when it is run on the host and inside the container. -The output must be different. This means the host and the pod are using a -different user namespace. When user namespaces are not enabled, the host and the -pod use the same user namespace. +The last number of the `uid_map` file inside the container must be 65536, on the +host it must be a bigger number. If you are running the kubelet inside a user namespace, you need to compare the output from running the command in the pod to the output of running in the host: -```none +```shell readlink /proc/$pid/ns/user -user:[4026534732] ``` replacing `$pid` with the kubelet PID. diff --git a/content/en/docs/tasks/debug/debug-cluster/_index.md b/content/en/docs/tasks/debug/debug-cluster/_index.md index a10b0bdcff7d9..cde6043c0327d 100644 --- a/content/en/docs/tasks/debug/debug-cluster/_index.md +++ b/content/en/docs/tasks/debug/debug-cluster/_index.md @@ -203,7 +203,7 @@ status: type: PIDPressure - lastHeartbeatTime: "2022-02-17T22:20:15Z" lastTransitionTime: "2022-02-17T22:15:15Z" - message: kubelet is posting ready status. AppArmor enabled + message: kubelet is posting ready status reason: KubeletReady status: "True" type: Ready @@ -330,4 +330,3 @@ This is an incomplete list of things that could go wrong, and how to adjust your * Use `crictl` to [debug Kubernetes nodes](/docs/tasks/debug/debug-cluster/crictl/) * Get more information about [Kubernetes auditing](/docs/tasks/debug/debug-cluster/audit/) * Use `telepresence` to [develop and debug services locally](/docs/tasks/debug/debug-cluster/local-debugging/) - diff --git a/content/en/docs/tasks/debug/debug-cluster/resource-usage-monitoring.md b/content/en/docs/tasks/debug/debug-cluster/resource-usage-monitoring.md index eea8419e7f169..618458dcad0c7 100644 --- a/content/en/docs/tasks/debug/debug-cluster/resource-usage-monitoring.md +++ b/content/en/docs/tasks/debug/debug-cluster/resource-usage-monitoring.md @@ -84,7 +84,7 @@ solutions. The choice of monitoring platform depends heavily on your needs, budget, and technical resources. Kubernetes does not recommend any specific metrics pipeline; [many options](https://landscape.cncf.io/?group=projects-and-products&view-mode=card#observability-and-analysis--monitoring) are available. Your monitoring system should be capable of handling the [OpenMetrics](https://openmetrics.io/) metrics -transmission standard, and needs to chosen to best fit in to your overall design and deployment of +transmission standard and needs to be chosen to best fit into your overall design and deployment of your infrastructure platform. diff --git a/content/en/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions.md b/content/en/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions.md index f2e3e5d1e0ae2..867b4180eed48 100644 --- a/content/en/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions.md +++ b/content/en/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions.md @@ -719,12 +719,13 @@ crontab "my-new-cron-object" created ``` ### Validation ratcheting -{{< feature-state state="alpha" for_k8s_version="v1.28" >}} +{{< feature-state feature_gate_name="CRDValidationRatcheting" >}} -You need to enable the `CRDValidationRatcheting` +If you are using a version of Kubernetes older than v1.30, you need to explicitly +enable the `CRDValidationRatcheting` [feature gate](/docs/reference/command-line-tools-reference/feature-gates/) to use this behavior, which then applies to all CustomResourceDefinitions in your -cluster. +cluster. Provided you enabled the feature gate, Kubernetes implements _validation racheting_ for CustomResourceDefinitions. The API server is willing to accept updates to resources that @@ -751,10 +752,12 @@ validations are not supported by ratcheting under the implementation in Kubernet - `x-kubernetes-validations` For Kubernetes 1.28, CRD validation rules](#validation-rules) are ignored by ratcheting. Starting with Alpha 2 in Kubernetes 1.29, `x-kubernetes-validations` - are ratcheted. + are ratcheted only if they do not refer to `oldSelf`. Transition Rules are never ratcheted: only errors raised by rules that do not - use `oldSelf` will be automatically ratcheted if their values are unchanged. + use `oldSelf` will be automatically ratcheted if their values are unchanged. + + To write custom ratcheting logic for CEL expressions, check out [optionalOldSelf](#field-optional-oldself). - `x-kubernetes-list-type` Errors arising from changing the list type of a subschema will not be ratcheted. For example adding `set` onto a list with duplicates will always @@ -772,8 +775,10 @@ validations are not supported by ratcheting under the implementation in Kubernet To remove a previously specified `additionalProperties` validation will not be ratcheted. - `metadata` - Errors arising from changes to fields within an object's `metadata` are not - ratcheted. + Errors that come from Kubernetes' built-in validation of an object's `metadata` + are not ratcheted (such as object name, or characters in a label value). + If you specify your own additional rules for the metadata of a custom resource, + that additional validation will be ratcheted. ### Validation rules @@ -1177,10 +1182,11 @@ Setting `fieldPath` is optional. #### The `optionalOldSelf` field {#field-optional-oldself} -{{< feature-state state="alpha" for_k8s_version="v1.29" >}} +{{< feature-state feature_gate_name="CRDValidationRatcheting" >}} -The feature [CRDValidationRatcheting](#validation-ratcheting) must be enabled in order to -make use of this field. +If your cluster does not have [CRD validation ratcheting](#validation-ratcheting) enabled, +the CustomResourceDefinition API doesn't include this field, and trying to set it may result +in an error. The `optionalOldSelf` field is a boolean field that alters the behavior of [Transition Rules](#transition-rules) described below. Normally, a transition rule will not evaluate if `oldSelf` cannot be determined: @@ -1624,6 +1630,96 @@ my-new-cron-object * * * * * 1 7s The `NAME` column is implicit and does not need to be defined in the CustomResourceDefinition. {{< /note >}} +### Field selectors + +[Field Selectors](/docs/concepts/overview/working-with-objects/field-selectors/) +let clients select custom resources based on the value of one or more resource +fields. + +All custom resources support the `metadata.name` and `metadata.namespace` field +selectors. + +Fields declared in a {{< glossary_tooltip term_id="CustomResourceDefinition" text="CustomResourceDefinition" >}} +may also be used with field selectors when included in the `spec.versions[*].selectableFields` field of the +{{< glossary_tooltip term_id="CustomResourceDefinition" text="CustomResourceDefinition" >}}. + +#### Selectable fields for custom resources {#crd-selectable-fields} + +{{< feature-state state="alpha" for_k8s_version="v1.30" >}} +{{< feature-state feature_gate_name="CustomResourceFieldSelectors" >}} + +You need to enable the `CustomResourceFieldSelectors` +[feature gate](/docs/reference/command-line-tools-reference/feature-gates/) to +use this behavior, which then applies to all CustomResourceDefinitions in your +cluster. + +The `spec.versions[*].selectableFields` field of a {{< glossary_tooltip term_id="CustomResourceDefinition" text="CustomResourceDefinition" >}} may be used to +declare which other fields in a custom resource may be used in field selectors. +The following example adds the `.spec.color` and `.spec.size` fields as +selectable fields. + +Save the CustomResourceDefinition to `shirt-resource-definition.yaml`: + +{{% code_sample file="customresourcedefinition/shirt-resource-definition.yaml" %}} + +Create the CustomResourceDefinition: + +```shell +kubectl apply -f https://k8s.io/examples/customresourcedefinition/shirt-resource-definition.yaml +``` + +Define some Shirts by editing `shirt-resources.yaml`; for example: + +{{% code_sample file="customresourcedefinition/shirt-resources.yaml" %}} + +Create the custom resources: + +```shell +kubectl apply -f https://k8s.io/examples/customresourcedefinition/shirt-resources.yaml +``` + +Get all the resources: + +```shell +kubectl get shirts.stable.example.com +``` + +The output is: + +``` +NAME COLOR SIZE +example1 blue S +example2 blue M +example3 green M +``` + +Fetch blue shirts (retrieve Shirts with a `color` of `blue`): + +```shell +kubectl get shirts.stable.example.com --field-selector spec.color=blue +``` + +Should output: + +``` +NAME COLOR SIZE +example1 blue S +example2 blue M +``` + +Get only resources with a `color` of `green` and a `size` of `M`: + +```shell +kubectl get shirts.stable.example.com --field-selector spec.color=green,spec.size=M +``` + +Should output: + +``` +NAME COLOR SIZE +example2 blue M +``` + #### Priority Each column includes a `priority` field. Currently, the priority diff --git a/content/en/docs/tasks/extend-kubernetes/socks5-proxy-access-api.md b/content/en/docs/tasks/extend-kubernetes/socks5-proxy-access-api.md index 3e607a9cbaa38..549753f54bb33 100644 --- a/content/en/docs/tasks/extend-kubernetes/socks5-proxy-access-api.md +++ b/content/en/docs/tasks/extend-kubernetes/socks5-proxy-access-api.md @@ -39,7 +39,7 @@ Figure 1 represents what you're going to achieve in this task. graph LR; subgraph local[Local client machine] - client([client])-- local
          traffic .-> local_ssh[Local SSH
          SOCKS5 proxy]; + client([client])-. local
          traffic .-> local_ssh[Local SSH
          SOCKS5 proxy]; end local_ssh[SSH
          SOCKS5
          proxy]-- SSH Tunnel -->sshd diff --git a/content/en/docs/tasks/inject-data-application/define-environment-variable-container.md b/content/en/docs/tasks/inject-data-application/define-environment-variable-container.md index 73182d625f0d9..2b10561f4097f 100644 --- a/content/en/docs/tasks/inject-data-application/define-environment-variable-container.md +++ b/content/en/docs/tasks/inject-data-application/define-environment-variable-container.md @@ -102,6 +102,11 @@ Honorable`, and `Kubernetes`, respectively. The environment variable `MESSAGE` combines the set of all these environment variables and then uses it as a CLI argument passed to the `env-print-demo` container. +Environment variable names consist of letters, numbers, underscores, +dots, or hyphens, but the first character cannot be a digit. +If the `RelaxedEnvironmentVariableValidation` [feature gate](/docs/reference/command-line-tools-reference/feature-gates/) is enabled, +all [printable ASCII characters](https://www.ascii-code.com/characters/printable-characters) except "=" may be used for environment variable names. + ```yaml apiVersion: v1 kind: Pod diff --git a/content/en/docs/tasks/job/coarse-parallel-processing-work-queue.md b/content/en/docs/tasks/job/coarse-parallel-processing-work-queue.md index 3f94e249eb2dc..e64c8b3d6172d 100644 --- a/content/en/docs/tasks/job/coarse-parallel-processing-work-queue.md +++ b/content/en/docs/tasks/job/coarse-parallel-processing-work-queue.md @@ -48,14 +48,14 @@ Start RabbitMQ as follows: ```shell # make a Service for the StatefulSet to use -kubectl create -f https://kubernetes.io/examples/application/job/rabbitmq-service.yaml +kubectl create -f https://kubernetes.io/examples/application/job/rabbitmq/rabbitmq-service.yaml ``` ``` service "rabbitmq-service" created ``` ```shell -kubectl create -f https://kubernetes.io/examples/application/job/rabbitmq-statefulset.yaml +kubectl create -f https://kubernetes.io/examples/application/job/rabbitmq/rabbitmq-statefulset.yaml ``` ``` statefulset "rabbitmq" created @@ -84,7 +84,7 @@ Next install the `amqp-tools` so you can work with message queues. The next commands show what you need to run inside the interactive shell in that Pod: ```shell -apt-get update && apt-get install -y curl ca-certificates amqp-tools python dnsutils +apt-get update && apt-get install -y curl ca-certificates amqp-tools python3 dnsutils ``` Later, you will make a container image that includes these packages. diff --git a/content/en/docs/tasks/job/fine-parallel-processing-work-queue.md b/content/en/docs/tasks/job/fine-parallel-processing-work-queue.md index b865f49fd742d..f600f60df051e 100644 --- a/content/en/docs/tasks/job/fine-parallel-processing-work-queue.md +++ b/content/en/docs/tasks/job/fine-parallel-processing-work-queue.md @@ -59,6 +59,12 @@ You could also download the following files directly: - [`rediswq.py`](/examples/application/job/redis/rediswq.py) - [`worker.py`](/examples/application/job/redis/worker.py) +To start a single instance of Redis, you need to create the redis pod and redis service: + +```shell +kubectl apply -f https://k8s.io/examples/application/job/redis/redis-pod.yaml +kubectl apply -f https://k8s.io/examples/application/job/redis/redis-service.yaml +``` ## Filling the queue with tasks @@ -171,7 +177,7 @@ Since the workers themselves detect when the workqueue is empty, and the Job con know about the workqueue, it relies on the workers to signal when they are done working. The workers signal that the queue is empty by exiting with success. So, as soon as **any** worker exits with success, the controller knows the work is done, and that the Pods will exit soon. -So, you need to set the completion count of the Job to 1. The job controller will wait for +So, you need to leave the completion count of the Job unset. The job controller will wait for the other pods to complete too. ## Running the Job diff --git a/content/en/docs/tasks/job/pod-failure-policy.md b/content/en/docs/tasks/job/pod-failure-policy.md index 03c312c67ca3c..ee1bbb3ac8929 100644 --- a/content/en/docs/tasks/job/pod-failure-policy.md +++ b/content/en/docs/tasks/job/pod-failure-policy.md @@ -5,7 +5,7 @@ min-kubernetes-server-version: v1.25 weight: 60 --- -{{< feature-state for_k8s_version="v1.26" state="beta" >}} +{{< feature-state feature_gate_name="JobPodFailurePolicy" >}} diff --git a/content/en/docs/tasks/manage-gpus/scheduling-gpus.md b/content/en/docs/tasks/manage-gpus/scheduling-gpus.md index d02a20577e7f4..1466467a675d4 100644 --- a/content/en/docs/tasks/manage-gpus/scheduling-gpus.md +++ b/content/en/docs/tasks/manage-gpus/scheduling-gpus.md @@ -64,7 +64,7 @@ spec: gpu-vendor.example/example-gpu: 1 # requesting 1 GPU ``` -## Clusters containing different types of GPUs +## Manage clusters with different types of GPUs If different nodes in your cluster have different types of GPUs, then you can use [Node Labels and Node Selectors](/docs/tasks/configure-pod-container/assign-pods-nodes/) @@ -83,10 +83,46 @@ a different label key if you prefer. ## Automatic node labelling {#node-labeller} -If you're using AMD GPU devices, you can deploy -[Node Labeller](https://github.com/RadeonOpenCompute/k8s-device-plugin/tree/master/cmd/k8s-node-labeller). -Node Labeller is a {{< glossary_tooltip text="controller" term_id="controller" >}} that automatically -labels your nodes with GPU device properties. +As an administrator, you can automatically discover and label all your GPU enabled nodes +by deploying Kubernetes [Node Feature Discovery](https://github.com/kubernetes-sigs/node-feature-discovery) (NFD). +NFD detects the hardware features that are available on each node in a Kubernetes cluster. +Typically, NFD is configured to advertise those features as node labels, but NFD can also add extended resources, annotations, and node taints. +NFD is compatible with all [supported versions](/releases/version-skew-policy/#supported-versions) of Kubernetes. +By default NFD create the [feature labels](https://kubernetes-sigs.github.io/node-feature-discovery/master/usage/features.html) for the detected features. +Administrators can leverage NFD to also taint nodes with specific features, so that only pods that request those features can be scheduled on those nodes. -Similar functionality for NVIDIA is provided by -[GPU feature discovery](https://github.com/NVIDIA/gpu-feature-discovery/blob/main/README.md). +You also need a plugin for NFD that adds appropriate labels to your nodes; these might be generic +labels or they could be vendor specific. Your GPU vendor may provide a third party +plugin for NFD; check their documentation for more details. + +{{< highlight yaml "linenos=false,hl_lines=7-18" >}} +apiVersion: v1 +kind: Pod +metadata: + name: example-vector-add +spec: + restartPolicy: OnFailure + # You can use Kubernetes node affinity to schedule this Pod onto a node + # that provides the kind of GPU that its container needs in order to work + affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: "gpu.gpu-vendor.example/installed-memory" + operator: Gt # (greater than) + values: ["40535"] + - key: "feature.node.kubernetes.io/pci-10.present" # NFD Feature label + values: ["true"] # (optional) only schedule on nodes with PCI device 10 + containers: + - name: example-vector-add + image: "registry.example/example-vector-add:v42" + resources: + limits: + gpu-vendor.example/example-gpu: 1 # requesting 1 GPU +{{< /highlight >}} + +#### GPU vendor implementations + +- [Intel](https://intel.github.io/intel-device-plugins-for-kubernetes/cmd/gpu_plugin/README.html) +- [NVIDIA](https://github.com/NVIDIA/gpu-feature-discovery/#readme) diff --git a/content/en/docs/tasks/manage-kubernetes-objects/storage-version-migration.md b/content/en/docs/tasks/manage-kubernetes-objects/storage-version-migration.md new file mode 100644 index 0000000000000..b60ef782ee998 --- /dev/null +++ b/content/en/docs/tasks/manage-kubernetes-objects/storage-version-migration.md @@ -0,0 +1,313 @@ +--- +title: Migrate Kubernetes Objects Using Storage Version Migration + +reviewers: + - deads2k + - jpbetz + - enj + - nilekhc + +content_type: task +min-kubernetes-server-version: v1.30 +weight: 60 +--- + + +{{< feature-state feature_gate_name="StorageVersionMigrator" >}} + +Kubernetes relies on API data being actively re-written, to support some +maintenance activities related to at rest storage. Two prominent examples are +the versioned schema of stored resources (that is, the preferred storage schema +changing from v1 to v2 for a given resource) and encryption at rest +(that is, rewriting stale data based on a change in how the data should be encrypted). + +## {{% heading "prerequisites" %}} + +Install [`kubectl`](/docs/tasks/tools/#kubectl). + +{{< include "task-tutorial-prereqs.md" >}} {{< version-check >}} + + + + +## Re-encrypt Kubernetes secrets using storage version migration +- To begin with, [configure KMS provider](/docs/tasks/administer-cluster/kms-provider/) + to encrypt data at rest in etcd using following encryption configuration. + ```yaml + kind: EncryptionConfiguration + apiVersion: apiserver.config.k8s.io/v1 + resources: + - resources: + - secrets + providers: + - aescbc: + keys: + - name: key1 + secret: c2VjcmV0IGlzIHNlY3VyZQ== + ``` + Make sure to enable automatic reload of encryption +configuration file by setting `--encryption-provider-config-automatic-reload` to true. +- Create a Secret using kubectl. + ```shell + kubectl create secret generic my-secret --from-literal=key1=supersecret + ``` +- [Verify](/docs/tasks/administer-cluster/kms-provider/#verifying-that-the-data-is-encrypted) + the serialized data for that Secret object is prefixed with `k8s:enc:aescbc:v1:key1`. +- Update the encryption configuration file as follows to rotate the encryption key. + ```yaml + kind: EncryptionConfiguration + apiVersion: apiserver.config.k8s.io/v1 + resources: + - resources: + - secrets + providers: + - aescbc: + keys: + - name: key2 + secret: c2VjcmV0IGlzIHNlY3VyZSwgaXMgaXQ/ + - aescbc: + keys: + - name: key1 + secret: c2VjcmV0IGlzIHNlY3VyZQ== + ``` +- To ensure that previously created secret `my-secert` is re-encrypted +with new key `key2`, you will use _Storage Version Migration_. +- Create a StorageVersionMigration manifest named `migrate-secret.yaml` as follows: + ```yaml + kind: StorageVersionMigration + apiVersion: storagemigration.k8s.io/v1alpha1 + metadata: + name: secrets-migration + spec: + resource: + group: "" + version: v1 + resource: secrets + ``` + Create the object using _kubectl_ as follows: + ```shell + kubectl apply -f migrate-secret.yaml + ``` +- Monitor migration of Secrets by checking the `.status` of the StorageVersionMigration. + A successful migration should have its +`Succeeded` condition set to true. Get the StorageVersionMigration object +as follows: + ```shell + kubectl get storageversionmigration.storagemigration.k8s.io/secrets-migration -o yaml + ``` + + The output is similar to: + ```yaml + kind: StorageVersionMigration + apiVersion: storagemigration.k8s.io/v1alpha1 + metadata: + name: secrets-migration + uid: 628f6922-a9cb-4514-b076-12d3c178967c + resourceVersion: '90' + creationTimestamp: '2024-03-12T20:29:45Z' + spec: + resource: + group: "" + version: v1 + resource: secrets + status: + conditions: + - type: Running + status: 'False' + lastUpdateTime: '2024-03-12T20:29:46Z' + reason: StorageVersionMigrationInProgress + - type: Succeeded + status: 'True' + lastUpdateTime: '2024-03-12T20:29:46Z' + reason: StorageVersionMigrationSucceeded + resourceVersion: '84' + ``` +- [Verify](/docs/tasks/administer-cluster/kms-provider/#verifying-that-the-data-is-encrypted) + the stored secret is now prefixed with `k8s:enc:aescbc:v1:key2`. + +## Update the preferred storage schema of a CRD +Consider a scenario where a {{< glossary_tooltip term_id="CustomResourceDefinition" text="CustomResourceDefinition" >}} +(CRD) is created to serve custom resources (CRs) and is set as the preferred storage schema. When it's time +to introduce v2 of the CRD, it can be added for serving only with a conversion +webhook. This enables a smoother transition where users can create CRs using +either the v1 or v2 schema, with the webhook in place to perform the necessary +schema conversion between them. Before setting v2 as the preferred storage schema +version, it's important to ensure that all existing CRs stored as v1 are migrated to v2. +This migration can be achieved through _Storage Version Migration_ to migrate all CRs from v1 to v2. + +- Create a manifest for the CRD, named `test-crd.yaml`, as follows: + ```yaml + apiVersion: apiextensions.k8s.io/v1 + kind: CustomResourceDefinition + metadata: + name: selfierequests.stable.example.com + spec: + group: stable.example.com + names: + plural: SelfieRequests + singular: SelfieRequest + kind: SelfieRequest + listKind: SelfieRequestList + scope: Namespaced + versions: + - name: v1 + served: true + storage: true + schema: + openAPIV3Schema: + type: object + properties: + hostPort: + type: string + conversion: + strategy: Webhook + webhook: + clientConfig: + url: https://127.0.0.1:9443/crdconvert + caBundle: + conversionReviewVersions: + - v1 + - v2 + ``` + Create CRD using kubectl + ```shell + kubectl apply -f test-crd.yaml + ``` +- Create a manifest for an example testcrd. Name the manifest `cr1.yaml` and use these contents: + ```yaml + apiVersion: stable.example.com/v1 + kind: SelfieRequest + metadata: + name: cr1 + namespace: default + ``` + Create CR using kubectl + ```shell + kubectl apply -f cr1.yaml + ``` +- Verify that CR is written and stored as v1 by getting the object from etcd. + ```shell + ETCDCTL_API=3 etcdctl get /kubernetes.io/stable.example.com/testcrds/default/cr1 [...] | hexdump -C + ``` + where `[...]` contains the additional arguments for connecting to the etcd server. +- Update the CRD `test-crd.yaml` to include v2 version for serving and storage + and v1 as serving only, as follows: + ```yaml + apiVersion: apiextensions.k8s.io/v1 + kind: CustomResourceDefinition + metadata: + name: selfierequests.stable.example.com + spec: + group: stable.example.com + names: + plural: SelfieRequests + singular: SelfieRequest + kind: SelfieRequest + listKind: SelfieRequestList + scope: Namespaced + versions: + - name: v2 + served: true + storage: true + schema: + openAPIV3Schema: + type: object + properties: + host: + type: string + port: + type: string + - name: v1 + served: true + storage: false + schema: + openAPIV3Schema: + type: object + properties: + hostPort: + type: string + conversion: + strategy: Webhook + webhook: + clientConfig: + url: 'https://127.0.0.1:9443/crdconvert' + caBundle: + conversionReviewVersions: + - v1 + - v2 + ``` + Update CRD using kubectl + ```shell + kubectl apply -f test-crd.yaml + ``` +- Create CR resource file with name `cr2.yaml` as follows: + ```yaml + apiVersion: stable.example.com/v2 + kind: SelfieRequest + metadata: + name: cr2 + namespace: default + ``` +- Create CR using kubectl + ```shell + kubectl apply -f cr2.yaml + ``` +- Verify that CR is written and stored as v2 by getting the object from etcd. + ```shell + ETCDCTL_API=3 etcdctl get /kubernetes.io/stable.example.com/testcrds/default/cr2 [...] | hexdump -C + ``` + where `[...]` contains the additional arguments for connecting to the etcd server. +- Create a StorageVersionMigration manifest named `migrate-crd.yaml`, with the contents as follows: + ```yaml + kind: StorageVersionMigration + apiVersion: storagemigration.k8s.io/v1alpha1 + metadata: + name: crdsvm + spec: + resource: + group: stable.example.com + version: v1 + resource: SelfieRequest + ``` + Create the object using _kubectl_ as follows: + ```shell + kubectl apply -f migrate-crd.yaml + ``` +- Monitor migration of secrets using status. Successful migration should have + `Succeeded` condition set to "True" in the status field. Get the migration resource + as follows: + ```shell + kubectl get storageversionmigration.storagemigration.k8s.io/crdsvm -o yaml + ``` + + The output is similar to: + ```yaml + kind: StorageVersionMigration + apiVersion: storagemigration.k8s.io/v1alpha1 + metadata: + name: crdsvm + uid: 13062fe4-32d7-47cc-9528-5067fa0c6ac8 + resourceVersion: '111' + creationTimestamp: '2024-03-12T22:40:01Z' + spec: + resource: + group: stable.example.com + version: v1 + resource: testcrds + status: + conditions: + - type: Running + status: 'False' + lastUpdateTime: '2024-03-12T22:40:03Z' + reason: StorageVersionMigrationInProgress + - type: Succeeded + status: 'True' + lastUpdateTime: '2024-03-12T22:40:03Z' + reason: StorageVersionMigrationSucceeded + resourceVersion: '106' + ``` +- Verify that previously created cr1 is now written and stored as v2 by getting the object from etcd. + ```shell + ETCDCTL_API=3 etcdctl get /kubernetes.io/stable.example.com/testcrds/default/cr1 [...] | hexdump -C + ``` + where `[...]` contains the additional arguments for connecting to the etcd server. diff --git a/content/en/docs/tasks/network/extend-service-ip-ranges.md b/content/en/docs/tasks/network/extend-service-ip-ranges.md index fdce843c68c41..3b381158d7cd2 100644 --- a/content/en/docs/tasks/network/extend-service-ip-ranges.md +++ b/content/en/docs/tasks/network/extend-service-ip-ranges.md @@ -8,7 +8,7 @@ content_type: task --- -{{< feature-state state="alpha" for_k8s_version="v1.29" >}} +{{< feature-state feature_gate_name="MultiCIDRServiceAllocator" >}} This document shares how to extend the existing Service IP range assigned to a cluster. diff --git a/content/en/docs/tasks/run-application/configure-pdb.md b/content/en/docs/tasks/run-application/configure-pdb.md index b34c7d8dab140..c57e6b867d333 100644 --- a/content/en/docs/tasks/run-application/configure-pdb.md +++ b/content/en/docs/tasks/run-application/configure-pdb.md @@ -241,7 +241,7 @@ These pods are tracked via `.status.currentHealthy` field in the PDB status. ## Unhealthy Pod Eviction Policy -{{< feature-state for_k8s_version="v1.27" state="beta" >}} +{{< feature-state feature_gate_name="PDBUnhealthyPodEvictionPolicy" >}} {{< note >}} This feature is enabled by default. You can disable it by disabling the `PDBUnhealthyPodEvictionPolicy` diff --git a/content/en/docs/tasks/run-application/horizontal-pod-autoscale.md b/content/en/docs/tasks/run-application/horizontal-pod-autoscale.md index 9461ad4ae4ae9..f25317fef9a0d 100644 --- a/content/en/docs/tasks/run-application/horizontal-pod-autoscale.md +++ b/content/en/docs/tasks/run-application/horizontal-pod-autoscale.md @@ -278,12 +278,12 @@ pod usage is still within acceptable limits. ### Container resource metrics -{{< feature-state for_k8s_version="v1.27" state="beta" >}} +{{< feature-state feature_gate_name="HPAContainerMetrics" >}} The HorizontalPodAutoscaler API also supports a container metric source where the HPA can track the resource usage of individual containers across a set of Pods, in order to scale the target resource. This lets you configure scaling thresholds for the containers that matter most in a particular Pod. -For example, if you have a web application and a logging sidecar, you can scale based on the resource +For example, if you have a web application and a sidecar container that provides logging, you can scale based on the resource use of the web application, ignoring the sidecar container and its resource use. If you revise the target resource to have a new Pod specification with a different set of containers, @@ -596,8 +596,9 @@ guidelines, which cover this exact use case. ## {{% heading "whatsnext" %}} -If you configure autoscaling in your cluster, you may also want to consider running a -cluster-level autoscaler such as [Cluster Autoscaler](https://github.com/kubernetes/autoscaler/tree/master/cluster-autoscaler). +If you configure autoscaling in your cluster, you may also want to consider using +[cluster autoscaling](/docs/concepts/cluster-administration/cluster-autoscaling/) +to ensure you are running the right number of nodes. For more information on HorizontalPodAutoscaler: diff --git a/content/en/docs/tasks/tools/included/verify-kubectl.md b/content/en/docs/tasks/tools/included/verify-kubectl.md index b4eb0fe08d2a3..dd401aecec968 100644 --- a/content/en/docs/tasks/tools/included/verify-kubectl.md +++ b/content/en/docs/tasks/tools/included/verify-kubectl.md @@ -31,9 +31,9 @@ The connection to the server was refused - did you specify th ``` For example, if you are intending to run a Kubernetes cluster on your laptop (locally), -you will need a tool like Minikube to be installed first and then re-run the commands stated above. +you will need a tool like [Minikube](https://minikube.sigs.k8s.io/docs/start/) to be installed first and then re-run the commands stated above. -If kubectl cluster-info returns the url response but you can't access your cluster, +If `kubectl cluster-info` returns the url response but you can't access your cluster, to check whether it is configured properly, use: ```shell diff --git a/content/en/docs/tasks/tools/install-kubectl-linux.md b/content/en/docs/tasks/tools/install-kubectl-linux.md index 1e91727a4a5e6..57af2f5f6dfe1 100644 --- a/content/en/docs/tasks/tools/install-kubectl-linux.md +++ b/content/en/docs/tasks/tools/install-kubectl-linux.md @@ -139,6 +139,7 @@ The following methods exist for installing kubectl on Linux: # If the folder `/etc/apt/keyrings` does not exist, it should be created before the curl command, read the note below. # sudo mkdir -p -m 755 /etc/apt/keyrings curl -fsSL https://pkgs.k8s.io/core:/stable:/{{< param "version" >}}/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg + sudo chmod 644 /etc/apt/keyrings/kubernetes-apt-keyring.gpg # allow unprivileged APT programs to read this keyring ``` {{< note >}} @@ -151,6 +152,7 @@ In releases older than Debian 12 and Ubuntu 22.04, folder `/etc/apt/keyrings` do ```shell # This overwrites any existing configuration in /etc/apt/sources.list.d/kubernetes.list echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/{{< param "version" >}}/deb/ /' | sudo tee /etc/apt/sources.list.d/kubernetes.list + sudo chmod 644 /etc/apt/sources.list.d/kubernetes.list # helps tools such as command-not-found to work correctly ``` {{< note >}} diff --git a/content/en/docs/tasks/tools/install-kubectl-windows.md b/content/en/docs/tasks/tools/install-kubectl-windows.md index b035954fddce5..4e7b3e36ffd60 100644 --- a/content/en/docs/tasks/tools/install-kubectl-windows.md +++ b/content/en/docs/tasks/tools/install-kubectl-windows.md @@ -205,7 +205,8 @@ Below are the procedures to set up autocompletion for PowerShell. 1. After installing the plugin, clean up the installation files: ```powershell - del kubectl-convert.exe kubectl-convert.exe.sha256 + del kubectl-convert.exe + del kubectl-convert.exe.sha256 ``` ## {{% heading "whatsnext" %}} diff --git a/content/en/docs/tutorials/configuration/configure-redis-using-configmap.md b/content/en/docs/tutorials/configuration/configure-redis-using-configmap.md index 024dc04676ebd..a9cf3dae9458b 100644 --- a/content/en/docs/tutorials/configuration/configure-redis-using-configmap.md +++ b/content/en/docs/tutorials/configuration/configure-redis-using-configmap.md @@ -4,6 +4,7 @@ reviewers: - pmorie title: Configuring Redis using a ConfigMap content_type: tutorial +weight: 30 --- @@ -251,3 +252,4 @@ kubectl delete pod/redis configmap/example-redis-config * Learn more about [ConfigMaps](/docs/tasks/configure-pod-container/configure-pod-configmap/). +* Follow an example of [Updating configuration via a ConfigMap](/docs/tutorials/configuration/updating-configuration-via-a-configmap/). diff --git a/content/en/docs/tutorials/configuration/updating-configuration-via-a-configmap.md b/content/en/docs/tutorials/configuration/updating-configuration-via-a-configmap.md new file mode 100644 index 0000000000000..42882056e8242 --- /dev/null +++ b/content/en/docs/tutorials/configuration/updating-configuration-via-a-configmap.md @@ -0,0 +1,654 @@ +--- +title: Updating Configuration via a ConfigMap +content_type: tutorial +weight: 20 +--- + + +This page provides a step-by-step example of updating configuration within a Pod via a ConfigMap +and builds upon the [Configure a Pod to Use a ConfigMap](/docs/tasks/configure-pod-container/configure-pod-configmap/) task. +At the end of this tutorial, you will understand how to change the configuration for a running application. +This tutorial uses the `alpine` and `nginx` images as examples. + +## {{% heading "prerequisites" %}} +{{< include "task-tutorial-prereqs.md" >}} + +You need to have the [curl](https://curl.se/) command-line tool for making HTTP requests from +the terminal or command prompt. If you do not have `curl` available, you can install it. Check the +documentation for your local operating system. + +## {{% heading "objectives" %}} +* Update configuration via a ConfigMap mounted as a Volume +* Update environment variables of a Pod via a ConfigMap +* Update configuration via a ConfigMap in a multi-container Pod +* Update configuration via a ConfigMap in a Pod possessing a Sidecar Container + + + +## Update configuration via a ConfigMap mounted as a Volume {#rollout-configmap-volume} + +Use the `kubectl create configmap` command to create a ConfigMap from [literal values](/docs/tasks/configure-pod-container/configure-pod-configmap/#create-configmaps-from-literal-values): + +```shell +kubectl create configmap sport --from-literal=sport=football +``` +Below is an example of a Deployment manifest with the ConfigMap `sport` mounted as a +{{< glossary_tooltip text="volume" term_id="volume" >}} into the Pod's only container. +{{% code_sample file="deployments/deployment-with-configmap-as-volume.yaml" %}} + +Create the Deployment: +```shell +kubectl apply -f https://k8s.io/examples/deployments/deployment-with-configmap-as-volume.yaml +``` + +Check the pods for this Deployment to ensure they are ready (matching by +{{< glossary_tooltip text="selector" term_id="selector" >}}): +```shell +kubectl get pods --selector=app.kubernetes.io/name=configmap-volume +``` + +You should see an output similar to: +``` +NAME READY STATUS RESTARTS AGE +configmap-volume-6b976dfdcf-qxvbm 1/1 Running 0 72s +configmap-volume-6b976dfdcf-skpvm 1/1 Running 0 72s +configmap-volume-6b976dfdcf-tbc6r 1/1 Running 0 72s +``` + +On each node where one of these Pods is running, the kubelet fetches the data for +that ConfigMap and translates it to files in a local volume. +The kubelet then mounts that volume into the container, as specified in the Pod template. +The code running in that container loads the information from the file +and uses it to print a report to stdout. +You can check this report by viewing the logs for one of the Pods in that Deployment: +```shell +# Pick one Pod that belongs to the Deployment, and view its logs +kubectl logs deployments/configmap-volume +``` + +You should see an output similar to: +``` +Found 3 pods, using pod/configmap-volume-76d9c5678f-x5rgj +Thu Jan 4 14:06:46 UTC 2024 My preferred sport is football +Thu Jan 4 14:06:56 UTC 2024 My preferred sport is football +Thu Jan 4 14:07:06 UTC 2024 My preferred sport is football +Thu Jan 4 14:07:16 UTC 2024 My preferred sport is football +Thu Jan 4 14:07:26 UTC 2024 My preferred sport is football +``` + +Edit the ConfigMap: +```shell +kubectl edit configmap sport +``` + +In the editor that appears, change the value of key `sport` from `football` to `cricket`. Save your changes. +The kubectl tool updates the ConfigMap accordingly (if you see an error, try again). + +Here's an example of how that manifest could look after you edit it: + +```yaml +apiVersion: v1 +data: + sport: cricket +kind: ConfigMap +# You can leave the existing metadata as they are. +# The values you'll see won't exactly match these. +metadata: + creationTimestamp: "2024-01-04T14:05:06Z" + name: sport + namespace: default + resourceVersion: "1743935" + uid: 024ee001-fe72-487e-872e-34d6464a8a23 +``` + +You should see the following output: +``` +configmap/sport edited +``` + +Tail (follow the latest entries in) the logs of one of the pods that belongs to this Deployment: +```shell +kubectl logs deployments/configmap-volume --follow +``` +After few seconds, you should see the log output change as follows: +``` +Thu Jan 4 14:11:36 UTC 2024 My preferred sport is football +Thu Jan 4 14:11:46 UTC 2024 My preferred sport is football +Thu Jan 4 14:11:56 UTC 2024 My preferred sport is football +Thu Jan 4 14:12:06 UTC 2024 My preferred sport is cricket +Thu Jan 4 14:12:16 UTC 2024 My preferred sport is cricket +``` + +When you have a ConfigMap that is mapped into a running Pod using either a +`configMap` volume or a `projected` volume, and you update that ConfigMap, +the running Pod sees the update almost immediately. +However, your application only sees the change if it is written to either poll for changes, +or watch for file updates. +An application that loads its configuration once at startup will not notice a change. + + +{{< note >}} +The total delay from the moment when the ConfigMap is updated to the moment when +new keys are projected to the Pod can be as long as kubelet sync period. +Also check [Mounted ConfigMaps are updated automatically](/docs/tasks/configure-pod-container/configure-pod-configmap/#mounted-configmaps-are-updated-automatically). +{{< /note >}} + +## Update environment variables of a Pod via a ConfigMap {#rollout-configmap-env} +Use the `kubectl create configmap` command to create a ConfigMap from [literal values](/docs/tasks/configure-pod-container/configure-pod-configmap/#create-configmaps-from-literal-values): + +```shell +kubectl create configmap fruits --from-literal=fruits=apples +``` + +Below is an example of a Deployment manifest with an environment variable configured via the ConfigMap `fruits`. +{{% code_sample file="deployments/deployment-with-configmap-as-envvar.yaml" %}} + +Create the Deployment: +```shell +kubectl apply -f https://k8s.io/examples/deployments/deployment-with-configmap-as-envvar.yaml +``` + +Check the pods for this Deployment to ensure they are ready (matching by +{{< glossary_tooltip text="selector" term_id="selector" >}}): +```shell +kubectl get pods --selector=app.kubernetes.io/name=configmap-env-var +``` + +You should see an output similar to: +``` +NAME READY STATUS RESTARTS AGE +configmap-env-var-59cfc64f7d-74d7z 1/1 Running 0 46s +configmap-env-var-59cfc64f7d-c4wmj 1/1 Running 0 46s +configmap-env-var-59cfc64f7d-dpr98 1/1 Running 0 46s +``` + +The key-value pair in the ConfigMap is configured as an environment variable in the container of the Pod. +Check this by viewing the logs of one Pod that belongs to the Deployment. +```shell +kubectl logs deployment/configmap-env-var +``` + +You should see an output similar to: +``` +Found 3 pods, using pod/configmap-env-var-7c994f7769-l74nq +Thu Jan 4 16:07:06 UTC 2024 The basket is full of apples +Thu Jan 4 16:07:16 UTC 2024 The basket is full of apples +Thu Jan 4 16:07:26 UTC 2024 The basket is full of apples +``` + +Edit the ConfigMap: +```shell +kubectl edit configmap fruits +``` + +In the editor that appears, change the value of key `fruits` from `apples` to `mangoes`. Save your changes. +The kubectl tool updates the ConfigMap accordingly (if you see an error, try again). + +Here's an example of how that manifest could look after you edit it: +```yaml +apiVersion: v1 +data: + fruits: mangoes +kind: ConfigMap +# You can leave the existing metadata as they are. +# The values you'll see won't exactly match these. +metadata: + creationTimestamp: "2024-01-04T16:04:19Z" + name: fruits + namespace: default + resourceVersion: "1749472" + +``` + +You should see the following output: +``` +configmap/fruits edited +``` + +Tail the logs of the Deployment and observe the output for few seconds: +```shell +# As the text explains, the output does NOT change +kubectl logs deployments/configmap-env-var --follow +``` + +Notice that the output remains **unchanged**, even though you edited the ConfigMap: +``` +Thu Jan 4 16:12:56 UTC 2024 The basket is full of apples +Thu Jan 4 16:13:06 UTC 2024 The basket is full of apples +Thu Jan 4 16:13:16 UTC 2024 The basket is full of apples +Thu Jan 4 16:13:26 UTC 2024 The basket is full of apples +``` + +{{< note >}} +Although the value of the key inside the ConfigMap has changed, the environment variable in the Pod still shows the earlier value. This is because environment variables for a process running inside a Pod are **not** updated when the source data changes; if you wanted to force an update, you would need to have Kubernetes replace your existing Pods. The new Pods would then run with the updated information. +{{< /note >}} + +You can trigger that replacement. Perform a rollout for the Deployment, using +[`kubectl rollout`](/docs/reference/kubectl/generated/kubectl_rollout/): +```shell +# Trigger the rollout +kubectl rollout restart deployment configmap-env-var + +# Wait for the rollout to complete +kubectl rollout status deployment configmap-env-var --watch=true +``` + +Next, check the Deployment: +```shell +kubectl get deployment configmap-env-var +``` + +You should see an output similar to: +``` +NAME READY UP-TO-DATE AVAILABLE AGE +configmap-env-var 3/3 3 3 12m +``` + +Check the Pods: +```shell +kubectl get pods --selector=app.kubernetes.io/name=configmap-env-var +``` + +The rollout causes Kubernetes to make a new {{< glossary_tooltip term_id="replica-set" text="ReplicaSet" >}} for the Deployment; that means the existing Pods eventually terminate, and new ones are created. After few seconds, you should see an output similar to: +``` +NAME READY STATUS RESTARTS AGE +configmap-env-var-6d94d89bf5-2ph2l 1/1 Running 0 13s +configmap-env-var-6d94d89bf5-74twx 1/1 Running 0 8s +configmap-env-var-6d94d89bf5-d5vx8 1/1 Running 0 11s +``` + +{{< note >}} +Please wait for the older Pods to fully terminate before proceeding with the next steps. +{{< /note >}} + +View the logs for a Pod in this Deployment: +```shell +# Pick one Pod that belongs to the Deployment, and view its logs +kubectl logs deployment/configmap-env-var +``` + +You should see an output similar to the below: +``` +Found 3 pods, using pod/configmap-env-var-6d9ff89fb6-bzcf6 +Thu Jan 4 16:30:35 UTC 2024 The basket is full of mangoes +Thu Jan 4 16:30:45 UTC 2024 The basket is full of mangoes +Thu Jan 4 16:30:55 UTC 2024 The basket is full of mangoes +``` + +This demonstrates the scenario of updating environment variables in a Pod that are derived +from a ConfigMap. Changes to the ConfigMap values are applied to the Pod during the subsequent +rollout. If Pods get created for another reason, such as scaling up the Deployment, then the new Pods +also use the latest configuration values; if you don't trigger a rollout, then you might find that your +app is running with a mix of old and new environment variable values. + + +## Update configuration via a ConfigMap in a multi-container Pod {#rollout-configmap-multiple-containers} + +Use the `kubectl create configmap` command to create a ConfigMap from [literal values](/docs/tasks/configure-pod-container/configure-pod-configmap/#create-configmaps-from-literal-values): + +```shell +kubectl create configmap color --from-literal=color=red +``` +Below is an example manifest for a Deployment that manages a set of Pods, each with two containers. The two containers share an `emptyDir` volume that they use to communicate. +The first container runs a web server (`nginx`). The mount path for the shared volume in the web server container is `/usr/share/nginx/html`. The second helper container is based on `alpine`, and for this container the `emptyDir` volume is mounted at `/pod-data`. The helper container writes a file in HTML that has its content based on a ConfigMap. The web server container serves the HTML via HTTP. + +{{% code_sample file="deployments/deployment-with-configmap-two-containers.yaml" %}} + +Create the Deployment: +```shell +kubectl apply -f https://k8s.io/examples/deployments/deployment-with-configmap-two-containers.yaml +``` + +Check the pods for this Deployment to ensure they are ready (matching by +{{< glossary_tooltip text="selector" term_id="selector" >}}): +```shell +kubectl get pods --selector=app.kubernetes.io/name=configmap-two-containers +``` +You should see an output similar to: +``` +NAME READY STATUS RESTARTS AGE +configmap-two-containers-565fb6d4f4-2xhxf 2/2 Running 0 20s +configmap-two-containers-565fb6d4f4-g5v4j 2/2 Running 0 20s +configmap-two-containers-565fb6d4f4-mzsmf 2/2 Running 0 20s +```` + +Expose the Deployment (the `kubectl` tool creates a +{{}} for you): +```shell +kubectl expose deployment configmap-two-containers --name=configmap-service --port=8080 --target-port=80 +``` + +Use `kubectl` to forward the port: +```shell +kubectl port-forward service/configmap-service 8080:8080 & # this stays running in the background +``` + +Access the service. +```shell +curl http://localhost:8080 +``` + +You should see an output similar to: +``` +Fri Jan 5 08:08:22 UTC 2024 My preferred color is red +``` + +Edit the ConfigMap: +```shell +kubectl edit configmap color +``` + +In the editor that appears, change the value of key `color` from `red` to `blue`. Save your changes. +The kubectl tool updates the ConfigMap accordingly (if you see an error, try again). + +Here's an example of how that manifest could look after you edit it: + +```yaml +apiVersion: v1 +data: + color: blue +kind: ConfigMap +# You can leave the existing metadata as they are. +# The values you'll see won't exactly match these. +metadata: + creationTimestamp: "2024-01-05T08:12:05Z" + name: color + namespace: configmap + resourceVersion: "1801272" + uid: 80d33e4a-cbb4-4bc9-ba8c-544c68e425d6 +``` + +Loop over the service URL for few seconds. +```shell +# Cancel this when you're happy with it (Ctrl-C) +while true; do curl --connect-timeout 7.5 http://localhost:8080; sleep 10; done +``` + +You should see the output change as follows: +``` +Fri Jan 5 08:14:00 UTC 2024 My preferred color is red +Fri Jan 5 08:14:02 UTC 2024 My preferred color is red +Fri Jan 5 08:14:20 UTC 2024 My preferred color is red +Fri Jan 5 08:14:22 UTC 2024 My preferred color is red +Fri Jan 5 08:14:32 UTC 2024 My preferred color is blue +Fri Jan 5 08:14:43 UTC 2024 My preferred color is blue +Fri Jan 5 08:15:00 UTC 2024 My preferred color is blue +``` + +## Update configuration via a ConfigMap in a Pod possessing a sidecar container {#rollout-configmap-sidecar} + +The above scenario can be replicated by using a [Sidecar Container](/docs/concepts/workloads/pods/sidecar-containers/) as a helper container to write the HTML file. +As a Sidecar Container is conceptually an Init Container, it is guaranteed to start before the main web server container. +This ensures that the HTML file is always available when the web server is ready to serve it. +Please see [Enabling sidecar containers](/docs/concepts/workloads/pods/sidecar-containers/#enabling-sidecar-containers) to utilize this feature. + +If you are continuing from the previous scenario, you can reuse the ConfigMap named `color` for this scenario. +If you are executing this scenario independently, use the `kubectl create configmap` command to create a ConfigMap from [literal values](/docs/tasks/configure-pod-container/configure-pod-configmap/#create-configmaps-from-literal-values): + +```shell +kubectl create configmap color --from-literal=color=blue +``` + +Below is an example manifest for a Deployment that manages a set of Pods, each with a main container and a sidecar container. The two containers share an `emptyDir` volume that they use to communicate. +The main container runs a web server (NGINX). The mount path for the shared volume in the web server container is `/usr/share/nginx/html`. The second container is a Sidecar Container based on Alpine Linux which acts as a helper container. For this container the `emptyDir` volume is mounted at `/pod-data`. The Sidecar Container writes a file in HTML that has its content based on a ConfigMap. The web server container serves the HTML via HTTP. + +{{% code_sample file="deployments/deployment-with-configmap-and-sidecar-container.yaml" %}} + +Create the Deployment: +```shell +kubectl apply -f https://k8s.io/examples/deployments/deployment-with-configmap-and-sidecar-container.yaml +``` + +Check the pods for this Deployment to ensure they are ready (matching by +{{< glossary_tooltip text="selector" term_id="selector" >}}): +```shell +kubectl get pods --selector=app.kubernetes.io/name=configmap-sidecar-container +``` +You should see an output similar to: +``` +NAME READY STATUS RESTARTS AGE +configmap-sidecar-container-5fb59f558b-87rp7 2/2 Running 0 94s +configmap-sidecar-container-5fb59f558b-ccs7s 2/2 Running 0 94s +configmap-sidecar-container-5fb59f558b-wnmgk 2/2 Running 0 94s +```` + +Expose the Deployment (the `kubectl` tool creates a +{{}} for you): +```shell +kubectl expose deployment configmap-sidecar-container --name=configmap-sidecar-service --port=8081 --target-port=80 +``` + +Use ```kubectl``` to forward the port: +```shell +kubectl port-forward service/configmap-sidecar-service 8081:8081 & # this stays running in the background +``` + +Access the service. +```shell +curl http://localhost:8081 +``` + +You should see an output similar to: +``` +Sat Feb 17 13:09:05 UTC 2024 My preferred color is blue +``` + +Edit the ConfigMap: +```shell +kubectl edit configmap color +``` + +In the editor that appears, change the value of key `color` from `blue` to `green`. Save your changes. +The kubectl tool updates the ConfigMap accordingly (if you see an error, try again). + +Here's an example of how that manifest could look after you edit it: + +```yaml +apiVersion: v1 +data: + color: green +kind: ConfigMap +# You can leave the existing metadata as they are. +# The values you'll see won't exactly match these. +metadata: + creationTimestamp: "2024-02-17T12:20:30Z" + name: color + namespace: default + resourceVersion: "1054" + uid: e40bb34c-58df-4280-8bea-6ed16edccfaa +``` + +Loop over the service URL for few seconds. +```shell +# Cancel this when you're happy with it (Ctrl-C) +while true; do curl --connect-timeout 7.5 http://localhost:8081; sleep 10; done +``` + +You should see the output change as follows: +``` +Sat Feb 17 13:12:35 UTC 2024 My preferred color is blue +Sat Feb 17 13:12:45 UTC 2024 My preferred color is blue +Sat Feb 17 13:12:55 UTC 2024 My preferred color is blue +Sat Feb 17 13:13:05 UTC 2024 My preferred color is blue +Sat Feb 17 13:13:15 UTC 2024 My preferred color is green +Sat Feb 17 13:13:25 UTC 2024 My preferred color is green +Sat Feb 17 13:13:35 UTC 2024 My preferred color is green +``` + +## Update configuration via an immutable ConfigMap that is mounted as a volume {#rollout-configmap-immutable-volume} + +{{< note >}} +Immutable ConfigMaps are especially used for configuration that is constant and is **not** expected to change over time. Marking a ConfigMap as immutable allows a performance improvement where the kubelet does not watch for changes. + +If you do need to make a change, you should plan to either: +- change the name of the ConfigMap, and switch to running Pods that reference the new name +- replace all the nodes in your cluster that have previously run a Pod that used the old value +- restart the kubelet on any node where the kubelet previously loaded the old ConfigMap +{{< /note >}} + +An example manifest for an [Immutable ConfigMap](/docs/concepts/configuration/configmap/#configmap-immutable) is shown below. +{{% code_sample file="configmap/immutable-configmap.yaml" %}} + +Create the Immutable ConfigMap: +```shell +kubectl apply -f https://k8s.io/examples/configmap/immutable-configmap.yaml +``` + +Below is an example of a Deployment manifest with the Immutable ConfigMap `company-name-20150801` mounted as a +{{< glossary_tooltip text="volume" term_id="volume" >}} into the Pod's only container. +{{% code_sample file="deployments/deployment-with-immutable-configmap-as-volume.yaml" %}} + +Create the Deployment: +```shell +kubectl apply -f https://k8s.io/examples/deployments/deployment-with-immutable-configmap-as-volume.yaml +``` + +Check the pods for this Deployment to ensure they are ready (matching by +{{< glossary_tooltip text="selector" term_id="selector" >}}): +```shell +kubectl get pods --selector=app.kubernetes.io/name=immutable-configmap-volume +``` + +You should see an output similar to: +``` +NAME READY STATUS RESTARTS AGE +immutable-configmap-volume-78b6fbff95-5gsfh 1/1 Running 0 62s +immutable-configmap-volume-78b6fbff95-7vcj4 1/1 Running 0 62s +immutable-configmap-volume-78b6fbff95-vdslm 1/1 Running 0 62s +``` + +The Pod's container refers to the data defined in the ConfigMap and uses it to print a report to stdout. You can check this report by viewing the logs for one of the Pods in that Deployment: +```shell +# Pick one Pod that belongs to the Deployment, and view its logs +kubectl logs deployments/immutable-configmap-volume +``` + +You should see an output similar to: +``` +Found 3 pods, using pod/immutable-configmap-volume-78b6fbff95-5gsfh +Wed Mar 20 03:52:34 UTC 2024 The name of the company is ACME, Inc. +Wed Mar 20 03:52:44 UTC 2024 The name of the company is ACME, Inc. +Wed Mar 20 03:52:54 UTC 2024 The name of the company is ACME, Inc. +``` + +{{< note >}} +Once a ConfigMap is marked as immutable, it is not possible to revert this change +nor to mutate the contents of the data or the binaryData field. +In order to modify the behavior of the Pods that use this configuration, +you will create a new immutable ConfigMap and edit the Deployment +to define a slightly different pod template, referencing the new ConfigMap. +{{< /note >}} + +Create a new immutable ConfigMap by using the manifest shown below: +{{% code_sample file="configmap/new-immutable-configmap.yaml" %}} + +```shell +kubectl apply -f https://k8s.io/examples/configmap/new-immutable-configmap.yaml +``` + +You should see an output similar to: +``` +configmap/company-name-20240312 created +``` + +Check the newly created ConfigMap: + +```shell +kubectl get configmap +``` + +You should see an output displaying both the old and new ConfigMaps: +``` +NAME DATA AGE +company-name-20150801 1 22m +company-name-20240312 1 24s +``` + +Modify the Deployment to reference the new ConfigMap. + +Edit the Deployment: +```shell +kubectl edit deployment immutable-configmap-volume +``` + +In the editor that appears, update the existing volume definition to use the new ConfigMap. + +```yaml +volumes: +- configMap: + defaultMode: 420 + name: company-name-20240312 # Update this field + name: config-volume +``` +You should see the following output: +``` +deployment.apps/immutable-configmap-volume edited +``` + +This will trigger a rollout. Wait for all the previous Pods to terminate and the new Pods to be in a ready state. + +Monitor the status of the Pods: +```shell +kubectl get pods --selector=app.kubernetes.io/name=immutable-configmap-volume +``` + +``` +NAME READY STATUS RESTARTS AGE +immutable-configmap-volume-5fdb88fcc8-29v8n 1/1 Running 0 13s +immutable-configmap-volume-5fdb88fcc8-52ddd 1/1 Running 0 14s +immutable-configmap-volume-5fdb88fcc8-n5jx4 1/1 Running 0 15s +immutable-configmap-volume-78b6fbff95-5gsfh 1/1 Terminating 0 32m +immutable-configmap-volume-78b6fbff95-7vcj4 1/1 Terminating 0 32m +immutable-configmap-volume-78b6fbff95-vdslm 1/1 Terminating 0 32m + +``` + +You should eventually see an output similar to: +``` +NAME READY STATUS RESTARTS AGE +immutable-configmap-volume-5fdb88fcc8-29v8n 1/1 Running 0 43s +immutable-configmap-volume-5fdb88fcc8-52ddd 1/1 Running 0 44s +immutable-configmap-volume-5fdb88fcc8-n5jx4 1/1 Running 0 45s +``` + +View the logs for a Pod in this Deployment: +```shell +# Pick one Pod that belongs to the Deployment, and view its logs +kubectl logs deployment/immutable-configmap-volume +``` + +You should see an output similar to the below: +``` +Found 3 pods, using pod/immutable-configmap-volume-5fdb88fcc8-n5jx4 +Wed Mar 20 04:24:17 UTC 2024 The name of the company is Fiktivesunternehmen GmbH +Wed Mar 20 04:24:27 UTC 2024 The name of the company is Fiktivesunternehmen GmbH +Wed Mar 20 04:24:37 UTC 2024 The name of the company is Fiktivesunternehmen GmbH +``` + +Once all the deployments have migrated to use the new immutable ConfigMap, it is advised to delete the old one. + +```shell +kubectl delete configmap company-name-20150801 +``` + +## Summary + +Changes to a ConfigMap mounted as a Volume on a Pod are available seamlessly after the subsequent kubelet sync. + +Changes to a ConfigMap that configures environment variables for a Pod are available after the subsequent rollout for the Pod. + +Once a ConfigMap is marked as immutable, it is not possible to revert this change (you cannot make an immutable ConfigMap mutable), and you also cannot make any change to the contents of the `data` or the `binaryData` field. You can delete and recreate the ConfigMap, or you can make a new different ConfigMap. When you delete a ConfigMap, running containers +and their Pods maintain a mount point to any volume that referenced that existing ConfigMap. + + +## {{% heading "cleanup" %}} +Terminate the `kubectl port-forward` commands in case they are running. + +Delete the resources created during the tutorial: +```shell +kubectl delete deployment configmap-volume configmap-env-var configmap-two-containers configmap-sidecar-container immutable-configmap-volume +kubectl delete service configmap-service configmap-sidecar-service +kubectl delete configmap sport fruits color company-name-20240312 + +kubectl delete configmap company-name-20150801 # In case it was not handled during the task execution +``` \ No newline at end of file diff --git a/content/en/docs/tutorials/hello-minikube.md b/content/en/docs/tutorials/hello-minikube.md index 293c97c6393e1..0afa96251ed93 100644 --- a/content/en/docs/tutorials/hello-minikube.md +++ b/content/en/docs/tutorials/hello-minikube.md @@ -2,12 +2,6 @@ title: Hello Minikube content_type: tutorial weight: 5 -menu: - main: - title: "Get Started" - weight: 10 - post: > -

          Ready to get your hands dirty? Build a simple Kubernetes cluster that runs a sample app.

          card: name: tutorials weight: 10 diff --git a/content/en/docs/tutorials/kubernetes-basics/deploy-app/deploy-intro.html b/content/en/docs/tutorials/kubernetes-basics/deploy-app/deploy-intro.html index 3c3a27afa0617..3411ce8f54d0c 100644 --- a/content/en/docs/tutorials/kubernetes-basics/deploy-app/deploy-intro.html +++ b/content/en/docs/tutorials/kubernetes-basics/deploy-app/deploy-intro.html @@ -153,7 +153,7 @@

          View the app

          export POD_NAME=$(kubectl get pods -o go-template --template '{{range .items}}{{.metadata.name}}{{"\n"}}{{end}}')
          echo Name of the Pod: $POD_NAME

          You can access the Pod through the proxied API, by running:

          -

          curl http://localhost:8001/api/v1/namespaces/default/pods/$POD_NAME/

          +

          curl http://localhost:8001/api/v1/namespaces/default/pods/$POD_NAME:8080/proxy/

          In order for the new Deployment to be accessible without using the proxy, a Service is required which will be explained in Module 4.

          diff --git a/content/en/docs/tutorials/kubernetes-basics/scale/scale-intro.html b/content/en/docs/tutorials/kubernetes-basics/scale/scale-intro.html index 6a15b53c9eab6..04dadeed81637 100644 --- a/content/en/docs/tutorials/kubernetes-basics/scale/scale-intro.html +++ b/content/en/docs/tutorials/kubernetes-basics/scale/scale-intro.html @@ -17,23 +17,19 @@
          -
          -

          Objectives

          -
            -
          • Scale an app using kubectl.
          • -
          -
          -
          + +

          Objectives

          +
            +
          • Scale an app using kubectl.
          • +
          +

          Scaling an application

          Previously we created a Deployment, and then exposed it publicly via a Service. The Deployment created only one Pod for running our application. When traffic increases, we will need to scale the application to keep up with user demand.

          If you haven't worked through the earlier sections, start from Using minikube to create a cluster.

          -

          Scaling is accomplished by changing the number of replicas in a Deployment

          - {{< note >}} -

          If you are trying this after the previous section, you may have deleted the Service exposing the Deployment. In that case, please expose the Deployment again using the following command:

          kubectl expose deployment/kubernetes-bootcamp --type="NodePort" --port 8080

          - {{< /note >}} +

          Scaling is accomplished by changing the number of replicas in a Deployment.

          @@ -47,7 +43,14 @@

          Summary:

          -
          + +
          +
          + {{< note >}} +

          If you are trying this after the previous section, you may have deleted the Service exposing the Deployment. In that case, please expose the Deployment again using the following command:

          kubectl expose deployment/kubernetes-bootcamp --type="NodePort" --port 8080

          + {{< /note >}} +
          +
          diff --git a/content/en/docs/tutorials/kubernetes-basics/update/update-intro.html b/content/en/docs/tutorials/kubernetes-basics/update/update-intro.html index f151f5a8e21fc..28e7681af4027 100644 --- a/content/en/docs/tutorials/kubernetes-basics/update/update-intro.html +++ b/content/en/docs/tutorials/kubernetes-basics/update/update-intro.html @@ -133,7 +133,7 @@

          Update the version of the app

          and look for the Image field:

          kubectl describe pods

          To update the image of the application to version 2, use the set image subcommand, followed by the deployment name and the new image version:

          -

          kubectl set image deployments/kubernetes-bootcamp kubernetes-bootcamp=jocatalin/kubernetes-bootcamp:v2

          +

          kubectl set image deployments/kubernetes-bootcamp kubernetes-bootcamp=docker.io/jocatalin/kubernetes-bootcamp:v2

          The command notified the Deployment to use a different image for your app and initiated a rolling update. Check the status of the new Pods, and view the old one terminating with the get pods subcommand:

          kubectl get pods

          diff --git a/content/en/docs/tutorials/security/apparmor.md b/content/en/docs/tutorials/security/apparmor.md index a98f079a60991..c7c51d92365d1 100644 --- a/content/en/docs/tutorials/security/apparmor.md +++ b/content/en/docs/tutorials/security/apparmor.md @@ -8,10 +8,10 @@ weight: 30 -{{< feature-state for_k8s_version="v1.4" state="beta" >}} +{{< feature-state feature_gate_name="AppArmor" >}} -AppArmor is a Linux kernel security module that supplements the standard Linux user and group based +[AppArmor](https://apparmor.net/) is a Linux kernel security module that supplements the standard Linux user and group based permissions to confine programs to a limited set of resources. AppArmor can be configured for any application to reduce its potential attack surface and provide greater in-depth defense. It is configured through profiles tuned to allow the access needed by a specific program or container, @@ -19,7 +19,7 @@ such as Linux capabilities, network access, file permissions, etc. Each profile *enforcing* mode, which blocks access to disallowed resources, or *complain* mode, which only reports violations. -AppArmor can help you to run a more secure deployment by restricting what containers are allowed to +On Kubernetes, AppArmor can help you to run a more secure deployment by restricting what containers are allowed to do, and/or provide better auditing through system logs. However, it is important to keep in mind that AppArmor is not a silver bullet and can only do so much to protect against exploits in your application code. It is important to provide good, restrictive profiles, and harden your @@ -30,7 +30,7 @@ applications and cluster from other angles as well. ## {{% heading "objectives" %}} -* See an example of how to load a profile on a node +* See an example of how to load a profile on a Node * Learn how to enforce the profile on a Pod * Learn how to check that the profile is loaded * See what happens when a profile is violated @@ -41,23 +41,10 @@ applications and cluster from other angles as well. ## {{% heading "prerequisites" %}} -Make sure: +AppArmor is an optional kernel module and Kubernetes feature, so verify it is supported on your +Nodes before proceeding: -1. Kubernetes version is at least v1.4 -- Kubernetes support for AppArmor was added in - v1.4. Kubernetes components older than v1.4 are not aware of the new AppArmor annotations, and - will **silently ignore** any AppArmor settings that are provided. To ensure that your Pods are - receiving the expected protections, it is important to verify the Kubelet version of your nodes: - - ```shell - kubectl get nodes -o=jsonpath=$'{range .items[*]}{@.metadata.name}: {@.status.nodeInfo.kubeletVersion}\n{end}' - ``` - ``` - gke-test-default-pool-239f5d02-gyn2: v1.4.0 - gke-test-default-pool-239f5d02-x1kf: v1.4.0 - gke-test-default-pool-239f5d02-xwux: v1.4.0 - ``` - -2. AppArmor kernel module is enabled -- For the Linux kernel to enforce an AppArmor profile, the +1. AppArmor kernel module is enabled -- For the Linux kernel to enforce an AppArmor profile, the AppArmor kernel module must be installed and enabled. Several distributions enable the module by default, such as Ubuntu and SUSE, and many others provide optional support. To check whether the module is enabled, check the `/sys/module/apparmor/parameters/enabled` file: @@ -67,24 +54,17 @@ Make sure: Y ``` - If the Kubelet contains AppArmor support (>= v1.4), it will refuse to run a Pod with AppArmor - options if the kernel module is not enabled. - - {{< note >}} - Ubuntu carries many AppArmor patches that have not been merged into the upstream Linux - kernel, including patches that add additional hooks and features. Kubernetes has only been - tested with the upstream version, and does not promise support for other features. - {{< /note >}} + The kubelet verifies that AppArmor is enabled on the host before admitting a pod with AppArmor + explicitly configured. -3. Container runtime supports AppArmor -- Currently all common Kubernetes-supported container - runtimes should support AppArmor, like {{< glossary_tooltip term_id="docker">}}, - {{< glossary_tooltip term_id="cri-o" >}} or {{< glossary_tooltip term_id="containerd" >}}. - Please refer to the corresponding runtime documentation and verify that the cluster fulfills - the requirements to use AppArmor. +3. Container runtime supports AppArmor -- All common Kubernetes-supported container + runtimes should support AppArmor, including {{< glossary_tooltip term_id="containerd" >}} and + {{< glossary_tooltip term_id="cri-o" >}}. Please refer to the corresponding runtime + documentation and verify that the cluster fulfills the requirements to use AppArmor. 4. Profile is loaded -- AppArmor is applied to a Pod by specifying an AppArmor profile that each - container should be run with. If any of the specified profiles is not already loaded in the - kernel, the Kubelet (>= v1.4) will reject the Pod. You can view which profiles are loaded on a + container should be run with. If any of the specified profiles are not loaded in the + kernel, the kubelet will reject the Pod. You can view which profiles are loaded on a node by checking the `/sys/kernel/security/apparmor/profiles` file. For example: ```shell @@ -100,76 +80,52 @@ Make sure: For more details on loading profiles on nodes, see [Setting up nodes with profiles](#setting-up-nodes-with-profiles). -As long as the Kubelet version includes AppArmor support (>= v1.4), the Kubelet will reject a Pod -with AppArmor options if any of the prerequisites are not met. You can also verify AppArmor support -on nodes by checking the node ready condition message (though this is likely to be removed in a -later release): - -```shell -kubectl get nodes -o=jsonpath='{range .items[*]}{@.metadata.name}: {.status.conditions[?(@.reason=="KubeletReady")].message}{"\n"}{end}' -``` -``` -gke-test-default-pool-239f5d02-gyn2: kubelet is posting ready status. AppArmor enabled -gke-test-default-pool-239f5d02-x1kf: kubelet is posting ready status. AppArmor enabled -gke-test-default-pool-239f5d02-xwux: kubelet is posting ready status. AppArmor enabled -``` - - - ## Securing a Pod {{< note >}} -AppArmor is currently in beta, so options are specified as annotations. Once support graduates to -general availability, the annotations will be replaced with first-class fields. +Prior to Kubernetes v1.30, AppArmor was specified through annotations. Use the documentation version +selector to view the documentation with this deprecated API. {{< /note >}} -AppArmor profiles are specified *per-container*. To specify the AppArmor profile to run a Pod -container with, add an annotation to the Pod's metadata: +AppArmor profiles can be specified at the pod level or container level. The container AppArmor +profile takes precedence over the pod profile. ```yaml -container.apparmor.security.beta.kubernetes.io/: +securityContext: + appArmorProfile: + type: ``` -Where `` is the name of the container to apply the profile to, and `` -specifies the profile to apply. The `profile_ref` can be one of: - -* `runtime/default` to apply the runtime's default profile -* `localhost/` to apply the profile loaded on the host with the name `` -* `unconfined` to indicate that no profiles will be loaded +Where `` is one of: -See the [API Reference](#api-reference) for the full details on the annotation and profile name formats. +* `RuntimeDefault` to use the runtime's default profile +* `Localhost` to use a profile loaded on the host (see below) +* `Unconfined` to run without AppArmor -Kubernetes AppArmor enforcement works by first checking that all the prerequisites have been -met, and then forwarding the profile selection to the container runtime for enforcement. If the -prerequisites have not been met, the Pod will be rejected, and will not run. +See the [API Reference](#api-reference) for the full details on the AppArmor profile API. -To verify that the profile was applied, you can look for the AppArmor security option listed in the container created event: +To verify that the profile was applied, you can check that the container's root process is +running with the correct profile by examining its proc attr: ```shell -kubectl get events | grep Created -``` -``` -22s 22s 1 hello-apparmor Pod spec.containers{hello} Normal Created {kubelet e2e-test-stclair-node-pool-31nt} Created container with docker id 269a53b202d3; Security:[seccomp=unconfined apparmor=k8s-apparmor-example-deny-write] +kubectl exec -- cat /proc/1/attr/current ``` -You can also verify directly that the container's root process is running with the correct profile by checking its proc attr: +The output should look something like this: -```shell -kubectl exec -- cat /proc/1/attr/current -``` ``` -k8s-apparmor-example-deny-write (enforce) +cri-containerd.apparmor.d (enforce) ``` ## Example *This example assumes you have already set up a cluster with AppArmor support.* -First, we need to load the profile we want to use onto our nodes. This profile denies all file writes: +First, load the profile you want to use onto your Nodes. This profile blocks all file write operations: -```shell +``` #include profile k8s-apparmor-example-deny-write flags=(attach_disconnected) { @@ -182,16 +138,14 @@ profile k8s-apparmor-example-deny-write flags=(attach_disconnected) { } ``` -Since we don't know where the Pod will be scheduled, we'll need to load the profile on all our -nodes. For this example we'll use SSH to install the profiles, but other approaches are +The profile needs to loaded onto all nodes, since you don't know where the pod will be scheduled. +For this example you can use SSH to install the profiles, but other approaches are discussed in [Setting up nodes with profiles](#setting-up-nodes-with-profiles). ```shell -NODES=( - # The SSH-accessible domain names of your nodes - gke-test-default-pool-239f5d02-gyn2.us-central1-a.my-k8s - gke-test-default-pool-239f5d02-x1kf.us-central1-a.my-k8s - gke-test-default-pool-239f5d02-xwux.us-central1-a.my-k8s) +# This example assumes that node names match host names, and are reachable via SSH. +NODES=($(kubectl get nodes -o name)) + for NODE in ${NODES[*]}; do ssh $NODE 'sudo apparmor_parser -q < @@ -207,38 +161,26 @@ EOF' done ``` -Next, we'll run a simple "Hello AppArmor" pod with the deny-write profile: +Next, run a simple "Hello AppArmor" Pod with the deny-write profile: {{% code_sample file="pods/security/hello-apparmor.yaml" %}} ```shell -kubectl create -f ./hello-apparmor.yaml -``` - -If we look at the pod events, we can see that the Pod container was created with the AppArmor -profile "k8s-apparmor-example-deny-write": - -```shell -kubectl get events | grep hello-apparmor -``` -``` -14s 14s 1 hello-apparmor Pod Normal Scheduled {default-scheduler } Successfully assigned hello-apparmor to gke-test-default-pool-239f5d02-gyn2 -14s 14s 1 hello-apparmor Pod spec.containers{hello} Normal Pulling {kubelet gke-test-default-pool-239f5d02-gyn2} pulling image "busybox" -13s 13s 1 hello-apparmor Pod spec.containers{hello} Normal Pulled {kubelet gke-test-default-pool-239f5d02-gyn2} Successfully pulled image "busybox" -13s 13s 1 hello-apparmor Pod spec.containers{hello} Normal Created {kubelet gke-test-default-pool-239f5d02-gyn2} Created container with docker id 06b6cd1c0989; Security:[seccomp=unconfined apparmor=k8s-apparmor-example-deny-write] -13s 13s 1 hello-apparmor Pod spec.containers{hello} Normal Started {kubelet gke-test-default-pool-239f5d02-gyn2} Started container with docker id 06b6cd1c0989 +kubectl create -f hello-apparmor.yaml ``` -We can verify that the container is actually running with that profile by checking its proc attr: +You can verify that the container is actually running with that profile by checking `/proc/1/attr/current`: ```shell kubectl exec hello-apparmor -- cat /proc/1/attr/current ``` + +The output should be: ``` k8s-apparmor-example-deny-write (enforce) ``` -Finally, we can see what happens if we try to violate the profile by writing to a file: +Finally, you can see what happens if you violate the profile by writing to a file: ```shell kubectl exec hello-apparmor -- touch /tmp/test @@ -248,119 +190,71 @@ touch: /tmp/test: Permission denied error: error executing remote command: command terminated with non-zero exit code: Error executing in Docker Container: 1 ``` -To wrap up, let's look at what happens if we try to specify a profile that hasn't been loaded: +To wrap up, see what happens if you try to specify a profile that hasn't been loaded: ```shell kubectl create -f /dev/stdin < Annotations: container.apparmor.security.beta.kubernetes.io/hello=localhost/k8s-apparmor-example-allow-write Status: Pending -Reason: AppArmor -Message: Pod Cannot enforce AppArmor: profile "k8s-apparmor-example-allow-write" is not loaded -IP: -Controllers: -Containers: - hello: - Container ID: - Image: busybox - Image ID: - Port: - Command: - sh - -c - echo 'Hello AppArmor!' && sleep 1h - State: Waiting - Reason: Blocked - Ready: False - Restart Count: 0 - Environment: - Mounts: - /var/run/secrets/kubernetes.io/serviceaccount from default-token-dnz7v (ro) -Conditions: - Type Status - Initialized True - Ready False - PodScheduled True -Volumes: - default-token-dnz7v: - Type: Secret (a volume populated by a Secret) - SecretName: default-token-dnz7v - Optional: false -QoS Class: BestEffort -Node-Selectors: -Tolerations: +... Events: - FirstSeen LastSeen Count From SubobjectPath Type Reason Message - --------- -------- ----- ---- ------------- -------- ------ ------- - 23s 23s 1 {default-scheduler } Normal Scheduled Successfully assigned hello-apparmor-2 to e2e-test-stclair-node-pool-t1f5 - 23s 23s 1 {kubelet e2e-test-stclair-node-pool-t1f5} Warning AppArmor Cannot enforce AppArmor: profile "k8s-apparmor-example-allow-write" is not loaded + Type Reason Age From Message + ---- ------ ---- ---- ------- + Normal Scheduled 10s default-scheduler Successfully assigned default/hello-apparmor to gke-test-default-pool-239f5d02-x1kf + Normal Pulled 8s kubelet Successfully pulled image "busybox:1.28" in 370.157088ms (370.172701ms including waiting) + Normal Pulling 7s (x2 over 9s) kubelet Pulling image "busybox:1.28" + Warning Failed 7s (x2 over 8s) kubelet Error: failed to get container spec opts: failed to generate apparmor spec opts: apparmor profile not found k8s-apparmor-example-allow-write + Normal Pulled 7s kubelet Successfully pulled image "busybox:1.28" in 90.980331ms (91.005869ms including waiting) ``` -Note the pod status is Pending, with a helpful error message: `Pod Cannot enforce AppArmor: profile -"k8s-apparmor-example-allow-write" is not loaded`. An event was also recorded with the same message. +An Event provides the error message with the reason, the specific wording is runtime-dependent: +``` + Warning Failed 7s (x2 over 8s) kubelet Error: failed to get container spec opts: failed to generate apparmor spec opts: apparmor profile not found +``` ## Administration -### Setting up nodes with profiles +### Setting up Nodes with profiles -Kubernetes does not currently provide any native mechanisms for loading AppArmor profiles onto -nodes. There are lots of ways to set up the profiles though, such as: +Kubernetes {{< skew currentVersion >}} does not provide any built-in mechanisms for loading AppArmor profiles onto +Nodes. Profiles can be loaded through custom infrastructure or tools like the +[Kubernetes Security Profiles Operator](https://github.com/kubernetes-sigs/security-profiles-operator). -* Through a [DaemonSet](/docs/concepts/workloads/controllers/daemonset/) that runs a Pod on each node to - ensure the correct profiles are loaded. An example implementation can be found - [here](https://git.k8s.io/kubernetes/test/images/apparmor-loader). -* At node initialization time, using your node initialization scripts (e.g. Salt, Ansible, etc.) or - image. -* By copying the profiles to each node and loading them through SSH, as demonstrated in the - [Example](#example). - -The scheduler is not aware of which profiles are loaded onto which node, so the full set of profiles -must be loaded onto every node. An alternative approach is to add a node label for each profile (or -class of profiles) on the node, and use a +The scheduler is not aware of which profiles are loaded onto which Node, so the full set of profiles +must be loaded onto every Node. An alternative approach is to add a Node label for each profile (or +class of profiles) on the Node, and use a [node selector](/docs/concepts/scheduling-eviction/assign-pod-node/) to ensure the Pod is run on a -node with the required profile. - -### Disabling AppArmor - -If you do not want AppArmor to be available on your cluster, it can be disabled by a command-line flag: - -``` ---feature-gates=AppArmor=false -``` - -When disabled, any Pod that includes an AppArmor profile will fail validation with a "Forbidden" -error. - -{{}} -Even if the Kubernetes feature is disabled, runtimes may still enforce the default profile. The -option to disable the AppArmor feature will be removed when AppArmor graduates to general -availability (GA). -{{}} +Node with the required profile. ## Authoring Profiles @@ -379,30 +273,31 @@ logs or through `journalctl`. More information is provided in [AppArmor failures](https://gitlab.com/apparmor/apparmor/wikis/AppArmor_Failures). -## API Reference +## Specifying AppArmor confinement + +{{< caution >}} +Prior to Kubernetes v1.30, AppArmor was specified through annotations. Use the documentation version +selector to view the documentation with this deprecated API. +{{< /caution >}} -### Pod Annotation +### AppArmor profile within security context {#appArmorProfile} -Specifying the profile a container will run with: +You can specify the `appArmorProfile` on either a container's `securityContext` or on a Pod's +`securityContext`. If the profile is set at the pod level, it will be used as the default profile +for all containers in the pod (including init, sidecar, and ephemeral containers). If both a pod & container +AppArmor profile are set, the container's profile will be used. -- **key**: `container.apparmor.security.beta.kubernetes.io/` - Where `` matches the name of a container in the Pod. - A separate profile can be specified for each container in the Pod. -- **value**: a profile reference, described below +An AppArmor profile has 2 fields: -### Profile Reference +`type` _(required)_ - indicates which kind of AppArmor profile will be applied. Valid options are: + - `Localhost` - a profile pre-loaded on the node (specified by `localhostProfile`). + - `RuntimeDefault` - the container runtime's default profile. + - `Unconfined` - no AppArmor enforcement. -- `runtime/default`: Refers to the default runtime profile. - - Equivalent to not specifying a profile, except it still - requires AppArmor to be enabled. - - In practice, many container runtimes use the same OCI default profile, defined here: - https://github.com/containers/common/blob/main/pkg/apparmor/apparmor_linux_template.go -- `localhost/`: Refers to a profile loaded on the node (localhost) by name. - - The possible profile names are detailed in the - [core policy reference](https://gitlab.com/apparmor/apparmor/wikis/AppArmor_Core_Policy_Reference#profile-names-and-attachment-specifications). -- `unconfined`: This effectively disables AppArmor on the container. +`localhostProfile` - The name of a profile loaded on the node that should be used. +The profile must be preconfigured on the node to work. +This option must be provided if and only if the `type` is `Localhost`. -Any other profile reference format is invalid. ## {{% heading "whatsnext" %}} diff --git a/content/en/docs/tutorials/stateful-application/basic-stateful-set.md b/content/en/docs/tutorials/stateful-application/basic-stateful-set.md index f74fcf71ffc8a..0ed82662b4c34 100644 --- a/content/en/docs/tutorials/stateful-application/basic-stateful-set.md +++ b/content/en/docs/tutorials/stateful-application/basic-stateful-set.md @@ -68,8 +68,8 @@ After this tutorial, you will be familiar with the following. ## Creating a StatefulSet -Begin by creating a StatefulSet using the example below. It is similar to the -example presented in the +Begin by creating a StatefulSet (and the Service that it relies upon) using +the example below. It is similar to the example presented in the [StatefulSets](/docs/concepts/workloads/controllers/statefulset/) concept. It creates a [headless Service](/docs/concepts/services-networking/service/#headless-services), `nginx`, to publish the IP addresses of Pods in the StatefulSet, `web`. @@ -118,6 +118,8 @@ web 2 1 20s ### Ordered Pod creation +A StatefulSet defaults to creating its Pods in a strict order. + For a StatefulSet with _n_ replicas, when Pods are being deployed, they are created sequentially, ordered from _{0..n-1}_. Examine the output of the `kubectl get` command in the first terminal. Eventually, the output will @@ -144,6 +146,8 @@ Notice that the `web-1` Pod is not launched until the `web-0` Pod is _Running_ (see [Pod Phase](/docs/concepts/workloads/pods/pod-lifecycle/#pod-phase)) and _Ready_ (see `type` in [Pod Conditions](/docs/concepts/workloads/pods/pod-lifecycle/#pod-conditions)). +Later in this tutorial you will practice [parallel startup](#parallel-pod-management). + {{< note >}} To configure the integer ordinal assigned to each Pod in a StatefulSet, see [Start ordinal](/docs/concepts/workloads/controllers/statefulset/#start-ordinal). @@ -300,7 +304,8 @@ Address 1: 10.244.2.8 The Pods' ordinals, hostnames, SRV records, and A record names have not changed, but the IP addresses associated with the Pods may have changed. In the cluster used for this tutorial, they have. This is why it is important not to configure -other applications to connect to Pods in a StatefulSet by IP address. +other applications to connect to Pods in a StatefulSet by the IP address +of a particular Pod (it is OK to connect to Pods by resolving their hostname). #### Discovery for specific Pods in a StatefulSet @@ -317,6 +322,13 @@ liveness and readiness, you can use the SRV records of the Pods ( application will be able to discover the Pods' addresses when they transition to Running and Ready. +If your application wants to find any healthy Pod in a StatefulSet, +and therefore does not need to track each specific Pod, +you could also connect to the IP address of a `type: ClusterIP` Service, +backed by the Pods in that StatefulSet. You can use the same Service that +tracks the StatefulSet (specified in the `serviceName` of the StatefulSet) +or a separate Service that selects the right set of Pods. + ### Writing to stable storage Get the PersistentVolumeClaims for `web-0` and `web-1`: @@ -421,13 +433,18 @@ mounted to the appropriate mount points. ## Scaling a StatefulSet -Scaling a StatefulSet refers to increasing or decreasing the number of replicas. +Scaling a StatefulSet refers to increasing or decreasing the number of replicas +(horizontal scaling). This is accomplished by updating the `replicas` field. You can use either [`kubectl scale`](/docs/reference/generated/kubectl/kubectl-commands/#scale) or [`kubectl patch`](/docs/reference/generated/kubectl/kubectl-commands/#patch) to scale a StatefulSet. ### Scaling up +Scaling up means adding more replicas. +Provided that your app is able to distribute work across the StatefulSet, the new +larger set of Pods can perform more of that work. + In one terminal window, watch the Pods in the StatefulSet: ```shell @@ -481,6 +498,10 @@ subsequent Pod. ### Scaling down +Scaling down means reducing the number of replicas. For example, you +might do this because the level of traffic to a service has decreased, +and at the current scale there are idle resources. + In one terminal, watch the StatefulSet's Pods: ```shell @@ -521,9 +542,9 @@ web-3 1/1 Terminating 0 42s ### Ordered Pod termination -The controller deleted one Pod at a time, in reverse order with respect to its -ordinal index, and it waited for each to be completely shutdown before -deleting the next. +The control plane deleted one Pod at a time, in reverse order with respect +to its ordinal index, and it waited for each Pod to be completely shut down +before deleting the next one. Get the StatefulSet's PersistentVolumeClaims: @@ -541,7 +562,10 @@ www-web-4 Bound pvc-e11bb5f8-b508-11e6-932f-42010a800002 1Gi RWO ``` There are still five PersistentVolumeClaims and five PersistentVolumes. -When exploring a Pod's [stable storage](#writing-to-stable-storage), we saw that the PersistentVolumes mounted to the Pods of a StatefulSet are not deleted when the StatefulSet's Pods are deleted. This is still true when Pod deletion is caused by scaling the StatefulSet down. +When exploring a Pod's [stable storage](#writing-to-stable-storage), you saw that +the PersistentVolumes mounted to the Pods of a StatefulSet are not deleted when the +StatefulSet's Pods are deleted. This is still true when Pod deletion is caused by +scaling the StatefulSet down. ## Updating StatefulSets @@ -1145,16 +1169,35 @@ For some distributed systems, the StatefulSet ordering guarantees are unnecessary and/or undesirable. These systems require only uniqueness and identity. -You can specify a Pod management policy to avoid this strict ordering; -either [`OrderedReady`](/docs/concepts/workloads/controllers/statefulset/#orderedready-pod-management) (the default) -or [`Parallel`](/docs/concepts/workloads/controllers/statefulset/#parallel-pod-management). +You can specify a [Pod management policy](/docs/concepts/workloads/controllers/statefulset/#pod-management-policies) +to avoid this strict ordering; either `OrderedReady` (the default), or `Parallel`. + +### OrderedReady Pod management + +`OrderedReady` pod management is the default for StatefulSets. It tells the +StatefulSet controller to respect the ordering guarantees demonstrated +above. + +Use this when your application requires or expects that changes, such as rolling out a new +version of your application, happen in the strict order of the ordinal (pod number) that the StatefulSet provides. +In other words, if you have Pods `app-0`, `app-1` and `app-2`, Kubernetes will update `app-0` first and check it. +Once the checks are good, Kubernetes updates `app-1` and finally `app-2`. + +If you added two more Pods, Kubernetes would set up `app-3` and wait for that to become healthy before deploying +`app-4`. + +Because this is the default setting, you've already practised using it. ### Parallel Pod management -`Parallel` pod management tells the StatefulSet controller to launch or -terminate all Pods in parallel, and not to wait for Pods to become Running -and Ready or completely terminated prior to launching or terminating another -Pod. This option only affects the behavior for scaling operations. Updates are not affected. +The alternative, `Parallel` pod management, tells the StatefulSet controller to launch or +terminate all Pods in parallel, and not to wait for Pods to become `Running` +and `Ready` or completely terminated prior to launching or terminating another +Pod. + +The `Parallel` pod management option only affects the behavior for scaling operations. Updates are not affected; +Kubernetes still rolls out changes in order. For this tutorial, the application is very simple: a webserver that +tells you its hostname (because this is a StatefulSet, the hostname for each Pod is different and predictable). {{% code_sample file="application/web/web-parallel.yaml" %}} @@ -1168,61 +1211,50 @@ In one terminal, watch the Pods in the StatefulSet. kubectl get pod -l app=nginx --watch ``` -In another terminal, create the StatefulSet and Service in the manifest: +In another terminal, reconfigure the StatefulSet for `Parallel` Pod management: ```shell kubectl apply -f https://k8s.io/examples/application/web/web-parallel.yaml ``` ``` -service/nginx created -statefulset.apps/web created +service/nginx updated +statefulset.apps/web updated ``` -Examine the output of the `kubectl get` command that you executed in the first terminal. - -```shell -# This should already be running -kubectl get pod -l app=nginx --watch -``` -``` -NAME READY STATUS RESTARTS AGE -web-0 0/1 Pending 0 0s -web-0 0/1 Pending 0 0s -web-1 0/1 Pending 0 0s -web-1 0/1 Pending 0 0s -web-0 0/1 ContainerCreating 0 0s -web-1 0/1 ContainerCreating 0 0s -web-0 1/1 Running 0 10s -web-1 1/1 Running 0 10s -``` - -The StatefulSet controller launched both `web-0` and `web-1` at almost the -same time. - -Keep the second terminal open, and, in another terminal window scale the +Keep the terminal open where you're running the watch. In another terminal window, scale the StatefulSet: ```shell -kubectl scale statefulset/web --replicas=4 +kubectl scale statefulset/web --replicas=5 ``` ``` statefulset.apps/web scaled ``` -Examine the output of the terminal where the `kubectl get` command is running. +Examine the output of the terminal where the `kubectl get` command is running. It may look something like ``` web-3 0/1 Pending 0 0s web-3 0/1 Pending 0 0s web-3 0/1 Pending 0 7s web-3 0/1 ContainerCreating 0 7s -web-2 1/1 Running 0 10s +web-2 0/1 Pending 0 0s +web-4 0/1 Pending 0 0s +web-2 1/1 Running 0 8s +web-4 0/1 ContainerCreating 0 4s web-3 1/1 Running 0 26s +web-4 1/1 Running 0 2s ``` -The StatefulSet launched two new Pods, and it did not wait for -the first to become Running and Ready prior to launching the second. +The StatefulSet launched three new Pods, and it did not wait for +the first to become Running and Ready prior to launching the second and third Pods. + +This approach is useful if your workload has a stateful element, or needs Pods to be able to identify each other +with predictable naming, and especially if you sometimes need to provide a lot more capacity quickly. If this +simple web service for the tutorial suddenly got an extra 1,000,000 requests per minute then you would want to run +some more Pods - but you also would not want to wait for each new Pod to launch. Starting the extra Pods in parallel +cuts the time between requesting the extra capacity and having it available for use. ## {{% heading "cleanup" %}} diff --git a/content/en/examples/access/deployment-replicas-policy.yaml b/content/en/examples/access/deployment-replicas-policy.yaml index e12a8a0961fad..d7d11e9a20ced 100644 --- a/content/en/examples/access/deployment-replicas-policy.yaml +++ b/content/en/examples/access/deployment-replicas-policy.yaml @@ -1,4 +1,4 @@ -apiVersion: admissionregistration.k8s.io/v1alpha1 +apiVersion: admissionregistration.k8s.io/v1 kind: ValidatingAdmissionPolicy metadata: name: "deploy-replica-policy.example.com" diff --git a/content/en/examples/access/image-matches-namespace-environment.policy.yaml b/content/en/examples/access/image-matches-namespace-environment.policy.yaml index 1a3da26898608..cf7508d253091 100644 --- a/content/en/examples/access/image-matches-namespace-environment.policy.yaml +++ b/content/en/examples/access/image-matches-namespace-environment.policy.yaml @@ -2,7 +2,7 @@ # Except for "exempt" deployments, or any containers that do not belong to the "example.com" organization (e.g. common sidecars). # For example, if the namespace has a label of {"environment": "staging"}, all container images must be either staging.example.com/* # or do not contain "example.com" at all, unless the deployment has {"exempt": "true"} label. -apiVersion: admissionregistration.k8s.io/v1beta1 +apiVersion: admissionregistration.k8s.io/v1 kind: ValidatingAdmissionPolicy metadata: name: "image-matches-namespace-environment.policy.example.com" diff --git a/content/en/examples/access/validating-admission-policy-audit-annotation.yaml b/content/en/examples/access/validating-admission-policy-audit-annotation.yaml index 5a7a20ac56af4..1c422a825447f 100644 --- a/content/en/examples/access/validating-admission-policy-audit-annotation.yaml +++ b/content/en/examples/access/validating-admission-policy-audit-annotation.yaml @@ -1,4 +1,4 @@ -apiVersion: admissionregistration.k8s.io/v1alpha1 +apiVersion: admissionregistration.k8s.io/v1 kind: ValidatingAdmissionPolicy metadata: name: "demo-policy.example.com" @@ -11,6 +11,8 @@ spec: operations: ["CREATE", "UPDATE"] resources: ["deployments"] validations: - - key: "high-replica-count" - expression: "object.spec.replicas > 50" + - expression: "object.spec.replicas > 50" messageExpression: "'Deployment spec.replicas set to ' + string(object.spec.replicas)" + auditAnnotations: + - key: "high-replica-count" + valueExpression: "'Deployment spec.replicas set to ' + string(object.spec.replicas)" diff --git a/content/en/examples/access/validating-admission-policy-match-conditions.yaml b/content/en/examples/access/validating-admission-policy-match-conditions.yaml index 9a49adf15212c..eafebd2c2c274 100644 --- a/content/en/examples/access/validating-admission-policy-match-conditions.yaml +++ b/content/en/examples/access/validating-admission-policy-match-conditions.yaml @@ -1,4 +1,4 @@ -apiVersion: admissionregistration.k8s.io/v1alpha1 +apiVersion: admissionregistration.k8s.io/v1 kind: ValidatingAdmissionPolicy metadata: name: "demo-policy.example.com" diff --git a/content/en/examples/configmap/immutable-configmap.yaml b/content/en/examples/configmap/immutable-configmap.yaml new file mode 100644 index 0000000000000..032cf424d0332 --- /dev/null +++ b/content/en/examples/configmap/immutable-configmap.yaml @@ -0,0 +1,7 @@ +apiVersion: v1 +data: + company_name: "ACME, Inc." # existing fictional company name +kind: ConfigMap +immutable: true +metadata: + name: company-name-20150801 \ No newline at end of file diff --git a/content/en/examples/configmap/new-immutable-configmap.yaml b/content/en/examples/configmap/new-immutable-configmap.yaml new file mode 100644 index 0000000000000..2ac9c8bc4d0bd --- /dev/null +++ b/content/en/examples/configmap/new-immutable-configmap.yaml @@ -0,0 +1,7 @@ +apiVersion: v1 +data: + company_name: "Fiktivesunternehmen GmbH" # new fictional company name +kind: ConfigMap +immutable: true +metadata: + name: company-name-20240312 \ No newline at end of file diff --git a/content/en/examples/controllers/frontend.yaml b/content/en/examples/controllers/frontend.yaml index b9f31044ec103..30d9590e47d70 100644 --- a/content/en/examples/controllers/frontend.yaml +++ b/content/en/examples/controllers/frontend.yaml @@ -18,4 +18,4 @@ spec: spec: containers: - name: php-redis - image: gcr.io/google_samples/gb-frontend:v3 + image: us-docker.pkg.dev/google-samples/containers/gke/gb-frontend:v5 diff --git a/content/en/examples/controllers/job-success-policy.yaml b/content/en/examples/controllers/job-success-policy.yaml new file mode 100644 index 0000000000000..1f7927b2f34fc --- /dev/null +++ b/content/en/examples/controllers/job-success-policy.yaml @@ -0,0 +1,25 @@ +apiVersion: batch/v1 +kind: Job +spec: + parallelism: 10 + completions: 10 + completionMode: Indexed # Required for the success policy + successPolicy: + rules: + - succeededIndexes: 0,2-3 + succeededCount: 1 + template: + spec: + containers: + - name: main + image: python + command: # Provided that at least one of the Pods with 0, 2, and 3 indexes has succeeded, + # the overall Job is a success. + - python3 + - -c + - | + import os, sys + if os.environ.get("JOB_COMPLETION_INDEX") == "2": + sys.exit(0) + else: + sys.exit(1) diff --git a/content/en/examples/customresourcedefinition/shirt-resource-definition.yaml b/content/en/examples/customresourcedefinition/shirt-resource-definition.yaml new file mode 100644 index 0000000000000..111d0d74896dc --- /dev/null +++ b/content/en/examples/customresourcedefinition/shirt-resource-definition.yaml @@ -0,0 +1,36 @@ +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: shirts.stable.example.com +spec: + group: stable.example.com + scope: Namespaced + names: + plural: shirts + singular: shirt + kind: Shirt + versions: + - name: v1 + served: true + storage: true + schema: + openAPIV3Schema: + type: object + properties: + spec: + type: object + properties: + color: + type: string + size: + type: string + selectableFields: + - jsonPath: .spec.color + - jsonPath: .spec.size + additionalPrinterColumns: + - jsonPath: .spec.color + name: Color + type: string + - jsonPath: .spec.size + name: Size + type: string diff --git a/content/en/examples/customresourcedefinition/shirt-resources.yaml b/content/en/examples/customresourcedefinition/shirt-resources.yaml new file mode 100644 index 0000000000000..8a123333cc715 --- /dev/null +++ b/content/en/examples/customresourcedefinition/shirt-resources.yaml @@ -0,0 +1,24 @@ +--- +apiVersion: stable.example.com/v1 +kind: Shirt +metadata: + name: example1 +spec: + color: blue + size: S +--- +apiVersion: stable.example.com/v1 +kind: Shirt +metadata: + name: example2 +spec: + color: blue + size: M +--- +apiVersion: stable.example.com/v1 +kind: Shirt +metadata: + name: example3 +spec: + color: green + size: M diff --git a/content/en/examples/deployments/deployment-with-configmap-and-sidecar-container.yaml b/content/en/examples/deployments/deployment-with-configmap-and-sidecar-container.yaml new file mode 100644 index 0000000000000..5a25efac3f389 --- /dev/null +++ b/content/en/examples/deployments/deployment-with-configmap-and-sidecar-container.yaml @@ -0,0 +1,42 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: configmap-sidecar-container + labels: + app.kubernetes.io/name: configmap-sidecar-container +spec: + replicas: 3 + selector: + matchLabels: + app.kubernetes.io/name: configmap-sidecar-container + template: + metadata: + labels: + app.kubernetes.io/name: configmap-sidecar-container + spec: + volumes: + - name: shared-data + emptyDir: {} + - name: config-volume + configMap: + name: color + containers: + - name: nginx + image: nginx + volumeMounts: + - name: shared-data + mountPath: /usr/share/nginx/html + initContainers: + - name: alpine + image: alpine:3 + restartPolicy: Always + volumeMounts: + - name: shared-data + mountPath: /pod-data + - name: config-volume + mountPath: /etc/config + command: + - /bin/sh + - -c + - while true; do echo "$(date) My preferred color is $(cat /etc/config/color)" > /pod-data/index.html; + sleep 10; done; diff --git a/content/en/examples/deployments/deployment-with-configmap-as-envvar.yaml b/content/en/examples/deployments/deployment-with-configmap-as-envvar.yaml new file mode 100644 index 0000000000000..8e28b93543c17 --- /dev/null +++ b/content/en/examples/deployments/deployment-with-configmap-as-envvar.yaml @@ -0,0 +1,32 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: configmap-env-var + labels: + app.kubernetes.io/name: configmap-env-var +spec: + replicas: 3 + selector: + matchLabels: + app.kubernetes.io/name: configmap-env-var + template: + metadata: + labels: + app.kubernetes.io/name: configmap-env-var + spec: + containers: + - name: alpine + image: alpine:3 + env: + - name: FRUITS + valueFrom: + configMapKeyRef: + key: fruits + name: fruits + command: + - /bin/sh + - -c + - while true; do echo "$(date) The basket is full of $FRUITS"; + sleep 10; done; + ports: + - containerPort: 80 \ No newline at end of file diff --git a/content/en/examples/deployments/deployment-with-configmap-as-volume.yaml b/content/en/examples/deployments/deployment-with-configmap-as-volume.yaml new file mode 100644 index 0000000000000..260cc8634107d --- /dev/null +++ b/content/en/examples/deployments/deployment-with-configmap-as-volume.yaml @@ -0,0 +1,33 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: configmap-volume + labels: + app.kubernetes.io/name: configmap-volume +spec: + replicas: 3 + selector: + matchLabels: + app.kubernetes.io/name: configmap-volume + template: + metadata: + labels: + app.kubernetes.io/name: configmap-volume + spec: + containers: + - name: alpine + image: alpine:3 + command: + - /bin/sh + - -c + - while true; do echo "$(date) My preferred sport is $(cat /etc/config/sport)"; + sleep 10; done; + ports: + - containerPort: 80 + volumeMounts: + - name: config-volume + mountPath: /etc/config + volumes: + - name: config-volume + configMap: + name: sport \ No newline at end of file diff --git a/content/en/examples/deployments/deployment-with-configmap-two-containers.yaml b/content/en/examples/deployments/deployment-with-configmap-two-containers.yaml new file mode 100644 index 0000000000000..e46e527c603e6 --- /dev/null +++ b/content/en/examples/deployments/deployment-with-configmap-two-containers.yaml @@ -0,0 +1,40 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: configmap-two-containers + labels: + app.kubernetes.io/name: configmap-two-containers +spec: + replicas: 3 + selector: + matchLabels: + app.kubernetes.io/name: configmap-two-containers + template: + metadata: + labels: + app.kubernetes.io/name: configmap-two-containers + spec: + volumes: + - name: shared-data + emptyDir: {} + - name: config-volume + configMap: + name: color + containers: + - name: nginx + image: nginx + volumeMounts: + - name: shared-data + mountPath: /usr/share/nginx/html + - name: alpine + image: alpine:3 + volumeMounts: + - name: shared-data + mountPath: /pod-data + - name: config-volume + mountPath: /etc/config + command: + - /bin/sh + - -c + - while true; do echo "$(date) My preferred color is $(cat /etc/config/color)" > /pod-data/index.html; + sleep 10; done; diff --git a/content/en/examples/deployments/deployment-with-immutable-configmap-as-volume.yaml b/content/en/examples/deployments/deployment-with-immutable-configmap-as-volume.yaml new file mode 100644 index 0000000000000..d536acf675e44 --- /dev/null +++ b/content/en/examples/deployments/deployment-with-immutable-configmap-as-volume.yaml @@ -0,0 +1,33 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: immutable-configmap-volume + labels: + app.kubernetes.io/name: immutable-configmap-volume +spec: + replicas: 3 + selector: + matchLabels: + app.kubernetes.io/name: immutable-configmap-volume + template: + metadata: + labels: + app.kubernetes.io/name: immutable-configmap-volume + spec: + containers: + - name: alpine + image: alpine:3 + command: + - /bin/sh + - -c + - while true; do echo "$(date) The name of the company is $(cat /etc/config/company_name)"; + sleep 10; done; + ports: + - containerPort: 80 + volumeMounts: + - name: config-volume + mountPath: /etc/config + volumes: + - name: config-volume + configMap: + name: company-name-20150801 \ No newline at end of file diff --git a/content/en/examples/examples_test.go b/content/en/examples/examples_test.go index a3a51e0c5596c..f0d4a13bbd419 100644 --- a/content/en/examples/examples_test.go +++ b/content/en/examples/examples_test.go @@ -21,7 +21,6 @@ import ( "bytes" "fmt" "io" - "io/ioutil" "os" "path/filepath" "strings" @@ -365,7 +364,7 @@ func walkConfigFiles(inDir string, t *testing.T, fn func(name, path string, data file := filepath.Base(path) if ext := filepath.Ext(file); ext == ".json" || ext == ".yaml" { - data, err := ioutil.ReadFile(path) + data, err := os.ReadFile(path) if err != nil { return err } diff --git a/content/en/examples/pods/probe/http-liveness.yaml b/content/en/examples/pods/probe/http-liveness.yaml index 48ca861c14271..ecc1a6ff2e12e 100644 --- a/content/en/examples/pods/probe/http-liveness.yaml +++ b/content/en/examples/pods/probe/http-liveness.yaml @@ -7,9 +7,9 @@ metadata: spec: containers: - name: liveness - image: registry.k8s.io/liveness + image: registry.k8s.io/e2e-test-images/agnhost:2.40 args: - - /server + - liveness livenessProbe: httpGet: path: /healthz diff --git a/content/en/examples/pods/security/hello-apparmor.yaml b/content/en/examples/pods/security/hello-apparmor.yaml index 000645f1c72c9..a434db1d15bff 100644 --- a/content/en/examples/pods/security/hello-apparmor.yaml +++ b/content/en/examples/pods/security/hello-apparmor.yaml @@ -2,11 +2,11 @@ apiVersion: v1 kind: Pod metadata: name: hello-apparmor - annotations: - # Tell Kubernetes to apply the AppArmor profile "k8s-apparmor-example-deny-write". - # Note that this is ignored if the Kubernetes node is not running version 1.4 or greater. - container.apparmor.security.beta.kubernetes.io/hello: localhost/k8s-apparmor-example-deny-write spec: + securityContext: + appArmorProfile: + type: Localhost + localhostProfile: k8s-apparmor-example-deny-write containers: - name: hello image: busybox:1.28 diff --git a/content/en/examples/pods/security/seccomp/profiles/fine-grained.json b/content/en/examples/pods/security/seccomp/profiles/fine-grained.json index 2eeaf9133e3c2..5b38b68ed41f2 100644 --- a/content/en/examples/pods/security/seccomp/profiles/fine-grained.json +++ b/content/en/examples/pods/security/seccomp/profiles/fine-grained.json @@ -57,7 +57,11 @@ "sendto", "set_tid_address", "setitimer", - "writev" + "writev", + "fstatfs", + "getdents64", + "pipe2", + "getrlimit" ], "action": "SCMP_ACT_ALLOW" } diff --git a/content/en/examples/storage/rro.yaml b/content/en/examples/storage/rro.yaml new file mode 100644 index 0000000000000..1ffc6b038971b --- /dev/null +++ b/content/en/examples/storage/rro.yaml @@ -0,0 +1,28 @@ +apiVersion: v1 +kind: Pod +metadata: + name: rro +spec: + volumes: + - name: mnt + hostPath: + # tmpfs is mounted on /mnt/tmpfs + path: /mnt + containers: + - name: busybox + image: busybox + args: ["sleep", "infinity"] + volumeMounts: + # /mnt-rro/tmpfs is not writable + - name: mnt + mountPath: /mnt-rro + readOnly: true + mountPropagation: None + recursiveReadOnly: Enabled + # /mnt-ro/tmpfs is writable + - name: mnt + mountPath: /mnt-ro + readOnly: true + # /mnt-rw/tmpfs is writable + - name: mnt + mountPath: /mnt-rw diff --git a/content/en/examples/validatingadmissionpolicy/basic-example-binding.yaml b/content/en/examples/validatingadmissionpolicy/basic-example-binding.yaml index 52de1049c253e..9ad4c6a319a05 100644 --- a/content/en/examples/validatingadmissionpolicy/basic-example-binding.yaml +++ b/content/en/examples/validatingadmissionpolicy/basic-example-binding.yaml @@ -1,4 +1,4 @@ -apiVersion: admissionregistration.k8s.io/v1beta1 +apiVersion: admissionregistration.k8s.io/v1 kind: ValidatingAdmissionPolicyBinding metadata: name: "demo-binding-test.example.com" @@ -8,4 +8,4 @@ spec: matchResources: namespaceSelector: matchLabels: - environment: test \ No newline at end of file + environment: test diff --git a/content/en/examples/validatingadmissionpolicy/basic-example-policy.yaml b/content/en/examples/validatingadmissionpolicy/basic-example-policy.yaml index bfdb9ee214184..720839fd480f2 100644 --- a/content/en/examples/validatingadmissionpolicy/basic-example-policy.yaml +++ b/content/en/examples/validatingadmissionpolicy/basic-example-policy.yaml @@ -1,4 +1,4 @@ -apiVersion: admissionregistration.k8s.io/v1beta1 +apiVersion: admissionregistration.k8s.io/v1 kind: ValidatingAdmissionPolicy metadata: name: "demo-policy.example.com" diff --git a/content/en/examples/validatingadmissionpolicy/binding-with-param-prod.yaml b/content/en/examples/validatingadmissionpolicy/binding-with-param-prod.yaml index a2186ee86234c..b0ad21916235f 100644 --- a/content/en/examples/validatingadmissionpolicy/binding-with-param-prod.yaml +++ b/content/en/examples/validatingadmissionpolicy/binding-with-param-prod.yaml @@ -1,4 +1,4 @@ -apiVersion: admissionregistration.k8s.io/v1beta1 +apiVersion: admissionregistration.k8s.io/v1 kind: ValidatingAdmissionPolicyBinding metadata: name: "replicalimit-binding-nontest" diff --git a/content/en/examples/validatingadmissionpolicy/binding-with-param.yaml b/content/en/examples/validatingadmissionpolicy/binding-with-param.yaml index cad7a5b02f4bf..596d21e459f3a 100644 --- a/content/en/examples/validatingadmissionpolicy/binding-with-param.yaml +++ b/content/en/examples/validatingadmissionpolicy/binding-with-param.yaml @@ -1,4 +1,4 @@ -apiVersion: admissionregistration.k8s.io/v1beta1 +apiVersion: admissionregistration.k8s.io/v1 kind: ValidatingAdmissionPolicyBinding metadata: name: "replicalimit-binding-test.example.com" diff --git a/content/en/examples/validatingadmissionpolicy/failure-policy-ignore.yaml b/content/en/examples/validatingadmissionpolicy/failure-policy-ignore.yaml index 53e3990a1ffff..04fbf2ce9d26b 100644 --- a/content/en/examples/validatingadmissionpolicy/failure-policy-ignore.yaml +++ b/content/en/examples/validatingadmissionpolicy/failure-policy-ignore.yaml @@ -1,4 +1,4 @@ -apiVersion: admissionregistration.k8s.io/v1beta1 +apiVersion: admissionregistration.k8s.io/v1 kind: ValidatingAdmissionPolicy spec: ... diff --git a/content/en/examples/validatingadmissionpolicy/policy-with-param.yaml b/content/en/examples/validatingadmissionpolicy/policy-with-param.yaml index c493115987bd4..03977e275d494 100644 --- a/content/en/examples/validatingadmissionpolicy/policy-with-param.yaml +++ b/content/en/examples/validatingadmissionpolicy/policy-with-param.yaml @@ -1,4 +1,4 @@ -apiVersion: admissionregistration.k8s.io/v1beta1 +apiVersion: admissionregistration.k8s.io/v1 kind: ValidatingAdmissionPolicy metadata: name: "replicalimit-policy.example.com" diff --git a/content/en/examples/validatingadmissionpolicy/typechecking-multiple-match.yaml b/content/en/examples/validatingadmissionpolicy/typechecking-multiple-match.yaml index 77a49d192c558..620fea458cae4 100644 --- a/content/en/examples/validatingadmissionpolicy/typechecking-multiple-match.yaml +++ b/content/en/examples/validatingadmissionpolicy/typechecking-multiple-match.yaml @@ -1,4 +1,4 @@ -apiVersion: admissionregistration.k8s.io/v1beta1 +apiVersion: admissionregistration.k8s.io/v1 kind: ValidatingAdmissionPolicy metadata: name: "replica-policy.example.com" diff --git a/content/en/examples/validatingadmissionpolicy/typechecking.yaml b/content/en/examples/validatingadmissionpolicy/typechecking.yaml index f088420811c54..a44fdc30893fb 100644 --- a/content/en/examples/validatingadmissionpolicy/typechecking.yaml +++ b/content/en/examples/validatingadmissionpolicy/typechecking.yaml @@ -1,4 +1,4 @@ -apiVersion: admissionregistration.k8s.io/v1beta1 +apiVersion: admissionregistration.k8s.io/v1 kind: ValidatingAdmissionPolicy metadata: name: "deploy-replica-policy.example.com" @@ -12,4 +12,4 @@ spec: validations: - expression: "object.replicas > 1" # should be "object.spec.replicas > 1" message: "must be replicated" - reason: Invalid \ No newline at end of file + reason: Invalid diff --git a/content/en/includes/partner-style.css b/content/en/includes/partner-style.css deleted file mode 100644 index dc120872e033c..0000000000000 --- a/content/en/includes/partner-style.css +++ /dev/null @@ -1,201 +0,0 @@ -/* SECTIONS */ -.section { - clear: both; - padding: 0px; - margin-bottom: 2em; -} - -.kcsp_section { - clear: both; - padding: 0px; - margin-bottom: 2em; -} - -/* COLUMN SETUP */ -.col { - display: block; - float:left; - margin: 1% 0 1% 1.6%; - background-color: #f9f9f9; -} -.col:first-child { margin-left: 0; } - - -/* GROUPING */ -.group:before, -.group:after { - content:""; - display:table; -} -.group:after { - clear:both; -} -.group { - zoom:1; /* For IE 6/7 */ -} - -/* GRID OF THREE */ -.span_3_of_3 { - width: 35%; - background-color: #f9f9f9; - padding: 20px; -} -.span_2_of_3 { - width: 35%; - background-color: #f9f9f9; - padding: 20px; -} -.span_1_of_3 { - width: 35%; - background-color: #f9f9f9; - padding: 20px; -} - -.col-container { - display: table; /* Make the container element behave like a table */ - width: 100%; /* Set full-width to expand the whole page */ - padding-bottom: 30px; -} - -.col-nav { - display: table-cell; /* Make elements inside the container behave like table cells */ - width: 18%; - background-color: #f9f9f9; - padding: 20px; - border: 5px solid white; -} - -/* GO FULL WIDTH AT LESS THAN 480 PIXELS */ - -@media only screen and (max-width: 480px) { - .col { margin: 1% 0 1% 0%;} - .span_3_of_3, .span_2_of_3, .span_1_of_3 { width: 100%; } -} - -@media only screen and (max-width: 650px) { - .col-nav { - display: block; - width: 100%; - } -} - -.button{ - max-width: 100%; - box-sizing: border-box; - margin: 0; - display: inline-block; - border-radius: 6px; - padding: 0 20px; - line-height: 40px; - color: #ffffff; - font-size: 16px; - background-color: #3371e3; - text-decoration: none; - } - -h5 { - font-size: 16px; - line-height: 1.5em; - margin-bottom: 2em; -} - -#usersGrid a { - display: inline-block; - background-color: #f9f9f9; -} - -#ktpContainer, #distContainer, #kcspContainer, #isvContainer, #servContainer { - position: relative; - width: 100%; - display: flex; - justify-content: space-between; - flex-wrap: wrap; -} - -#isvContainer { - margin-bottom: 80px; -} - -#kcspContainer { - margin-bottom: 80px; -} - -#distContainer { - margin-bottom: 80px; -} - -#ktpContainer { - margin-bottom: 80px; -} - -.partner-box { - position: relative; - width: 47%; - max-width: 48%; - min-width: 48%; - margin-bottom: 20px; - padding: 20px; - flex: 1; - display: flex; - justify-content: left; - align-items: flex-start; -} - -.partner-box img { - background-color: #f9f9f9; -} - -.partner-box > div { - margin-left: 30px; -} - -.partner-box a { - color: #3576E3; -} - -@media screen and (max-width: 1024px) { - .partner-box { - flex-direction: column; - justify-content: flex-start; - } - - .partner-box > div { - margin: 20px 0 0; - } -} - -@media screen and (max-width: 568px) { - #ktpContainer, #distContainter, #kcspContainer, #isvContainer, #servContainer { - justify-content: center; - } - - .partner-box { - flex-direction: column; - justify-content: flex-start; - width: 100%; - max-width: 100%; - min-width: 100%; - } - - .partner-box > div { - margin: 20px 0 0; - } -} - -@media screen and (max-width: 568px) { - #ktpContainer, #distContainer, #kcspContainer, #isvContainer, #servContainer { - justify-content: center; - } - - .partner-box { - flex-direction: column; - justify-content: flex-start; - width: 100%; - max-width: 100%; - min-width: 100%; - } - - .partner-box > div { - margin: 20px 0 0; - } -} diff --git a/content/en/includes/task-tutorial-prereqs-node-upgrade.md b/content/en/includes/task-tutorial-prereqs-node-upgrade.md new file mode 100644 index 0000000000000..2ed717dd1544d --- /dev/null +++ b/content/en/includes/task-tutorial-prereqs-node-upgrade.md @@ -0,0 +1,3 @@ +You need to have shell access to all the nodes, and the kubectl command-line tool must +be configured to communicate with your cluster. It is recommended to run this tutorial +on a cluster with at least two nodes that are not acting as control plane hosts. diff --git a/content/en/partners/_index.html b/content/en/partners/_index.html index 7ce5cd0d14e2d..15b8e800648fa 100644 --- a/content/en/partners/_index.html +++ b/content/en/partners/_index.html @@ -4,13 +4,16 @@ abstract: Growing the Kubernetes ecosystem. class: gridPage cid: partners +body_class: partners +menu: + main: + weight: 40 ---
          Kubernetes works with partners to create a strong, vibrant codebase that supports a spectrum of complementary platforms.
          -
          Kubernetes Certified Service Providers
          @@ -19,10 +22,8 @@


          Interested in becoming a KCSP? -
          -
          Certified Kubernetes Distributions, Hosted Platforms, and Installers
          Software conformance ensures that every vendor’s version of Kubernetes supports the required APIs. @@ -30,10 +31,8 @@


          Interested in becoming Kubernetes Certified? -
          -
          Kubernetes Training Partners
          @@ -42,12 +41,7 @@


          Interested in becoming a KTP? -
          {{< cncf-landscape helpers=true >}} -
          - - \ No newline at end of file + \ No newline at end of file diff --git a/content/en/releases/patch-releases.md b/content/en/releases/patch-releases.md index 10d29c31813f2..82cdaeba49621 100644 --- a/content/en/releases/patch-releases.md +++ b/content/en/releases/patch-releases.md @@ -76,11 +76,7 @@ Timelines may vary with the severity of bug fixes, but for easier planning we will target the following monthly release points. Unplanned, critical releases may also occur in between these. -| Monthly Patch Release | Cherry Pick Deadline | Target date | -| --------------------- | -------------------- | ----------- | -| February 2024 | 2024-02-09 | 2024-02-14 | -| March 2024 | 2024-03-08 | 2024-03-13 | -| April 2024 | 2024-04-12 | 2024-04-17 | +{{< upcoming-releases >}} ## Detailed Release History for Active Branches diff --git a/content/en/training/_index.html b/content/en/training/_index.html index 471dbbc29bc8b..c60d0dcfa0fd7 100644 --- a/content/en/training/_index.html +++ b/content/en/training/_index.html @@ -5,6 +5,10 @@ layout: basic cid: training class: training +body_class: training +menu: + main: + weight: 30 ---
          diff --git a/content/es/OWNERS b/content/es/OWNERS index 71d9254f8b558..2095344d3fbf4 100644 --- a/content/es/OWNERS +++ b/content/es/OWNERS @@ -8,6 +8,14 @@ reviewers: approvers: - sig-docs-es-owners +- sig-docs-website-owners # important due to no_parent_owners option labels: +- area/localization - language/es + +# Disable inheritance so that the localization team don't end up as approvers for all +# languages. +# https://github.com/kubernetes/community/blob/master/communication/website-guidelines.md +options: + no_parent_owners: true diff --git a/content/es/docs/concepts/cluster-administration/addons.md b/content/es/docs/concepts/cluster-administration/addons.md index 85a9ced075a91..4d0488caa887c 100644 --- a/content/es/docs/concepts/cluster-administration/addons.md +++ b/content/es/docs/concepts/cluster-administration/addons.md @@ -74,7 +74,7 @@ En esta página se listan algunos de los complementos disponibles con sus respec Pods y entornos no Kubernetes con visibilidad y supervisión de la seguridad. * [Romana](https://github.com/romana) es una solución de red de capa 3 para las redes de Pods que también son compatibles con la API de [NetworkPolicy](/docs/concepts/services-networking/network-policies/). -* [Weave Net](https://www.weave.works/docs/net/latest/kubernetes/kube-addon/) +* [Weave Net](https://github.com/rajch/weave#using-weave-on-kubernetes) proporciona redes y políticas de red, funciona en ambos lados de una partición de red y no requiere una base de datos externa. diff --git a/content/es/docs/concepts/services-networking/endpoint-slices.md b/content/es/docs/concepts/services-networking/endpoint-slices.md new file mode 100644 index 0000000000000..a47700edf092c --- /dev/null +++ b/content/es/docs/concepts/services-networking/endpoint-slices.md @@ -0,0 +1,192 @@ +--- +reviewers: +- freehan +title: EndpointSlices +content_type: concept +weight: 60 +description: >- + La API de EndpointSlice es el mecanismo que Kubernetes utiliza para permitir que tu Servicio + escale para manejar un gran número de backends, y permite que el clúster actualice tu lista de + + backends saludables eficientemente. +--- + + + +{{< feature-state for_k8s_version="v1.21" state="stable" >}} + +La API de _EndpointSlice_ de Kubernetes proporciona una forma de rastrear los endpoints de red +dentro de un clúster Kubernetes. EndpointSlices ofrece una alternativa más escalable +y extensible a [Endpoints](/docs/concepts/services-networking/service/#endpoints). + + + + +## EndpointSlice API {#recurso-endpointslice} + +En Kubernetes, un EndpointSlice contiene referencias a un conjunto de endpoints de red. El plano de control crea automáticamente EndpointSlices para cualquier Servicio de Kubernetes que tenga especificado un {{< glossary_tooltip text="selector" term_id="selector" >}}. Estos EndpointSlices incluyen referencias a todos los Pods que coinciden con el selector de Servicio. Los EndpointSlices agrupan los endpoints de la red mediante combinaciones únicas de protocolo, número de puerto y nombre de Servicio. + +El nombre de un objeto EndpointSlice debe ser un +[nombre de subdominio DNS](/docs/concepts/overview/working-with-objects/names#dns-subdomain-names) +válido. + +A modo de ejemplo, a continuación se muestra un objeto EndpointSlice de ejemplo, propiedad del Servicio `example` +de Kubernetes. + +```yaml +apiVersion: discovery.k8s.io/v1 +kind: EndpointSlice +metadata: + name: example-abc + labels: + kubernetes.io/service-name: example +addressType: IPv4 +ports: + - name: http + protocol: TCP + port: 80 +endpoints: + - addresses: + - "10.1.2.3" + conditions: + ready: true + hostname: pod-1 + nodeName: node-1 + zone: us-west2-a +``` + +Por defecto, el plano de control crea y gestiona EndpointSlices para que no tengan más de 100 endpoints cada una. Puedes configurar esto con la bandera de funcionalidad +`--max-endpoints-per-slice` +{{< glossary_tooltip text="kube-controller-manager" term_id="kube-controller-manager" >}} +hasta un máximo de 1000. + + +EndpointSlices puede actuar como la fuente de verdad +{{< glossary_tooltip term_id="kube-proxy" text="kube-proxy" >}} sobre cómo enrutar el tráfico interno. + +### Tipos de dirección + +EndpointSlices admite tres tipos de direcciones: + +* IPv4 +* IPv6 +* FQDN (Fully Qualified Domain Name) + +Cada objeto `EndpointSlice` representa un tipo de dirección IP específico. Si tienes un servicio disponible a través de IPv4 e IPv6, habrá al menos dos objetos `EndpointSlice` (uno para IPv4 y otro para IPv6). + +### Condiciones + +La API EndpointSlice almacena condiciones sobre los endpoints que pueden ser útiles para los consumidores. +Las tres condiciones son `ready`, `serving` y `terminating`. + +#### Ready + +`ready` es una condición que corresponde a la condición `Ready` de un Pod. Un Pod en ejecución con la condición `Ready` establecida a `True` debería tener esta condición EndpointSlice también establecida a `true`. Por razones de compatibilidad, `ready` NUNCA es `true` cuando un Pod está terminando. Los consumidores deben referirse a la condición `serving` para inspeccionar la disponibilidad de los Pods que están terminando. La única excepción a esta regla son los servicios con `spec.publishNotReadyAddresses` a `true`. Los endpoints de estos servicios siempre tendrán la condición `ready` a `true`. + +#### Serving + +{{< feature-state for_k8s_version="v1.26" state="stable" >}} + +La condición `serving` es casi idéntica a la condición `ready`. La diferencia es que los consumidores de la API EndpointSlice deben comprobar la condición `serving` si se preocupan por la disponibilidad del pod mientras el pod también está terminando. + +{{< note >}} + +Aunque `serving` es casi idéntico a `ready`, se añadió para evitar romper el significado existente de `ready`. Podría ser inesperado para los clientes existentes si `ready` pudiera ser `true` para los endpoints de terminación, ya que históricamente los endpoints de terminación nunca se incluyeron en la API Endpoints o EndpointSlice para empezar. Por esta razón, `ready` es _siempre_ `false` para los Endpoints que terminan, y se ha añadido una nueva condición `serving` en la v1.20 para que los clientes puedan realizar un seguimiento de la disponibilidad de los pods que terminan independientemente de la semántica existente para `ready`. + +{{< /note >}} + +#### Terminating + +{{< feature-state for_k8s_version="v1.22" state="beta" >}} + +`Terminating` es una condición que indica si un endpoint está terminando. En el caso de los pods, se trata de cualquier pod que tenga establecida una marca de tiempo de borrado. + +### Información sobre topología {#topology} + +Cada endpoint dentro de un EndpointSlice puede contener información topológica relevante. La información de topología incluye la ubicación del endpoint e información sobre el Nodo y la zona correspondientes. Estos están disponibles en los siguientes campos por endpoint en EndpointSlices: + +* `nodeName` - El nombre del Nodo en el que se encuentra este endpoint. +* `zone` - La zona en la que se encuentra este endpoint. + + +{{< note >}} +En la API v1, el endpoint `topology` se eliminó en favor de los campos dedicados `nodeName` y `zone`. + +La configuración de campos de topología arbitrarios en el campo `endpoint` de un recurso `EndpointSlice` ha quedado obsoleta y no se admite en la API v1. En su lugar, la API v1 permite establecer campos individuales `nodeName` y `zone`. Estos campos se traducen automáticamente entre versiones de la API. Por ejemplo, el valor de la clave "topology.kubernetes.io/zone" en el campo `topology` de la API v1beta1 es accesible como campo `zone` en la API v1. +{{< /note >}} + +### Administración + +En la mayoría de los casos, el plano de control (concretamente, el endpoint slice {{< glossary_tooltip text="controller" term_id="controller" >}}) crea y gestiona objetos EndpointSlice. Existe una variedad de otros casos de uso para EndpointSlices, como implementaciones de servicios Mesh, que podrían dar lugar a que otras entidades o controladores gestionen conjuntos adicionales de EndpointSlices. + +Para garantizar que varias entidades puedan gestionar EndpointSlices sin interferir unas con otras, Kubernetes define el parámetro +{{< glossary_tooltip term_id="label" text="label" >}} +`endpointslice.kubernetes.io/managed-by`, que indica la entidad que gestiona un EndpointSlice. +El controlador de endpoint slice establece `endpointslice-controller.k8s.io` como valor para esta etiqueta en todos los EndpointSlices que gestiona. Otras entidades que gestionen EndpointSlices también deben establecer un valor único para esta etiqueta. + +### Propiedad + +En la mayoría de los casos de uso, los EndpointSlices son propiedad del Servicio para el que el objeto EndpointSlices rastree los endpoints. Esta propiedad se indica mediante una referencia de propietario en cada EndpointSlice, así como una etiqueta `kubernetes.io/service-name` que permite búsquedas sencillas de todos los EndpointSlices que pertenecen a un Servicio. + +### Replicación de EndpointSlice + +En algunos casos, las aplicaciones crean recursos Endpoints personalizados. Para garantizar que estas aplicaciones no tengan que escribir simultáneamente en recursos Endpoints y EndpointSlice, el plano de control del clúster refleja la mayoría de los recursos Endpoints en los EndpointSlices correspondientes. + + +El plano de control refleja los recursos de los Endpoints a menos que: +* El recurso Endpoints tenga una etiqueta `endpointslice.kubernetes.io/skip-mirror` con el valor en `true`. +* El recurso Endpoints tenga una anotación `control-plane.alpha.kubernetes.io/leader`. +* El recurso Service correspondiente no exista. +* El recurso Service correspondiente tiene un selector no nulo. + +Los recursos Endpoints individuales pueden traducirse en múltiples EndpointSlices. Esto ocurrirá si un recurso Endpoints tiene +múltiples subconjuntos o incluye endpoints con múltiples familias IP (IPv4 e IPv6). Se reflejará un máximo de 1000 direcciones +por subconjunto en EndpointSlices. + +### Distribución de EndpointSlices + +Cada EndpointSlice tiene un conjunto de puertos que se aplica a todos los endpoints dentro del recurso. Cuando se utilizan puertos con nombre para un Servicio, los Pods pueden terminar con diferentes números de puerto de destino para el mismo puerto con nombre, requiriendo diferentes EndpointSlices. Esto es similar a la lógica detrás de cómo se agrupan los subconjuntos con Endpoints. + +El plano de control intenta llenar los EndpointSlices tanto como sea posible, pero no los reequilibra activamente. La lógica es bastante sencilla: + +1. Iterar a través de los EndpointSlices existentes, eliminar los endpoints que ya no se deseen y actualizar los endpoints coincidentes que hayan cambiado. +2. Recorrer los EndpointSlices que han sido modificados en el primer paso y rellenarlos con los nuevos endpoints necesarios. +3. Si aún quedan nuevos endpoints por añadir, intente encajarlos en un slice que no se haya modificado previamente y/o cree otros nuevos. + +Es importante destacar que el tercer paso prioriza limitar las actualizaciones de EndpointSlice sobre una distribución perfectamente completa de EndpointSlices. Por ejemplo, si hay 10 nuevos endpoints que añadir y 2 EndpointSlices con espacio para 5 endpoints más cada uno, este enfoque creará un nuevo EndpointSlice en lugar de llenar los 2 EndpointSlices existentes. En otras palabras, es preferible una única creación de EndpointSlice que múltiples actualizaciones de EndpointSlice. + +Con kube-proxy ejecutándose en cada Nodo y vigilando los EndpointSlices, cada cambio en un EndpointSlice se vuelve relativamente caro ya que será transmitido a cada Nodo del clúster. Este enfoque pretende limitar el número de cambios que necesitan ser enviados a cada Nodo, incluso si puede resultar con múltiples EndpointSlices que no están llenos. + + +En la práctica, esta distribución menos que ideal debería ser poco frecuente. La mayoría de los cambios procesados por el controlador EndpointSlice serán lo suficientemente pequeños como para caber en un EndpointSlice existente, y si no, es probable que pronto sea necesario un nuevo EndpointSlice de todos modos. Las actualizaciones continuas de los Deployments también proporcionan un reempaquetado natural de los EndpointSlices con todos los Pods y sus correspondientes endpoints siendo reemplazados. + + +### Endpoints duplicados + +Debido a la naturaleza de los cambios de EndpointSlice, los endpoints pueden estar representados en más de un EndpointSlice al mismo tiempo. Esto ocurre de forma natural, ya que los cambios en diferentes objetos EndpointSlice pueden llegar a la vigilancia / caché del cliente de Kubernetes en diferentes momentos. + +{{< note >}} +Los clientes de la API EndpointSlice deben iterar a través de todos los EndpointSlices existentes asociados a un Servicio y construir una lista completa de endpoints de red únicos. Es importante mencionar que los endpoints pueden estar duplicados en diferentes EndpointSlices. + +Puedes encontrar una implementación de referencia sobre cómo realizar esta agregación y deduplicación de endpoints como parte del código `EndpointSliceCache` dentro de `kube-proxy`. +{{< /note >}} + +## Comparación con endpoints {#motivación} + +La API Endpoints original proporcionaba una forma simple y directa de rastrear los endpoints de red en Kubernetes. A medida que los clústeres de Kubernetes y los {{< glossary_tooltip text="Services" term_id="service" >}} crecían para manejar más tráfico y enviar más tráfico a más Pods backend, las limitaciones de la API original se hicieron más visibles. +Más notablemente, estos incluyen desafíos con la ampliación a un mayor número de endpoints de red. + +Dado que todos los endpoints de red para un Servicio se almacenaban en un único objeto Endpoint, esos objetos Endpoints podían llegar a ser bastante grandes. Para los Services que permanecían estables (el mismo conjunto de endpoints durante un largo período de tiempo), el impacto era menos notable; incluso entonces, algunos casos de uso de Kubernetes no estaban bien servidos. + + +Cuando un Service tenía muchos Endpoints de backend y la carga de trabajo se escalaba con frecuencia o se introducían nuevos cambios con frecuencia, cada actualización del objeto Endpoint para ese Service suponía mucho tráfico entre los componentes del clúster de Kubernetes (dentro del plano de control y también entre los nodos y el servidor de API). Este tráfico adicional también tenía un coste en términos de uso de la CPU. + +Con EndpointSlices, la adición o eliminación de un único Pod desencadena el mismo _número_ de actualizaciones a los clientes que están pendientes de los cambios, pero el tamaño de esos mensajes de actualización es mucho menor a gran escala. + +EndpointSlices también ha permitido innovar en torno a nuevas funciones, como las redes de doble pila y el enrutamiento con conocimiento de la topología. + +## {{% heading "whatsnext" %}} + +* Sigue las instrucciones del tutorial [Conexión de aplicaciones con servicios](/docs/tutorials/services/connect-applications-service/) +* Lee la [Referencia API](/docs/reference/kubernetes-api/service-resources/endpoint-slice-v1/) para la API EndpointSlice +* Lee la [Referencia API](/docs/reference/kubernetes-api/service-resources/endpoints-v1/) para la API Endpoints diff --git a/content/es/docs/concepts/services-networking/ingress-controllers.md b/content/es/docs/concepts/services-networking/ingress-controllers.md new file mode 100644 index 0000000000000..e179cfbf34994 --- /dev/null +++ b/content/es/docs/concepts/services-networking/ingress-controllers.md @@ -0,0 +1,87 @@ +--- +title: Controladores Ingress +description: >- + Para que un [Ingress](/docs/concepts/services-networking/ingress/) funcione en tu clúster, + debe haber un _ingress controller_ en ejecución. + Debes seleccionar al menos un controlador Ingress y asegurarte de que está configurado en tu clúster. + En esta página se enumeran los controladores Ingress más comunes que se pueden implementar. +content_type: concept +weight: 50 +--- + + +Para que el recurso Ingress funcione, el clúster necesita tener un controlador Ingress corriendo. + +Mientras otro tipo de controladores que corren como parte del binario de `kube-controller-manager`, los controladores Ingress no son automaticamente iniciados dentro del clúster. Usa esta página para elegir la mejor implementación de controlador Ingress que funcione mejor para tu clúster. + +Kubernetes es un proyecto que soporta y mantiene los controladores Ingress de [AWS](https://github.com/kubernetes-sigs/aws-load-balancer-controller#readme), [GCE](https://git.k8s.io/ingress-gce/README.md#readme) y + [nginx](https://git.k8s.io/ingress-nginx/README.md#readme). + + + +## Controladores adicionales + +{{% thirdparty-content %}} + +* [AKS Application Gateway Ingress Controller](https://docs.microsoft.com/azure/application-gateway/tutorial-ingress-controller-add-on-existing?toc=https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fazure%2Faks%2Ftoc.json&bc=https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fazure%2Fbread%2Ftoc.json) es un controlador Ingress que controla la configuración de [Azure Application Gateway](https://docs.microsoft.com/azure/application-gateway/overview). +* [Alibaba Cloud MSE Ingress](https://www.alibabacloud.com/help/en/mse/user-guide/overview-of-mse-ingress-gateways) es un controlador Ingress que controla la configuración de [Alibaba Cloud Native Gateway](https://www.alibabacloud.com/help/en/mse/product-overview/cloud-native-gateway-overview?spm=a2c63.p38356.0.0.20563003HJK9is), el cual es una versión comercial de [Higress](https://github.com/alibaba/higress). +* [Apache APISIX ingress controller](https://github.com/apache/apisix-ingress-controller) es un [Apache APISIX](https://github.com/apache/apisix)-basado en un controlador Ingress. +* [Avi Kubernetes Operator](https://github.com/vmware/load-balancer-and-ingress-services-for-kubernetes) provee un balanceador de cargas L4-L7 usando [VMware NSX Advanced Load Balancer](https://avinetworks.com/). +* [BFE Ingress Controller](https://github.com/bfenetworks/ingress-bfe) es un controlador Ingress basado en [BFE](https://www.bfe-networks.net). +* [Cilium Ingress Controller](https://docs.cilium.io/en/stable/network/servicemesh/ingress/) es un controlador Ingress potenciado por [Cilium](https://cilium.io/). +* El [Citrix ingress controller](https://github.com/citrix/citrix-k8s-ingress-controller#readme) funciona con Citrix Application Delivery Controller. +* [Contour](https://projectcontour.io/) es un controlador Ingress basado en [Envoy](https://www.envoyproxy.io/). +* [Emissary-Ingress](https://www.getambassador.io/products/api-gateway) es un API Gateway [Envoy](https://www.envoyproxy.io)-basado en el controlador Ingress. +* [EnRoute](https://getenroute.io/) es un API Gateway basado en [Envoy](https://www.envoyproxy.io) que puede correr como un controlador Ingress. +* [Easegress IngressController](https://github.com/megaease/easegress/blob/main/doc/reference/ingresscontroller.md) es una API Gateway basada en [Easegress](https://megaease.com/easegress/) que puede correr como un controlador Ingress. +* F5 BIG-IP [Container Ingress Services for Kubernetes](https://clouddocs.f5.com/containers/latest/userguide/kubernetes/) + te permite usar un Ingress para configurar los servidores virtuales de F5 BIG-IP. +* [FortiADC Ingress Controller](https://docs.fortinet.com/document/fortiadc/7.0.0/fortiadc-ingress-controller/742835/fortiadc-ingress-controller-overview) soporta el recurso de Kubernetes Ingress y te permite manejar los objectos FortiADC desde Kubernetes. +* [Gloo](https://gloo.solo.io) es un controlador Ingress de código abierto basado en [Envoy](https://www.envoyproxy.io), + el cual ofrece la funcionalidad de API gateway. +* [HAProxy Ingress](https://haproxy-ingress.github.io/) es un controlador Ingress para + [HAProxy](https://www.haproxy.org/#desc). +* [Higress](https://github.com/alibaba/higress) es una API Gateway basada en [Envoy](https://www.envoyproxy.io) que puede funcionar como un controlador Ingress. +* El [HAProxy Ingress Controller for Kubernetes](https://github.com/haproxytech/kubernetes-ingress#readme) + es también un controlador Ingress para [HAProxy](https://www.haproxy.org/#desc). +* [Istio Ingress](https://istio.io/latest/docs/tasks/traffic-management/ingress/kubernetes-ingress/) + es un controlador Ingress basado en [Istio](https://istio.io/). +* El [Kong Ingress Controller for Kubernetes](https://github.com/Kong/kubernetes-ingress-controller#readme) + es un controlador Ingress que controla [Kong Gateway](https://konghq.com/kong/). +* [Kusk Gateway](https://kusk.kubeshop.io/) es un controlador Ingress OpenAPI-driven basado en [Envoy](https://www.envoyproxy.io). +* El [NGINX Ingress Controller for Kubernetes](https://www.nginx.com/products/nginx-ingress-controller/) + trabaja con el servidor web (como un proxy) [NGINX](https://www.nginx.com/resources/glossary/nginx/). +* El [ngrok Kubernetes Ingress Controller](https://github.com/ngrok/kubernetes-ingress-controller) es un controlador de código abierto para añadir acceso público seguro a sus servicios K8s utilizando la [plataforma ngrok](https://ngrok.com). +* El [OCI Native Ingress Controller](https://github.com/oracle/oci-native-ingress-controller#readme) es un controlador Ingress para Oracle Cloud Infrastructure el cual te permite manejar el [balanceador de cargas OCI](https://docs.oracle.com/en-us/iaas/Content/Balance/home.htm). +* El [Pomerium Ingress Controller](https://www.pomerium.com/docs/k8s/ingress.html) esta basado en [Pomerium](https://pomerium.com/), que ofrece una política de acceso sensible al contexto. +* [Skipper](https://opensource.zalando.com/skipper/kubernetes/ingress-controller/) es un enrutador HTTP y proxy inverso para la composición de servicios, incluyendo casos de uso como Kubernetes Ingress, diseñado como una biblioteca para construir su proxy personalizado. +* El [Traefik Kubernetes Ingress provider](https://doc.traefik.io/traefik/providers/kubernetes-ingress/) es un controlador Ingress para el [Traefik](https://traefik.io/traefik/) proxy. +* El [Tyk Operator](https://github.com/TykTechnologies/tyk-operator) amplía Ingress con recursos personalizados para aportar capacidades de gestión de API a Ingress. Tyk Operator funciona con el plano de control de código abierto Tyk Gateway y Tyk Cloud. +* [Voyager](https://voyagermesh.com) es un controlador Ingress para + [HAProxy](https://www.haproxy.org/#desc). +* [Wallarm Ingress Controller](https://www.wallarm.com/solutions/waf-for-kubernetes) es un controlador Ingress que proporciona capacidades de seguridad WAAP (WAF) y API. + +## Uso de varios controladores Ingress + +Puedes desplegar cualquier número de controladores Ingress utilizando [clase ingress](/docs/concepts/services-networking/ingress/#ingress-class) +dentro de un clúster. Ten en cuenta el `.metadata.name` de tu recurso de clase Ingress. Cuando creas un Ingress, necesitarás ese nombre para especificar el campo `ingressClassName` de su objeto Ingress (consulta [referencia IngressSpec v1](/docs/reference/kubernetes-api/service-resources/ingress-v1/#IngressSpec)). `ingressClassName` sustituye el antiguo [método de anotación](/docs/concepts/services-networking/ingress/#deprecated-annotation). + +Si no especificas una IngressClass para un Ingress, y tu clúster tiene exactamente una IngressClass marcada como predeterminada, Kubernetes [aplica](/docs/concepts/services-networking/ingress/#default-ingress-class) la IngressClass predeterminada del clúster al Ingress. +Se marca una IngressClass como predeterminada estableciendo la [anotación `ingressclass.kubernetes.io/is-default-class`](/docs/reference/labels-annotations-taints/#ingressclass-kubernetes-io-is-default-class) en esa IngressClass, con el valor de cadena `"true"`. + + +Lo ideal sería que todos los controladores Ingress cumplieran esta especificación, pero los distintos controladores Ingress funcionan de forma ligeramente diferente. + +{{< note >}} +Asegúrate de revisar la documentación de tu controlador Ingress para entender las advertencias de tu elección. +{{< /note >}} + + + +## {{% heading "whatsnext" %}} + + +* Más información [Ingress](/docs/concepts/services-networking/ingress/). +* [Configurar Ingress en Minikube con el controlador NGINX](/docs/tasks/access-application-cluster/ingress-minikube). + + diff --git a/content/es/docs/concepts/services-networking/ingress.md b/content/es/docs/concepts/services-networking/ingress.md new file mode 100644 index 0000000000000..6efefadba0247 --- /dev/null +++ b/content/es/docs/concepts/services-networking/ingress.md @@ -0,0 +1,748 @@ +--- +reviewers: + - raelga +title: Ingress +content_type: concept +description: >- + Permite que sean accesibles los servicios de red HTTP (o HTTPS) usando un mecanismo de configuración consciente del protocolo, que entiende conceptos como URIs, nombres de host, rutas y más. + El concepto de Ingress te permite mapear el tráfico a diferentes backend basado en las reglas que defines a través de la API de Kubernetes. +weight: 30 +--- + + +{{< feature-state for_k8s_version="v1.19" state="stable" >}} +{{< glossary_definition term_id="ingress" length="all" >}} + +{{< note >}} +El recurso Ingress está congelado. +Las nuevas características se añaden +al [API del Gateway](/docs/concepts/services-networking/gateway/) +{{< /note >}} + + + +## Terminología + +Para mayor claridad, esta guía define los siguientes términos: + +* Nodo: Una máquina worker en Kubernetes, parte de un clúster. +* Clúster: Un conjunto de Nodos que ejecutan aplicaciones en contenedores, + administrados por Kubernetes. + Para este ejemplo, y para los despliegues más comunes de Kubernetes, los nodos + en el clúster no son parte del internet público. +* Enrutador Edge: un enrutador que refuerza la política de seguridad del + cortafuegos para tu clúster. + Esto podría ser una puerta de entrada administrada por un proveedor de la nube + o una pieza física de hardware. +* Red del clúster: un conjunto de enlaces, lógicos o físicos, + que facilitan la comunicación dentro de un clúster de acuerdo con + el [modelo de redes](/docs/concepts/cluster-administration/networking/) de + Kubernetes. +* Service: Un {{< glossary_tooltip term_id="service" >}} que identifica + un conjunto de Pods que utilizan selectores de {{< glossary_tooltip text="label" term_id="label" >}}. + A menos que se indique de otra manera, los Services se asumen que tienen IPs + virtuales que solo se pueden enrutar dentro de la red del clúster. + +## ¿Qué es un Ingress? + +Un [Ingress](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#ingress-v1-networking-k8s-io) +expone rutas HTTP y HTTPS desde el exterior del clúster a los +{{< link text="servicios" url="es/docs/concepts/services-networking/service/" >}} dentro del clúster. +El control del tráfico es controlado por las reglas definidas en el recurso Ingress. + +Aquí tienes un ejemplo simple de un Ingress que envía todo su tráfico a un +Service: + +{{< figure src="/docs/images/ingress.svg" alt="ingress-diagram" class="diagram-large" caption="Figure. Ingress" link="https://mermaid.live/edit#pako:eNqNkstuwyAQRX8F4U0r2VHqPlSRKqt0UamLqlnaWWAYJygYLB59KMm_Fxcix-qmGwbuXA7DwAEzzQETXKutof0Ovb4vaoUQkwKUu6pi3FwXM_QSHGBt0VFFt8DRU2OWSGrKUUMlVQwMmhVLEV1Vcm9-aUksiuXRaO_CEhkv4WjBfAgG1TrGaLa-iaUw6a0DcwGI-WgOsF7zm-pN881fvRx1UDzeiFq7ghb1kgqFWiElyTjnuXVG74FkbdumefEpuNuRu_4rZ1pqQ7L5fL6YQPaPNiFuywcG9_-ihNyUkm6YSONWkjVNM8WUIyaeOJLO3clTB_KhL8NQDmVe-OJjxgZM5FhFiiFTK5zjDkxHBQ9_4zB4a-x20EGNSZhyaKmXrg7f5hSsvufUwTMXThtMWiot5Jh6p9ffimHijIezaSVoeN0uiqcfMJvf7w" >}} + +Un Ingress se puede configurar para otorgar URLs a los Services que son +accesibles desde el exterior, +para hacer balance de cargas del tráfico, finalizar SSL/TLS y ofrecer +alojamiento virtual basado en nombres. + +Un [controlador de Ingress](/docs/concepts/services-networking/ingress-controllers) +es responsable de complementar el Ingress, +comúnmente con un balanceador de cargas, +aunque también puedes configurar tu enrutador edge con frontends adicionales para +ayudar a manejar el tráfico. + +Un Ingress no expone puertos o protocolos arbitrariamente. Exponer servicios +distintos de HTTP o HTTPS al internet usa un servicio de +tipo [Service.Type=NodePort](/es/docs/concepts/services-networking/service/#tipo-nodeport) +o [Service.Type=LoadBalancer](/es/docs/concepts/services-networking/service/#loadbalancer). + +## Prerrequisitos + +Debes tener +un [controlador de Ingress](/docs/concepts/services-networking/ingress-controllers) +para satisfacer a un Ingress. +Crear únicamente un recurso Ingress no tiene ningún efecto. + +Puede que necesites desplegar un controlador Ingress controller tal como +el [ingress-nginx](https://kubernetes.github.io/ingress-nginx/deploy/). +Puedes elegir de un número +de [controladores de Ingress](/docs/concepts/services-networking/ingress-controllers). + +Idealmente, +todos los controladores de Ingress deberían encajar con la especificación de +referencia. +En realidad, los distintos controladores de Ingress operan ligeramente +diferente. + +{{< note >}} +Asegúrate de revisar la documentación del controlador de Ingress para entender +las precauciones de usarlo. +{{< /note >}} + +## El recurso Ingress + +Un ejemplo mínimo de un recurso Ingress: + +{{% code_sample file="service/networking/minimal-ingress.yaml" %}} + +Un Ingress necesita los campos `apiVersion`, `kind`, `metadata` y `spec`. +El nombre del objeto Ingress debe ser un +[nombre de subdominio DNS](es/docs/concepts/overview/working-with-objects/names#dns-subdomain-names) +válido. +Para información general sobre cómo trabajar con archivos de configuración, +mira [desplegando aplicaciones](/es/docs/tasks/run-application/run-stateless-application-deployment/), +[configurando contenedores](/docs/tasks/configure-pod-container/configure-pod-configmap/), +[administrando recursos](/docs/concepts/cluster-administration/manage-deployment/). + +Los Ingress usan anotaciones frecuentemente para configurar algunas opciones +dependiendo del controlador de Ingress, +un ejemplo de ello es +la [anotación rewrite-target](https://github.com/kubernetes/ingress-nginx/blob/main/docs/examples/rewrite/README.md). +Distintos [controladores de Ingress](/docs/concepts/services-networking/ingress-controllers) +soportan anotaciones diferentes. +Revisa la documentación para tu elección del controlador de Ingress para saber +qué anotaciones son soportadas. + +La [especificación Ingress](/docs/reference/kubernetes-api/service-resources/ingress-v1/#IngressSpec) +tiene toda la información que necesitas para configurar un balanceador de cargas +o un servidor proxy. +Mucho más importante, contiene un listado de reglas que emparejan contra todas +las peticiones entrantes. +El recurso Ingress solo soporta reglas para dirigir el tráfico HTTP(S). + +Si se omite la `ingressClassName`, se define +una [clase Ingress por defecto](#default-ingress-class). + +Existen algunos controladores de Ingress, +que trabajan sin la definición de una `IngressClass` por defecto. +Por ejemplo, el controlador Ingress-NGINX se puede configurar con +una [opción](https://kubernetes.github.io/ingress-nginx/user-guide/k8s-122-migration/#what-is-the-flag-watch-ingress-without-class) +`--watch-ingress-without-class`. +Sin embargo, +se [recomienda](https://kubernetes.github.io/ingress-nginx/user-guide/k8s-122-migration/#i-have-only-one-ingress-controller-in-my-cluster-what-should-i-do) +especificar el `IngressClass` por defecto como se +muestra [abajo](#default-ingress-class). + +### Reglas del Ingress + +Cada regla HTTP contiene la siguiente información: + +* Un host opcional. + En este ejemplo, + no se define un host así que la regla se aplica a todo el tráfico de + entrada HTTP a través de la dirección IP especificada. + Cuando se proporciona un host (por ejemplo, foo.bar.com), las reglas se + aplican a ese host. +* Un listado de rutas (por ejemplo, `/testpath`), cada una de las cuales tiene + un backend asociado con un `service.name` y un `service.port.name` o + un `service.port.number`. Tanto el host como la ruta deben coincidir con el + contenido de una petición de entrada antes que el balanceador de cargas dirija + el tráfico al Service referenciado. +* Un backend es una combinación de un Service y un puerto como se describe en la + [documentación del Service](/es/docs/concepts/services-networking/service/) o + un [recurso personalizado backend](#resource-backend) + a través de un {{< glossary_tooltip term_id="CustomResourceDefinition" text=" CRD" >}}. + Las peticiones HTTP (y HTTPS) al Ingress que coinciden con el host y la + ruta de la regla se envían al backend del listado. + +Un `defaultBackend` se configura frecuentemente en un controlador de Ingress +para dar servicio a cualquier petición que no coincide con una ruta en la +especificación. + +### DefaultBackend {#default-backend} + +Un Ingress sin reglas envía todo el tráfico a un único backend +y `.spec.defaultBackend` está en el backend que debería manejar las peticiones +en ese caso. +El `defaultBackend` es una opción de configuración convencional +del [controlador Ingress ](/docs/concepts/services-networking/ingress-controllers) +y no se especifica en tus recursos del Ingress. +Si no se especifican reglas `.spec.rules`, se debe +especificar `.spec.defaultBackend`. +Si no se establece un `defaultBackend`, las peticiones que no coincidan con +ninguna de las reglas las decidirá el controlador ingress (consulta la +documentación de tu controlador de ingress para saber cómo maneja este caso). + +Si ninguno de los hosts o rutas coincide con la petición HTTP en los objetos Ingress, +el tráfico será enrutado a tu backend predeterminado. + +### Resource backends {#resource-backend} + +Un `Resource` backend es una referencia de objeto +(ObjectRef en inglés) +a otro recurso de Kubernetes dentro del mismo espacio de nombres que el objeto +Ingress. +Este `Resource` es mutuamente exclusivo con el Service, +y la validación fallará si ambos se especifican. +Un uso común para un `Resource` backend es para ingresar datos a un backend de almacenamiento de datos con activos estáticos. + +{{% code_sample file="service/networking/ingress-resource-backend.yaml" %}} + +Luego de crear el Ingress mencionado arriba, +puedes verlo con el siguiente comando: + + +```bash +kubectl describe ingress ingress-resource-backend +``` + +``` +Name: ingress-resource-backend +Namespace: default +Address: +Default backend: APIGroup: k8s.example.com, Kind: StorageBucket, Name: static-assets +Rules: + Host Path Backends + ---- ---- -------- + * + /icons APIGroup: k8s.example.com, Kind: StorageBucket, Name: icon-assets +Annotations: +Events: +``` + +### Tipos de ruta + +Se requiere que cada ruta de un Ingress tenga un tipo de ruta correspondiente. +Las Rutas que no incluyen un `pathType` explícito fallarán la validación. +Hay 3 tipos de rutas soportadas: + +* `ImplementationSpecific`: Con este tipo de ruta, la coincidencia depende de la + IngressClass. + Las implementaciones pueden tratar esto como un `pathType` separado o + tratarlas de forma idéntica a los tipos de ruta `Prefix` o `Exact`. + +* `Exact`: Coincide la ruta de la URL exactamente con sensibilidad a mayúsculas + y minúsculas. + +* `Prefix`: Coincide basado en el prefijo de una ruta URL dividida por `/`. + La coincidencia es sensible a mayúsculas y minúsculas, y hecha en un elemento + de la ruta por elemento. + Un elemento de la ruta refiere a la lista de etiquetas en la ruta dividida por + el separador `/`. + Una petición es una coincidencia para la ruta _p_ si cada _p_ es un elemento + prefijo de _p_ de la ruta requerida. + +{{< note >}} +Si el último elemento de una ruta es una subcadena de caracteres del último +elemento de la solicitud de ruta, no es una coincidencia +(por ejemplo: `/foo/bar` +coincide con `/foo/bar/baz`, pero no coincide con `/foo/barbaz`). +{{< /note >}} + +### Ejemplos + +| Tipo | Ruta(s) | Ruta de la(s) peticion(es) | ¿Coincide? | +|----------|-----------------------------------|----------------------------|----------------------------------------| +| Prefijo | `/` | (todas las rutas) | Sí | +| Exacto | `/foo` | `/foo` | Si | +| Exacto | `/foo` | `/bar` | No | +| Exacto | `/foo` | `/foo/` | No | +| Exacto | `/foo/` | `/foo` | No | +| Prefijo | `/foo` | `/foo`, `/foo/` | Si | +| Prefijo | `/foo/` | `/foo`, `/foo/` | Si | +| Prefijo | `/aaa/bb` | `/aaa/bbb` | No | +| Prefijo | `/aaa/bbb` | `/aaa/bbb` | Si | +| Prefijo | `/aaa/bbb/` | `/aaa/bbb` | Si, ignora la barra diagonal | +| Prefijo | `/aaa/bbb` | `/aaa/bbb/` | Si, coincide con barra diagonal | +| Prefijo | `/aaa/bbb` | `/aaa/bbb/ccc` | Si, coincide con la subruta | +| Prefijo | `/aaa/bbb` | `/aaa/bbbxyz` | No, no coincide con el prefijo de cadena | +| Prefijo | `/`, `/aaa` | `/aaa/ccc` | Si, coincide con el prefijo `/aaa` | +| Prefijo | `/`, `/aaa`, `/aaa/bbb` | `/aaa/bbb` | Si, coincide con el prefijo `/aaa/bbb` | +| Prefijo | `/`, `/aaa`, `/aaa/bbb` | `/ccc` | Si, coincide con el prefijo`/` | +| Prefijo | `/aaa` | `/ccc` | No, usa el backend predeterminado | +| Mezclado | `/foo` (Prefijo), `/foo` (Exacto) | `/foo` | Si, prefiere la coincidencia exacta | + +#### Múltiples coincidencias + +En algunos casos, +muchas rutas dentro de un Ingress coincidirán con una petición. +En esos casos, +la precedencia se le dará al primero con la ruta más larga que coincide. +Si dos rutas todavía coinciden por igual, se le dará precedencia a las rutas con +una coincidencia de ruta exacta sobre las rutas que contienen prefijos. + +## Comodines Hostname + +Los hosts pueden ser coincidencias exactas +(por ejemplo “`foo.bar.com`”) o un comodín (por ejemplo “`*.foo.com`”). +Las coincidencias precisas requieren que el encabezado `host` coincida con el +campo `host`. +Las coincidencias de comodín requieren que el encabezado `host` sea igual al +sufijo de la regla del comodín. + +| Host | Encabezado Host | ¿Coincidencia? | +|-------------|-------------------|-----------------------------------------------------| +| `*.foo.com` | `bar.foo.com` | Coincide basado en el sufijo común | +| `*.foo.com` | `baz.bar.foo.com` | No coincide, el comodín solo cubre una etiqueta DNS | +| `*.foo.com` | `foo.com` | No coincide, el comodín solo cubre una etiqueta DNS | + +{{% code_sample file="service/networking/ingress-wildcard-host.yaml" %}} + +## La Clase Ingress + +Los Ingress pueden ser implementados por distintos controladores, +comúnmente con una configuración distinta. +Cada Ingress debería especificar una clase, +una referencia a un recurso IngressClass que contiene información adicional +incluyendo el nombre del controlador que debería implementar la clase. + +{{% code_sample file="service/networking/external-lb.yaml" %}} + +El campo `.spec.parameters` de un IngressClass te permite hacer referencia a +otro recurso que proporciona la configuración relacionada con esa IngressClass. + +El tipo específico de parámetros a usar depende del controlador de Ingress que +especificas en el campo `spec.controller` de la IngressClass. + +### Alcance de IngressClass + +Dependiendo de tu controlador de ingress, podrías ser capaz de usar parámetros +que se establecen en todo el clúster, o solamente para un namespace. + +{{< tabs name="tabs_ingressclass_parameter_scope" >}} +{{% tab name="Clúster" %}} +El alcance por defecto de los parámetros IngressClass es para todo el clúster. + +Si estableces el campo `spec.parameters` y no estableces el +campo `spec.parameters.scope`, +entonces el IngressClass se refiere al recurso cuyo alcance es todo el clúster. +El atributo `kind` (en combinación con el `apiGroup`) +de los parámetros se refiere a la API con alcance a todo el clúster +(posiblemente un recurso personalizado), y el `name` de los parámetros +identifica al recurso del clúster específico para esa API. + +Por ejemplo: + +```yaml +--- +apiVersion: networking.k8s.io/v1 +kind: IngressClass +metadata: + name: external-lb-1 +spec: + controller: example.com/ingress-controller + parameters: + # Los parámetros para este IngressClass se especifican en un + # ClusterIngressParameter (API group k8s.example.net) llamado + # "external-config-1". Esta definición le indica a Kubernetes + # de buscar por un parámetro de recurso con alcance a todo el clúster. + scope: Cluster + apiGroup: k8s.example.net + kind: ClusterIngressParameter + name: external-config-1 +``` + +{{% /tab %}} +{{% tab name="Namespaced" %}} +{{< feature-state for_k8s_version="v1.23" state="stable" >}} + +Si estableces el campo `spec.parameters` y el `spec.parameters.scope` +al `Namespace`, +entonces el IngressClass se refiere al recurso cuyo alcance es el namespace. +También debes establecer el campo `namespace` dentro de `spec.parameters` con el +Namespace que contiene los parámetros que quieres usar. + +El atributo `kind` (en combinación con `apiGroup`) +de los parámetros se refiere a la API restringida por un Namespace (por ejemplo: +ConfigMap), y el `name` de los parámetros identifica al recurso específico en el +namespace que has especificado en `namespace`. + +Los parámetros con alcance al Namespace ayudan al operador del clúster a delegar +el control sobre la configuración +(por ejemplo, ajustes del balanceador de cargas, definición de una API gateway) +que se usa para una carga de trabajo. +Si utilizas un parámetro con alcance al Namespace entonces: + +- El equipo operador del clúster necesita aprobar los cambios de un equipo + distinto cada vez que se aplica un nuevo cambio a la configuración. +- O el equipo operador del clúster debe definir específicamente estos controles + de acceso, tales como asociaciones de + roles [RBAC](/docs/reference/access-authn-authz/rbac/) y mapeos, que permitan + a la aplicación hacer cambios al recurso de parámetros con alcance al clúster. + +La API de la IngressClass por sí misma siempre tiene alcance al clúster. + +Aquí hay un ejemplo de una IngressClass que hace referencia a parámetros que +están restringidos por un Namespace: + +```yaml +--- +apiVersion: networking.k8s.io/v1 +kind: IngressClass +metadata: + name: external-lb-2 +spec: + controller: example.com/ingress-controller + parameters: + # Los parámetros para esta IngressClass se especifican en un + # IngressParameter (API group k8s.example.com) llamado "external-config", + # que está en el namespace "external-configuration". + scope: Namespace + apiGroup: k8s.example.com + kind: IngressParameter + namespace: external-configuration + name: external-config +``` + +{{% /tab %}} +{{< /tabs >}} + +### Anotación deprecada + +Antes que el recurso IngressClass y el campo `ingressClassName` se añadieran a +Kubernetes +1.18, +las clases Ingress se especificaban con una +anotación `kubernetes.io/ingress.class` en el Ingress. +Esta anotación nunca se definió formalmente, +pero era ampliamente soportada por los controladores de Ingress. + +El nuevo campo `ingressClassName` en los recursos Ingress es un reemplazo para +esa anotación, pero no es un equivalente directo. +Mientras que la anotación se utilizaba generalmente para hacer referencia al +nombre del controlador de Ingress que debería implementar el Ingress, el campo +es una referencia a un recurso IngressClass que contiene configuración adicional +del Ingress, incluyendo el nombre del controlador Ingress. + +### IngressClass por defecto {#default-ingress-class} + +Puedes marcar un ingressClass en particular por defecto para tu clúster. +Establecer la anotación `ingressclass.kubernetes.io/is-default-class` a `true` +en un recurso IngressClass +asegurará que los nuevos Ingress sin un campo `ingressClassName` especificado +sean asignados a esta IngressClass por defecto. + +{{< caution >}} +Si tienes más de una IngressClass marcada por defecto en tu clúster, +el controlador de admisión impide crear objetos que no tienen +un `ingressClassName` especificado. +Puedes resolver esto asegurándote que como máximo 1 IngressClass está marcado +como el predeterminado en tu clúster. +{{< /caution >}} + +Existen algunos controladores de ingress, +que funcionan sin una definición de una `ingressClass`. +Por ejemplo, el controlador Ingress-NGINX se puede configurar con +una [opción](https://kubernetes.github.io/ingress-nginx/#what-is-the-flag-watch-ingress-without-class) +`--watch-ingress-without-class`. +Sin embargo, +se [recomienda](https://kubernetes.github.io/ingress-nginx/#i-have-only-one-instance-of-the-ingresss-nginx-controller-in-my-cluster-what-should-i-do) +especificar el `IngressClass` predeterminado: + +{{% code_sample file="service/networking/default-ingressclass.yaml" %}} + +## Tipos de Ingress + +### Ingress respaldado por un único servicio {#single-service-ingress} + +Hay conceptos existentes de Kubernetes que te permiten exponer un Service +único +(mirar [alternativas](#alternativas)). +También puedes hacerlo con un Ingress especificando un *backend predeterminado* +sin reglas. + +{{% code_sample file="service/networking/test-ingress.yaml" %}} + +Si lo creas usando `kubectl apply -f` podrías mirar el estado del Ingress que +has creado: + +```bash +kubectl get ingress test-ingress +``` + +``` +NAME CLASS HOSTS ADDRESS PORTS AGE +test-ingress external-lb * 203.0.113.123 80 59s +``` + +Donde `203.0.113.123` es la IP asignada por el controlador Ingress para +satisfacer este Ingress. + +{{< note >}} +Los controladores de Ingress y los balanceadores de carga pueden tardar un +minuto o dos en asignar una dirección IP. +Hasta entonces, se podrá ver la dirección marcada como ``. +{{< /note >}} + +### Abanico Simple + +Una configuración de abanico enruta el tráfico de una única dirección IP a más +de un Service, +basado en la URI HTTP solicitada. +Un Ingress te permite tener el número de balanceadores de carga al mínimo. +Por ejemplo, una configuración como: + +{{< figure src="/docs/images/ingressFanOut.svg" alt="ingress-fanout-diagram" class="diagram-large" caption="Figure. Ingress Fan Out" link="https://mermaid.live/edit#pako:eNqNUslOwzAQ_RXLvYCUhMQpUFzUUzkgcUBwbHpw4klr4diR7bCo8O8k2FFbFomLPZq3jP00O1xpDpjijWHtFt09zAuFUCUFKHey8vf6NE7QrdoYsDZumGIb4Oi6NAskNeOoZJKpCgxK4oXwrFVgRyi7nCVXWZKRPMlysv5yD6Q4Xryf1Vq_WzDPooJs9egLNDbolKTpT03JzKgh3zWEztJZ0Niu9L-qZGcdmAMfj4cxvWmreba613z9C0B-AMQD-V_AdA-A4j5QZu0SatRKJhSqhZR0wjmPrDP6CeikrutQxy-Cuy2dtq9RpaU2dJKm6fzI5Glmg0VOLio4_5dLjx27hFSC015KJ2VZHtuQvY2fuHcaE43G0MaCREOow_FV5cMxHZ5-oPX75UM5avuXhXuOI9yAaZjg_aLuBl6B3RYaKDDtSw4166QrcKE-emrXcubghgunDaY1kxYizDqnH99UhakzHYykpWD9hjS--fEJoIELqQ" >}} + +Requeriría un Ingress como este: + +{{% code_sample file="service/networking/simple-fanout-example.yaml" %}} + +Cuando creas el Ingress con `kubectl apply -f`: + +```shell +kubectl describe ingress simple-fanout-example +``` + +``` +Name: simple-fanout-example +Namespace: default +Address: 178.91.123.132 +Default backend: default-http-backend:80 (10.8.2.3:8080) +Rules: + Host Path Backends + ---- ---- -------- + foo.bar.com + /foo service1:4200 (10.8.0.90:4200) + /bar service2:8080 (10.8.0.91:8080) +Events: + Type Reason Age From Message + ---- ------ ---- ---- ------- + Normal ADD 22s loadbalancer-controller default/test +``` + +El controlador de Ingress aprovisiona un balanceador de cargas específico para +la implementación que satisface al Ingress, +mientras los Services (`service1`, `service2`) existan. + +Cuando sea así, +podrás ver la dirección del balanceador de cargas en el campo de dirección. + +{{< note >}} + +Dependiendo +del [controlador de Ingress](/docs/concepts/services-networking/ingress-controllers/) +que uses, puede que necesites crear +un [Service](/es/docs/concepts/services-networking/service/) default-http-backend. +{{< /note >}} + +### Hosting virtual basado en nombre + +Los hostings virtuales basados en el nombre soportan enrutado de tráfico HTTP +a nombres hosts múltiples con la misma dirección IP. + +{{< figure src="/docs/images/ingressNameBased.svg" alt="ingress-namebase-diagram" class="diagram-large" caption="Figure. Ingress Name Based Virtual hosting" link="https://mermaid.live/edit#pako:eNqNkl9PwyAUxb8KYS-atM1Kp05m9qSJJj4Y97jugcLtRqTQAPVPdN_dVlq3qUt8gZt7zvkBN7xjbgRgiteW1Rt0_zjLNUJcSdD-ZBn21WmcoDu9tuBcXDHN1iDQVWHnSBkmUMEU0xwsSuK5DK5l745QejFNLtMkJVmSZmT1Re9NcTz_uDXOU1QakxTMJtxUHw7ss-SQLhehQEODTsdH4l20Q-zFyc84-Y67pghv5apxHuweMuj9eS2_NiJdPhix-kMgvwQShOyYMNkJoEUYM3PuGkpUKyY1KqVSdCSEiJy35gnoqCzLvo5fpPAbOqlfI26UsXQ0Ho9nB5CnqesRGTnncPYvSqsdUvqp9KRdlI6KojjEkB0mnLgjDRONhqENBYm6oXbLV5V1y6S7-l42_LowlIN2uFm_twqOcAW2YlK0H_i9c-bYb6CCHNO2FFCyRvkc53rbWptaMA83QnpjMS2ZchBh1nizeNMcU28bGEzXkrV_pArN7Sc0rBTu" >}} + +El siguiente Ingress le dice al balanceador de cargas de respaldo de enrutar las +peticiones basadas en +el [encabezado del Host ](https://tools.ietf.org/html/rfc7230#section-5.4). + +{{% code_sample file="service/networking/name-virtual-host-ingress.yaml" %}} + +Si creas un recurso Ingress sin ningún host definido en las reglas, +luego cualquier tráfico web a la dirección IP de tu controlador Ingress puede +coincidir sin requerir un host virtual basado en el nombre. + +Por ejemplo, el siguiente Ingress enruta el tráfico solicitado +para `first.bar.com` a `service1`, `second.bar.com` a `service2`, +y cualquier tráfico cuyo encabezado de petición del host no coincida +con `first.bar.com` y `second.bar.com` a `service3`. + +{{% code_sample file="service/networking/name-virtual-host-ingress-no-third-host.yaml" %}} + +### TLS + +Puedes segurizar un Ingress especificando un {{< glossary_tooltip term_id="secret" >}} que contiene una clave privada TLS y un certificado. +El recurso Ingress solo soporta un puerto TLS, +el 443, +y asume la terminación TLS en el punto del ingress +(El tráfico al Service y sus Pods es en texto plano). +Si la sección de configuración TLS especifica hosts diferentes, +se multiplexan en el mismo puerto de acuerdo con el hostname especificado a +través de la extensión TLS SNI (teniendo el cuenta que el controlador de Ingress +soporte SNI). +El secreto TLS debe contener claves llamadas `tls.crt` y `tls.key` que contiene +el certificado y llave privad para usar TLS. +Por ejemplo: + +```yaml +apiVersion: v1 +kind: Secret +metadata: + name: testsecret-tls + namespace: default +data: + tls.crt: base64 encoded cert + tls.key: base64 encoded key +type: kubernetes.io/tls +``` + +Al hacer referencia a este secreto en un Ingress le indica al controlador +Ingress de segurizar el canal desde el cliente al balanceador de cargas usando +TLS. +Necesitas asegurarte que el secreto TLS que has creado viene de un certificado que +contiene un nombre común (CN), también conocido como Nombre de dominio +calificado (FQDN en inglés) +para `https-example.foo.com`. + +{{< note >}} +Ten en cuenta que TLS no funcionará en la regla predeterminada porque los +certificados estarían emitidos para todos los sub-dominios posibles. +Por lo tanto, los `hosts` en la sección `tls` tienen que coincidir +explícitamente con el `host` en la sección `rules`. +{{< /note >}} + +{{% code_sample file="service/networking/tls-example-ingress.yaml" %}} + +{{< note >}} +Hay una diferencia entre las características TLS soportadas por varios +controladores Ingress. +Mira la documentación +en [nginx](https://kubernetes.github.io/ingress-nginx/user-guide/tls/), [GCE](https://git.k8s.io/ingress-gce/README.md#frontend-https), +o cualquier otro controlador Ingress específico de plataforma para entender cómo +funciona el TLS en tu entorno. +{{< /note >}} + +### Balanceo de cargas {#load-balancing} + +Un controlador de Ingress está configurado por defecto con algunos ajustes de +política de balanceo de cargas que aplica a todos los Ingress, como los +algoritmos de balanceo de cargas, esquema de pesos del backend y otros. +Otros conceptos más avanzados de balanceo de cargas (ej., sesiones persistentes, +pesos dinámicos) no están expuestos todavía a través del Ingress. +En su lugar, obtienes estas características a través del balanceador de cargas +usado por un Service. + +Vale la pena apuntar que aunque las revisiones de salud no se exponen +directamente a través del Ingress, existen conceptos paralelos en Kubernetes +tales +como [readiness probes](/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/) +que permiten lograr el mismo resultado final. +Revisa la documentación específica del controlador para conocer cómo manejar estas +revisiones de salud (por ejemplo: +[nginx](https://git.k8s.io/ingress-nginx/README.md), +o [GCE](https://git.k8s.io/ingress-gce/README.md#health-checks)). + +## Actualizando un Ingress + +Para actualizar un Ingress existente a un nuevo Host, +puedes actualizarlo editando el recurso: + +```shell +kubectl describe ingress test +``` + +``` +Name: test +Namespace: default +Address: 178.91.123.132 +Default backend: default-http-backend:80 (10.8.2.3:8080) +Rules: + Host Path Backends + ---- ---- -------- + foo.bar.com + /foo service1:80 (10.8.0.90:80) +Annotations: + nginx.ingress.kubernetes.io/rewrite-target: / +Events: + Type Reason Age From Message + ---- ------ ---- ---- ------- + Normal ADD 35s loadbalancer-controller default/test +``` + +```shell +kubectl edit ingress test +``` + +Esto muestra un editor con la configuración existente en formato YAML. +Modifícalo para incluir el nuevo Host: + +```yaml +spec: + rules: + - host: foo.bar.com + http: + paths: + - backend: + service: + name: service1 + port: + number: 80 + path: /foo + pathType: Prefix + - host: bar.baz.com + http: + paths: + - backend: + service: + name: service2 + port: + number: 80 + path: /foo + pathType: Prefix + #.. +``` + +Luego de guardar tus cambios, +kubectl actualiza el recurso en el servidor API, que le indica al controlador +Ingress de reconfigurar el balanceador de cargas. + +Verifica esto: + +```shell +kubectl describe ingress test +``` + +``` +Name: test +Namespace: default +Address: 178.91.123.132 +Default backend: default-http-backend:80 (10.8.2.3:8080) +Rules: + Host Path Backends + ---- ---- -------- + foo.bar.com + /foo service1:80 (10.8.0.90:80) + bar.baz.com + /foo service2:80 (10.8.0.91:80) +Annotations: + nginx.ingress.kubernetes.io/rewrite-target: / +Events: + Type Reason Age From Message + ---- ------ ---- ---- ------- + Normal ADD 45s loadbalancer-controller default/test +``` + +Puedes lograr el mismo resultado invocando `kubectl replace -f` en un fichero +YAML de Ingress. + +## Fallos a través de zonas de disponibilidad + +Las técnicas para distribuir el tráfico entre dominios de falla difieren entre +los proveedores de la nube. +Revisa la documentación +del [Ingress controller](/docs/concepts/services-networking/ingress-controllers) +relevante para detalles. + +## Alternativas + +Puedes exponer un Service de muchas maneras que no involucran directamente el +recurso Ingress: + +* Usa + un [Service.Type=LoadBalancer](es/docs/concepts/services-networking/service/#loadbalancer) +* Usa + un [Service.Type=NodePort](es/docs/concepts/services-networking/service/#nodeport) + +## {{% heading "whatsnext" %}} + +* Aprende sobre la API + del [Ingress](/docs/reference/kubernetes-api/service-resources/ingress-v1/) +* Aprende + sobre [Ingress controllers](/docs/concepts/services-networking/ingress-controllers/) +* [Configurar un Ingress en Minikube con el controlador NGINX](/docs/tasks/access-application-cluster/ingress-minikube/) diff --git a/content/es/docs/concepts/storage/persistent-volumes.md b/content/es/docs/concepts/storage/persistent-volumes.md new file mode 100644 index 0000000000000..adfc0ced9c61a --- /dev/null +++ b/content/es/docs/concepts/storage/persistent-volumes.md @@ -0,0 +1,1092 @@ +--- +reviewers: + - ramrodo + - krol3 + - electrocucaracha +title: Volúmenes Persistentes +feature: + title: Orquestación de almacenamiento + description: > + Monta automáticamente el sistema de almacenamiento de tu elección, ya sea de almacenamiento local, un proveedor de nube pública o un sistema de almacenamiento en red como iSCSI o NFS. +content_type: concept +weight: 20 +--- + + + +Este documento describe _volúmenes persistentes_ en Kubernetes. Se sugiere familiarizarse con +[volumes](/es/docs/concepts/storage/volumes/), [StorageClasses](/es/docs/concepts/storage/storage-classes/) +y [VolumeAttributesClasses](/docs/concepts/storage/volume-attributes-classes/). + + + +## Introducción + +La gestión del almacenamiento es un problema distinto al de la gestión de instancias de cómputo. +El subsistema PersistentVolume proporciona una API para usuarios y administradores +que abstrae los detalles de cómo se proporciona el almacenamiento de cómo se consume. +Para hacer esto, introducimos dos nuevos recursos de API: PersistentVolume y PersistentVolumeClaim. + +Un _PersistentVolume_ (PV) es una pieza de almacenamiento en el clúster que ha sido +provisionada por un administrador o provisionada dinámicamente usando +[Storage Classes](/es/docs/concepts/storage/storage-classes/). Es un recurso en +el clúster al igual que un nodo es un recurso del clúster. Los PVs son plugins de volumen como +Volúmenes, que tienen un ciclo de vida independiente de cualquier Pod individual que use el PV. +Este objeto API captura los detalles de la implementación del almacenamiento, sea +NFS, iSCSI o un sistema de almacenamiento específico de un proveedor de nube. + +Un _PersistentVolumeClaim_ (PVC) es una solicitud de almacenamiento por parte de un usuario. Es similar +a un Pod. Los Pods consumen recursos de nodos y los PVCs consumen recursos de PVs. Los Pods pueden +solicitar niveles específicos de recursos (CPU y Memoria). Las solicitudes pueden pedir tamaños específicos +y modos de acceso (por ejemplo, pueden montarse como ReadWriteOnce, ReadOnlyMany, +ReadWriteMany o ReadWriteOncePod, ver [Modos de Acceso](#modos-de-acceso)). + +Aunque los PersistentVolumeClaims permiten a un usuario consumir recursos de almacenamiento abstractos, +es común que los usuarios necesiten PersistentVolumes con propiedades variadas, tales como +rendimiento, para diferentes problemas. Los administradores del clúster necesitan poder +ofrecer una variedad de PersistentVolumes que difieran en más aspectos que el tamaño y los modos de acceso, sin exponer a los usuarios a los detalles de cómo se implementan esos volúmenes. +Para estas necesidades, existe el recurso _StorageClass_. + +Vea el [tutorial detallado con ejemplos prácticos](/docs/tasks/configure-pod-container/configure-persistent-volume-storage/). + +## Ciclo de vida de un volumen y una solicitud + +Los PVs son recursos en el clúster. Los PVCs son solicitudes para esos recursos y también actúan +como comprobantes de reclamo al recurso. La interacción entre PVs y PVCs sigue este ciclo de vida: + +### Aprovisionamiento + +Hay dos formas en que los PVs pueden ser aprovisionados: estáticamente o dinámicamente. + +#### Estático + +Un administrador del clúster crea un número de PVs. Llevan los detalles del +almacenamiento real, que está disponible para uso de los usuarios del clúster. Existen en la +API de Kubernetes y están disponibles para su consumo. + +#### Dinámico + +Cuando ninguno de los PVs estáticos creados por el administrador coincide con un PersistentVolumeClaim de un usuario, +el clúster puede intentar aprovisionar dinámicamente un volumen especialmente para el PVC. +Este aprovisionamiento se basa en StorageClasses: el PVC debe solicitar una +[clase de almacenamiento](/es/docs/concepts/storage/storage-classes/) y +el administrador debe haber creado y configurado esa clase para que ocurra el aprovisionamiento +dinámico. Las solicitudes que piden la clase `""` efectivamente desactivan +el aprovisionamiento dinámico para sí mismas. + +Para habilitar el aprovisionamiento dinámico de almacenamiento basado en clases de almacenamiento, el administrador del clúster +necesita habilitar el controlador de admisión `DefaultStorageClass` +[admission controller](/docs/reference/access-authn-authz/admission-controllers/#defaultstorageclass) +en el servidor API. Esto se puede hacer, por ejemplo, asegurándose de que `DefaultStorageClass` esté +entre la lista de valores delimitados por comas y ordenados para la bandera `--enable-admission-plugins` del +componente del servidor API. Para más información sobre las opciones de línea de comandos del servidor API, +consulta la documentación de [kube-apiserver](/docs/reference/command-line-tools-reference/kube-apiserver/). + +### Binding + +Un usuario crea, o en el caso de aprovisionamiento dinámico, ya ha creado, +un PersistentVolumeClaim con una cantidad específica de almacenamiento solicitado y con +ciertos modos de acceso. Un bucle de control en el plano de control observa los nuevos PVCs, encuentra +un PV coincidente (si es posible) y los une. Si un PV fue aprovisionado dinámicamente +para un nuevo PVC, el bucle siempre unirá ese PV al PVC. De lo contrario, +el usuario siempre obtendrá al menos lo que pidió, pero el volumen puede ser +superior a lo solicitado. Una vez unidos, los enlaces PersistentVolumeClaim son exclusivos, +independientemente de cómo se hayan unido. Una unión PVC a PV es un mapeo uno a uno, +utilizando un ClaimRef que es una unión bidireccional entre el PersistentVolume +y el PersistentVolumeClaim. + +Las solicitudes permanecerán sin unir indefinidamente si no existe un volumen coincidente. +Las solicitudes se unirán a medida que los volúmenes coincidentes estén disponibles. Por ejemplo, un +clúster aprovisionado con muchos PVs de 50Gi no coincidirá con un PVC que solicite 100Gi. +El PVC puede unirse cuando se agregue un PV de 100Gi al clúster. + +### Uso + +Los Pods usan las solicitudes como volúmenes. El clúster inspecciona la solicitud para encontrar el volumen unido +y monta ese volumen para un Pod. Para los volúmenes que admiten múltiples modos de acceso, el usuario especifica qué modo desea cuando utiliza su solicitud como volumen en un Pod. + +Una vez que un usuario tiene una solicitud y esa solicitud está unida, el PV unido pertenece al +usuario mientras lo necesiten. Los usuarios programan Pods y acceden a sus PVs reclamados incluyendo una sección de `persistentVolumeClaim` en el bloque `volumes` de un Pod. +Consulta [Solicitudes como Volúmenes](#solicitudes-como-volumenes) para más detalles sobre esto. + +### Protección de Objeto de Almacenamiento en Uso + +El propósito de la función de Protección de Objeto de Almacenamiento en Uso es asegurar que +las PersistentVolumeClaims (PVCs) en uso activo por un Pod y los PersistentVolumes (PVs) +que están unidos a PVCs no sean eliminados del sistema, ya que esto podría resultar en pérdida de datos. + +{{< note >}} +Un PVC está en uso activo por un Pod cuando existe un objeto Pod que está utilizando el PVC. +{{< /note >}} + +Si un usuario elimina un PVC en uso activo por un Pod, el PVC no se elimina inmediatamente. +La eliminación del PVC se pospone hasta que el PVC ya no esté en uso activo por ningún Pod. Además, +si un administrador elimina un PV que está unido a un PVC, el PV no se elimina inmediatamente. +La eliminación del PV se pospone hasta que el PV ya no esté unido a ningún PVC. + +Puedes ver que un PVC está protegido cuando el estado del PVC es `Terminating` y la lista de `Finalizers` incluye `kubernetes.io/pvc-protection`: + +```shell +kubectl describe pvc hostpath +Name: hostpath +Namespace: default +StorageClass: example-hostpath +Status: Terminating +Volume: +Labels: +Annotations: volume.beta.kubernetes.io/storage-class=example-hostpath + volume.beta.kubernetes.io/storage-provisioner=example.com/hostpath +Finalizers: [kubernetes.io/pvc-protection] +... +``` + +Puedes ver que un PV está protegido cuando el estado del PV es `Terminating` y la lista de `Finalizers` incluye también `kubernetes.io/pv-protection`: + +```shell +kubectl describe pv task-pv-volume +Name: task-pv-volume +Labels: type=local +Annotations: +Finalizers: [kubernetes.io/pv-protection] +StorageClass: standard +Status: Terminating +Claim: +Reclaim Policy: Delete +Access Modes: RWO +Capacity: 1Gi +Message: +Source: + Type: HostPath (bare host directory volume) + Path: /tmp/data + HostPathType: +Events: +``` + +### Reclamación + +Cuando un usuario ha concluido con el uso de su volumen, puede eliminar los objetos PVC de la +API que permite la recuperación del recurso. La política de reclamación para un PersistentVolume +le dice al clúster que hacer con el volumen después de que ha sido liberado de su solicitud. +Actualmente, los volúmenes pueden ser Retenidos, Reciclados o Eliminados. + +#### Retener + +La política de reclamación `Retain` permite la recuperación manual del recurso. +Cuando se elimina el PersistentVolumeClaim, el PersistentVolume todavía existe +y el volumen se considera "liberado". Pero aún no está disponible para +otra solicitud porque los datos del reclamante anterior permanecen en el volumen. +Un administrador puede reclamar manualmente el volumen con los siguientes pasos. + +1. Eliminar el PersistentVolume. El recurso de almacenamiento asociado en la infraestructura externa + todavía existe después de que se haya eliminado el PV. +1. Limpiar manualmente los datos en el recurso de almacenamiento asociado en consecuencia. +1. Eliminar manualmente el recurso de almacenamiento asociado. + +Si deseas reutilizar el mismo recurso de almacenamiento, crea un nuevo PersistentVolume con +la misma definición de recurso de almacenamiento. + +#### Eliminar + +Para los plugins de volumen que soportan la política de reclamación `Delete`, la eliminación remueve +tanto el objeto PersistentVolume de Kubernetes, como el recurso de almacenamiento asociado +en la infraestructura externa. Los volúmenes que fueron aprovisionados dinámicamente +heredan la [política de reclamación de su StorageClass](#politica-de-reclamacion), que +por defecto es `Delete`. El administrador debe configurar la StorageClass +de acuerdo con las expectativas de los usuarios; de lo contrario, el PV debe ser editado o +modificado después de que se haya creado. Consulta +[Cambiar la Política de Reclamación de un PersistentVolume](/docs/tasks/administer-cluster/change-pv-reclaim-policy/). + +#### Reciclar + +{{< warning >}} +La política de reclamación `Recycle` está obsoleta. En su lugar, el enfoque recomendado +es utilizar el aprovisionamiento dinámico. +{{< /warning >}} + +Si es compatible con el plugin de volumen subyacente, la política de reclamación `Recycle` realiza +un borrado básico (`rm -rf /elvolumen/*`) en el volumen y lo hace disponible nuevamente para una nueva solicitud. + +Sin embargo, un administrador puede configurar una plantilla de Pod reciclador personalizada usando +los argumentos de línea de comandos del administrador del controlador de Kubernetes como se describe en la +[referencia](/docs/reference/command-line-tools-reference/kube-controller-manager/). +La plantilla de Pod reciclador personalizada debe contener una especificación de `volumes`, como +se muestra en el ejemplo a continuación: + +```yaml +apiVersion: v1 +kind: Pod +metadata: + name: pv-recycler + namespace: default +spec: + restartPolicy: Never + volumes: + - name: vol + hostPath: + path: /any/path/it/will/be/replaced + containers: + - name: pv-recycler + image: "registry.k8s.io/busybox" + command: + [ + "/bin/sh", + "-c", + 'test -e /scrub && rm -rf /scrub/..?* /scrub/.[!.]* /scrub/* && test -z "$(ls -A /scrub)" || exit 1', + ] + volumeMounts: + - name: vol + mountPath: /scrub +``` + +Sin embargo, la ruta particular especificada en la plantilla de Pod reciclador personalizado en la parte de `volumes` se reemplaza con la ruta particular del volumen que está siendo reciclado. + +### Finalizador de protección de eliminación de PersistentVolume + +{{< feature-state for_k8s_version="v1.23" state="alpha" >}} + +Los finalizadores pueden agregarse en un PersistentVolume para asegurar que los PersistentVolumes +con política de reclamación `Delete` solo se eliminen después de que se eliminen los almacenamientos subyacentes. + +Los finalizadores recién introducidos `kubernetes.io/pv-controller` y +`external-provisioner.volume.kubernetes.io/finalizer` +solo se agregan a los volúmenes provisionados dinámicamente. + +El finalizador `kubernetes.io/pv-controller` se agrega a los volúmenes de plugins integrados. +El siguiente es un ejemplo. + +```shell +kubectl describe pv pvc-74a498d6-3929-47e8-8c02-078c1ece4d78 +Name: pvc-74a498d6-3929-47e8-8c02-078c1ece4d78 +Labels: +Annotations: kubernetes.io/createdby: vsphere-volume-dynamic-provisioner + pv.kubernetes.io/bound-by-controller: yes + pv.kubernetes.io/provisioned-by: kubernetes.io/vsphere-volume +Finalizers: [kubernetes.io/pv-protection kubernetes.io/pv-controller] +StorageClass: vcp-sc +Status: Bound +Claim: default/vcp-pvc-1 +Reclaim Policy: Delete +Access Modes: RWO +VolumeMode: Filesystem +Capacity: 1Gi +Node Affinity: +Message: +Source: + Type: vSphereVolume (a Persistent Disk resource in vSphere) + VolumePath: [vsanDatastore] d49c4a62-166f-ce12-c464-020077ba5d46/kubernetes-dynamic-pvc-74a498d6-3929-47e8-8c02-078c1ece4d78.vmdk + FSType: ext4 + StoragePolicyName: vSAN Default Storage Policy +Events: +``` + +El finalizador `external-provisioner.volume.kubernetes.io/finalizer` se agrega para los volúmenes CSI. +El siguiente es un ejemplo: + +```shell +Name: pvc-2f0bab97-85a8-4552-8044-eb8be45cf48d +Labels: +Annotations: pv.kubernetes.io/provisioned-by: csi.vsphere.vmware.com +Finalizers: [kubernetes.io/pv-protection external-provisioner.volume.kubernetes.io/finalizer] +StorageClass: fast +Status: Bound +Claim: demo-app/nginx-logs +Reclaim Policy: Delete +Access Modes: RWO +VolumeMode: Filesystem +Capacity: 200Mi +Node Affinity: +Message: +Source: + Type: CSI (a Container Storage Interface (CSI) volume source) + Driver: csi.vsphere.vmware.com + FSType: ext4 + VolumeHandle: 44830fa8-79b4-406b-8b58-621ba25353fd + ReadOnly: false + VolumeAttributes: storage.kubernetes.io/csiProvisionerIdentity=1648442357185-8081-csi.vsphere.vmware.com + type=vSphere CNS Block Volume +Events: +``` + +Cuando la bandera de funcionalidad `CSIMigration{provider}` está habilitada para un plugin de volumen integrado específico, +el finalizador `kubernetes.io/pv-controller` se reemplaza por el finalizador +`external-provisioner.volume.kubernetes.io/finalizer`. + +### Reservando un PersistentVolume + +El plano de control puede [unir PersistentVolumeClaims a PersistentVolumes correspondientes](#binding) +en el clúster. Sin embargo, si quieres que un PVC se una a un PV específico, necesitas pre-unirlos. + +Al especificar un PersistentVolume en un PersistentVolumeClaim, declaras una unión +entre ese PV y PVC específicos. Si el PersistentVolume existe y no ha reservado +PersistentVolumeClaims a través de su campo `claimRef`, entonces el PersistentVolume y +el PersistentVolumeClaim se unirán. + +La unión ocurre independientemente de algunos criterios de coincidencia de volumen, incluida la afinidad de nodo. +El plano de control aún verifica que la [clase de almacenamiento](/es/docs/concepts/storage/storage-classes/), +los modos de acceso y el tamaño de almacenamiento solicitado sean válidos. + +```yaml +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: foo-pvc + namespace: foo +spec: + storageClassName: "" # La cadena vacía debe establecerse explícitamente; de lo contrario, se establecerá la StorageClass predeterminada + volumeName: foo-pv + ... +``` + +Este método no garantiza ningún privilegio de unión al PersistentVolume. +Si otros PersistentVolumeClaims pudieran usar el PV que especificas, primero +necesitas reservar ese volumen de almacenamiento. Especifica el PersistentVolumeClaim relevante +en el campo `claimRef` del PV para que otros PVCs no puedan unirse a él. + +```yaml +apiVersion: v1 +kind: PersistentVolume +metadata: + name: foo-pv +spec: + storageClassName: "" + claimRef: + name: foo-pvc + namespace: foo + ... +``` + +Esto es útil si deseas consumir PersistentVolumes que tienen su `claimPolicy` establecido +en `Retain`, incluyendo casos donde estás reutilizando un PV existente. + +### Expandiendo Persistent Volume Claims + +{{< feature-state for_k8s_version="v1.24" state="stable" >}} + +El soporte para expandir PersistentVolumeClaims (PVCs) está habilitado por defecto. Puedes expandir +los siguientes tipos de volúmenes: + +- azureFile (obsoleto) +- {{< glossary_tooltip text="csi" term_id="csi" >}} +- flexVolume (obsoleto) +- rbd (obsoleto) +- portworxVolume (obsoleto) + +Solo puedes expandir un PVC si el campo `allowVolumeExpansion` de su clase de almacenamiento está establecido en verdadero. + +```yaml +apiVersion: storage.k8s.io/v1 +kind: StorageClass +metadata: + name: example-vol-default +provisioner: vendor-name.example/magicstorage +parameters: + resturl: "http://192.168.10.100:8080" + restuser: "" + secretNamespace: "" + secretName: "" +allowVolumeExpansion: true +``` + +Para solicitar un volumen más grande para un PVC, edita el objeto PVC y especifica un tamaño +mayor. Esto desencadena la expansión del volumen que respalda el PersistentVolume subyacente. Nunca se crea un nuevo PersistentVolume para satisfacer la solicitud. En cambio, se redimensiona un volumen existente. + +{{< warning >}} +Editar directamente el tamaño de un PersistentVolume puede impedir un redimensionamiento automático de ese volumen. +Si editas la capacidad de un PersistentVolume, y luego editas el `.spec` de un PersistentVolumeClaim coincidente para hacer que el tamaño del PersistentVolumeClaim coincida con el PersistentVolume, +entonces no ocurre ningún redimensionamiento de almacenamiento. +El plano de control de Kubernetes verá que el estado deseado de ambos recursos coincide, +concluirá que el tamaño del volumen de respaldo se ha aumentado manualmente +y que no es necesario ningún redimensionamiento. +{{< /warning >}} + +#### Expansión de volúmenes CSI + +{{< feature-state for_k8s_version="v1.24" state="stable" >}} + +El soporte para la expansión de volúmenes CSI está habilitado por defecto, pero también requiere que un +controlador CSI específico soporte la expansión de volumen. Consulta la documentación del +controlador CSI específico para obtener más información. + +#### Redimensionando un volumen que contiene un sistema de archivos + +Solo puedes redimensionar volúmenes que contienen un sistema de archivos si el sistema de archivos es XFS, Ext3 o Ext4. + +Cuando un volumen contiene un sistema de archivos, el sistema de archivos solo se redimensiona cuando un nuevo Pod está utilizando +el PersistentVolumeClaim en modo `ReadWrite`. La expansión del sistema de archivos se realiza cuando un Pod se está iniciando +o cuando un Pod está en ejecución y el sistema de archivos subyacente soporta la expansión en línea. + +Los FlexVolumes (obsoletos desde Kubernetes v1.23) permiten redimensionar si el controlador está configurado con la +capacidad `RequiresFSResize` en `true`. El FlexVolume se puede redimensionar al reiniciar el Pod. + +#### Redimensionando un PersistentVolumeClaim en uso + +{{< feature-state for_k8s_version="v1.24" state="stable" >}} + +En este caso, no necesitas eliminar y recrear un Pod o despliegue que esté utilizando un PVC existente. +Cualquier PVC en uso se vuelve automáticamente disponible para su Pod tan pronto como su sistema de archivos haya sido expandido. +Esta característica no tiene efecto en PVCs que no están en uso por un Pod o despliegue. Debes crear un Pod que +utilice el PVC antes de que la expansión pueda completarse. + +Similar a otros tipos de volúmenes - los volúmenes FlexVolume también pueden ser expandidos cuando están en uso por un Pod. + +{{< note >}} +El redimensionamiento de FlexVolume es posible solo cuando el controlador subyacente soporta el redimensionamiento. +{{< /note >}} + +#### Recuperación de fallos al expandir volúmenes + +Si un usuario especifica un nuevo tamaño que es demasiado grande para ser satisfecho por el sistema de almacenamiento subyacente, la expansión del PVC será reintentada continuamente hasta que el usuario o el administrador del clúster tomen alguna acción. Esto puede ser indeseable y por lo tanto Kubernetes proporciona los siguientes métodos de recuperación de tales fallos. + +{{< tabs name="recovery_methods" >}} +{{% tab name="Manualmente con acceso de Administrador del Clúster" %}} + +Si la expansión del almacenamiento subyacente falla, el administrador del clúster puede recuperar manualmente +el estado del Persistent Volume Claim (PVC) y cancelar las solicitudes de redimensionamiento. +De lo contrario, las solicitudes de redimensionamiento son reintentadas continuamente por el controlador sin +intervención del administrador. + +1. Marca el PersistentVolume (PV) que está vinculado al PersistentVolumeClaim (PVC) con una política de reclamación `Retain`. +2. Elimina el PVC. Dado que el PV tiene una política de reclamación `Retain`, no perderemos ningún dato al recrear el PVC. +3. Elimina la entrada `claimRef` de las especificaciones del PV, para que un nuevo PVC pueda vincularse a él. Esto debería hacer que el PV esté `Available` (Disponible). +4. Vuelve a crear el PVC con un tamaño menor que el PV y establece el campo `volumeName` del PVC con el nombre del PV. Esto debería vincular el nuevo PVC al PV existente. +5. No olvides restaurar la política de reclamación del PV. + +{{% /tab %}} +{{% tab name="Solicitando ampliación a un tamaño menor" %}} +{{% feature-state for_k8s_version="v1.23" state="alpha" %}} + +{{< note >}} +La recuperación de la expansión fallida de PVC por parte de los usuarios está disponible como una característica alfa desde Kubernetes 1.23. La funcionalidad `RecoverVolumeExpansionFailure` debe estar habilitada para que esta característica funcione. Consulta la documentación de [interruptores de funcionalidades](/docs/reference/command-line-tools-reference/feature-gates/) para más información. +{{< /note >}} + +Si el interruptor de funcionalidad de `RecoverVolumeExpansionFailure` está habilitado en tu clúster, y la expansión ha fallado para un PVC, puedes intentar nuevamente la expansión con un tamaño menor al valor previamente solicitado. Para solicitar un nuevo intento de expansión con un tamaño propuesto menor, edita `.spec.resources` para ese PVC y elige un valor que sea menor al valor que intentaste previamente. +Esto es útil si la expansión a un valor más alto no tuvo éxito debido a una restricción de capacidad. +Si eso ha ocurrido, o sospechas que podría haber ocurrido, puedes intentar nuevamente la expansión especificando un tamaño que esté dentro de los límites de capacidad del proveedor de almacenamiento subyacente. Puedes monitorear el estado de la operación de redimensionamiento observando `.status.allocatedResourceStatuses` y los eventos en el PVC. + +Ten en cuenta que, aunque puedes especificar una cantidad menor de almacenamiento que la solicitada anteriormente, el nuevo valor aún debe ser mayor que `.status.capacity`. +Kubernetes no admite reducir un PVC a menos de su tamaño actual. +{{% /tab %}} +{{% /tabs %}} + +## Tipos de Persistent Volumes + +Los tipos de PersistentVolume se implementan como plugins. Actualmente, Kubernetes admite los siguientes plugins: + +- [`csi`](/es/docs/concepts/storage/volumes/#csi) - Interfaz de Almacenamiento de Contenedores (CSI) +- [`fc`](/es/docs/concepts/storage/volumes/#fc) - Almacenamiento de Canal de Fibra (FC) +- [`hostPath`](/es/docs/concepts/storage/volumes/#hostpath) - Volumen HostPath + (solo para pruebas en un único nodo; NO FUNCIONARÁ en un clúster multinodo; + considera usar el volumen `local` en su lugar) +- [`iscsi`](/es/docs/concepts/storage/volumes/#iscsi) - iSCSI (SCSI sobre IP) almacenamiento +- [`local`](/es/docs/concepts/storage/volumes/#local) - dispositivos de almacenamiento locales + montados en los nodos. +- [`nfs`](/es/docs/concepts/storage/volumes/#nfs) - Almacenamiento del Sistema de Archivos de Red (NFS) + +Los siguientes tipos de PersistentVolume están obsoletos. +Esto significa que el soporte aún está disponible, pero se eliminará en una futura versión de Kubernetes. + +- [`azureFile`](/es/docs/concepts/storage/volumes/#azurefile) - Azure File + (**obsoleto** en v1.21) +- [`flexVolume`](/es/docs/concepts/storage/volumes/#flexvolume) - FlexVolume + (**obsoleto** en v1.23) +- [`portworxVolume`](/es/docs/concepts/storage/volumes/#portworxvolume) - Volumen Portworx + (**obsoleto** en v1.25) +- [`vsphereVolume`](/es/docs/concepts/storage/volumes/#vspherevolume) - Volumen VMDK de vSphere + (**obsoleto** en v1.19) +- [`cephfs`](/es/docs/concepts/storage/volumes/#cephfs) - Volumen CephFS + (**obsoleto** en v1.28) +- [`rbd`](/es/docs/concepts/storage/volumes/#rbd) - Dispositivo de Bloque Rados (RBD) + (**obsoleto** en v1.28) + +Versiones anteriores de Kubernetes también soportaban los siguientes tipos de PersistentVolume integrados: + +- [`awsElasticBlockStore`](/es/docs/concepts/storage/volumes/#awselasticblockstore) - AWS Elastic Block Store (EBS) + (**no disponible** en v1.27) +- [`azureDisk`](/es/docs/concepts/storage/volumes/#azuredisk) - Disco Azure + (**no disponible** en v1.27) +- [`cinder`](/es/docs/concepts/storage/volumes/#cinder) - Cinder (almacenamiento en bloque de OpenStack) + (**no disponible** en v1.26) +- `photonPersistentDisk` - Disco persistente del controlador Photon. + (**no disponible** a partir de v1.15) +- `scaleIO` - Volumen ScaleIO. + (**no disponible** a partir de v1.21) +- `flocker` - Almacenamiento Flocker. + (**no disponible** a partir de v1.25) +- `quobyte` - Volumen Quobyte. + (**no disponible** a partir de v1.25) +- `storageos` - Volumen StorageOS. + (**no disponible** a partir de v1.25) + +## Volúmenes Persistentes + +Cada PV contiene una especificación y un estado, que corresponden a la especificación y el estado del volumen. +El nombre de un objeto PersistentVolume debe ser un válido +[nombre de subdominio DNS](/docs/concepts/overview/working-with-objects/names#dns-subdomain-names). + +```yaml +apiVersion: v1 +kind: PersistentVolume +metadata: + name: pv0003 +spec: + capacity: + storage: 5Gi + volumeMode: Filesystem + accessModes: + - ReadWriteOnce + persistentVolumeReclaimPolicy: Recycle + storageClassName: slow + mountOptions: + - hard + - nfsvers=4.1 + nfs: + path: /tmp + server: 172.17.0.2 +``` + +{{< note >}} +Es posible que se requieran programas auxiliares relacionados con el tipo de volumen para el uso de un PersistentVolume dentro de un clúster. En este ejemplo, el PersistentVolume es de tipo NFS y se requiere el programa auxiliar /sbin/mount.nfs para permitir el montaje de sistemas de archivos NFS. +{{< /note >}} + +### Capacidad + +Por lo general, un PV tendrá una capacidad de almacenamiento específica. Esto se establece utilizando el atributo `capacity` del PV. Lea el término del glosario [Cantidad](/docs/reference/glossary/?all=true#term-quantity) para comprender las unidades esperadas por `capacity`. + +Actualmente, el tamaño de almacenamiento es el único recurso que se puede establecer o solicitar. En el futuro, los atributos adicionales pueden incluir IOPS, throughput, etc. + +### Modo de Volumen + +{{< feature-state for_k8s_version="v1.18" state="stable" >}} + +Kubernetes admite dos `volumeModes` (modos de volumen) para PersistentVolumes: `Filesystem` y `Block` (Sistema de archivos y Bloque). + +`volumeMode` es un parámetro opcional de la API. +`Filesystem` es el modo predeterminado que se utiliza cuando se omite el parámetro `volumeMode`. + +Un volumen con `volumeMode: Filesystem` se _monta_ en Pods en un directorio. Si el volumen está respaldado por un dispositivo de bloque y el dispositivo está vacío, Kubernetes crea un sistema de archivos en el dispositivo antes de montarlo por primera vez. + +Puedes establecer el valor de `volumeMode` en `Block` para utilizar un volumen como un dispositivo de bloque sin formato. Este tipo de volumen se presenta en un Pod como un dispositivo de bloque, sin ningún sistema de archivos en él. +Este modo es útil para proporcionar al Pod la forma más rápida posible de acceder a un volumen, sin ninguna capa de sistema de archivos entre el Pod y el volumen. + +Por otro lado, la aplicación que se ejecuta en el Pod debe saber cómo manejar un dispositivo de bloque sin formato. + +Consulta [Soporte para Volúmenes en Bloque sin Procesar](#soporte-para-volumenes-en-bloque-sin-procesar) para ver un ejemplo de cómo usar un volumen con `volumeMode: Block` en un Pod. + +### Modos de Acceso + +Un PersistentVolume puede montarse en un host de cualquier manera compatible con el proveedor de recursos. Como se muestra en la tabla a continuación, los proveedores tendrán diferentes capacidades y los modos de acceso de cada PV se establecerán en los modos específicos admitidos por ese volumen en particular. +Por ejemplo, NFS puede admitir múltiples clientes de lectura/escritura, pero un PV de NFS específico podría exportarse en el servidor como de solo lectura. Cada PV tiene su propio conjunto de modos de acceso que describen las capacidades específicas de ese PV en particular. + +Los modos de acceso son: + +`ReadWriteOnce` +: el volumen puede montarse como lectura-escritura por un solo nodo. El modo de acceso ReadWriteOnce aún puede permitir que varios Pods accedan al volumen cuando los Pods se ejecutan en el mismo nodo. Para el acceso de un solo Pod, consulta ReadWriteOncePod. + +`ReadOnlyMany` +: el volumen puede montarse como solo lectura por muchos nodos. + +`ReadWriteMany` +: el volumen puede montarse como lectura-escritura por muchos nodos. + +`ReadWriteOncePod` +: {{< feature-state for_k8s_version="v1.29" state="stable" >}} +el volumen puede montarse como lectura-escritura por un solo Pod. Utiliza el modo de acceso ReadWriteOncePod si deseas garantizar que solo un Pod en todo el clúster pueda leer ese PVC o escribir en él. + +{{< note >}} +El modo de acceso `ReadWriteOncePod` solo es compatible con los volúmenes {{< glossary_tooltip text="CSI" term_id="csi" >}} y Kubernetes versión 1.22+. Para utilizar esta función, deberás actualizar los siguientes [CSI sidecars](https://kubernetes-csi.github.io/docs/sidecar-containers.html) a estas versiones o superiores: + +- [csi-provisioner:v3.0.0+](https://github.com/kubernetes-csi/external-provisioner/releases/tag/v3.0.0) +- [csi-attacher:v3.3.0+](https://github.com/kubernetes-csi/external-attacher/releases/tag/v3.3.0) +- [csi-resizer:v1.3.0+](https://github.com/kubernetes-csi/external-resizer/releases/tag/v1.3.0) + {{< /note >}} + +En la línea de comandos (CLI), los modos de acceso se abrevian de la siguiente manera: + +- RWO - ReadWriteOnce (Lectura/Escritura para Uno) +- ROX - ReadOnlyMany (Solo Lectura para Muchos) +- RWX - ReadWriteMany (Lectura/Escritura para Muchos) +- RWOP - ReadWriteOncePod (Lectura/Escritura para Uno por Pod) + +{{< note >}} +Kubernetes utiliza modos de acceso de volumen para hacer coincidir las solicitudes de PersistentVolumeClaims y los PersistentVolumes. En algunos casos, los modos de acceso de volumen también restringen dónde se puede montar el PersistentVolume. Los modos de acceso de volumen **no** imponen protección contra escritura una vez que el almacenamiento se ha montado. Incluso si se especifican los modos de acceso como ReadWriteOnce, ReadOnlyMany o ReadWriteMany, no establecen ninguna restricción en el volumen. Por ejemplo, incluso si se crea un PersistentVolume como ReadOnlyMany, no garantiza que sea de solo lectura. Si los modos de acceso se especifican como ReadWriteOncePod, el volumen está restringido y solo se puede montar en un único Pod. +{{< /note >}} + +> **¡Importante!** Un volumen solo puede montarse utilizando un modo de acceso a la vez, incluso si admite varios modos. + +| Volume Plugin | ReadWriteOnce | ReadOnlyMany | ReadWriteMany | ReadWriteOncePod | +| :------------- | :-------------------: | :-------------------: | :--------------------------------: | --------------------- | --- | +| AzureFile | ✓ | ✓ | ✓ | - | +| CephFS | ✓ | ✓ | ✓ | - | +| CSI | depends on the driver | depends on the driver | depends on the driver | depends on the driver | +| FC | ✓ | ✓ | - | - | +| FlexVolume | ✓ | ✓ | depends on the driver | - | +| HostPath | ✓ | - | - | - | +| iSCSI | ✓ | ✓ | - | - | +| NFS | ✓ | ✓ | ✓ | - | +| RBD | ✓ | ✓ | - | - | +| VsphereVolume | ✓ | - | - (works when Pods are collocated) | - | +| PortworxVolume | ✓ | - | ✓ | - | - | + +### Clase + +Un PV puede tener una clase, que se especifica configurando el atributo `storageClassName` con el nombre de una [StorageClass](/es/docs/concepts/storage/storage-classes/). Un PV de una clase particular solo puede vincularse a PVC que soliciten esa clase. Un PV sin `storageClassName` no tiene clase y solo puede vincularse a PVC que no soliciten una clase en particular. + +En el pasado, en lugar del atributo `storageClassName`, se utilizaba la anotación `volume.beta.kubernetes.io/storage-class`. Esta anotación todavía funciona; sin embargo, quedará completamente en desuso en una versión futura de Kubernetes. + +### Política de Reclamación + +Las políticas de reclamación actuales son: + +- Retain (Retener) -- reclamación manual +- Recycle (Reciclar) -- limpieza básica (`rm -rf /elvolumen/*`) +- Delete (Eliminar) -- eliminar el volumen + +Para Kubernetes {{< skew currentVersion >}}, solo los tipos de volumen `nfs` y `hostPath` admiten el reciclaje. + +### Opciones de Montaje + +Un administrador de Kubernetes puede especificar opciones de montaje adicionales cuando se monta un Persistent Volume en un nodo. + +{{< note >}} +No todos los tipos de Persistent Volumes admiten opciones de montaje. +{{< /note >}} + +Los siguientes tipos de volumen admiten opciones de montaje: + +- `azureFile` +- `cephfs` (**desaconsejado** en v1.28) +- `cinder` (**desaconsejado** en v1.18) +- `iscsi` +- `nfs` +- `rbd` (**desaconsejado** en v1.28) +- `vsphereVolume` + +Las opciones de montaje no se validan. Si una opción de montaje es inválida, el montaje falla. + +En el pasado, en lugar del atributo `mountOptions`, se utilizaba la anotación `volume.beta.kubernetes.io/mount-options`. Esta anotación todavía funciona; sin embargo, quedará completamente en desuso en una versión futura de Kubernetes. Se recomienda utilizar el atributo `mountOptions` para especificar las opciones de montaje en lugar de la anotación. + +### Afinidad de Nodos + +{{< note >}} +Para la mayoría de los tipos de volumen, no es necesario establecer este campo. +Debes establecer esto explícitamente para los volúmenes [locales](/es/docs/concepts/storage/volumes/#local). +{{< /note >}} + +Un PV puede especificar la afinidad de nodos para definir restricciones que limiten desde qué nodos se puede acceder a este volumen. Los Pods que utilizan un PV solo se programarán en nodos seleccionados por la afinidad de nodos. Para especificar la afinidad de nodos, configura `nodeAffinity` en `.spec` de un PV. La referencia de API de [PersistentVolume](/docs/reference/kubernetes-api/config-and-storage-resources/persistent-volume-v1/#PersistentVolumeSpec) tiene más detalles sobre este campo. + +### Fase + +Un PersistentVolume estará en una de las siguientes fases: + +`Available` (Disponible) +: un recurso gratuito que aún no está vinculado a una solicitud + +`Bound` (Vinculado) +: el volumen está vinculado a una solicitud + +`Released` (Liberado) +: la solicitud ha sido eliminada, pero el recurso de almacenamiento asociado aún no ha sido reclamado por el clúster + +`Failed` (Fallido) +: el volumen ha fallado en su proceso de reclamación (automatizada) + +Puedes ver el nombre de la PVC vinculada al PV utilizando `kubectl describe persistentvolume `. + +#### Marca de tiempo de transición de fase + +{{< feature-state for_k8s_version="v1.29" state="beta" >}} + +El campo `.status` de un PersistentVolume puede incluir un campo `lastPhaseTransitionTime` en versión alfa. Este campo registra la marca de tiempo de la última transición de fase del volumen. Para volúmenes recién creados, la fase se establece en `Pending` (Pendiente) y `lastPhaseTransitionTime` se establece en el tiempo actual. + +{{< note >}} +Debes habilitar el [interruptor de funcionalidad](/docs/reference/command-line-tools-reference/feature-gates/) `PersistentVolumeLastPhaseTransitionTime` para poder usar o ver el campo `lastPhaseTransitionTime`. +{{< /note >}} + +## PersistentVolumeClaims + +Cada PVC contiene un spec (especificación) y un status (estado), que es la especificación y el estado de la solicitud. El nombre de un objeto PersistentVolumeClaim debe ser un [nombre de subdominio DNS válido](/docs/concepts/overview/working-with-objects/names#dns-subdomain-names). + +```yaml +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: myclaim +spec: + accessModes: + - ReadWriteOnce + volumeMode: Filesystem + resources: + requests: + storage: 8Gi + storageClassName: slow + selector: + matchLabels: + release: "stable" + matchExpressions: + - { key: environment, operator: In, values: [dev] } +``` + +### Modos de Acceso + +Las solicitudes utilizan [las mismas convenciones que los volúmenes](#modos-de-acceso) al solicitar almacenamiento con modos de acceso específicos. + +### Modos de Volumen + +Las solicitudes utilizan [la misma convención que los volúmenes](#modo-de-volumen) para indicar el consumo del volumen como un sistema de archivos o un dispositivo de bloque. + +### Recursos + +Las solicitudes, al igual que los Pods, pueden solicitar cantidades específicas de un recurso. En este caso, la solicitud es para almacenamiento. El mismo [modelo de recurso](https://git.k8s.io/design-proposals-archive/scheduling/resources.md) se aplica tanto a los volúmenes como a las solicitudes. + +### Selector + +Las solicitudes pueden especificar un [selector de etiqueta](/es/docs/concepts/overview/working-with-objects/labels/#label-selectors) para filtrar aún más el conjunto de volúmenes. Solo los volúmenes cuyas etiquetas coincidan con el selector pueden vincularse a la solicitud. El selector puede constar de dos campos: + +- `matchLabels` (coincidencia de etiquetas) - el volumen debe tener una etiqueta con este valor. +- `matchExpressions` (expresiones de coincidencia) - una lista de requisitos especificados por clave, lista de valores y operador que relaciona la clave y los valores. Los operadores válidos incluyen In, NotIn, Exists y DoesNotExist. + +Todos los requisitos, tanto de `matchLabels` como de `matchExpressions`, se combinan mediante un operador AND: todos deben cumplirse para que haya coincidencia. + +### Clase + +Una solicitud puede solicitar una clase en particular especificando el nombre de una [StorageClass](/es/docs/concepts/storage/storage-classes/) utilizando el atributo `storageClassName`. Solo los PV de la clase solicitada, es decir, aquellos con el mismo `storageClassName` que el PVC, pueden vincularse al PVC. + +Las PVC no necesariamente tienen que solicitar una clase. Una PVC con su `storageClassName` configurado igual a `""` siempre se interpreta como una solicitud de un PV sin clase, por lo que solo puede vincularse a PV sin clase (sin anotación o con `""` configurado). Una PVC sin `storageClassName` no es exactamente lo mismo y se trata de manera diferente por parte del clúster, dependiendo de si el plugin de admisión [`DefaultStorageClass`](/docs/reference/access-authn-authz/admission-controllers/#defaultstorageclass) está activado. + +- Si el plugin de admisión está activado, el administrador puede especificar una StorageClass predeterminada. Todas las PVC que no tengan `storageClassName` solo podrán vincularse a los PV de esa clase predeterminada. La especificación de una StorageClass predeterminada se realiza configurando la anotación `storageclass.kubernetes.io/is-default-class` igual a `true` en un objeto StorageClass. Si el administrador no especifica una predeterminada, el clúster responderá a la creación de PVC como si el plugin de admisión estuviera desactivado. Si se especifican más de una StorageClass predeterminada, la más nueva se utilizará cuando se provisione dinámicamente la PVC. +- Si el plugin de admisión está desactivado, no existe una noción de una StorageClass predeterminada. Todas las PVC que tengan `storageClassName` configurado como `""` solo podrán vincularse a los PV que también tengan `storageClassName` configurado como `""`. Sin embargo, las PVC sin `storageClassName` pueden actualizarse más adelante una vez que esté disponible la StorageClass predeterminada. Si la PVC se actualiza, ya no se vinculará a los PV que tengan `storageClassName` configurado como `""`. + +Consulta [asignación retroactiva de StorageClass predeterminada](#retroactive-default-storageclass-assignment) para obtener más detalles. + +Según el método de instalación, el administrador puede implementar una StorageClass predeterminada en un clúster de Kubernetes mediante el administrador de complementos durante la instalación. + +Cuando una PVC especifica un `selector` además de solicitar una StorageClass, los requisitos se combinan mediante una operación AND: solo se puede vincular un PV de la clase solicitada y con las etiquetas solicitadas a la PVC. + +{{< note >}} +Actualmente, una PVC con un `selector` no vacío no puede tener un PV provisionado dinámicamente para ella. +{{< /note >}} + +En el pasado, en lugar del atributo `storageClassName`, se utilizaba la anotación `volume.beta.kubernetes.io/storage-class`. Esta anotación todavía funciona; sin embargo, no será compatible en futuras versiones de Kubernetes. Se recomienda utilizar el atributo `storageClassName` en su lugar. + +#### Asignación retroactiva de StorageClass predeterminada + +{{< feature-state for_k8s_version="v1.28" state="stable" >}} + +Puedes crear una PersistentVolumeClaim sin especificar un `storageClassName` para la nueva PVC, incluso cuando no exista una StorageClass predeterminada en tu clúster. En este caso, la nueva PVC se crea tal como la definiste, y el `storageClassName` de esa PVC permanece sin configurar hasta que esté disponible la predeterminada. + +Cuando está disponible una StorageClass predeterminada, el plano de control identifica cualquier PVC existente sin `storageClassName`. Para las PVC que tienen un valor vacío para `storageClassName` o que no tienen esta clave, el plano de control actualiza esas PVC para establecer `storageClassName` de acuerdo con la nueva StorageClass predeterminada. Si tienes una PVC existente donde `storageClassName` es `""`, y configuras una StorageClass predeterminada, entonces esta PVC no se actualizará. + +Para seguir vinculando a PV con `storageClassName` configurado como `""` (mientras existe una StorageClass predeterminada), debes establecer el `storageClassName` de la PVC asociada en `""`. + +Este comportamiento ayuda a los administradores a cambiar la StorageClass predeterminada eliminando primero la antigua y luego creando o configurando otra. Este breve período en el que no hay una predeterminada hace que las PVC creadas en ese momento sin `storageClassName` no tengan ninguna predeterminada, pero debido a la asignación retroactiva de la StorageClass predeterminada, esta forma de cambiar las predeterminadas es segura. + +## Solicitudes como Volúmenes + +Los Pods acceden al almacenamiento utilizando la solicitud como un volumen. Las solicitudes deben existir en el mismo Namespace que el Pod que utiliza la solicitud. El clúster encuentra la solicitud en el Namespace del Pod y la utiliza para obtener el PersistentVolume que respalda la solicitud. Luego, el volumen se monta en el host y dentro del Pod. + +```yaml +apiVersion: v1 +kind: Pod +metadata: + name: mypod +spec: + containers: + - name: myfrontend + image: nginx + volumeMounts: + - mountPath: "/var/www/html" + name: mypd + volumes: + - name: mypd + persistentVolumeClaim: + claimName: myclaim +``` + +### Una Nota sobre Espacios de Nombres + +Las vinculaciones de PersistentVolumes son exclusivas y, dado que las PersistentVolumeClaims son objetos con espacio de nombres, montar solicitudes con modos "Many" (`ROX`, `RWX`) solo es posible dentro de un mismo espacio de nombres (namespace). + +### Los PersistentVolumes de tipo `hostPath` + +Los PersistentVolumes de tipo `hostPath` utilizan un archivo o directorio en el nodo para emular almacenamiento conectado a la red. Consulta [un ejemplo de un volumen de tipo `hostPath`](/docs/tasks/configure-pod-container/configure-persistent-volume-storage/#create-a-persistentvolume). + +## Soporte para Volúmenes en Bloque sin Procesar + +{{< feature-state for_k8s_version="v1.18" state="stable" >}} + +Los siguientes complementos de volumen admiten volúmenes en bloque sin procesar, incluida la provisión dinámica cuando corresponda: + +- CSI +- FC (Fibre Channel) +- iSCSI +- Volumen local +- OpenStack Cinder +- RBD (desaconsejado) +- RBD (Ceph Block Device; desaconsejado) +- VsphereVolume + +### PersistentVolume que Utiliza un Volumen en Bloque sin Procesar {#persistent-volume-using-a-raw-block-volume} + +```yaml +apiVersion: v1 +kind: PersistentVolume +metadata: + name: block-pv +spec: + capacity: + storage: 10Gi + accessModes: + - ReadWriteOnce + volumeMode: Block + persistentVolumeReclaimPolicy: Retain + fc: + targetWWNs: ["50060e801049cfd1"] + lun: 0 + readOnly: false +``` + +### PersistentVolumeClaim Solicitando un Volumen en Bloque sin Procesar {#persistent-volume-claim-requesting-a-raw-block-volume} + +```yaml +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: block-pvc +spec: + accessModes: + - ReadWriteOnce + volumeMode: Block + resources: + requests: + storage: 10Gi +``` + +### Especificación de Pod Agregando la Ruta del Dispositivo en Bloque sin Procesar en el Contenedor + +```yaml +apiVersion: v1 +kind: Pod +metadata: + name: pod-with-block-volume +spec: + containers: + - name: fc-container + image: fedora:26 + command: ["/bin/sh", "-c"] + args: ["tail -f /dev/null"] + volumeDevices: + - name: data + devicePath: /dev/xvda + volumes: + - name: data + persistentVolumeClaim: + claimName: block-pvc +``` + +{{< note >}} +Cuando agregas un dispositivo en bloque sin procesar para un Pod, especificas la ruta del dispositivo en el contenedor en lugar de una ruta de montaje. +{{< /note >}} + +### Vinculación de Volúmenes en Bloque + +Si un usuario solicita un volumen en bloque sin procesar indicándolo mediante el campo `volumeMode` en la especificación de PersistentVolumeClaim, las reglas de vinculación difieren ligeramente de versiones anteriores que no consideraban este modo como parte de la especificación. A continuación, se muestra una tabla de las posibles combinaciones que el usuario y el administrador pueden especificar para solicitar un dispositivo en bloque sin procesar. La tabla indica si el volumen se vinculará o no dadas las combinaciones: Matriz de vinculación de volumen para volúmenes provisionados estáticamente: + +| PV volumeMode | PVC volumeMode | Resultado | +| ------------- | :------------: | ------: | +| unspecified | unspecified | BIND | +| unspecified | Block | NO BIND | +| unspecified | Filesystem | BIND | +| Block | unspecified | NO BIND | +| Block | Block | BIND | +| Block | Filesystem | NO BIND | +| Filesystem | Filesystem | BIND | +| Filesystem | Block | NO BIND | +| Filesystem | unspecified | BIND | + +{{< note >}} +Solo se admiten volúmenes provisionados estáticamente en la versión alfa. Los administradores deben tener en cuenta estos valores al trabajar con dispositivos en bloque sin procesar. +{{< /note >}} + +## Soporte para Instantáneas de Volúmenes y Restauración de Volúmenes desde Instantáneas + +{{< feature-state for_k8s_version="v1.20" state="stable" >}} + +Las instantáneas de volúmenes solo admiten los plugins de volumen CSI fuera del árbol. Para obtener más detalles, consulta [Instantáneas de Volúmenes](/es/docs/concepts/storage/volume-snapshots/). Los plugins de volumen dentro del árbol están obsoletos. Puedes obtener información sobre los plugins de volumen obsoletos en el [FAQ de Plugins de Volumen](https://github.com/kubernetes/community/blob/master/sig-storage/volume-plugin-faq.md). + +### Crear una PersistentVolumeClaim desde una Instantánea de Volumen {#create-persistent-volume-claim-from-volume-snapshot} + +```yaml +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: restore-pvc +spec: + storageClassName: csi-hostpath-sc + dataSource: + name: new-snapshot-test + kind: VolumeSnapshot + apiGroup: snapshot.storage.k8s.io + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 10Gi +``` + +## Clonación de Volúmenes + +[Clonación de Volúmenes](/es/docs/concepts/storage/volume-pvc-datasource/) +solo está disponible para plugins de volumen CSI. + +### Crear una PersistentVolumeClaim desde una PVC existente {#create-persistent-volume-claim-from-an-existing-pvc} + +```yaml +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: cloned-pvc +spec: + storageClassName: my-csi-plugin + dataSource: + name: existing-src-pvc-name + kind: PersistentVolumeClaim + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 10Gi +``` + +## Pobladores de Volúmenes y Fuentes de Datos + +{{< feature-state for_k8s_version="v1.24" state="beta" >}} + +Kubernetes admite pobladores de volúmenes personalizados. +Para utilizar pobladores de volúmenes personalizados, debes habilitar la característica `AnyVolumeDataSource` +[feature gate](/docs/reference/command-line-tools-reference/feature-gates/) para el kube-apiserver y kube-controller-manager. + +Los pobladores de volúmenes aprovechan un campo de especificación de PVC llamado `dataSourceRef`. A diferencia del campo `dataSource`, que solo puede contener una referencia a otra PersistentVolumeClaim o a un VolumeSnapshot, el campo `dataSourceRef` puede contener una referencia a cualquier objeto en el mismo Namespace, excepto los objetos principales que no sean PVC. Para los clústeres que tienen habilitada la característica, se prefiere el uso de `dataSourceRef` en lugar de `dataSource`. + +## Fuentes de Datos entre Espacios de Nombres + +{{< feature-state for_k8s_version="v1.26" state="alpha" >}} + +Kubernetes admite fuentes de datos de volúmenes entre espacios de nombres. +Para utilizar fuentes de datos de volúmenes entre espacios de nombres, debes habilitar las características `AnyVolumeDataSource` y `CrossNamespaceVolumeDataSource` +[Interruptores de funcionalidades (feature gates)](/docs/reference/command-line-tools-reference/feature-gates/) para el kube-apiserver y kube-controller-manager. +Además, debes habilitar la característica `CrossNamespaceVolumeDataSource` para el csi-provisioner. + +Al habilitar la característica `CrossNamespaceVolumeDataSource`, puedes especificar un Namespace en el campo dataSourceRef. + +{{< note >}} +Cuando especificas un Namespace para una fuente de datos de volumen, Kubernetes verifica la existencia de un ReferenceGrant en el otro Namespace antes de aceptar la referencia. ReferenceGrant forma parte de las API de extensiones de `gateway.networking.k8s.io`. Consulta [ReferenceGrant](https://gateway-api.sigs.k8s.io/api-types/referencegrant/) en la documentación de la API de Gateway para obtener detalles. Esto significa que debes extender tu clúster de Kubernetes con al menos ReferenceGrant de la API de Gateway antes de poder utilizar este mecanismo. +{{< /note >}} + +## Las referencias a fuentes de datos + +El campo `dataSourceRef` se comporta de manera casi idéntica al campo `dataSource`. Si se especifica uno mientras que el otro no, el servidor de la API asignará el mismo valor a ambos campos. Ninguno de los campos puede cambiarse después de su creación, y cualquier intento de especificar valores diferentes para los dos campos resultará en un error de validación. Por lo tanto, los dos campos siempre tendrán el mismo contenido. + +Hay dos diferencias importantes entre el campo `dataSourceRef` y el campo `dataSource` que los usuarios deben tener en cuenta: + +- El campo `dataSource` ignora los valores no válidos (como si el campo estuviera en blanco), mientras que el campo `dataSourceRef` nunca ignora los valores y generará un error si se utiliza un valor no válido. Los valores no válidos son cualquier objeto central (objetos sin apiGroup) excepto PVCs. + +- El campo `dataSourceRef` puede contener diferentes tipos de objetos, mientras que el campo `dataSource` solo permite PVCs y VolumeSnapshots. + +Cuando se habilita la característica `CrossNamespaceVolumeDataSource`, existen diferencias adicionales: + +- El campo `dataSource` solo permite objetos locales, mientras que el campo `dataSourceRef` permite objetos en cualquier Namespaces. +- Cuando se especifica un Namespace, `dataSource` y `dataSourceRef` no están sincronizados. + +Los usuarios siempre deben utilizar `dataSourceRef` en clústeres que tengan habilitada la puerta de enlace de características y recurrir a `dataSource` en clústeres que no la tengan habilitada. No es necesario mirar ambos campos bajo ninguna circunstancia. Los valores duplicados con semántica ligeramente diferente existen solo por compatibilidad con versiones anteriores. En particular, una mezcla de controladores más antiguos y más nuevos pueden interoperar porque los campos son iguales. + +### Uso de pobladores de volúmenes + +Los pobladores de volúmenes son controladores que pueden crear volúmenes no vacíos, donde el contenido del volumen es determinado por un Recurso Personalizado. Los usuarios crean un volumen poblado haciendo referencia a un Recurso Personalizado utilizando el campo `dataSourceRef`: + +```yaml +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: populated-pvc +spec: + dataSourceRef: + name: example-name + kind: ExampleDataSource + apiGroup: example.storage.k8s.io + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 10Gi +``` + +Dado que los pobladores de volúmenes son componentes externos, los intentos de crear una PVC que los utilice pueden fallar si no se han instalado todos los componentes correctos. Los controladores externos deben generar eventos en la PVC para proporcionar retroalimentación sobre el estado de la creación, incluyendo advertencias si la PVC no puede ser creada debido a la falta de algún componente necesario. Esto ayuda a los usuarios a comprender por qué la creación de la PVC ha fallado y qué componentes faltan para que funcione correctamente. + +Puedes instalar el controlador [volume data source validator](https://github.com/kubernetes-csi/volume-data-source-validator) en tu clúster. Este controlador genera eventos de advertencia en una PVC en caso de que no haya ningún poblador registrado para manejar ese tipo de fuente de datos. Cuando se instala un poblador adecuado para una PVC, es responsabilidad de ese controlador de poblador informar sobre eventos relacionados con la creación del volumen y problemas durante el proceso. Esto proporciona información útil para los usuarios y administradores del clúster sobre el estado y los problemas relacionados con las PVC que utilizan pobladores de volúmenes. + +### Uso de una fuente de datos de volumen entre Namespaces + +{{< feature-state for_k8s_version="v1.26" state="alpha" >}} + +Crea un ReferenceGrant para permitir que el propietario del Namespace acepte la referencia. +Define un volumen poblado especificando una fuente de datos de volumen entre Namespaces utilizando el campo `dataSourceRef`. Debes tener un ReferenceGrant válido en el Namespace de origen previamente: + +```yaml +apiVersion: gateway.networking.k8s.io/v1beta1 +kind: ReferenceGrant +metadata: + name: allow-ns1-pvc + namespace: default +spec: + from: + - group: "" + kind: PersistentVolumeClaim + namespace: ns1 + to: + - group: snapshot.storage.k8s.io + kind: VolumeSnapshot + name: new-snapshot-demo +``` + +```yaml +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: foo-pvc + namespace: ns1 +spec: + storageClassName: example + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi + dataSourceRef: + apiGroup: snapshot.storage.k8s.io + kind: VolumeSnapshot + name: new-snapshot-demo + namespace: default + volumeMode: Filesystem +``` + +## Escribiendo configuraciones portátiles + +Si estás escribiendo plantillas de configuración o ejemplos que se ejecutarán en una amplia gama de clústeres y necesitas almacenamiento persistente, se recomienda que utilices el siguiente patrón: + +- Incluye objetos PersistentVolumeClaim en tu conjunto de configuración (junto con Despliegues, ConfigMaps, etc.). +- No incluyas objetos PersistentVolume en la configuración, ya que el usuario que instala la configuración puede no tener permisos para crear PersistentVolumes. +- Ofrece al usuario la opción de proporcionar un nombre de clase de almacenamiento al instanciar la plantilla. + - Si el usuario proporciona un nombre de clase de almacenamiento, coloca ese valor en el campo `persistentVolumeClaim.storageClassName`. + Esto hará que la PVC coincida con la clase de almacenamiento correcta si el administrador del clúster ha habilitado las StorageClasses. + - Si el usuario no proporciona un nombre de clase de almacenamiento, deja el campo `persistentVolumeClaim.storageClassName` como nulo. Esto hará que se provisione automáticamente un PV para el usuario con la StorageClass predeterminada en el clúster. Muchos entornos de clúster tienen una StorageClass predeterminada instalada, o los administradores pueden crear su propia StorageClass predeterminada. +- En tus herramientas, observa las PVC que no se están enlazando después de algún tiempo y comunica esto al usuario, ya que esto puede indicar que el clúster no tiene soporte de almacenamiento dinámico (en cuyo caso el usuario debe crear un PV correspondiente) o que el clúster no tiene un sistema de almacenamiento (en cuyo caso el usuario no puede implementar configuraciones que requieran PVCs). + +## {{% heading "whatsnext" %}} + +- Aprende más sobre [Cómo crear un PersistentVolume](/docs/tasks/configure-pod-container/configure-persistent-volume-storage/#create-a-persistentvolume). +- Aprende más sobre [Cómo crear un PersistentVolumeClaim](/docs/tasks/configure-pod-container/configure-persistent-volume-storage/#create-a-persistentvolumeclaim). +- Lee el [documento de diseño de almacenamiento persistente](https://git.k8s.io/design-proposals-archive/storage/persistent-storage.md). + +### Referencias de API {#reference} + +Puedes encontrar información detallada sobre las APIs [`PersistentVolume`](/docs/reference/kubernetes-api/config-and-storage-resources/persistent-volume-v1/) y [`PersistentVolumeClaim`](/docs/reference/kubernetes-api/config-and-storage-resources/persistent-volume-claim-v1/) en la documentación oficial de Kubernetes. Estos enlaces te llevarán a las páginas de referencia que describen las especificaciones y los campos de estas API, junto con ejemplos y ejercicios de uso. diff --git a/content/es/docs/concepts/storage/volumes.md b/content/es/docs/concepts/storage/volumes.md index e12e6bf25c996..f5ebc66aec3bb 100644 --- a/content/es/docs/concepts/storage/volumes.md +++ b/content/es/docs/concepts/storage/volumes.md @@ -1022,7 +1022,7 @@ Para apagar el complemento `vsphereVolume` y no cargarlo por el administrador de ## Uso de subPath {#using-subpath} Algunas veces es útil compartir un volumen para múltiples usos en un único Pod. -La propiedad `volumeMounts.subPath` especifica una sub-ruta dentro del volumen referenciado en lugar de su raíz. +La propiedad `volumeMounts[*].subPath` especifica una sub-ruta dentro del volumen referenciado en lugar de su raíz. El siguiente ejemplo muestra cómo configurar un Pod con la pila LAMP (Linux Apache MySQL PHP) usando un único volumen compartido. Esta configuración de ejemplo usando `subPath` no se recomienda para su uso en producción. @@ -1198,7 +1198,7 @@ For more details, see the [FlexVolume](https://github.com/kubernetes/community/b La propagación del montaje permite compartir volúmenes montados por un contenedor para otros contenedores en el mismo Pod, o aun para otros pods en el mismo nodo. -La propagación del montaje de un volumen es controlada por el campo `mountPropagation` en `Container.volumeMounts`. Sus valores son: +La propagación del montaje de un volumen es controlada por el campo `mountPropagation` en `containers[*].volumeMounts`. Sus valores son: - `None` - Este montaje de volumen no recibirá ningún montaje posterior que el host haya montado en este volumen o en cualquiera de sus subdirectorios. De manera similar, los montajes creados por el contenedor no serán visibles en el host. Este es el modo por defecto. diff --git a/content/es/docs/reference/glossary/ingress.md b/content/es/docs/reference/glossary/ingress.md new file mode 100644 index 0000000000000..651bbac84509f --- /dev/null +++ b/content/es/docs/reference/glossary/ingress.md @@ -0,0 +1,20 @@ +--- +title: Ingress +id: ingress +date: 2018-04-12 +full_link: /docs/concepts/services-networking/ingress/ +short_description: > + Un objeto de la API que administra el acceso externo a los servicios en un clúster, típicamente HTTP. + +aka: +tags: +- networking +- architecture +- extension +--- +Un objeto de la API que administra el acceso externo a los servicios en un clúster, típicamente HTTP. + + + +Un Ingress podría proveer balanceo de cargas, terminación SSL y hosting virtual basado en nombres. + diff --git a/content/es/docs/tasks/manage-kubernetes-objects/kustomization.md b/content/es/docs/tasks/manage-kubernetes-objects/kustomization.md new file mode 100644 index 0000000000000..e899476639d1f --- /dev/null +++ b/content/es/docs/tasks/manage-kubernetes-objects/kustomization.md @@ -0,0 +1,1004 @@ +--- +title: Manejo Declarativo de Objectos de Kubernetes usando Kustomize +content_type: task +weight: 20 +--- + + + +[Kustomize](https://github.com/kubernetes-sigs/kustomize) es una herramienta independiente para personalizar objetos de Kubernetes a través de un [archivo de kustomization](https://kubectl.docs.kubernetes.io/references/kustomize/glossary/#kustomization). + +Desde la versión 1.14, Kubectl también admite la gestión de objetos de Kubernetes utilizando un archivo de kustomización. Para ver Recursos encontrados en un directorio que contiene un archivo de kustomización, ejecuta el siguiente comando: + + +```shell +kubectl kustomize +``` + +Para aplicar esos Recursos, ejecuta `kubectl apply` con la bandera `--kustomize` o `-k` : + +```shell +kubectl apply -k +``` + + + +## {{% heading "prerequisites" %}} + + +Instala [`kubectl`](/docs/tasks/tools/). + +{{< include "task-tutorial-prereqs.md" >}} {{< version-check >}} + + + + + +## Descripción General de Kustomize + +Kustomize es una herramienta para personalizar configuraciones de Kubernetes. Ofrece características para manejar archivos de configuración de aplicaciones, tales como: + +* Generar recursos a partir de otras fuentes. +* Establecer campos transversales para los recursos. +* Componer y personalizar colecciones de recursos. + +### Generando Recursos + +ConfigMaps y Secrets almacenan configuración o datos sensibles utilizados por otros objetos de Kubernetes, como los Pods. La fuente de verdad de los ConfigMaps o Secrets suele ser externa a un clúster, como un archivo `.properties` o un archivo de clave SSH. +Kustomize tiene `secretGenerator` y `configMapGenerator`, que generan Secret y ConfigMap a partir de archivos o literales. + +#### configMapGenerator + +Para generar un ConfigMap desde un archivo, añade una entrada en la lista `files` en `configMapGenerator`. Aquí tienes un ejemplo de cómo generar un ConfigMap con un elemento de datos de un archivo `.properties`: + +```shell +# Crear un archivo application.properties +cat <application.properties +FOO=Bar +EOF + +cat <./kustomization.yaml +configMapGenerator: +- name: example-configmap-1 + files: + - application.properties +EOF +``` + +El ConfigMap generado se puede examinar con el siguiente comando: + +```shell +kubectl kustomize ./ +``` + +El ConfigMap generado es: + +```yaml +apiVersion: v1 +data: + application.properties: | + FOO=Bar +kind: ConfigMap +metadata: + name: example-configmap-1-8mbdf7882g +``` + +Para generar un ConfigMap desde un archivo env, añade una entrada en la lista de `envs` en `configMapGenerator`. Aquí tienes un ejemplo de cómo generar un ConfigMap con un elemento de datos de un archivo `.env`: + +```shell +# Crear un archivo .env +cat <.env +FOO=Bar +EOF + +cat <./kustomization.yaml +configMapGenerator: +- name: example-configmap-1 + envs: + - .env +EOF +``` + +El ConfigMap generado se puede examinar con el siguiente comando: + +```shell +kubectl kustomize ./ +``` + +El ConfigMap generado es: + +```yaml +apiVersion: v1 +data: + FOO: Bar +kind: ConfigMap +metadata: + name: example-configmap-1-42cfbf598f +``` + +{{< note >}} +Cada variable en el archivo `.env` se convierte en una clave separada en el ConfigMap que generas. Esto es diferente del ejemplo anterior, que incorpora un archivo llamado `application.properties` (y todas sus entradas) como el valor para una única clave. +{{< /note >}} + +Los ConfigMaps también pueden generarse a partir de pares clave-valor literales. Para generar un ConfigMap a partir de una literal clave-valor, añade una entrada a la lista `literals` en configMapGenerator. Aquí hay un ejemplo de cómo generar un ConfigMap con un elemento de datos de un par clave-valor: + +```shell +cat <./kustomization.yaml +configMapGenerator: +- name: example-configmap-2 + literals: + - FOO=Bar +EOF +``` + +El ConfigMap generado se puede verificar con el siguiente comando: + +```shell +kubectl kustomize ./ +``` + +El ConfigMap generado es: + +```yaml +apiVersion: v1 +data: + FOO: Bar +kind: ConfigMap +metadata: + name: example-configmap-2-g2hdhfc6tk +``` + +Para usar un ConfigMap generado en un Deployment, refiérelo por el nombre del configMapGenerator. Kustomize reemplazará automáticamente este nombre con el nombre generado. + +Este es un ejemplo de un Deployment que utiliza un ConfigMap generado: + +```yaml +# Crear un archivo application.properties +cat <application.properties +FOO=Bar +EOF + +cat <deployment.yaml +apiVersion: apps/v1 +kind: Deployment +metadata: + name: my-app + labels: + app: my-app +spec: + selector: + matchLabels: + app: my-app + template: + metadata: + labels: + app: my-app + spec: + containers: + - name: app + image: my-app + volumeMounts: + - name: config + mountPath: /config + volumes: + - name: config + configMap: + name: example-configmap-1 +EOF + +cat <./kustomization.yaml +resources: +- deployment.yaml +configMapGenerator: +- name: example-configmap-1 + files: + - application.properties +EOF +``` + +Genera el ConfigMap y Deployment: + +```shell +kubectl kustomize ./ +``` + +El Deployment generado hara referencia al ConfigMap generado por nombre: + +```yaml +apiVersion: v1 +data: + application.properties: | + FOO=Bar +kind: ConfigMap +metadata: + name: example-configmap-1-g4hk9g2ff8 +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app: my-app + name: my-app +spec: + selector: + matchLabels: + app: my-app + template: + metadata: + labels: + app: my-app + spec: + containers: + - image: my-app + name: app + volumeMounts: + - mountPath: /config + name: config + volumes: + - configMap: + name: example-configmap-1-g4hk9g2ff8 + name: config +``` + +#### secretGenerator + +Puedes generar Secrets a partir de archivos o pares clave-valor literales. Para generar un Secret a partir de un archivo, añade una entrada a la lista `files` en `secretGenerator`. Aquí tienes un ejemplo de cómo generar un Secret con un elemento de datos de un archivo. + +```shell +# Crea un archivo password.txt +cat <./password.txt +username=admin +password=secret +EOF + +cat <./kustomization.yaml +secretGenerator: +- name: example-secret-1 + files: + - password.txt +EOF +``` + +El Secret generado se vería de la siguiente manera: + +```yaml +apiVersion: v1 +data: + password.txt: dXNlcm5hbWU9YWRtaW4KcGFzc3dvcmQ9c2VjcmV0Cg== +kind: Secret +metadata: + name: example-secret-1-t2kt65hgtb +type: Opaque +``` + +Para generar un Secret a partir de una literal clave-valor, añade una entrada a la lista `literals` en `secretGenerator`. Aquí tienes un ejemplo de cómo generar un Secret con un elemento de datos de un par clave-valor. + +```shell +cat <./kustomization.yaml +secretGenerator: +- name: example-secret-2 + literals: + - username=admin + - password=secret +EOF +``` + +El Secret generado se verá de la siguiente manera: + +```yaml +apiVersion: v1 +data: + password: c2VjcmV0 + username: YWRtaW4= +kind: Secret +metadata: + name: example-secret-2-t52t6g96d8 +type: Opaque +``` + +Al igual que los ConfigMaps, los Secrets generados pueden utilizarse en Deployments refiriéndose al nombre del secretGenerator. + +```shell +# Crea un archivo password.txt +cat <./password.txt +username=admin +password=secret +EOF + +cat <deployment.yaml +apiVersion: apps/v1 +kind: Deployment +metadata: + name: my-app + labels: + app: my-app +spec: + selector: + matchLabels: + app: my-app + template: + metadata: + labels: + app: my-app + spec: + containers: + - name: app + image: my-app + volumeMounts: + - name: password + mountPath: /secrets + volumes: + - name: password + secret: + secretName: example-secret-1 +EOF + +cat <./kustomization.yaml +resources: +- deployment.yaml +secretGenerator: +- name: example-secret-1 + files: + - password.txt +EOF +``` + +#### generatorOptions + +Los ConfigMaps y Secrets generados tienen un sufijo de hash de contenido añadido. Esto asegura que se genere un nuevo ConfigMap o Secret cuando se cambian los contenidos. Para desactivar el comportamiento de añadir un sufijo, se puede utilizar `generatorOptions`. Además, es posible especificar opciones transversales para los ConfigMaps y Secrets generados. + +```shell +cat <./kustomization.yaml +configMapGenerator: +- name: example-configmap-3 + literals: + - FOO=Bar +generatorOptions: + disableNameSuffixHash: true + labels: + type: generated + annotations: + note: generated +EOF +``` + +Ejecuta `kubectl kustomize ./` para visualizar el ConfigMap generado: + +```yaml +apiVersion: v1 +data: + FOO: Bar +kind: ConfigMap +metadata: + annotations: + note: generated + labels: + type: generated + name: example-configmap-3 +``` + +### Establecer campos transversales + +Es bastante común establecer campos transversales para todos los recursos de Kubernetes en un proyecto. +Algunos casos de uso para establecer campos transversales: + +* Establecer el mismo espacio de nombres para todos los Recursos +* Agregar el mismo prefijo o sufijo de nombre +* Agregar el mismo conjunto de etiquetas +* Agregar el mismo conjunto de anotaciones + +Aquí hay un ejemplo: + +```shell +# Crea un deployment.yaml +cat <./deployment.yaml +apiVersion: apps/v1 +kind: Deployment +metadata: + name: nginx-deployment + labels: + app: nginx +spec: + selector: + matchLabels: + app: nginx + template: + metadata: + labels: + app: nginx + spec: + containers: + - name: nginx + image: nginx +EOF + +cat <./kustomization.yaml +namespace: my-namespace +namePrefix: dev- +nameSuffix: "-001" +commonLabels: + app: bingo +commonAnnotations: + oncallPager: 800-555-1212 +resources: +- deployment.yaml +EOF +``` + +Ejecuta `kubectl kustomize ./` para ver que esos campos están todos establecidos en el Recurso Deployment: + +```yaml +apiVersion: apps/v1 +kind: Deployment +metadata: + annotations: + oncallPager: 800-555-1212 + labels: + app: bingo + name: dev-nginx-deployment-001 + namespace: my-namespace +spec: + selector: + matchLabels: + app: bingo + template: + metadata: + annotations: + oncallPager: 800-555-1212 + labels: + app: bingo + spec: + containers: + - image: nginx + name: nginx +``` + +### Componiendo y Personalizando Recursos + +Es común componer un conjunto de recursos en un proyecto y gestionarlos dentro del mismo archivo o directorio. + +Kustomize ofrece la composición de recursos desde diferentes archivos y la aplicación de parches u otras personalizaciones a ellos. + +#### Composición + +Kustomize admite la composición de diferentes recursos. El campo `resources`, en el archivo `kustomization.yaml`, define la lista de recursos para incluir en una configuración. Establece la ruta al archivo de configuración de un recurso en la lista `resources`. + +Aquí hay un ejemplo de una aplicación NGINX compuesta por un Deployment y un Service: + +```shell +# Crea un archivo deployment.yaml +cat < deployment.yaml +apiVersion: apps/v1 +kind: Deployment +metadata: + name: my-nginx +spec: + selector: + matchLabels: + run: my-nginx + replicas: 2 + template: + metadata: + labels: + run: my-nginx + spec: + containers: + - name: my-nginx + image: nginx + ports: + - containerPort: 80 +EOF + +# Crea un archivo service.yaml +cat < service.yaml +apiVersion: v1 +kind: Service +metadata: + name: my-nginx + labels: + run: my-nginx +spec: + ports: + - port: 80 + protocol: TCP + selector: + run: my-nginx +EOF + +# Crea un kustomization.yaml que los integra +cat <./kustomization.yaml +resources: +- deployment.yaml +- service.yaml +EOF +``` + +Los Recursos de `kubectl kustomize ./` contienen tanto los objetos de Deployment como los de Service. + +#### Personalizando + +Los parches pueden usarse para aplicar diferentes personalizaciones a los recursos. Kustomize admite diferentes mecanismos de parcheo a través de `patchesStrategicMerge` y `patchesJson6902`. `patchesStrategicMerge` es una lista de rutas de archivo. Cada archivo debe resolverse en un [parche de fusión estratégica](https://github.com/kubernetes/community/blob/master/contributors/devel/sig-api-machinery/strategic-merge-patch.md). Los nombres dentro de los parches deben coincidir con los nombres de recursos que ya están cargados. Se recomiendan pequeños parches que hagan una sola cosa. Por ejemplo, crear un parche para aumentar el número de réplicas del Deployment y otro parche para establecer el límite de memoria. + +```shell +# Crea un archivo deployment.yaml +cat < deployment.yaml +apiVersion: apps/v1 +kind: Deployment +metadata: + name: my-nginx +spec: + selector: + matchLabels: + run: my-nginx + replicas: 2 + template: + metadata: + labels: + run: my-nginx + spec: + containers: + - name: my-nginx + image: nginx + ports: + - containerPort: 80 +EOF + +# Crea un parche increase_replicas.yaml +cat < increase_replicas.yaml +apiVersion: apps/v1 +kind: Deployment +metadata: + name: my-nginx +spec: + replicas: 3 +EOF + +# Crea otro parche set_memory.yaml +cat < set_memory.yaml +apiVersion: apps/v1 +kind: Deployment +metadata: + name: my-nginx +spec: + template: + spec: + containers: + - name: my-nginx + resources: + limits: + memory: 512Mi +EOF + +cat <./kustomization.yaml +resources: +- deployment.yaml +patchesStrategicMerge: +- increase_replicas.yaml +- set_memory.yaml +EOF +``` + +Ejecuta `kubectl kustomize ./` para visualizar el Deployment: + +```yaml +apiVersion: apps/v1 +kind: Deployment +metadata: + name: my-nginx +spec: + replicas: 3 + selector: + matchLabels: + run: my-nginx + template: + metadata: + labels: + run: my-nginx + spec: + containers: + - image: nginx + name: my-nginx + ports: + - containerPort: 80 + resources: + limits: + memory: 512Mi +``` + +No todos los recursos o campos admiten parches de fusión estratégica. Para admitir la modificación de campos arbitrarios en recursos arbitrarios, +Kustomize ofrece la implementacion a través de [JSON patch](https://tools.ietf.org/html/rfc6902) `patchesJson6902`. +Para encontrar el Recurso correcto para un parche Json, el grupo, versión, tipo y nombre de ese recurso necesitan ser especificados en `kustomization.yaml`. Por ejemplo, aumentar el número de réplicas de un objeto de Deployment también se puede hacer a través de `patchesJson6902`. + +```shell +# Crea un archivo deployment.yaml +cat < deployment.yaml +apiVersion: apps/v1 +kind: Deployment +metadata: + name: my-nginx +spec: + selector: + matchLabels: + run: my-nginx + replicas: 2 + template: + metadata: + labels: + run: my-nginx + spec: + containers: + - name: my-nginx + image: nginx + ports: + - containerPort: 80 +EOF + +# Crea un parche en json +cat < patch.yaml +- op: replace + path: /spec/replicas + value: 3 +EOF + +# Crea un kustomization.yaml +cat <./kustomization.yaml +resources: +- deployment.yaml + +patchesJson6902: +- target: + group: apps + version: v1 + kind: Deployment + name: my-nginx + path: patch.yaml +EOF +``` + +Ejecuta `kubectl kustomize ./` para ver que el campo `replicas` está actualizado: + +```yaml +apiVersion: apps/v1 +kind: Deployment +metadata: + name: my-nginx +spec: + replicas: 3 + selector: + matchLabels: + run: my-nginx + template: + metadata: + labels: + run: my-nginx + spec: + containers: + - image: nginx + name: my-nginx + ports: + - containerPort: 80 +``` + +Además de los parches, Kustomize también ofrece personalizar imágenes de contenedores o inyectar valores de campos de otros objetos en contenedores sin crear parches. Por ejemplo, puedes cambiar la imagen utilizada dentro de los contenedores especificando la nueva imagen en el campo `images` en `kustomization.yaml`. + +```shell +cat < deployment.yaml +apiVersion: apps/v1 +kind: Deployment +metadata: + name: my-nginx +spec: + selector: + matchLabels: + run: my-nginx + replicas: 2 + template: + metadata: + labels: + run: my-nginx + spec: + containers: + - name: my-nginx + image: nginx + ports: + - containerPort: 80 +EOF + +cat <./kustomization.yaml +resources: +- deployment.yaml +images: +- name: nginx + newName: my.image.registry/nginx + newTag: 1.4.0 +EOF +``` +Ejecuta `kubectl kustomize ./` para ver que el campo `image` ha sido actualizado: + +```yaml +apiVersion: apps/v1 +kind: Deployment +metadata: + name: my-nginx +spec: + replicas: 2 + selector: + matchLabels: + run: my-nginx + template: + metadata: + labels: + run: my-nginx + spec: + containers: + - image: my.image.registry/nginx:1.4.0 + name: my-nginx + ports: + - containerPort: 80 +``` + +A veces, la aplicación que se ejecuta en un Pod puede necesitar usar valores de configuración de otros objetos. Por ejemplo, un Pod de un objeto de Deployment necesita leer el nombre del Service correspondiente desde Env o como un argumento de comando. + +Dado que el nombre del Service puede cambiar a medida que se agrega `namePrefix` o `nameSuffix` en el archivo `kustomization.yaml`. No se recomienda codificar de manera fija el nombre del Service en el argumento del comando. Para este uso, Kustomize puede inyectar el nombre del Service en los contenedores a través de vars. + +```shell +# Crea un archivo deployment.yaml (citando el delimitador de documento aquí) +cat <<'EOF' > deployment.yaml +apiVersion: apps/v1 +kind: Deployment +metadata: + name: my-nginx +spec: + selector: + matchLabels: + run: my-nginx + replicas: 2 + template: + metadata: + labels: + run: my-nginx + spec: + containers: + - name: my-nginx + image: nginx + command: ["start", "--host", "$(MY_SERVICE_NAME)"] +EOF + +# Crea un archivo service.yaml +cat < service.yaml +apiVersion: v1 +kind: Service +metadata: + name: my-nginx + labels: + run: my-nginx +spec: + ports: + - port: 80 + protocol: TCP + selector: + run: my-nginx +EOF + +cat <./kustomization.yaml +namePrefix: dev- +nameSuffix: "-001" + +resources: +- deployment.yaml +- service.yaml + +vars: +- name: MY_SERVICE_NAME + objref: + kind: Service + name: my-nginx + apiVersion: v1 +EOF +``` + +Ejecuta `kubectl kustomize ./` para ver que el nombre del Service inyectado en la sección de contaierns es `dev-my-nginx-001`: + +```yaml +apiVersion: apps/v1 +kind: Deployment +metadata: + name: dev-my-nginx-001 +spec: + replicas: 2 + selector: + matchLabels: + run: my-nginx + template: + metadata: + labels: + run: my-nginx + spec: + containers: + - command: + - start + - --host + - dev-my-nginx-001 + image: nginx + name: my-nginx +``` + +## Bases y Overlays + + +Kustomize tiene los conceptos de **bases** y **overlays**. Una **base** es un directorio con un `kustomization.yaml`, que contiene un conjunto de recursos y personalización asociada. Una **base** puede ser un directorio local o un directorio de un repositorio remoto, siempre que haya un ``kustomization.yaml`` presente dentro. Un **overlay** es un directorio con un ``kustomization.yaml`` que se refiere a otros directorios de kustomization como sus `bases`. Una **base** no tiene conocimiento de un **overlay** y puede ser utilizada en múltiples **overlays**. Un **overlay** puede tener múltiples **bases** y compone todos los recursos de las **bases** y también puede tener personalizaciones encima de ellos. + +Aquí hay un ejemplo de una base: + +```shell + +# Crea un directorio que tendrá la **base** + +mkdir base + +# Crea el archivo base/deployment.yaml +cat < base/deployment.yaml +apiVersion: apps/v1 +kind: Deployment +metadata: + name: my-nginx +spec: + selector: + matchLabels: + run: my-nginx + replicas: 2 + template: + metadata: + labels: + run: my-nginx + spec: + containers: + - name: my-nginx + image: nginx +EOF + +# Crea el archivo base/service.yaml +cat < base/service.yaml +apiVersion: v1 +kind: Service +metadata: + name: my-nginx + labels: + run: my-nginx +spec: + ports: + - port: 80 + protocol: TCP + selector: + run: my-nginx +EOF +# Crea un archivo base/kustomization.yaml +cat < base/kustomization.yaml +resources: +- deployment.yaml +- service.yaml +EOF +``` + +Esta **base** puede ser utilizada en múltiples **overlays**. Puedes agregar diferentes `namePrefix` u otros campos transversales en diferentes **overlays**. Aquí hay dos **overlays** utilizando la misma **base**. + +```shell +mkdir dev +cat < dev/kustomization.yaml +resources: +- ../base +namePrefix: dev- +EOF + +mkdir prod +cat < prod/kustomization.yaml +resources: +- ../base +namePrefix: prod- +EOF +``` + +## Cómo aplicar/ver/eliminar objetos usando Kustomize + +Usa `--kustomize` o `-k` en comandos de `kubectl` para reconocer recursos gestionados por +`kustomization.yaml`. +Nota que `-k` debe apuntar a un directorio de kustomization, tal como: + +```shell +kubectl apply -k / +``` + +Dando como resultado el siguiente`kustomization.yaml`, + +```shell +# Crea un archivo deployment.yaml +cat < deployment.yaml +apiVersion: apps/v1 +kind: Deployment +metadata: + name: my-nginx +spec: + selector: + matchLabels: + run: my-nginx + replicas: 2 + template: + metadata: + labels: + run: my-nginx + spec: + containers: + - name: my-nginx + image: nginx + ports: + - containerPort: 80 +EOF + +# Crea un archivo kustomization.yaml +cat <./kustomization.yaml +namePrefix: dev- +commonLabels: + app: my-nginx +resources: +- deployment.yaml +EOF +``` + +Ejecuta el siguiente comando para aplicar el objeto de Deployment `dev-my-nginx`: + +```shell +> kubectl apply -k ./ +deployment.apps/dev-my-nginx created +``` + +Ejecuta uno de los siguientes comandos para ver el objeto de Deployment `dev-my-nginx`: + +```shell +kubectl get -k ./ +``` + +```shell +kubectl describe -k ./ +``` + +Ejecuta el siguiente comando para comparar el objecto Deployment `dev-my-nginx` contra el +estado en el que estaría el clúster si se aplicara el manifiesto: +```shell +kubectl diff -k ./ +``` + +Ejecuta el siguiente comando para eliminar el objeto de Deployment `dev-my-nginx`: + +```shell +> kubectl delete -k ./ +deployment.apps "dev-my-nginx" deleted +``` + +## Kustomize Feature List + +| Campo | Tipo | Explicación | +|-----------------------|--------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------| +| namespace | string | Agregar namespace a todos los recursos | +| namePrefix | string | El valor de este campo se antepone a los nombres de todos los recursos | +| nameSuffix | string | El valor de este campo se añade al final de los nombres de todos los recursos | +| commonLabels | map[string]string | Etiquetas para agregar a los recursos y selectores. | +| commonAnnotations | map[string]string | Anotaciones para agregar a todos los recursos | +| resources | []string | Cada entrada en esta lista debe resolverse en un archivo de configuración de recurso existente | +| configMapGenerator | [][ConfigMapArgs](https://github.com/kubernetes-sigs/kustomize/blob/master/api/types/configmapargs.go#L7) | Cada entrada en esta lista genera un ConfigMap | +| secretGenerator | [][SecretArgs](https://github.com/kubernetes-sigs/kustomize/blob/master/api/types/secretargs.go#L7) | Cada entrada en esta lista genera un Secret | +| generatorOptions | [GeneratorOptions](https://github.com/kubernetes-sigs/kustomize/blob/master/api/types/generatoroptions.go#L7) | Modifica comportamientos de todos los generadores de ConfigMap y Secret | +| bases | []string | Cada entrada en esta lista debe resolverse en un directorio que contenga un archivo kustomization.yaml | +| patchesStrategicMerge | []string | Cada entrada en esta lista debe resolver un parche de fusión estratégica de un objeto de Kubernetes | +| patchesJson6902 | [][Patch](https://github.com/kubernetes-sigs/kustomize/blob/master/api/types/patch.go#L10) | Cada entrada en esta lista debe resolverse en un objeto de Kubernetes y un parche Json | +| vars | [][Var](https://github.com/kubernetes-sigs/kustomize/blob/master/api/types/var.go#L19) | Cada entrada es para capturar texto del campo de un recurso | +| images | [][Image](https://github.com/kubernetes-sigs/kustomize/blob/master/api/types/image.go#L8) | Cada entrada es para modificar el nombre, las etiquetas y/o el digesto de una imagen sin crear parches | +| configurations | []string | Cada entrada en esta lista debe resolverse en un archivo que contenga [Configuraciones de transformador de Kustomize](https://github.com/kubernetes-sigs/kustomize/tree/master/examples/transformerconfigs) | +| crds | []string | Cada entrada en esta lista debería resolver a un archivo de definición OpenAPI para los tipos de Kubernetes. | + +## {{% heading "whatsnext" %}} + + +* [Kustomize](https://github.com/kubernetes-sigs/kustomize) +* [Documentación de Kubectl](https://kubectl.docs.kubernetes.io) +* [Referencia de Comando de Kubectl](/docs/reference/generated/kubectl/kubectl-commands/) +* [Referencia de Kubernetes API](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/) diff --git a/content/es/docs/tasks/run-application/force-delete-stateful-set-pod.md b/content/es/docs/tasks/run-application/force-delete-stateful-set-pod.md new file mode 100644 index 0000000000000..2864766f5ccfa --- /dev/null +++ b/content/es/docs/tasks/run-application/force-delete-stateful-set-pod.md @@ -0,0 +1,109 @@ +--- +reviewers: +- ramrodo +title: Eliminación Forzosa de Pods de StatefulSet +content_type: task +weight: 70 +--- + + +Esta página muestra cómo eliminar Pods que son parte de un +{{< glossary_tooltip text="StatefulSet" term_id="StatefulSet" >}}, +y explica las consideraciones a tener en cuenta al hacerlo. + +## {{% heading "prerequisites" %}} + +- Esta es una tarea bastante avanzada y tiene el potencial de violar algunas de las propiedades + inherentes de StatefulSet. +- Antes de proceder, familiarízate con las consideraciones enumeradas a continuación. + + + +## Consideraciones de StatefulSet + +En la operación normal de un StatefulSet, **nunca** hay necesidad de eliminar forzosamente un Pod de StatefulSet. +El [controlador de StatefulSet](/es/docs/concepts/workloads/controllers/statefulset/) es responsable de +crear, escalar y eliminar miembros del StatefulSet. Intenta asegurar que el número especificado +de Pods, desde el ordinal 0 hasta N-1, estén vivos y listos. StatefulSet asegura que, en cualquier momento, +exista como máximo un Pod con una identidad dada, corriendo en un clúster. Esto se refiere a la semántica de +*como máximo uno* proporcionada por un StatefulSet. + +La eliminación manual forzada debe realizarse con precaución, ya que tiene el potencial de violar la +semántica de como máximo uno, inherente a StatefulSet. Los StatefulSets pueden usarse para ejecutar aplicaciones distribuidas y +agrupadas que necesitan una identidad de red estable y almacenamiento estable. +Estas aplicaciones a menudo tienen configuraciones que dependen de un conjunto de un número fijo de +miembros con identidades fijas. Tener múltiples miembros con la misma identidad puede ser desastroso +y puede llevar a pérdida de datos (por ejemplo, escenario de cerebro dividido en sistemas basados en quórum). + +## Eliminar Pods + +Puedes realizar una eliminación de Pod paulatina con el siguiente comando: + +```shell +kubectl delete pods +``` + +Para que lo anterior conduzca a una terminación paulatina, el Pod no debe especificar un +`pod.Spec.TerminationGracePeriodSeconds` de 0. La práctica de establecer un +`pod.Spec.TerminationGracePeriodSeconds` de 0 segundos es insegura y se desaconseja rotundamente +para los Pods de StatefulSet. La eliminación paulatina es segura y garantizará que el Pod +se apague de [manera paulatina](/docs/concepts/workloads/pods/pod-lifecycle/#pod-termination), antes de que kubelet elimine el nombre en el apiserver. + +Un Pod no se elimina automáticamente cuando un nodo no es accesible. +Los Pods que se ejecutan en un Nodo inaccesible entran en el estado 'Terminating' o 'Unknown' después de un +[tiempo de espera](es/docs/concepts/architecture/nodes/#Estados). +Los Pods también pueden entrar en estos estados cuando el usuario intenta la eliminación paulatina de un Pod +en un nodo inaccesible. +Las únicas formas en que un Pod en tal estado puede ser eliminado del apiserver son las siguientes: + +- El objeto Node es eliminado (ya sea por ti, o por el [Controlador de Nodo](/es/docs/concepts/architecture/nodes/#controlador-de-nodos)).). +- Kubelet, en el nodo no responsivo, comienza a responder, mata el Pod y elimina la entrada del apiserver. +- Eliminación forzada del Pod por el usuario. +- +La mejor práctica recomendada es usar el primer o segundo enfoque. Si un nodo está confirmado +como muerto (por ejemplo, desconectado permanentemente de la red, apagado, etc.), entonces elimina +el objeto Node. Si el nodo es afectado de una partición de red, entonces trata de resolver esto +o espera a que se resuelva. Cuando la partición se solucione, kubelet completará la eliminación +del Pod y liberará su nombre en el apiserver. + +Normalmente, el sistema completa la eliminación una vez que el Pod ya no se está ejecutando en un nodo, o +el nodo es eliminado por un administrador. Puedes anular esto forzando la eliminación del Pod. + +### Eliminación Forzosa + +Las eliminaciones forzosas **no** esperan confirmación de kubelet de que el Pod ha sido terminado. +Independientemente de si una eliminación forzosa tiene éxito en matar un Pod, inmediatamente +liberará el nombre del apiserver. Esto permitiría que el controlador de StatefulSet cree un Pod de reemplazo +con esa misma identidad; esto puede llevar a la duplicación de un Pod que aún está en ejecución, +y si dicho Pod todavía puede comunicarse con los otros miembros del StatefulSet, +violará la semántica de como máximo uno que StatefulSet está diseñado para garantizar. + +Cuando eliminas forzosamente un Pod de StatefulSet, estás afirmando que el Pod en cuestión nunca +volverá a hacer contacto con otros Pods en el StatefulSet y su nombre puede ser liberado de forma segura para que +se cree un reemplazo. + + +Si quieres eliminar un Pod de forma forzosa usando la versión de kubectl >= 1.5, haz lo siguiente: + +```shell +kubectl delete pods --grace-period=0 --force +``` + +Si estás usando cualquier versión de kubectl <= 1.4, deberías omitir la opción `--force` y usar: + +```shell +kubectl delete pods --grace-period=0 +``` + +Si incluso después de estos comandos el pod está atascado en el estado `Unknown`, usa el siguiente comando para +eliminar el Pod del clúster: + +```shell +kubectl patch pod -p '{"metadata":{"finalizers":null}}' +``` + +Siempre realiza la eliminación forzosa de Pods de StatefulSet con cuidado y con pleno conocimiento de los riesgos involucrados. + +## {{% heading "whatsnext" %}} + +Aprende más sobre [depurar un StatefulSet](/docs/tasks/debug/debug-application/debug-statefulset/). diff --git a/content/es/docs/tasks/tools/included/verify-kubectl.md b/content/es/docs/tasks/tools/included/verify-kubectl.md index 15bd90692cd55..9bc4d582f3df8 100644 --- a/content/es/docs/tasks/tools/included/verify-kubectl.md +++ b/content/es/docs/tasks/tools/included/verify-kubectl.md @@ -24,7 +24,7 @@ The connection to the server was refused - did you specify th Por ejemplo, si tiene la intención de ejecutar un clúster de Kubernetes en su computadora portátil (localmente), primero necesitará instalar una herramienta como Minikube y luego volver a ejecutar los comandos indicados anteriormente. -Si kubectl cluster-info devuelve la respuesta de la URL pero no puede acceder a su clúster, para verificar si está configurado correctamente, use: +Si `kubectl cluster-info` devuelve la respuesta de la URL pero no puede acceder a su clúster, para verificar si está configurado correctamente, use: ```shell kubectl cluster-info dump diff --git a/content/es/docs/tutorials/kubernetes-basics/create-cluster/cluster-interactive.html b/content/es/docs/tutorials/kubernetes-basics/create-cluster/cluster-interactive.html index 6743729d49ec4..6e04566bea0b1 100644 --- a/content/es/docs/tutorials/kubernetes-basics/create-cluster/cluster-interactive.html +++ b/content/es/docs/tutorials/kubernetes-basics/create-cluster/cluster-interactive.html @@ -9,8 +9,7 @@ - - +
          diff --git a/content/es/docs/tutorials/kubernetes-basics/deploy-app/deploy-interactive.html b/content/es/docs/tutorials/kubernetes-basics/deploy-app/deploy-interactive.html index 2ec6de59e93f9..74b4c50469cfd 100644 --- a/content/es/docs/tutorials/kubernetes-basics/deploy-app/deploy-interactive.html +++ b/content/es/docs/tutorials/kubernetes-basics/deploy-app/deploy-interactive.html @@ -9,8 +9,6 @@ - -
          diff --git a/content/es/examples/service/networking/default-ingressclass.yaml b/content/es/examples/service/networking/default-ingressclass.yaml new file mode 100644 index 0000000000000..0602ad8c9d16d --- /dev/null +++ b/content/es/examples/service/networking/default-ingressclass.yaml @@ -0,0 +1,10 @@ +apiVersion: networking.k8s.io/v1 +kind: IngressClass +metadata: + labels: + app.kubernetes.io/component: controller + name: nginx-example + annotations: + ingressclass.kubernetes.io/is-default-class: "true" +spec: + controller: k8s.io/ingress-nginx diff --git a/content/es/examples/service/networking/example-ingress.yaml b/content/es/examples/service/networking/example-ingress.yaml new file mode 100644 index 0000000000000..085c71324f71f --- /dev/null +++ b/content/es/examples/service/networking/example-ingress.yaml @@ -0,0 +1,18 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: example-ingress + annotations: + nginx.ingress.kubernetes.io/rewrite-target: /$1 +spec: + rules: + - host: hello-world.info + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: web + port: + number: 8080 diff --git a/content/es/examples/service/networking/external-lb.yaml b/content/es/examples/service/networking/external-lb.yaml new file mode 100644 index 0000000000000..adcf7a2fd0a53 --- /dev/null +++ b/content/es/examples/service/networking/external-lb.yaml @@ -0,0 +1,10 @@ +apiVersion: networking.k8s.io/v1 +kind: IngressClass +metadata: + name: external-lb +spec: + controller: example.com/ingress-controller + parameters: + apiGroup: k8s.example.com + kind: IngressParameters + name: external-lb diff --git a/content/es/examples/service/networking/ingress-resource-backend.yaml b/content/es/examples/service/networking/ingress-resource-backend.yaml new file mode 100644 index 0000000000000..87b6bbd0f3757 --- /dev/null +++ b/content/es/examples/service/networking/ingress-resource-backend.yaml @@ -0,0 +1,20 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: ingress-resource-backend +spec: + defaultBackend: + resource: + apiGroup: k8s.example.com + kind: StorageBucket + name: static-assets + rules: + - http: + paths: + - path: /icons + pathType: ImplementationSpecific + backend: + resource: + apiGroup: k8s.example.com + kind: StorageBucket + name: icon-assets diff --git a/content/es/examples/service/networking/ingress-wildcard-host.yaml b/content/es/examples/service/networking/ingress-wildcard-host.yaml new file mode 100644 index 0000000000000..2be7016706cee --- /dev/null +++ b/content/es/examples/service/networking/ingress-wildcard-host.yaml @@ -0,0 +1,26 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: ingress-wildcard-host +spec: + rules: + - host: "foo.bar.com" + http: + paths: + - pathType: Prefix + path: "/bar" + backend: + service: + name: service1 + port: + number: 80 + - host: "*.foo.com" + http: + paths: + - pathType: Prefix + path: "/foo" + backend: + service: + name: service2 + port: + number: 80 diff --git a/content/es/examples/service/networking/minimal-ingress.yaml b/content/es/examples/service/networking/minimal-ingress.yaml new file mode 100644 index 0000000000000..55a5837510af1 --- /dev/null +++ b/content/es/examples/service/networking/minimal-ingress.yaml @@ -0,0 +1,18 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: minimal-ingress + annotations: + nginx.ingress.kubernetes.io/rewrite-target: / +spec: + ingressClassName: nginx-example + rules: + - http: + paths: + - path: /testpath + pathType: Prefix + backend: + service: + name: test + port: + number: 80 diff --git a/content/es/examples/service/networking/name-virtual-host-ingress-no-third-host.yaml b/content/es/examples/service/networking/name-virtual-host-ingress-no-third-host.yaml new file mode 100644 index 0000000000000..16a560b1ff287 --- /dev/null +++ b/content/es/examples/service/networking/name-virtual-host-ingress-no-third-host.yaml @@ -0,0 +1,35 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: name-virtual-host-ingress-no-third-host +spec: + rules: + - host: first.bar.com + http: + paths: + - pathType: Prefix + path: "/" + backend: + service: + name: service1 + port: + number: 80 + - host: second.bar.com + http: + paths: + - pathType: Prefix + path: "/" + backend: + service: + name: service2 + port: + number: 80 + - http: + paths: + - pathType: Prefix + path: "/" + backend: + service: + name: service3 + port: + number: 80 diff --git a/content/es/examples/service/networking/name-virtual-host-ingress.yaml b/content/es/examples/service/networking/name-virtual-host-ingress.yaml new file mode 100644 index 0000000000000..213a73d261250 --- /dev/null +++ b/content/es/examples/service/networking/name-virtual-host-ingress.yaml @@ -0,0 +1,26 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: name-virtual-host-ingress +spec: + rules: + - host: foo.bar.com + http: + paths: + - pathType: Prefix + path: "/" + backend: + service: + name: service1 + port: + number: 80 + - host: bar.foo.com + http: + paths: + - pathType: Prefix + path: "/" + backend: + service: + name: service2 + port: + number: 80 diff --git a/content/es/examples/service/networking/simple-fanout-example.yaml b/content/es/examples/service/networking/simple-fanout-example.yaml new file mode 100644 index 0000000000000..19fef9455be70 --- /dev/null +++ b/content/es/examples/service/networking/simple-fanout-example.yaml @@ -0,0 +1,23 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: simple-fanout-example +spec: + rules: + - host: foo.bar.com + http: + paths: + - path: /foo + pathType: Prefix + backend: + service: + name: service1 + port: + number: 4200 + - path: /bar + pathType: Prefix + backend: + service: + name: service2 + port: + number: 8080 diff --git a/content/es/examples/service/networking/test-ingress.yaml b/content/es/examples/service/networking/test-ingress.yaml new file mode 100644 index 0000000000000..acd384ab5633a --- /dev/null +++ b/content/es/examples/service/networking/test-ingress.yaml @@ -0,0 +1,10 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: test-ingress +spec: + defaultBackend: + service: + name: test + port: + number: 80 diff --git a/content/es/examples/service/networking/tls-example-ingress.yaml b/content/es/examples/service/networking/tls-example-ingress.yaml new file mode 100644 index 0000000000000..fe5d52a0cbef0 --- /dev/null +++ b/content/es/examples/service/networking/tls-example-ingress.yaml @@ -0,0 +1,20 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: tls-example-ingress +spec: + tls: + - hosts: + - https-example.foo.com + secretName: testsecret-tls + rules: + - host: https-example.foo.com + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: service1 + port: + number: 80 diff --git a/content/fr/OWNERS b/content/fr/OWNERS index c91ec02821e6f..48861fdfd397a 100644 --- a/content/fr/OWNERS +++ b/content/fr/OWNERS @@ -8,6 +8,15 @@ reviewers: approvers: - sig-docs-fr-owners +- sig-docs-website-owners # important due to no_parent_owners option labels: +- area/localization - language/fr + +# Disable inheritance so that the localization team don't end up as approvers for all +# languages. +# https://github.com/kubernetes/community/blob/master/communication/website-guidelines.md +options: + no_parent_owners: true + diff --git a/content/fr/docs/concepts/storage/volumes.md b/content/fr/docs/concepts/storage/volumes.md index c2fdf583cb49a..40ff82c474349 100644 --- a/content/fr/docs/concepts/storage/volumes.md +++ b/content/fr/docs/concepts/storage/volumes.md @@ -972,7 +972,7 @@ Plus d'exemples sont disponibles [ici](https://github.com/kubernetes/examples/tr ## Utilisation de subPath Parfois, il est utile de partager un volume pour plusieurs utilisations dans un même Pod. -La propriété `volumeMounts.subPath` peut être utilisée pour spécifier un sous-chemin à l'intérieur du volume référencé au lieu de sa racine. +La propriété `volumeMounts[*].subPath` peut être utilisée pour spécifier un sous-chemin à l'intérieur du volume référencé au lieu de sa racine. Voici un exemple d'un Pod avec une stack LAMP (Linux Apache Mysql PHP) utilisant un unique volume partagé. Le contenu HTML est mappé à son dossier `html` et les bases de données seront stockées dans son dossier `mysql` : diff --git a/content/fr/docs/concepts/workloads/pods/pod-lifecycle.md b/content/fr/docs/concepts/workloads/pods/pod-lifecycle.md index 833b60fbf52e2..3957d69355977 100644 --- a/content/fr/docs/concepts/workloads/pods/pod-lifecycle.md +++ b/content/fr/docs/concepts/workloads/pods/pod-lifecycle.md @@ -328,8 +328,8 @@ metadata: spec: containers: - args: - - /server - image: registry.k8s.io/liveness + - liveness + image: registry.k8s.io/e2e-test-images/agnhost:2.40 livenessProbe: httpGet: # lorsque "host" n'est pas défini, "PodIP" sera utilisé diff --git a/content/fr/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes.md b/content/fr/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes.md index 3778d6792457f..a2be2bb607b02 100644 --- a/content/fr/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes.md +++ b/content/fr/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes.md @@ -102,7 +102,7 @@ liveness-exec 1/1 Running 1 1m ## Définir une requête HTTP de liveness Un autre type de liveness probe utilise une requête GET HTTP. Voici la configuration -d'un Pod qui fait fonctionner un conteneur basé sur l'image `registry.k8s.io/liveness`. +d'un Pod qui fait fonctionner un conteneur basé sur l'image `registry.k8s.io/e2e-test-images/agnhost`. {{% codenew file="pods/probe/http-liveness.yaml" %}} @@ -180,7 +180,6 @@ Vous pouvez utiliser un [ContainerPort](/docs/reference/generated/kubernetes-api ports: - name: liveness-port containerPort: 8080 - hostPort: 8080 livenessProbe: httpGet: @@ -200,7 +199,6 @@ Ainsi, l'exemple précédent deviendrait : ports: - name: liveness-port containerPort: 8080 - hostPort: 8080 livenessProbe: httpGet: diff --git a/content/fr/docs/tasks/tools/install-kubectl.md b/content/fr/docs/tasks/tools/install-kubectl.md index 6990ca158b853..8eb865aecd38b 100644 --- a/content/fr/docs/tasks/tools/install-kubectl.md +++ b/content/fr/docs/tasks/tools/install-kubectl.md @@ -13,7 +13,7 @@ card: --- -L'outil en ligne de commande de kubernetes, [kubectl](/docs/user-guide/kubectl/), vous permet d'exécuter des commandes dans les clusters Kubernetes. Vous pouvez utiliser kubectl pour déployer des applications, inspecter et gérer les ressources du cluster et consulter les logs. Pour une liste complète des opérations kubectl, voir [Aperçu de kubectl](/fr/docs/reference/kubectl/overview/). +L'outil en ligne de commande de kubernetes, [kubectl](/fr/docs/reference/kubectl/), vous permet d'exécuter des commandes dans les clusters Kubernetes. Vous pouvez utiliser kubectl pour déployer des applications, inspecter et gérer les ressources du cluster et consulter les logs. Pour une liste complète des opérations kubectl, voir [Aperçu de kubectl](/fr/docs/reference/kubectl/overview/). ## {{% heading "prerequisites" %}} diff --git a/content/fr/docs/tutorials/kubernetes-basics/_index.html b/content/fr/docs/tutorials/kubernetes-basics/_index.html index b8ce6eff8b824..8a6c9bb324212 100644 --- a/content/fr/docs/tutorials/kubernetes-basics/_index.html +++ b/content/fr/docs/tutorials/kubernetes-basics/_index.html @@ -8,14 +8,13 @@ title: Pas à pas des bases --- + - -
          @@ -67,9 +66,9 @@

          Modules de base Kubernetes

          @@ -79,25 +78,25 @@

          Modules de base Kubernetes

          @@ -108,7 +107,7 @@

          Modules de base Kubernetes

          diff --git a/content/fr/docs/tutorials/kubernetes-basics/create-cluster/cluster-interactive.html b/content/fr/docs/tutorials/kubernetes-basics/create-cluster/cluster-interactive.html index c8137aa9872a3..5fcc57e46bd59 100644 --- a/content/fr/docs/tutorials/kubernetes-basics/create-cluster/cluster-interactive.html +++ b/content/fr/docs/tutorials/kubernetes-basics/create-cluster/cluster-interactive.html @@ -9,8 +9,6 @@ - -
          diff --git a/content/fr/docs/tutorials/kubernetes-basics/create-cluster/cluster-intro.html b/content/fr/docs/tutorials/kubernetes-basics/create-cluster/cluster-intro.html index ff117322b213e..01c97fdebf790 100644 --- a/content/fr/docs/tutorials/kubernetes-basics/create-cluster/cluster-intro.html +++ b/content/fr/docs/tutorials/kubernetes-basics/create-cluster/cluster-intro.html @@ -9,7 +9,6 @@ -
          @@ -96,7 +95,7 @@

          Schéma du Cluster

          diff --git a/content/fr/docs/tutorials/kubernetes-basics/deploy-app/deploy-interactive.html b/content/fr/docs/tutorials/kubernetes-basics/deploy-app/deploy-interactive.html index de064cd22e353..594c2f3d6e67e 100644 --- a/content/fr/docs/tutorials/kubernetes-basics/deploy-app/deploy-interactive.html +++ b/content/fr/docs/tutorials/kubernetes-basics/deploy-app/deploy-interactive.html @@ -9,8 +9,7 @@ - - +
          @@ -29,7 +28,7 @@
          diff --git a/content/fr/docs/tutorials/kubernetes-basics/deploy-app/deploy-intro.html b/content/fr/docs/tutorials/kubernetes-basics/deploy-app/deploy-intro.html index ff41cae0dd0a8..c60ce4752b8e6 100644 --- a/content/fr/docs/tutorials/kubernetes-basics/deploy-app/deploy-intro.html +++ b/content/fr/docs/tutorials/kubernetes-basics/deploy-app/deploy-intro.html @@ -9,7 +9,6 @@ -
          @@ -71,7 +70,7 @@

          Déploiement de votre première application sur Kube

          Vous pouvez créer et gérer un déploiement à l'aide de l'interface de ligne de commande, Kubectl.

          Kubectl utilise l'API Kubernetes pour interagir avec le cluster. Dans ce module, vous apprendrez les commandes Kubectl les plus courantes nécessaires à la création de déploiements exécutant vos applications sur un cluster Kubernetes.

          -

          Lorsque vous créez un déploiement, vous devez spécifier l'image de conteneur de votre application et le nombre de réplicas que vous souhaitez exécuter. Vous pouvez modifier ces informations ultérieurement en mettant à jour votre déploiement.; Modules 5 et 6 du bootcamp, expliquez comment vous pouvez faire évoluer et mettre à jour vos déploiements.

          +

          Lorsque vous créez un déploiement, vous devez spécifier l'image de conteneur de votre application et le nombre de réplicas que vous souhaitez exécuter. Vous pouvez modifier ces informations ultérieurement en mettant à jour votre déploiement.; Modules 5 et 6 du bootcamp, expliquez comment vous pouvez faire évoluer et mettre à jour vos déploiements.

          @@ -99,7 +98,7 @@

          Déploiement de votre première application sur Kube diff --git a/content/fr/docs/tutorials/kubernetes-basics/explore/explore-intro.html b/content/fr/docs/tutorials/kubernetes-basics/explore/explore-intro.html index 724cfb8bccb2f..9d9dc2c548cbc 100644 --- a/content/fr/docs/tutorials/kubernetes-basics/explore/explore-intro.html +++ b/content/fr/docs/tutorials/kubernetes-basics/explore/explore-intro.html @@ -105,7 +105,7 @@

          Aperçu des Nœuds

          Dépannage avec kubectl

          -

          Dans le module 2, vous avez utilisé l'interface de ligne de commande Kubectl. Vous continuerez à l'utiliser dans le module 3 pour obtenir des informations sur les applications déployées et leurs environnements. Les opérations les plus courantes peuvent être effectuées avec les commandes kubectl suivantes:

          +

          Dans le module 2, vous avez utilisé l'interface de ligne de commande Kubectl. Vous continuerez à l'utiliser dans le module 3 pour obtenir des informations sur les applications déployées et leurs environnements. Les opérations les plus courantes peuvent être effectuées avec les commandes kubectl suivantes:

          • kubectl get - liste les ressources
          • kubectl describe - affiche des informations détaillées sur une ressource
          • @@ -128,7 +128,7 @@

            Dépannage avec kubectl

            diff --git a/content/fr/examples/pods/probe/http-liveness.yaml b/content/fr/examples/pods/probe/http-liveness.yaml index 48ca861c14271..ecc1a6ff2e12e 100644 --- a/content/fr/examples/pods/probe/http-liveness.yaml +++ b/content/fr/examples/pods/probe/http-liveness.yaml @@ -7,9 +7,9 @@ metadata: spec: containers: - name: liveness - image: registry.k8s.io/liveness + image: registry.k8s.io/e2e-test-images/agnhost:2.40 args: - - /server + - liveness livenessProbe: httpGet: path: /healthz diff --git a/content/hi/OWNERS b/content/hi/OWNERS index 56a923860891d..e9cebcab05249 100644 --- a/content/hi/OWNERS +++ b/content/hi/OWNERS @@ -8,6 +8,14 @@ reviewers: approvers: - sig-docs-hi-owners +- sig-docs-website-owners # important due to no_parent_owners option labels: +- area/localization - language/hi + +# Disable inheritance so that the localization team don't end up as approvers for all +# languages. +# https://github.com/kubernetes/community/blob/master/communication/website-guidelines.md +options: + no_parent_owners: true diff --git a/content/hi/docs/home/_index.md b/content/hi/docs/home/_index.md index 090b7c752b8ba..ec855749fac8b 100644 --- a/content/hi/docs/home/_index.md +++ b/content/hi/docs/home/_index.md @@ -41,11 +41,11 @@ cards: button_path: "/docs/tasks" - name: training title: "प्रशिक्षण" - description: "कुबेरनेट्स में प्रमाणित हो कर अपने क्लाउड नेटिव प्रोजेक्ट सफल बनाएं!" + description: "कुबेरनेट्स में प्रमाणित हो कर अपने क्लाउड नेटिव प्रोजेक्ट को सफल बनाएं!" button: "प्रशिक्षण देखें" - button_path: "/training" + button_path: "/hi/training" - name: reference - title: संदर्भ जानकारी देखें + title: संदर्भ मे दी गई जानकारी को देखें description: शब्दावली, कमांड लाइन सिंटैक्स, API संसाधनो के प्रकार और टूल सेटअप करने के प्रलेखन। button: संदर्भ देखें button_path: /docs/reference diff --git a/content/hi/docs/reference/glossary/workload.md b/content/hi/docs/reference/glossary/workload.md new file mode 100644 index 0000000000000..daa516e625aa6 --- /dev/null +++ b/content/hi/docs/reference/glossary/workload.md @@ -0,0 +1,21 @@ +--- +title: कार्यभार (Workload) +id: workloads +date: 2019-02-13 +full_link: /docs/concepts/workloads/ +short_description: > + कार्यभार एक ऐप्लिकेशन है जो कुबेरनेट्स पर चल रहा है। + +aka: +tags: +- fundamental +--- + कार्यभार एक ऐप्लिकेशन है जो कुबेरनेट्स पर चल रहा है। + + + +विविध मुख्य वस्तुएं एक कार्यभार के विविध प्रकारों अथवा भागों का प्रतिनिधित्व करती हैं। जैसे डेमनसेट, डिप्लॉयमेंट, जॉब, रेप्लिकासेट और स्टेटफुलसेट। + + + +उदाहरण के लिए एक कार्यभार जिसमें वेब सर्वर और डेटाबेस है, उसमे से डेटाबेस को एक {{< glossary_tooltip term_id="StatefulSet" text="स्टेटफुलसेट" >}} मे, और वेब सर्वर को एक {{< glossary_tooltip term_id="Deployment" text="डिप्लॉयमेंट" >}} मे चलाया जा सकता है। diff --git a/content/hi/docs/tasks/tools/included/verify-kubectl.md b/content/hi/docs/tasks/tools/included/verify-kubectl.md index c6bfa7ec99043..73d0bce0af393 100644 --- a/content/hi/docs/tasks/tools/included/verify-kubectl.md +++ b/content/hi/docs/tasks/tools/included/verify-kubectl.md @@ -27,7 +27,7 @@ The connection to the server was refused - did you specify th उदाहरण के लिए, यदि आप अपने लैपटॉप (स्थानीय रूप से) पर कुबेरनेट्स क्लस्टर चलाना चाहते हैं, तो आपको पहले मिनीक्यूब (minikube) जैसे टूल को इंस्टॉल करना होगा और ऊपर बताए गए कमांड को फिर से चलाना होगा। -यदि kubectl cluster-info URL प्रतिक्रिया देता है, लेकिन आप अपने क्लस्टर को एक्सेस नहीं कर पा रहें हैं, तो यह जाँचने के लिए कि क्या यह ठीक से कॉन्फ़िगर किया गया है, इस कमांड का उपयोग करें: +यदि `kubectl cluster-info` URL प्रतिक्रिया देता है, लेकिन आप अपने क्लस्टर को एक्सेस नहीं कर पा रहें हैं, तो यह जाँचने के लिए कि क्या यह ठीक से कॉन्फ़िगर किया गया है, इस कमांड का उपयोग करें: ```shell kubectl cluster-info dump diff --git a/content/hi/docs/tutorials/kubernetes-basics/deploy-app/deploy-intro.html b/content/hi/docs/tutorials/kubernetes-basics/deploy-app/deploy-intro.html index 10022ef7b6926..9a66ea7ac214d 100644 --- a/content/hi/docs/tutorials/kubernetes-basics/deploy-app/deploy-intro.html +++ b/content/hi/docs/tutorials/kubernetes-basics/deploy-app/deploy-intro.html @@ -9,7 +9,7 @@ - +
            @@ -65,13 +65,12 @@

            कुबेरनेट्स पर अपना
            -

            +

            आप कुबेरनेट्स कमांड लाइन इंटरफेस, kubectl का उपयोग करके डिप्लॉयमेंट बना और प्रबंधित कर सकते हैं। kubectl क्लस्टर के साथ बातचीत करने के लिए कुबेरनेट्स एपीआई का उपयोग करता है। इस मॉड्यूल में, आप कुबेरनेट्स क्लस्टर पर आपके एप्लिकेशन चलाने वाले डिप्लॉयमेंट बनाने के लिए आवश्यक सबसे सामान्य kubectl कमांड सीखेंगे।

            जब आप कोई डिप्लॉयमेंट बनाते हैं, तो आपको अपने एप्लिकेशन के लिए कंटेनर इमेज और चलाने के लिए इच्छित प्रतिकृतियों की संख्या निर्दिष्ट करने की आवश्यकता होगी। आप अपने कामकाज को अपडेट करके बाद में उस जानकारी को बदल सकते हैं; बूटकैंप के मॉड्यूल 5 और 6 चर्चा करते हैं कि आप अपने डिप्लॉयमेंट को कैसे स्केल और अपडेट कर सकते हैं।

            -
            diff --git a/content/hi/training/_index.html b/content/hi/training/_index.html new file mode 100644 index 0000000000000..0223d0ce38162 --- /dev/null +++ b/content/hi/training/_index.html @@ -0,0 +1,154 @@ +--- +title: प्रशिक्षण +bigheader: कुबेरनेट्स प्रशिक्षण और प्रमाणन +abstract: प्रशिक्षण कार्यक्रम, प्रमाणपत्र, और भागीदार। +layout: basic +cid: training +class: training +--- + +
            +
            +
            +
            +

            अपना क्लाउड नेटिव करियर बनाएं

            +

            कुबेरनेट्स क्लाउड नेटिव आंदोलन के मूल में है। लिनक्स फाउंडेशन और हमारे प्रशिक्षण कंट्रीब्यूटरों से प्रशिक्षण और प्रमाणन आपको अपने करियर में निवेश करने, कुबेरनेट्स सीखने और अपनी क्लाउड नेटिव प्रोजेक्ट्स को सफल बनाने की सुविधा देता है।

            +
            +
            +
            + +
            +
            + +
            +
            + +
            +
            + +
            +
            + +
            +
            +
            +
            +
            + +
            +
            +
            +

            edX पर निःशुल्क पाठ्यक्रम लें

            +
            +
            +
            +
            +
            + कुबेरनेट्स का परिचय
             
            +
            +

            क्या आप कुबेरनेट्स सीखना चाहते हैं? इस प्रबंधन प्रणाली से कंटेनराइजेड एप्लिकेशन्स को सशक्त रूप से प्रबंधित करने के लिए महत्वपूर्ण उपकरण प्राप्त करें।

            +
            + कोर्स पर जाएँ +
            +
            +
            +
            +
            + क्लाउड इंफ्रास्ट्रक्चर टेक्नोलॉजीज का परिचय +
            +

            ओपन सोर्स में प्रमुख, लिनक्स फाउंडेशन से सीधे क्लाउड टेक्नोलॉजीज के निर्माण और प्रबंधन के मूलतत्त्व सीखें।

            +
            + कोर्स पर जाएँ +
            +
            +
            +
            +
            + लिनक्स का परिचय +
            +

            क्या आपने कभी लिनक्स नहीं सीखा? या आप अपने ज्ञान को ताज़ा करना चाहते हैं? प्रमुख लिनक्स वितरण फैमिलीज़ में ग्राफिकल इंटरफ़ेस और कमांड लाइन दोनों का उपयोग करके लिनक्स का अच्छा कार्यसाधक ज्ञान विकसित करें।

            +
            + कोर्स पर जाएँ +
            +
            +
            +
            + +
            +
            +
            +

            लिनक्स फाउंडेशन के साथ सीखें

            +

            लिनक्स फाउंडेशन कुबेरनेट्स अनुप्रयोग विकास और संचालन जीवनचक्र के सभी पहलुओं के लिए प्रशिक्षक के नेतृत्व वाले और स्व-गति वाले पाठ्यक्रम प्रदान करता है।

            +

            + पाठ्यक्रम देखें +
            +
            +
            + +
            +
            +

            कुबेरनेट्स प्रमाणित बनें

            +
            +
            +
            + कुबेरनेट्स और क्लाउड नेटिव एसोसिएट (KCNA) +
            +

            कुबेरनेट्स और क्लाउड नेटिव एसोसिएट (KCNA) परीक्षा कुबेरनेट्स और व्यापक क्लाउड नेटिव इकोसिस्टम में उपयोगकर्ता के मूलभूत ज्ञान और कौशल को प्रदर्शित करती है।

            +

            KCNA प्रमाणित व्यक्ति संपूर्ण क्लाउड नेटिव इकोसिस्टम, और विशेष रूप से कुबेरनेट्स के वैचारिक ज्ञान की पुष्टि करेगा।

            +
            + प्रमाणीकरण पर जाएँ +
            +
            + +
            + कुबेरनेट्स और क्लाउड नेटिव सिक्योरिटी एसोसिएट(KCSA) +
            +

            KCSA पूर्व-पेशेवर प्रमाणन है, जो क्लाउड नेटिव इकोसिस्टम में सुरक्षा टैकनोलजीज़ के मूलभूत ज्ञान और कौशल की प्रदर्शित समझ के माध्यम से पेशेवर स्तर पर आगे बढ़ने में रुचि रखने वाले उम्मीदवारों के लिए डिज़ाइन किया गया है।

            +

            KCSA प्रमाणित व्यक्ति अनुपालन उद्देश्यों को पूरा करने के लिए कुबेरनेट क्लस्टर के बुनियादी सुरक्षा कॉन्फ़िगरेशन की समझ की पुष्टि करेगा।

            +
            + प्रमाणीकरण पर जाएँ +
            +
            +
            + प्रमाणित कुबेरनेट्स एप्लिकेशन डेवलपर (CKAD) +
            +

            प्रमाणित कुबेरनेट्स एप्लिकेशन डेवलपर (CKAD) परीक्षा प्रमाणित करती है कि उपयोगकर्ता कुबेरनेट्स के लिए क्लाउड नेटिव एप्लिकेशन को डिज़ाइन, निर्माण, कॉन्फ़िगर और प्रदर्शित कर सकते हैं।

            +

            CKAD एप्लिकेशन संसाधनों को परिभाषित कर सकता है और कुबेरनेट्स में स्केलेबल एप्लिकेशन और टूल के निर्माण, निगरानी और समस्या निवारण के लिए मूल सिद्धांतों का उपयोग कर सकता है।

            +
            + प्रमाणीकरण पर जाएँ +
            +
            +
            + प्रमाणित कुबेरनेट्स प्रशासक (CKA) +
            + +

            प्रमाणित कुबेरनेट्स प्रशासक (CKA) कार्यक्रम आश्वासन प्रदान करता है कि CKA के पास कुबेरनेट्स प्रशासकों की जिम्मेदारियों को निभाने के लिए कौशल, ज्ञान और योग्यता है।

            +

            CKA प्रमाणित व्यक्ति ने बुनियादी स्थापना के साथ-साथ उत्पादन-ग्रेड कुबेरनेट्स क्लस्टर को कॉन्फ़िगर और प्रबंधित करने की क्षमता का प्रदर्शन करते हैं।

            +
            + प्रमाणीकरण पर जाएँ +
            +
            +
            + प्रमाणित कुबेरनेट्स सुरक्षा विशेषज्ञ (CKS) +
            + +

            प्रमाणित कुबेरनेट्स सुरक्षा विशेषज्ञ (CKS) कार्यक्रम आश्वासन प्रदान करता है कि धारक सर्वोत्तम प्रथाओं की एक विस्तृत श्रृंखला के साथ सहज और सक्षम है। CKS प्रमाणन निर्माण, तैनाती और रनटाइम के दौरान कंटेनर-आधारित अनुप्रयोगों और कुबेरनेट्स प्लेटफार्मों को सुरक्षित करने के कौशल को शामिल करता है।

            +

            CKS के लिए उम्मीदवारों के पास वर्तमान प्रमाणित कुबेरनेट्स प्रशासक (CKA) प्रमाणन होना चाहिए ताकि यह प्रदर्शित हो सके कि CKS में बैठने से पहले उनके पास पर्याप्त कुबेरनेट्स विशेषज्ञता है।

            +
            + प्रमाणीकरण पर जाएँ +
            +
            +
            +
            + +
            +
            +
            +

            कुबेरनेट्स ट्रेनिंग पार्टनर्स

            +

            कुबेरनेट्स ट्रेनिंग पार्टनर्स" हमारे नेटवर्क को और क्लाउड नेटिव परियोजनाओं को सीधे सेवा करने के लिए प्रशिक्षण प्रदान करते हैं।

            +
            +
            +
            + {{< cncf-landscape helpers=false category="kubernetes-training-partner" >}} +
            +
            diff --git a/content/id/OWNERS b/content/id/OWNERS index 40fe7fb3b6183..0d0f6f5a8b2a6 100644 --- a/content/id/OWNERS +++ b/content/id/OWNERS @@ -1,6 +1,6 @@ # See the OWNERS docs at https://go.k8s.io/owners -# This is the localization project for Bahasa. +# This is the localization project for Bahasa Indonesia. # Teams and members are visible at https://github.com/orgs/kubernetes/teams. reviewers: @@ -8,6 +8,14 @@ reviewers: approvers: - sig-docs-id-owners +- sig-docs-website-owners # important due to no_parent_owners option labels: +- area/localization - language/id + +# Disable inheritance so that the localization team don't end up as approvers for all +# languages. +# https://github.com/kubernetes/community/blob/master/communication/website-guidelines.md +options: + no_parent_owners: true diff --git a/content/id/docs/concepts/_index.md b/content/id/docs/concepts/_index.md index 623b3fac3af63..a786f9fb0a400 100644 --- a/content/id/docs/concepts/_index.md +++ b/content/id/docs/concepts/_index.md @@ -33,10 +33,10 @@ misalnya dengan mekanisme `start` atau `stop` kontainer, melakukan *scale* repli suatu aplikasi, dan lain sebagainya. *Control Plane* Kubernetes terdiri dari sekumpulan `process` yang dijalankan di klaster: -* **Kubernetes Master** terdiri dari tiga buah *process* yang dijalankan pada sebuah *node* di klaster kamu, *node* ini disebut sebagai *master*, yang terdiri [kube-apiserver](/docs/admin/kube-apiserver/), [kube-controller-manager](/docs/admin/kube-controller-manager/) dan [kube-scheduler](/docs/admin/kube-scheduler/). +* **Kubernetes Master** terdiri dari tiga buah *process* yang dijalankan pada sebuah *node* di klaster kamu, *node* ini disebut sebagai *master*, yang terdiri [kube-apiserver](/id/docs/concepts/overview/components/#kube-apiserver), [kube-controller-manager](/id/docs/concepts/overview/components/#kube-controller-manager) dan [kube-scheduler](/id/docs/concepts/overview/components/#kube-scheduler). * Setiap *node* non-master pada klaster kamu menjalankan dua buah *process*: - * **[kubelet](/docs/admin/kubelet/)**, yang menjadi perantara komunikasi dengan *master*. - * **[kube-proxy](/docs/admin/kube-proxy/)**, sebuah *proxy* yang merupakan representasi jaringan yang ada pada setiap *node*. + * **[kubelet](/id/docs/concepts/overview/components/#kubelet)**, yang menjadi perantara komunikasi dengan *master*. + * **[kube-proxy](/id/docs/concepts/overview/components/#kube-proxy)**, sebuah *proxy* yang merupakan representasi jaringan yang ada pada setiap *node*. ## Objek Kubernetes diff --git a/content/id/docs/concepts/extend-kubernetes/compute-storage-net/device-plugins.md b/content/id/docs/concepts/extend-kubernetes/compute-storage-net/device-plugins.md index 40263d5e3557a..eadf3c51baca3 100644 --- a/content/id/docs/concepts/extend-kubernetes/compute-storage-net/device-plugins.md +++ b/content/id/docs/concepts/extend-kubernetes/compute-storage-net/device-plugins.md @@ -212,7 +212,7 @@ pluginapi.Device{ID: "25102017", Health: pluginapi.Healthy, Topology:&pluginapi. Berikut beberapa contoh implementasi _plugin_ perangkat: -* [Plugin perangkat AMD GPU](https://github.com/RadeonOpenCompute/k8s-device-plugin) +* [Plugin perangkat AMD GPU](https://github.com/ROCm/k8s-device-plugin) * [Plugin perangkat Intel](https://github.com/intel/intel-device-plugins-for-kubernetes) untuk perangkat GPU, FPGA, dan QuickAssist Intel * [Plugin perangkat KubeVirt](https://github.com/kubevirt/kubernetes-device-plugins) untuk virtualisasi hardware-assisted * [Plugin perangkat NVIDIA GPU](https://github.com/NVIDIA/k8s-device-plugin) diff --git a/content/id/docs/concepts/services-networking/ingress.md b/content/id/docs/concepts/services-networking/ingress.md index 8e129ff223cf7..6d68a8b8e0592 100644 --- a/content/id/docs/concepts/services-networking/ingress.md +++ b/content/id/docs/concepts/services-networking/ingress.md @@ -37,7 +37,7 @@ Sebuah *Ingress* dapat dikonfigurasi agar berbagai *Service* memiliki URL yang d Sebuah [kontroler Ingress](/id/docs/concepts/services-networking/ingress-controllers) bertanggung jawab untuk menjalankan fungsi Ingress yaitu sebagai *loadbalancer*, meskipun dapat juga digunakan untuk mengatur *edge router* atau *frontend* tambahan untuk menerima trafik. Sebuah *Ingress* tidak mengekspos sembarang *port* atau protokol. Mengekspos *Service* untuk protokol selain HTTP ke HTTPS internet biasanya dilakukan dengan menggunakan -*service* dengan tipe [Service.Type=NodePort](/id/docs/concepts/services-networking/service/#nodeport) atau +*service* dengan tipe [Service.Type=NodePort](/id/docs/concepts/services-networking/service/#type-nodeport) atau [Service.Type=LoadBalancer](/id/docs/concepts/services-networking/service/#loadbalancer). ## Prasyarat diff --git a/content/id/docs/concepts/storage/volumes.md b/content/id/docs/concepts/storage/volumes.md index 3c9634575838d..7163da298d459 100644 --- a/content/id/docs/concepts/storage/volumes.md +++ b/content/id/docs/concepts/storage/volumes.md @@ -899,7 +899,7 @@ Lebih banyak contoh dapat ditemukan [di sini](https://github.com/kubernetes/exam ## Menggunakan subPath -Terkadang, diperlukan untuk membagi sebuah Volume untuk banyak kegunaan berbeda pada sebuah Pod. Kolom `volumeMounts.subPath` dapat digunakan untuk merinci sebuah _sub-path_ di dalam Volume yang dimaksud, menggantikan _root path_-nya. +Terkadang, diperlukan untuk membagi sebuah Volume untuk banyak kegunaan berbeda pada sebuah Pod. Kolom `volumeMounts[*].subPath` dapat digunakan untuk merinci sebuah _sub-path_ di dalam Volume yang dimaksud, menggantikan _root path_-nya. Berikut contoh sebuah Pod dengan _stack_ LAMP (Linux Apache Mysql PHP) menggunakan sebuah Volume yang dibagi-bagi. Isi HTML-nya dipetakan ke dalam direktori `html`-nya, dan _database_-nya akan disimpan di dalam direktori `mysql`-nya. @@ -1099,7 +1099,7 @@ Untuk lebih lanjut, dapat ditemukan [di sini](https://github.com/kubernetes/comm _Mount propagation_ memungkinkan berbagi volume-volume yang ditambatkan oleh sebuah Container kepada Container-container lain di dalam Pod yang sama, atau bahkan pada Pod lainnya di dalam Node yang sama. -_Mount propagation_ dari sebuah volume diatur oleh kolom `mountPropagation` di dalam `Container.volumeMounts`. +_Mount propagation_ dari sebuah volume diatur oleh kolom `mountPropagation` di dalam `containers[*].volumeMounts`. Nilai-nilainya adalah sebagai berikut: * `None` - Tambatan volume ini tidak akan menerima apapun tambatan selanjutnya yang ditambatkan pada volume ini atau apapun sub-direktori yang dimilikinya oleh _host_. diff --git a/content/id/docs/concepts/workloads/pods/pod-lifecycle.md b/content/id/docs/concepts/workloads/pods/pod-lifecycle.md index adad4be97f846..171312cf24b4b 100644 --- a/content/id/docs/concepts/workloads/pods/pod-lifecycle.md +++ b/content/id/docs/concepts/workloads/pods/pod-lifecycle.md @@ -267,8 +267,8 @@ metadata: spec: containers: - args: - - /server - image: registry.k8s.io/liveness + - liveness + image: registry.k8s.io/e2e-test-images/agnhost:2.40 livenessProbe: httpGet: # ketika "host" tidak ditentukan, "PodIP" akan digunakan diff --git a/content/id/docs/home/_index.md b/content/id/docs/home/_index.md index bf74b6727be4c..c9627941774c6 100644 --- a/content/id/docs/home/_index.md +++ b/content/id/docs/home/_index.md @@ -50,6 +50,8 @@ cards: - name: download title: Unduh Kubernetes description: Untuk instalasi atau pembaharuan Kubernetes ke versi terbaru, lihat catatan rilis saat ini. + button: Unduh Kubernetes Sekarang + button_path: /releases/download/ - name: about title: Tentang dokumentasi description: Situs ini merupakan dokumentasi dari Kubernetes versi saat ini dan 4 versi sebelumnya. diff --git a/content/id/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes.md b/content/id/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes.md index e03a9d97a331a..d891019ecce47 100644 --- a/content/id/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes.md +++ b/content/id/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes.md @@ -126,7 +126,7 @@ liveness-exec 1/1 Running 1 1m ## Mendefinisikan probe liveness dengan permintaan HTTP Jenis kedua dari _probe liveness_ menggunakan sebuah permintaan GET HTTP. Berikut ini -berkas konfigurasi untuk Pod yang menjalankan Container dari image `registry.k8s.io/liveness`. +berkas konfigurasi untuk Pod yang menjalankan Container dari image `registry.k8s.io/e2e-test-images/agnhost`. {{% codenew file="pods/probe/http-liveness.yaml" %}} @@ -227,7 +227,6 @@ dengan nama untuk melakukan pemeriksaan _liveness_ HTTP atau TCP: ports: - name: liveness-port containerPort: 8080 - hostPort: 8080 livenessProbe: httpGet: @@ -251,7 +250,6 @@ Sehingga, contoh sebelumnya menjadi: ports: - name: liveness-port containerPort: 8080 - hostPort: 8080 livenessProbe: httpGet: diff --git a/content/id/docs/tasks/configure-pod-container/configure-service-account.md b/content/id/docs/tasks/configure-pod-container/configure-service-account.md index f469b257d85cd..af796a99dd51f 100644 --- a/content/id/docs/tasks/configure-pod-container/configure-service-account.md +++ b/content/id/docs/tasks/configure-pod-container/configure-service-account.md @@ -174,7 +174,7 @@ Isi dari `token` tidak dirinci di sini. - Membuat sebuah imagePullSecret, seperti yang dijelaskan pada [Menentukan ImagePullSecret pada Pod](/id/docs/concepts/containers/images/#tentukan-imagepullsecrets-pada-sebuah-pod). ```shell - kubectl create secret docker-registry myregistrykey --docker-server=DUMMY_SERVER \ + kubectl create secret docker-registry myregistrykey --docker-server= \ --docker-username=DUMMY_USERNAME --docker-password=DUMMY_DOCKER_PASSWORD \ --docker-email=DUMMY_DOCKER_EMAIL ``` @@ -250,7 +250,7 @@ kubectl replace serviceaccount default -f ./sa.yaml Ketika Pod baru dibuat dalam Namespace yang sedang aktif dan menggunakan ServiceAccount, Pod baru akan memiliki _field_ `spec.imagePullSecrets` yang ditentukan secara otomatis: ```shell -kubectl run nginx --image=nginx --restart=Never +kubectl run nginx --image=/nginx --restart=Never kubectl get pod nginx -o=jsonpath='{.spec.imagePullSecrets[0].name}{"\n"}' ``` diff --git a/content/id/examples/pods/probe/http-liveness.yaml b/content/id/examples/pods/probe/http-liveness.yaml index 48ca861c14271..ecc1a6ff2e12e 100644 --- a/content/id/examples/pods/probe/http-liveness.yaml +++ b/content/id/examples/pods/probe/http-liveness.yaml @@ -7,9 +7,9 @@ metadata: spec: containers: - name: liveness - image: registry.k8s.io/liveness + image: registry.k8s.io/e2e-test-images/agnhost:2.40 args: - - /server + - liveness livenessProbe: httpGet: path: /healthz diff --git a/content/it/OWNERS b/content/it/OWNERS index 1152b909db0b1..e5aaf46e6cfc4 100644 --- a/content/it/OWNERS +++ b/content/it/OWNERS @@ -6,6 +6,14 @@ reviewers: approvers: - sig-docs-it-owners +- sig-docs-website-owners # important due to no_parent_owners option labels: -- language/it \ No newline at end of file +- area/localization +- language/it + +# Disable inheritance so that the localization team don't end up as approvers for all +# languages. +# https://github.com/kubernetes/community/blob/master/communication/website-guidelines.md +options: + no_parent_owners: true \ No newline at end of file diff --git a/content/ja/OWNERS b/content/ja/OWNERS index 5e85fee1d5a58..78e0afc6c4e0d 100644 --- a/content/ja/OWNERS +++ b/content/ja/OWNERS @@ -8,6 +8,14 @@ reviewers: approvers: - sig-docs-ja-owners +- sig-docs-website-owners # important due to no_parent_owners option labels: +- area/localization - language/ja + +# Disable inheritance so that the localization team don't end up as approvers for all +# languages. +# https://github.com/kubernetes/community/blob/master/communication/website-guidelines.md +options: + no_parent_owners: true diff --git a/content/ja/blog/_posts/2022-02-17-updated-dockershim-faq.md b/content/ja/blog/_posts/2022-02-17-updated-dockershim-faq.md index 4d92d4ae0aa01..6fe17ff191b48 100644 --- a/content/ja/blog/_posts/2022-02-17-updated-dockershim-faq.md +++ b/content/ja/blog/_posts/2022-02-17-updated-dockershim-faq.md @@ -36,7 +36,7 @@ Kubernetesの初期のバージョンは、特定のコンテナランタイム Docker Engineです。その後、Kubernetesは他のコンテナランタイムと連携するためのサポートを追加しました。 オーケストレーター(Kubernetesなど)と多くの異なるコンテナランタイムの間の相互運用を可能にするため、 CRI標準が[作成](/blog/2016/12/container-runtime-interface-cri-in-kubernetes/)されました。 -Docker Engineはそのインターフェイス(CRI)を実装していないため、Kubernetesプロジェクトは移行を支援する特別なコードを作成し、 +Docker Engineはそのインターフェース(CRI)を実装していないため、Kubernetesプロジェクトは移行を支援する特別なコードを作成し、 その _dockershim_ コードをKubernetes自身の一部としました。 dockershimコードは常に一時的な解決策であることを意図されていました(このためshimと名付けられています)。 diff --git a/content/ja/blog/_posts/2023-01-06-unhealthy-pod-eviction-policy-for-pdb.md b/content/ja/blog/_posts/2023-01-06-unhealthy-pod-eviction-policy-for-pdb.md new file mode 100644 index 0000000000000..eafaf5e8fc0bb --- /dev/null +++ b/content/ja/blog/_posts/2023-01-06-unhealthy-pod-eviction-policy-for-pdb.md @@ -0,0 +1,91 @@ +--- +layout: blog +title: "Kubernetes 1.26: PodDisruptionBudgetによって保護された不健全なPodに対する退避ポリシー" +date: 2023-01-06 +slug: "unhealthy-pod-eviction-policy-for-pdbs" +--- + +**著者:** Filip Křepinský (Red Hat), Morten Torkildsen (Google), Ravi Gudimetla (Apple) + + +アプリケーションの中断がその可用性に影響を与えないようにすることは、簡単な作業ではありません。 +先月リリースされたKubernetes v1.26では、[PodDisruptionBudget](/docs/concepts/workloads/pods/disruptions/#pod-disruption-budgets) (PDB) に +_不健全なPodの退避ポリシー_ を指定して、ノード管理操作中に可用性を維持できるようになりました。 +この記事では、アプリケーション所有者が中断をより柔軟に管理できるようにするために、PDBにどのような変更が導入されたのかを詳しく説明します。 + +## これはどのような問題を解決しますか?{#what-problem-does-this-solve} + +APIによって開始されるPodの退避では、PodDisruptionBudget(PDB)が考慮されます。 +これは、退避によるPodへの[自発的な中断](/ja/docs/concepts/scheduling-eviction/#pod-disruption)の要求は保護されたアプリケーションを中断してはならず、 +PDBの`.status.currentHealthy`が`.status.desiredHealthy`を下回ってはいけないことを意味します。 +[Unhealthy](/docs/tasks/run-application/configure-pdb/#healthiness-of-a-pod)な実行中のPodはPDBステータスにはカウントされませんが、 +これらの退避はアプリケーションが中断されない場合にのみ可能です。 +これにより、中断されたアプリケーションやまだ開始されていないアプリケーションが、退避によって追加のダウンタイムが発生することなく、できるだけ早く可用性を達成できるようになります。 + +残念ながら、これは手動の介入なしでノードをドレインしたいクラスター管理者にとって問題を引き起こします。 +(バグまたは構成ミスにより)Podが`CrashLoopBackOff`状態になっているアプリケーション、または単に準備ができていないPodがあるアプリケーションが誤動作している場合、このタスクはさらに困難になります。 +アプリケーションのすべてのPodが正常でない場合、PDBの違反により退避リクエストは失敗します。その場合、ノードのドレインは進行できません。 + +一方で、次の目的で従来の動作に依存するユーザーもいます。 + +- 基盤となるリソースまたはストレージを保護しているPodの削除によって引き起こされるデータ損失を防止する +- アプリケーションに対して可能な限り最高の可用性を実現する + +Kubernetes 1.26では、PodDisruptionBudget APIに新しい実験的フィールド`.spec.unhealthyPodEvictionPolicy`が導入されました。 +このフィールドを有効にすると、これらの要件の両方をサポートできるようになります。 + +## どのように機能しますか?{#how-does-it-work} + +APIによって開始される退避は、Podの安全な終了をトリガーするプロセスです。 +このプロセスは、APIを直接呼び出すか、`kubectl drain`コマンドを使用するか、クラスター内の他のアクターを使用して開始できます。 +このプロセス中に、十分な数のPodが常にクラスター内で実行されていることを確認するために、すべてのPodの削除が適切なPDBと照合されます。 + +次のポリシーにより、PDBの作成者は、プロセスが不健全なPodを処理する方法をより詳細に制御できるようになります。 + +`IfHealthyBudget`と`AlwaysAllow`の2つのポリシーから選択できます。 + +前者の`IfHealthyBudget`は、従来の動作に従って、デフォルトで得られる最高の可用性を実現します。 +不健全なPodは、アプリケーションが利用可能な最小数の`.status.desiredHealthy`だけPodがある場合にのみ中断できます。 + +PDBの`spec.unhealthyPodEvictionPolicy`フィールドを`AlwaysAllow`に設定することにより、アプリケーションにとってベストエフォートの可用性を選択することになります。 +このポリシーを使用すると、不健全なPodをいつでも削除できます。これにより、クラスターの保守とアップグレードが容易になります。 + +多くの場合、`AlwaysAllow`がより良い選択であると考えられますが、一部の重要なワークロードでは、 +不健全なPodであってもノードドレインやAPIによって開始される他の形式の退避から保護する方が望ましい場合もあります。 + +## どのように利用できますか?{#how-do-i-use-it} + +これはアルファ機能であるため、kube-apiserverに対してコマンドライン引数`--feature-gates=PDBUnhealthyPodEvictionPolicy=true`を指定して +`PDBUnhealthyPodEvictionPolicy`[フィーチャーゲート](/ja/docs/reference/command-line-tools-reference/feature-gates/)を有効にする必要があります。 + +ここに例を示します。クラスターでフィーチャーゲートを有効にし、プレーンなWebサーバーを実行するDeploymentをすでに定義していると仮定します。 +そのDeploymentのPodに`app: nginx`というラベルを付けました。 +回避可能な中断を制限したいと考えており、このアプリにはベストエフォートの可用性で十分であることがわかっています。 +WebサーバーのPodが不健全な場合でも、退避を許可することにしました。 +不健全なPodを排除するための`AlwaysAllow`ポリシーを使用して、このアプリケーションを保護するPDBを作成します。 + +```yaml +apiVersion: policy/v1 +kind: PodDisruptionBudget +metadata: + name: nginx-pdb +spec: + selector: + matchLabels: + app: nginx + maxUnavailable: 1 + unhealthyPodEvictionPolicy: AlwaysAllow +``` + + +## もっと学ぶには?{#how-can-i-learn-more} + + +- KEPを読んでください: [Unhealthy Pod Eviction Policy for PDBs](https://github.com/kubernetes/enhancements/tree/master/keps/sig-apps/3017-pod-healthy-policy-for-pdb) +- PodDisruptionBudgetについてのドキュメントを読んでください: [Unhealthy Pod Eviction Policy](/docs/tasks/run-application/configure-pdb/#unhealthy-pod-eviction-policy) +- [PodDisruptionBudget](/docs/concepts/workloads/pods/disruptions/#pod-disruption-budgets)、[draining of Nodes](/docs/tasks/administer-cluster/safely-drain-node/)および[evictions](/ja/docs/concepts/scheduling-eviction/api-eviction/)についてKubernetesドキュメントを確認してください + + +## どうすれば参加できますか?{#how-do-i-get-involved} + +フィードバックがある場合は、Slackの[#sig-apps](https://kubernetes.slack.com/archives/C18NZM5K9) チャンネル(必要な場合は https://slack.k8s.io/ にアクセスして招待を受けてください)、またはSIG Appsメーリングリストにご連絡ください。kubernetes-sig-apps@googlegroups.com diff --git a/content/ja/blog/_posts/2024-01-15-SIG-Release-Spotlight/index.md b/content/ja/blog/_posts/2024-01-15-SIG-Release-Spotlight/index.md new file mode 100644 index 0000000000000..9e1cf673b3600 --- /dev/null +++ b/content/ja/blog/_posts/2024-01-15-SIG-Release-Spotlight/index.md @@ -0,0 +1,86 @@ +--- +layout: blog +title: "SIG Releaseスポットライト(リリース・チーム・サブプロジェクト)" +date: 2024-01-15 +slug: sig-release-spotlight-2023 +--- + +**筆者:** Nitish Kumar + +リリース・スペシャル・インタレスト・グループ(SIG Release)は、Kubernetesが4ヶ月ごとに最先端の機能とバグ修正でその刃を研ぐ場所です。Kubernetesのような大きなプロジェクトが、新バージョンをリリースするまでのタイムラインをどのように効率的に管理しているのか、またリリースチームの内部はどのようになっているのか、考えたことはありますか?このような疑問に興味がある方、もっと知りたい方、SIG Releaseの仕事に関わりたい方は、ぜひ読んでみてください! + +SIG ReleaseはKubernetesの開発と進化において重要な役割を担っています。その主な責任は、Kubernetesの新バージョンのリリースプロセスを管理することです。[通常3〜4ヶ月ごと](https://www.kubernetes.dev/resources/release/)の定期的なリリースサイクルで運営されています。このサイクルの間、Kubernetesリリースチームは他のSIGやコントリビューターと密接に連携し、円滑でうまく調整されたリリースを保証します。これには、リリーススケジュールの計画、コードフリーズとテストフェーズの期限の設定、バイナリ、ドキュメント、リリースノートなどのリリース成果物の作成が含まれます。 + +さらに読み進める前に、SIG Releaseにはリリース・エンジニアリングとリリース・チームという2つのサブプロジェクトがあることに注意してください。 + +このブログ記事では、[Nitish Kumar](https://twitter.com/nitishfy)がSIG Releaseのテクニカル・リーダーであるVerónica López (PlanetScale)にインタビューし、Release Teamサブプロジェクトにスポットライトを当て、リリース・プロセスがどのように見えるか、そして参加する方法について説明します。 + +1. **最初の計画から最終的なリリースまで、Kubernetesの新バージョンの典型的なリリースプロセスはどのようなものですか?スムーズなリリースを保証するために使用している特定の方法論やツールはありますか?** + + Kubernetesの新バージョンのリリースプロセスは、十分に構造化されたコミュニティ主導の取り組みです。私たちが従う特定の方法論やツールはありませんが、物事を整理しておくための一連の手順を記載したカレンダーはあります。完全なリリースプロセスは次のようになります: + +- **リリースチームの立ち上げ**: 新しいリリースのさまざまなコンポーネントの管理を担当するKubernetesコミュニティのボランティアを含むリリースチームの結成から始めます。これは通常、前のリリースが終了する前に行われます。チームが結成されると、リリースチームリーダーとブランチマネージャーが通常の成果物のカレンダーを提案する間に、新しいメンバーがオンボードされます。例として、SIG Releaseのリポジトリに作成された[v1.29チーム結成のissue](https://github.com/kubernetes/sig-release/issues/2307)を見てください。コントリビューターがリリースチームの一員になるには、通常リリースシャドウプログラムを通りますが、それがSIG Releaseに参加する唯一の方法というわけではありません。 + +- **初期段階**: 各リリースサイクルの最初の数週間で、SIG ReleaseはKubernetes機能強化提案(KEPs)で概説された新機能や機能強化の進捗を熱心に追跡します。これらの機能のすべてがまったく新しいものではありませんが、多くの場合、アルファ段階から始まり、その後ベータ段階に進み、最終的には安定したステータスに到達します。 + +- **機能の成熟段階**: 通常、コミュニティからのフィードバックを集めるため、実験的な新機能を含むアルファ・リリースを2、3回行い、その後、機能がより安定し、バグの修正が中心となるベータ・リリースを2、3回行います。この段階でのユーザーからのフィードバックは非常に重要で、この段階で発生する可能性のあるバグやその他の懸念に対処するために、追加のベータ・リリースを作成しなければならないこともあります。これがクリアされると、実際のリリースの前にリリース候補(RC)を作成します。このサイクルを通じて、リリースノートやユーザーガイドなどのドキュメントの更新や改善に努めます。 + +- **安定化段階**: 新リリースの数週間前にコードフリーズを実施し、この時点以降は新機能の追加を禁止します。メインリリースと並行して、私たちはKubernetesの古い公式サポートバージョンのパッチを毎月作成し続けているので、Kubernetesバージョンのライフサイクルはその後数ヶ月に及ぶと言えます。完全なリリースサイクル全体を通して、リリースノートやユーザーガイドを含むドキュメントの更新と改善に努めます。 + + {{< figure src="sig-release-overview.png" alt="リリースチームのオンボーディング; 初期段階; 機能の成熟段階; 安定化段階" >}} + +2. **各リリースで安定性と新機能の導入のバランスをどのように扱っていますか?どのような基準で、どの機能をリリースに含めるかを決定するのですか?** + + 終わりのないミッションですが、重要なのは私たちのプロセスとガイドラインを尊重することだと考えています。私たちのガイドラインは、このプロジェクトに豊富な知識と経験をもたらしてくれるコミュニティの何十人ものメンバーから、何時間にもわたって議論とフィードバックを重ねた結果です。もし厳格なガイドラインがなかったら、私たちの注意を必要とするもっと生産的な議題に時間を使う代わりに、同じ議論を何度も繰り返してしまうでしょう。すべての重要な例外は、チームメンバーの大半の合意を必要とするため、品質を確保することができます。 + + 何がリリースになるかを決定するプロセスは、リリースチームがワークフローを引き継ぐずっと前から始まっています。各SIGと経験豊富なコントリビューターが、機能や変更を含めるかどうかを決定します。その後、リリースチームが、それらの貢献がドキュメント、テスト、後方互換性などの要件を満たしていることを確認し、正式に許可します。同様のプロセスは月例パッチリリースのチェリーピックでも行われ、完全なKEPを必要とするPRや、影響を受けるすべてのブランチを含まない修正は受け入れないという厳しいポリシーがあります。 + +3. **Kubernetesの開発とリリース中に遭遇した最も大きな課題は何ですか?これらの課題をどのように克服しましたか?** + + リリースのサイクルごとに、さまざまな課題が発生します。新たに発見されたCVE(Common Vulnerabilities and Exposures)のような土壇場の問題に取り組んだり、内部ツール内のバグを解決したり、以前のリリースの機能によって引き起こされた予期せぬリグレッションに対処したりすることもあります。私たちがしばしば直面するもう1つの障害は、私たちのチームは大規模ですが、私たちのほとんどがボランティアベースで貢献していることです。時には人手が足りないと感じることもありますが、私たちは常に組織化し、うまくやりくりしています。 + +4. **新しい貢献者として、SIG Releaseに参加するための理想的な道はどのようなものでしょうか?誰もが自分のタスクに忙殺されているコミュニティで、効果的に貢献するために適切なタスクを見つけるにはどうすればいいのでしょうか?** + + オープンソースコミュニティへの関わり方は人それぞれです。SIG Releaseは、リリースを出荷できるように自分たちでツールを書くという、自分勝手なチームです。[SIG K8s Infra](https://github.com/kubernetes/community/blob/master/sig-k8s-infra/README.md)のような他のSIGとのコラボレーションも多いのですが、私たちが使用するツールはすべて、コストを削減しつつ、私たちの大規模な技術的ニーズに合わせて作られたものでなければなりません。このため、「単に」リリースを作成するだけでなく、さまざまなタイプのプロジェクトを手伝ってくれるボランティアを常に探しています。 + + 私たちの現在のプロジェクトでは、[Go](https://go.dev/)プログラミング、Kubernetes内部の理解、Linuxパッケージング、サプライチェーンセキュリティ、テクニカルライティング、一般的なオープンソースプロジェクトのメンテナンスなどのスキルが必要です。このスキルセットは、プロジェクトの成長とともに常に進化しています。 + + 理想的な道筋として、私たちはこう提案します: + + - どのように機能が管理されているか、リリースカレンダー、リリースチームの全体的な構造など、コードに慣れる。 + - [Slack](https://communityinviter.com/apps/kubernetes/community)(#sig-release)などのKubernetesコミュニティのコミュニケーションチャンネルに参加する。 + - コミュニティ全員が参加できる[SIG Releaseウィークリーミーティング](https://github.com/kubernetes/community/tree/master/sig-release#meetings)に参加する。これらのミーティングに参加することは、あなたのスキルセットや興味に関連すると思われる進行中のプロジェクトや将来のプロジェクトについて学ぶ素晴らしい方法です。 + + 経験豊富な貢献者は皆、かつてあなたのような立場にあったことを忘れないでください。遠慮せずに質問し、議論に参加し、貢献するための小さな一歩を踏み出しましょう。 + + {{< figure src="sig-release-meetings.png" alt="SIG Releaseに関する質問" >}} + +5. **リリースシャドウプログラムとは何ですか?また、他の様々なSIGに含まれるシャドウプログラムとの違いは何ですか?** + + リリースシャドウプログラムは、Kubernetesのリリースサイクルを通して、リリースチームの経験豊富なメンバーをシャドウイングする機会を提供します。これは、Kubernetesのリリースに必要な、サブチームにまたがるすべての困難な仕事を見るまたとないチャンスです。多くの人は、私たちの仕事は3ヶ月ごとにリリースを切ることだけだと思っていますが、それは氷山の一角にすぎません。 + + 私たちのプログラムは通常、特定のKubernetesリリースサイクルに沿っており、それは約3ヶ月の予測可能なタイムラインを持っています。このプログラムではKubernetesの新機能を書くことはありませんが、リリースチームは新リリースと何千人ものコントリビューターとの最後のステップであるため、高い責任感が求められます。 + +6. **一般的に、次のKubernetesリリースのリリースシャドウ/リリースリードとしてボランティアに参加する人に求める資格は何ですか?** + + どの役割もある程度の技術的能力を必要としますが、Goの実践的な経験やKubernetes APIに精通していることを必要とするものもあれば、技術的な内容を明確かつ簡潔に伝えるのが得意な人を必要とするものもあります。技術的な専門知識よりも、熱意とコミットメントを重視しています。もしあなたが正しい姿勢を持っていて、Kubernetesやリリース・エンジニアリングの仕事を楽しんでいることが伝われば、たとえそれがあなたが余暇を利用して立ち上げた個人的なプロジェクトであったとしても、チームは必ずあなたを指導します。セルフスターターであること、そして質問をすることを恐れないことは、私たちのチームであなたを大きく前進させます。 + +7. **リリースシャドープログラムに何度も不合格になった人に何を勧めますか?** + + 応募し続けることです。 + + リリースサイクルごとに応募者数が飛躍的に増えているため、選ばれるのが難しくなり、落胆することもありますが、不採用になったからといって、あなたに才能がないというわけではないことを知っておいてください。すべての応募者を受け入れることは現実的に不可能です、しかし、ここに私たちが提案する代替案があります。: + + 毎週開催されるKubernetes SIGのリリースミーティングに参加して、自己紹介をし、チームや私たちが取り組んでいるプロジェクトに慣れてください。 + + リリースチームはSIG Releaseに参加する方法の1つですが、私たちは常に手伝ってくれる人を探しています。繰り返しになりますが、一定の技術的な能力に加えて、私たちが最も求めている特性は、信頼できる人であり、それには時間が必要です。 + + {{< figure src="sig-release-motivation.png" alt="SIG Releaseのモチベーション" >}} + +8. **リリースチームがKubernetes v1.28に特に期待している進行中の取り組みや今後の機能について教えてください。これらの進歩は、Kubernetesの長期的なビジョンとどのように整合しているのでしょうか?** + + Kubernetesのパッケージをコミュニティインフラ上でついに公開できることに興奮しています。数年前からやりたいと思っていたことですが、移行する前に整えなければならない技術的な意味合いが多いプロジェクトです。それが終われば、生産性を向上させ、ワークフロー全体をコントロールできるようになります。 + +## 最後に + +さて、この対談はここで終わりですが、学習はこれで終わりではありません。このインタビューが、SIG Releaseが何をしているのか、そしてどのように手助けを始めたらいいのか、ある程度わかっていただけたと思います。重要なこととして、この記事はSIG Releaseの最初のサブプロジェクトであるリリース・チームを取り上げています。次回のSIG Releaseのスポットライトブログでは、Release Engineeringサブプロジェクトにスポットライトを当て、その活動内容や参加方法について紹介します。最後に、SIG Releaseの運営方法についてより深く理解するために、[SIG Release憲章](https://github.com/kubernetes/community/tree/master/sig-release)をご覧ください。 diff --git a/content/ja/blog/_posts/2024-01-15-SIG-Release-Spotlight/sig-release-meetings.png b/content/ja/blog/_posts/2024-01-15-SIG-Release-Spotlight/sig-release-meetings.png new file mode 100644 index 0000000000000..96c01b6a4dceb Binary files /dev/null and b/content/ja/blog/_posts/2024-01-15-SIG-Release-Spotlight/sig-release-meetings.png differ diff --git a/content/ja/blog/_posts/2024-01-15-SIG-Release-Spotlight/sig-release-motivation.png b/content/ja/blog/_posts/2024-01-15-SIG-Release-Spotlight/sig-release-motivation.png new file mode 100644 index 0000000000000..02cb9429ebe30 Binary files /dev/null and b/content/ja/blog/_posts/2024-01-15-SIG-Release-Spotlight/sig-release-motivation.png differ diff --git a/content/ja/blog/_posts/2024-01-15-SIG-Release-Spotlight/sig-release-overview.png b/content/ja/blog/_posts/2024-01-15-SIG-Release-Spotlight/sig-release-overview.png new file mode 100644 index 0000000000000..0361c3e22d181 Binary files /dev/null and b/content/ja/blog/_posts/2024-01-15-SIG-Release-Spotlight/sig-release-overview.png differ diff --git a/content/ja/blog/_posts/2024-01-23-image-filesystem.md b/content/ja/blog/_posts/2024-01-23-image-filesystem.md new file mode 100644 index 0000000000000..49ddbe2adcb00 --- /dev/null +++ b/content/ja/blog/_posts/2024-01-23-image-filesystem.md @@ -0,0 +1,203 @@ +--- +layout: blog +title: 'Kubernetesでコンテナを別ファイルシステムに格納する設定方法' +date: 2024-01-23 +slug: kubernetes-separate-image-filesystem +--- + +**著者:** Kevin Hannon (Red Hat) + +**翻訳者:** Taisuke Okamoto (IDC Frontier Inc), Junya Okabe (University of Tsukuba), nasa9084 (LY Corporation) + +Kubernetesクラスターの稼働、運用する上でよくある問題は、ディスク容量が不足することです。 +ノードがプロビジョニングされる際には、コンテナイメージと実行中のコンテナのために十分なストレージスペースを確保することが重要です。 +通常、[コンテナランタイム](/ja/docs/setup/production-environment/container-runtimes/)は`/var`に書き込みます。 +これは別のパーティションとして、ルートファイルシステム上に配置できます。 +CRI-Oはデフォルトで、コンテナとイメージを`/var/lib/containers`に書き込みますが、containerdはコンテナとイメージを`/var/lib/containerd`に書き込みます。 + +このブログ記事では、コンテナランタイムがデフォルトのパーティションとは別にコンテンツを保存する方法に注目したいと思います。 +これにより、Kubernetesの設定をより柔軟に行うことができ、デフォルトのファイルシステムはそのままに、コンテナストレージ用に大きなディスクを追加する方法が提供されます。 + +もう少し説明が必要な領域は、Kubernetesがディスクに書き込む場所/内容です。 + +## Kubernetesディスク使用状況を理解する + +Kubernetesには永続(persistent)データと一時(ephemeral)データがあります。 +kubeletとローカルのKubernetes固有ストレージのベースパスは設定可能ですが、通常は`/var/lib/kubelet`と想定されています。 +Kubernetesのドキュメントでは、これは時々ルートファイルシステムまたはノードファイルシステムと呼ばれます。 +このデータの大部分は、次のようにカテゴリー分けされます。 + +- エフェメラルストレージ +- ログ +- コンテナランタイム + +ルート/ノード・ファイルシステムは`/`ではなく、`/var/lib/kubelet`があるディスクのため、ほとんどのPOSIXシステムとは異なります。 + +### エフェメラルストレージ + +Podやコンテナは、動作に一時的または短期的なローカルストレージを必要とする場合があります。 +エフェメラルストレージの寿命は個々のPodの寿命を超えず、エフェメラルストレージはPod間で共有することはできません。 + +### ログ + +デフォルトでは、Kubernetesは各実行中のコンテナのログを`/var/log`内のファイルとして保存します。 +これらのログは一時的であり、ポッドが実行されている間に大きくなりすぎないようにkubeletによって監視されます。 + +各ノードの[ログローテーション](/ja/docs/concepts/cluster-administration/logging/#log-rotation)設定をカスタマイズしてこれらのログのサイズを管理し、ノードローカルストレージに依存しないためにログの配信を設定することができます(サードパーティーのソリューションを使用)。 + +### コンテナランタイム + +コンテナランタイムには、コンテナとイメージのための2つの異なるストレージ領域があります。 + +- 読み取り専用レイヤー:イメージは通常、コンテナが実行されている間に変更されないため、読み取り専用レイヤーとして表されます。読み取り専用レイヤーには、複数のレイヤーが組み合わされて単一の読み取り専用レイヤーになることがあります。コンテナがファイルシステムに書き込んでいる場合、コンテナの上にはエフェメラルストレージを提供する薄いレイヤーがあります。 + +- 書き込み可能レイヤー:コンテナランタイムによっては、ローカルの書き込みがレイヤー化された書き込みメカニズム(たとえば、Linux上の`overlayfs`やWindows上のCimFS)として実装されることがあります。これは書き込み可能レイヤーと呼ばれます。ローカルの書き込みは、コンテナイメージの完全なクローンで初期化された書き込み可能なファイルシステムを使用する場合もあります。これは、ハイパーバイザ仮想化に基づく一部のランタイムで使用されます。 + +コンテナランタイムのファイルシステムには、読み取り専用レイヤーと書き込み可能レイヤーの両方が含まれます。これはKubernetesドキュメントでは`imagefs`と見なされています。 + +## コンテナランタイムの構成 + +### CRI-O + +CRI-Oは、コンテナランタイムが永続データと一時データをどのように保存するかを制御するためのTOML形式のストレージ構成ファイルを使用します。 +CRI-Oは[ストレージライブラリ](https://github.com/containers/storage)を利用します。 +一部のLinuxディストリビューションには、ストレージに関するマニュアルエントリ(`man 5 containers-storage.conf`)があります。 +ストレージの主な設定は、`/etc/containers/storage.conf`にあり、一時データの場所やルートディレクトリを制御することができます。 +ルートディレクトリは、CRI-Oが永続データを保存する場所です。 + +```toml +[storage] +# Default storage driver +driver = "overlay" +# Temporary storage location +runroot = "/var/run/containers/storage" +# Primary read/write location of container storage +graphroot = "/var/lib/containers/storage" +``` + +- `graphroot` + - コンテナランタイムから保存される永続データを指します + - SELinuxが有効になっている場合、これは`/var/lib/containers/storage`と一致させる必要があります +- `runroot` + - コンテナに対する一時的な読み書きアクセスを提供します + - これは一時ファイルシステムに配置することを推奨します + +ここでは、`/var/lib/containers/storage`に合うようにgraphrootディレクトリのラベルを変更する簡単な方法を紹介します: + +```bash +semanage fcontext -a -e /var/lib/containers/storage +restorecon -R -v +``` + +### containerd + +コンテナランタイムであるcontainerdは、永続データと一時データの保存先を制御するためのTOML形式の構成ファイルを使用します。構成ファイルのデフォルトパスは、`/etc/containerd/config.toml`にあります。 + +containerdストレージの関連フィールドは、`root`と`state`です。 + +- `root` + - containerdのメタデータのルートディレクトリ + - デフォルトは`/var/lib/containerd`です + - また、OSがそれを要求する場合は、ルートにSELinuxラベルも必要です +- `state` + - containerdの一時データ + - デフォルトは、`/run/containerd`です + +## Kubernetesノードの圧迫による退避 + +Kubernetesは、コンテナファイルシステムがノードファイルシステムと分離されているかどうかを自動的に検出します。 +ファイルシステムを分離する場合、Kubernetesはノードファイルシステムとコンテナランタイムファイルシステムの両方を監視する責任があります。 +Kubernetesドキュメントでは、ノードファイルシステムとコンテナランタイムファイルシステムをそれぞれnodefsとimagefsと呼んでいます。 +nodefsまたはimagefsのいずれかがディスク容量不足になると、ノード全体がディスク圧迫があると見なされます。 +Kubernetesは、まず未使用のコンテナやイメージを削除してスペースを回収し、その後にポッドを追い出すことでスペースを再利用します。 +nodefsとimagefsの両方を持つノードでは、kubeletはimagefs上の未使用のコンテナイメージを[ガベージコレクト](/ja/docs/concepts/architecture/garbage-collection/#containers-images)し、nodefsからは終了したポッドとそれらのコンテナを削除します。 +nodefsのみが存在する場合、Kubernetesのガベージコレクションには、終了したコンテナ、ポッド、そして未使用のイメージが含まれます。 + +Kubernetesでは、ディスクがいっぱいかどうかを判断するためのより多くの構成が可能です。 +kubelet内の退避マネージャーには、関連する閾値を制御するいくつかの構成設定があります。 +ファイルシステムの場合、関連する測定値は`nodefs.available`、`nodefs.inodesfree`、`imagefs.available`、および`imagefs.inodesfree`です。 +コンテナランタイム用に専用のディスクがない場合、imagefsは無視されます。 + +ユーザーは、既存のデフォルト値を使用できます: + +- `memory.available` < 100MiB +- `nodefs.available` < 10% +- `imagefs.available` < 15% +- `nodefs.inodesFree` < 5% (Linuxノード) + +Kubernetesでは、kubeletの構成ファイル内の`EvictionHard`と`EvictionSoft`にユーザー定義の値を設定することができます。 + +`EvictionHard` + 限界値を定義します。これらの限界値を超えると、Grace Periodなしでポッドが追い出されます。 + +`EvictionSoft` + 限界値を定義します。これらの限界値を超えると、Grace Periodが設定されたシグナルごとにポッドが追い出されます。 + +`EvictionHard`の値を指定すると、デフォルト値が置き換えられます。 +したがって、すべてのシグナルを設定することが重要です。 + +たとえば、次に示すkubeletの設定は、[退避シグナル](/docs/concepts/scheduling-eviction/node-pressure-eviction/#eviction-signals-and-thresholds)と猶予期間オプションを設定するために使用できます。 + +```yaml +apiVersion: kubelet.config.k8s.io/v1beta1 +kind: KubeletConfiguration +address: "192.168.0.8" +port: 20250 +serializeImagePulls: false +evictionHard: + memory.available: "100Mi" + nodefs.available: "10%" + nodefs.inodesFree: "5%" + imagefs.available: "15%" + imagefs.inodesFree: "5%" +evictionSoft: + memory.available: "100Mi" + nodefs.available: "10%" + nodefs.inodesFree: "5%" + imagefs.available: "15%" + imagefs.inodesFree: "5%" +evictionSoftGracePeriod: + memory.available: "1m30s" + nodefs.available: "2m" + nodefs.inodesFree: "2m" + imagefs.available: "2m" + imagefs.inodesFree: "2m" +evictionMaxPodGracePeriod: 60s +``` + +## 問題点 + +Kubernetesプロジェクトでは、退避のデフォルト設定を使用するか、退避に関連するすべてのフィールドを設定することをお勧めしています。 +デフォルト設定を使用するか、独自の`evictionHard`設定を指定できます。 +シグナルの設定を忘れると、Kubernetesはそのリソースを監視しません。 +管理者やユーザーが遭遇する可能性のある一般的な設定ミスの1つは、新しいファイルシステムを`/var/lib/containers/storage`または`/var/lib/containerd`にマウントすることです。 +Kubernetesは別のファイルシステムを検出するため、これを行った場合は`imagefs.inodesfree`と`imagefs.available`が必要に応じて設定に一致していることを確認する必要があります。 + +もう一つの混乱の領域は、イメージファイルシステムをノードに定義した場合でも、エフェメラルストレージの報告が変わらないことです。 +イメージファイルシステム(`imagefs`)は、コンテナイメージのレイヤーを保存するために使用されます。 +コンテナが自分自身のルートファイルシステムに書き込む場合、そのローカルな書き込みはコンテナイメージのサイズには含まれません。 +コンテナランタイムがこれらのローカルな変更を保存する場所は、ランタイムによって定義されますが、通常はイメージファイルシステムです。 +Pod内のコンテナがファイルシステムをバックエンドとする`emptyDir`ボリュームに書き込んでいる場合、これはノードファイルシステムからスペースを使用します。 +kubeletは常に、`nodefs`で表されるファイルシステムに基づいてエフェメラルストレージの容量と割り当てを報告します。 +これは、実際には一時的な書き込みがイメージファイルシステムに行われている場合に混乱の原因となる可能性があります。 + +## 今後の課題 + +[KEP-4191](https://github.com/kubernetes/enhancements/issues/4191)に取り組むことで、エフェメラルの報告の制限を解消し、コンテナランタイムにより多くの構成オプションを提供することが期待されています。 +この提案では、Kubernetesは書き込み可能なレイヤーが読み取り専用のレイヤー(イメージ)と分離されているかどうかを検出します。 +これにより、書き込み可能なレイヤーを含むすべてのエフェメラルストレージを同じディスクに配置することが可能になります。 +また、イメージ用に別のディスクを使用することも可能になります。 + +## 参加するためにはどうすればよいですか? + +参加したい場合は、Kubernetesの[SIG Node](https://github.com/kubernetes/community/tree/master/sig-node)に参加することができます。 + +フィードバックを共有したい場合は、Slackチャンネルの[#sig-node](https://kubernetes.slack.com/archives/C0BP8PW9G)で行うことができます。 +まだそのSlackワークスペースに参加していない場合は、[https://slack.k8s.io/](https://slack.k8s.io/)から招待状を取得できます。 + +素晴らしいレビューを提供し、貴重な洞察を共有し、トピックのアイデアを提案してくれたすべてのコントリビューターに特別な感謝を捧げます。 + +- Peter Hunt +- Mrunal Patel +- Ryan Phillips +- Gaurav Singh diff --git a/content/ja/blog/_posts/2024-02-22-k8s-book-club/csantana_k8s_book_club.jpg b/content/ja/blog/_posts/2024-02-22-k8s-book-club/csantana_k8s_book_club.jpg new file mode 100644 index 0000000000000..989ba7228df01 Binary files /dev/null and b/content/ja/blog/_posts/2024-02-22-k8s-book-club/csantana_k8s_book_club.jpg differ diff --git a/content/ja/blog/_posts/2024-02-22-k8s-book-club/index.md b/content/ja/blog/_posts/2024-02-22-k8s-book-club/index.md new file mode 100644 index 0000000000000..edf28a34e8a00 --- /dev/null +++ b/content/ja/blog/_posts/2024-02-22-k8s-book-club/index.md @@ -0,0 +1,96 @@ +------ +layout: blog +title: "Kubernetesブッククラブを覗く" +slug: k8s-book-club +date: 2024-02-22 +--- + +**著者**: Frederico Muñoz (SAS Institute) + +Kubernetesとそれを取り巻く技術のエコシステム全体を学ぶことは、課題がないわけではありません。 +このインタビューでは、[AWSのCarlos Santana](https://www.linkedin.com/in/csantanapr/)さんに、コミュニティベースの学習体験を利用するために、彼がどのようにして[Kubernetesブッククラブ](https://community.cncf.io/kubernetes-virtual-book-club/)を作ったのか、その会がどのような活動をするのか、そしてどのようにして参加するのかについて伺います。 + +![KubeCon NA 2023で話すCarlos Santanaさん](csantana_k8s_book_club.jpg) + +**Frederico Muñoz (FSM)**: こんにちはCarlosさん、時間をとってくれてありがとう。 +まずはじめに、ご自身のことを少し教えていただけますか? + +**Carlos Santana (CS)**: もちろんです。 +6年前に本番環境でKubernetesをデプロイした経験が、[Knative](https://knative.dev/)に参加するきっかけとなり、その後リリースチームを通じてKubernetesに貢献しました。 +アップストリームのKubernetesでの作業は、私がオープンソースで得た最高の経験のひとつです。 +過去2年間、AWSのシニア・スペシャリスト・ソリューション・アーキテクトとしての役割で、私は大企業がKubernetes上に内部開発者プラットフォーム(IDP)を構築することを支援してきました。 +今後、私のオープンソースへの貢献は、[Argo](https://github.com/argoproj)や[Crossplane](https://www.crossplane.io/)、[Backstage](https://www.cncf.io/projects/backstage/)のようなCNCFのプロジェクトや[CNOE](https://cnoe.io/)を対象にしています。 + +## ブッククラブの創設 + +**FSM**: それであなたがKubernetesに辿り着いたわけですが、その時点でブッククラブを始めた動機は何だったのでしょうか? + + +**CS**: Kubernetesブッククラブのアイデアは、[TGIK](https://github.com/vmware-archive/tgik)のライブ配信での何気ない提案から生まれました。 +私にとって、それは単に本を読むということ以上に、学習コミュニティを作るということでした。 +このプラットフォームは知識の源であるだけでなく、特にパンデミックの困難な時期にはサポートシステムでもありました。 +この取り組みが、メンバーたちの対処と成長に役立っていることを目の当たりにして、喜ばしいと思っています。 +最初の本[Production Kubernetes](https://www.oreilly.com/library/view/production-kubernetes/9781492092292/)は、2021年3月5日に始めて36週間かかりました。 +現在は、1冊の本をカバーするのにそれほど時間はかからず、1週間に1章か2章です。 + +**FSM**: Kubernetesブッククラブの仕組みについて教えてください。どのように本を選び、どのように読み進めるのですか? + +**CS**: 私たちは、グループの関心とニーズに基づいて本を共同で選んでいます。 +この実践的なアプローチは、メンバー、とくに初心者が複雑な概念をより簡単に理解するのに役立ちます。 +毎週2つのシリーズがあり、EMEAのタイムゾーンのものと、私がUSで組織しているものです。 +各オーガナイザーは共同ホストと協力してSlack上で本を選び、各章の議論するために、数週間に渡りホストのラインナップを整えます。 + + +**FSM**: 私の記憶が間違っていなければ、Kubernetesブッククラブは17冊目に突入しています。 +物事を活発に保つための秘密のレシピがあるのですか? + +**CS**: ブッククラブを活発で魅力的なものに保つ秘訣は、いくつかの重要な要素にあります。 + +まず、一貫性が重要です。 +休みの日やKubeConのような大きなイベントの時だけミーティングをキャンセルして、定期的なスケジュールを維持するよう努力しています。 +この規則性は、メンバーの参加を維持し、信頼できるコミュニティを築くのに役立っています。 + +次に、セッションを面白く、対話式のものにすることが重要です。 +たとえば、ミートアップ中にポップアップ・クイズを頻繁に導入します。これはメンバーの理解度をテストするだけでなく、楽しみの要素も加えています。 +このアプローチによって内容の関連性が維持され、理論的な概念が実社会のシナリオでどのように適用されるかをメンバーが理解するのに役立ちます。 + +## ブッククラブで扱うトピック + +**FSM**: 書籍の主なトピックは、Kubernetes、GitOps、セキュリティ、SRE、オブザーバビリティになっています。 +これはとくに人気という観点で、Cloud Native Landscapeの反映でしょうか? + +**CS**: 私たちの旅は『Production Kubernetes』から始まり、実用的な本番環境向けのソリューションに焦点を当てる方向性を設定しました。 +それ以来、私たちはCNCF Landscapeのさまざまな側面を掘り下げ、異なるテーマに沿って本を揃えています。 +各テーマは、それがセキュリティであれ、オブザーバビリティであれ、サービスメッシュであれ、コミュニティ内の関連性と需要にもとづいて選択されています。 +たとえば、Kubernetes認定に関する最近のテーマでは、書籍の著者を積極的なホストとして参加させ、彼らの専門知識で議論を充実させました。 + +**FSM**: プロジェクトに最近変化があったことは知っています。[Cloud Native Community Group](https://community.cncf.io/)としてCNCFに統合されたことです。 +この変更について少しお話いただけますか? + +**CS**: CNCFはブッククラブをCloud Native Community Groupとして快く受け入れてくれました。 +これは私たちの運営を合理化し、影響範囲を拡大する重要な進展です。 +この連携はKubernetes Community Days (KCD)のミートアップで使用されているものと同様に、管理機能の強化に役立っています。 +現在では、メンバーシップ、イベントのスケジューリング、メーリングリスト、Webカンファレンスの開催、セッションの記録など、より強固な体制が整っています。 + +**FSM**: CNCFとの関わりは、この半年間のKubernetesブッククラブの成長やエンゲージメントにどのような影響を与えましたか? + +**CS**: 半年前にCNCFコミュニティの一員になって以来、Kubernetesブッククラブでは大きな定量的な変化を目の当たりにしてきました。 +会員数は600人以上に急増し、この間に40以上のイベントを企画・実施することに成功しました。 +さらに期待されるのは、1回のイベントに平均30人が参加するという安定した動員数です。 +この成長とエンゲージメントは、コミュニティにおける影響やKubernetesブッククラブの影響範囲に関して、私たちのCNCF加盟が肯定的な影響である明確な指標です。 + +## ブッククラブに参加する + +**FSM**: 参加を希望する人は、どうすればいいのでしょうか? + +**CS**: 参加するためには3つの段階があります。 + +- まず、[Kubernetesブッククラブコミュニティ](https://community.cncf.io/kubernetes-virtual-book-club/)に参加します +- 次に、コミュニティページ上の[イベント](https://community.cncf.io/kubernetes-virtual-book-club/)に出欠連絡をします +- 最後に、CNCFのSlackチャンネル[#kubernetes-book-club](https://cloud-native.slack.com/archives/C05EYA14P37)に参加します + +**FSM**: 素晴らしい、ありがとうございます!最後に何かコメントをお願いします。 + +**CS**: Kubernetesブッククラブは、単に本について議論する専門家のグループというだけではなく、それ以上です。 +それは、[Neependra Khare](https://www.linkedin.com/in/neependra/)さん、[Eric Smalling](https://www.linkedin.com/in/ericsmalling/)さん、[Sevi Karakulak](https://www.linkedin.com/in/sevikarakulak/)さん、[Chad M. Crowell](https://www.linkedin.com/in/chadmcrowell/)さん、そして[Walid (CNJ) Shaari](https://www.linkedin.com/in/walidshaari/)さんの主催と企画を手伝ってくれる素晴らしいボランティアであり、活気のあるコミュニティです。 +KubeConで私たちを見て、Kubernetesブッククラブのステッカーをゲットしてください! diff --git a/content/ja/blog/_posts/2024-03-07-cri-o-seccomp-oci-artifacts.md b/content/ja/blog/_posts/2024-03-07-cri-o-seccomp-oci-artifacts.md new file mode 100644 index 0000000000000..3a4060c3925b4 --- /dev/null +++ b/content/ja/blog/_posts/2024-03-07-cri-o-seccomp-oci-artifacts.md @@ -0,0 +1,432 @@ +--- +layout: blog +title: "CRI-O: OCIレジストリからのseccompプロファイルの適用" +date: 2024-03-07 +slug: cri-o-seccomp-oci-artifacts +--- + +**著者:** Kevin Hannon (Red Hat) + +**翻訳者:** Taisuke Okamoto (IDC Frontier Inc), atoato88 (NEC Corporation), Junya Okabe (University of Tsukuba) + +seccompはセキュアなコンピューティングモードを意味し、Linuxカーネルのバージョン2.6.12以降の機能として提供されました。 +これは、プロセスの特権をサンドボックス化し、ユーザースペースからカーネルへの呼び出しを制限するために使用できます。 +Kubernetesでは、ノードに読み込まれたseccompプロファイルをPodやコンテナに自動的に適用することができます。 + +しかし、Kubernetesでseccompプロファイルを配布することは大きな課題です。 +なぜなら、JSONファイルがワークロードが実行可能なすべてのノードで利用可能でなければならないからです。 +[Security Profiles Operator](https://sigs.k8s.io/security-profiles-operator)などのプロジェクトは、クラスター内でデーモンとして実行することでこの問題を解決しています。 +この設定から、[コンテナランタイム](/docs/setup/production-environment/container-runtimes)がこの配布プロセスの一部を担当できるかどうかが興味深い点です。 + +通常、ランタイムはローカルパスからプロファイルを適用します。たとえば: + +```yaml +apiVersion: v1 +kind: Pod +metadata: + name: pod +spec: + containers: + - name: container + image: nginx:1.25.3 + securityContext: + seccompProfile: + type: Localhost + localhostProfile: nginx-1.25.3.json +``` + +プロファイル`nginx-1.25.3.json`はkubeletのルートディレクトリ内に`seccomp`ディレクトリを追加して利用可能でなければなりません。 +これは、ディスク上のプロファイルのデフォルトの場所が`/var/lib/kubelet/seccomp/nginx-1.25.3.json`になることを指しています。 +プロファイルが利用できない場合、ランタイムは次のようにコンテナの作成に失敗します。 + +```shell +kubectl get pods +``` + +```console +NAME READY STATUS RESTARTS AGE +pod 0/1 CreateContainerError 0 38s +``` + +```shell +kubectl describe pod/pod | tail +``` + +```console +Tolerations: node.kubernetes.io/not-ready:NoExecute op=Exists for 300s + node.kubernetes.io/unreachable:NoExecute op=Exists for 300s +Events: + Type Reason Age From Message + ---- ------ ---- ---- ------- + Normal Scheduled 117s default-scheduler Successfully assigned default/pod to 127.0.0.1 + Normal Pulling 117s kubelet Pulling image "nginx:1.25.3" + Normal Pulled 111s kubelet Successfully pulled image "nginx:1.25.3" in 5.948s (5.948s including waiting) + Warning Failed 7s (x10 over 111s) kubelet Error: setup seccomp: unable to load local profile "/var/lib/kubelet/seccomp/nginx-1.25.3.json": open /var/lib/kubelet/seccomp/nginx-1.25.3.json: no such file or directory + Normal Pulled 7s (x9 over 111s) kubelet Container image "nginx:1.25.3" already present on machine +``` + +`Localhost`プロファイルを手動で配布する必要があるという大きな障害は、多くのエンドユーザーが`RuntimeDefault`に戻るか、さらには`Unconfined`(seccompが無効になっている)でワークロードを実行することになる可能性が高いということです。 + +## CRI-Oが救世主 + +Kubernetesのコンテナランタイム[CRI-O](https://github.com/cri-o/cri-o)は、カスタムアノテーションを使用してさまざまな機能を提供しています。 +v1.30のリリースでは、アノテーションの新しい集合である`seccomp-profile.kubernetes.cri-o.io/POD`と`seccomp-profile.kubernetes.cri-o.io/`のサポートが[追加](https://github.com/cri-o/cri-o/pull/7719)されました。 +これらのアノテーションを使用すると、以下を指定することができます: + +- 特定のコンテナ用のseccompプロファイルは、次のように使用されます:`seccomp-profile.kubernetes.cri-o.io/` (例:`seccomp-profile.kubernetes.cri-o.io/webserver: 'registry.example/example/webserver:v1'`) +- Pod内のすべてのコンテナに対するseccompプロファイルは、コンテナ名の接尾辞を使用せず、予約された名前`POD`を使用して次のように使用されます:`seccomp-profile.kubernetes.cri-o.io/POD` +- イメージ全体のseccompプロファイルは、イメージ自体がアノテーション`seccomp-profile.kubernetes.cri-o.io/POD`または`seccomp-profile.kubernetes.cri-o.io/`を含んでいる場合に使用されます + +CRI-Oは、ランタイムがそれを許可するように構成されている場合、および`Unconfined`として実行されるワークロードに対してのみ、そのアノテーションを尊重します。 +それ以外のすべてのワークロードは、引き続き`securityContext`からの値を優先して使用します。 + +アノテーション単体では、プロファイルの配布にはあまり役立ちませんが、それらの参照方法が役立ちます! +たとえば、OCIアーティファクトを使用して、通常のコンテナイメージのようにseccompプロファイルを指定できるようになりました。 + +```yaml +apiVersion: v1 +kind: Pod +metadata: + name: pod + annotations: + seccomp-profile.kubernetes.cri-o.io/POD: quay.io/crio/seccomp:v2 +spec: … +``` + +イメージ`quay.io/crio/seccomp:v2`には、実際のプロファイル内容を含む`seccomp.json`ファイルが含まれています。 +[ORAS](https://oras.land)や[Skopeo](https://github.com/containers/skopeo)などのツールを使用して、イメージの内容を検査できます。 + +```shell +oras pull quay.io/crio/seccomp:v2 +``` + +```console +Downloading 92d8ebfa89aa seccomp.json +Downloaded 92d8ebfa89aa seccomp.json +Pulled [registry] quay.io/crio/seccomp:v2 +Digest: sha256:f0205dac8a24394d9ddf4e48c7ac201ca7dcfea4c554f7ca27777a7f8c43ec1b +``` + +```shell +jq . seccomp.json | head +``` + +```yaml +{ + "defaultAction": "SCMP_ACT_ERRNO", + "defaultErrnoRet": 38, + "defaultErrno": "ENOSYS", + "archMap": [ + { + "architecture": "SCMP_ARCH_X86_64", + "subArchitectures": [ + "SCMP_ARCH_X86", + "SCMP_ARCH_X32" +``` + +```shell +# イメージのプレーンマニフェストを調べる +skopeo inspect --raw docker://quay.io/crio/seccomp:v2 | jq . +``` + +```yaml +{ + "schemaVersion": 2, + "mediaType": "application/vnd.oci.image.manifest.v1+json", + "config": + { + "mediaType": "application/vnd.cncf.seccomp-profile.config.v1+json", + "digest": "sha256:ca3d163bab055381827226140568f3bef7eaac187cebd76878e0b63e9e442356", + "size": 3, + }, + "layers": + [ + { + "mediaType": "application/vnd.oci.image.layer.v1.tar", + "digest": "sha256:92d8ebfa89aa6dd752c6443c27e412df1b568d62b4af129494d7364802b2d476", + "size": 18853, + "annotations": { "org.opencontainers.image.title": "seccomp.json" }, + }, + ], + "annotations": { "org.opencontainers.image.created": "2024-02-26T09:03:30Z" }, +} +``` + +イメージマニフェストには、特定の必要な構成メディアタイプ(`application/vnd.cncf.seccomp-profile.config.v1+json`)への参照と、`seccomp.json`ファイルを指す単一のレイヤー(`application/vnd.oci.image.layer.v1.tar`)が含まれています。 +それでは、この新機能を試してみましょう! + +### 特定のコンテナやPod全体に対してアノテーションを使用する + +CRI-Oは、アノテーションを利用する前に適切に構成する必要があります。 +これを行うには、ランタイムの `allowed_annotations`配列にアノテーションを追加します。 +これは、次のようなドロップイン構成`/etc/crio/crio.conf.d/10-crun.conf`を使用して行うことができます: + +```toml +[crio.runtime] +default_runtime = "crun" + +[crio.runtime.runtimes.crun] +allowed_annotations = [ + "seccomp-profile.kubernetes.cri-o.io", +] +``` + +それでは、CRI-Oを最新の`main`コミットから実行します。 +これは、ソースからビルドするか、[静的バイナリバンドル](https://github.com/cri-o/packaging?tab=readme-ov-file#using-the-static-binary-bundles-directly)を使用するか、[プレリリースパッケージ](https://github.com/cri-o/packaging?tab=readme-ov-file#usage)を使用することで行うことができます。 + +これを実証するために、[`local-up-cluster.sh`](https://github.com/cri-o/cri-o?tab=readme-ov-file#running-kubernetes-with-cri-o)を使って単一ノードのKubernetesクラスターをセットアップし、コマンドラインから`crio`バイナリを実行しました。 +クラスターが起動して実行されているので、seccomp `Unconfined`として実行されているアノテーションのないPodを試してみましょう: + +```shell +cat pod.yaml +``` + +```yaml +apiVersion: v1 +kind: Pod +metadata: + name: pod +spec: + containers: + - name: container + image: nginx:1.25.3 + securityContext: + seccompProfile: + type: Unconfined +``` + +```shell +kubectl apply -f pod.yaml +``` + +ワークロードが起動して実行中です: + +```shell +kubectl get pods +``` + +```console +NAME READY STATUS RESTARTS AGE +pod 1/1 Running 0 15s +``` + +[`crictl`](https://sigs.k8s.io/cri-tools)を使用してコンテナを検査しても、seccompプロファイルが適用されていないことがわかります: + +```shell +export CONTAINER_ID=$(sudo crictl ps --name container -q) +sudo crictl inspect $CONTAINER_ID | jq .info.runtimeSpec.linux.seccomp +``` + +```console +null +``` + +では、Podを変更して、コンテナにプロファイル`quay.io/crio/seccomp:v2`を適用します: + +```yaml +apiVersion: v1 +kind: Pod +metadata: + name: pod + annotations: + seccomp-profile.kubernetes.cri-o.io/container: quay.io/crio/seccomp:v2 +spec: + containers: + - name: container + image: nginx:1.25.3 +``` + +新しいseccompプロファイルを適用するには、Podを削除して再作成する必要があります。 +再作成のみが新しいseccompプロファイルを適用するためです: + +```shell +kubectl delete pod/pod +``` + +```console +pod "pod" deleted +``` + +```shell +kubectl apply -f pod.yaml +``` + +```console +pod/pod created +``` + +CRI-Oのログには、ランタイムがアーティファクトを取得したことが示されます: + +```console +WARN[…] Allowed annotations are specified for workload [seccomp-profile.kubernetes.cri-o.io] +INFO[…] Found container specific seccomp profile annotation: seccomp-profile.kubernetes.cri-o.io/container=quay.io/crio/seccomp:v2 id=26ddcbe6-6efe-414a-88fd-b1ca91979e93 name=/runtime.v1.RuntimeService/CreateContainer +INFO[…] Pulling OCI artifact from ref: quay.io/crio/seccomp:v2 id=26ddcbe6-6efe-414a-88fd-b1ca91979e93 name=/runtime.v1.RuntimeService/CreateContainer +INFO[…] Retrieved OCI artifact seccomp profile of len: 18853 id=26ddcbe6-6efe-414a-88fd-b1ca91979e93 name=/runtime.v1.RuntimeService/CreateContainer +``` + +>And the container is finally using the profile: + +そして、コンテナは最終的にプロファイルを使用しています: + +```shell +export CONTAINER_ID=$(sudo crictl ps --name container -q) +sudo crictl inspect $CONTAINER_ID | jq .info.runtimeSpec.linux.seccomp | head +``` + +```yaml +{ + "defaultAction": "SCMP_ACT_ERRNO", + "defaultErrnoRet": 38, + "architectures": [ + "SCMP_ARCH_X86_64", + "SCMP_ARCH_X86", + "SCMP_ARCH_X32" + ], + "syscalls": [ + { +``` + +ユーザーが接尾辞`/container`を予約名`/POD`に置き換えると、Pod内のすべてのコンテナに対して同じことが機能します。 +たとえば: + +```yaml +apiVersion: v1 +kind: Pod +metadata: + name: pod + annotations: + seccomp-profile.kubernetes.cri-o.io/POD: quay.io/crio/seccomp:v2 +spec: + containers: + - name: container + image: nginx:1.25.3 +``` + +### コンテナイメージにアノテーションを使用する + +特定のワークロードにOCIアーティファクトとしてseccompプロファイルを指定する機能は素晴らしいですが、ほとんどのユーザーはseccompプロファイルを公開されたコンテナイメージに関連付けたいと考えています。 +これは、コンテナイメージ自体に適用されるメタデータであるコンテナイメージアノテーションを使用して行うことができます。 +たとえば、[Podman](https://podman.io)を使用して、イメージのビルド中に直接イメージアノテーションを追加することができます: + +```shell +podman build \ + --annotation seccomp-profile.kubernetes.cri-o.io=quay.io/crio/seccomp:v2 \ + -t quay.io/crio/nginx-seccomp:v2 . +``` + +プッシュされたイメージには、そのアノテーションが含まれます: + +```shell +skopeo inspect --raw docker://quay.io/crio/nginx-seccomp:v2 | + jq '.annotations."seccomp-profile.kubernetes.cri-o.io"' +``` + +```console +"quay.io/crio/seccomp:v2" +``` + +そのイメージを使用して、CRI-OのテストPod定義に組み込む場合: + +```yaml +apiVersion: v1 +kind: Pod +metadata: + name: pod + # Podのアノテーションが設定されていません +spec: + containers: + - name: container + image: quay.io/crio/nginx-seccomp:v2 +``` + +その後、CRI-Oのログには、イメージのアノテーションが評価され、プロファイルが適用されたことが示されます: + +```shell +kubectl delete pod/pod +``` + +```console +pod "pod" deleted +``` + +```shell +kubectl apply -f pod.yaml +``` + +```console +pod/pod created +``` + +```console +INFO[…] Found image specific seccomp profile annotation: seccomp-profile.kubernetes.cri-o.io=quay.io/crio/seccomp:v2 id=c1f22c59-e30e-4046-931d-a0c0fdc2c8b7 name=/runtime.v1.RuntimeService/CreateContainer +INFO[…] Pulling OCI artifact from ref: quay.io/crio/seccomp:v2 id=c1f22c59-e30e-4046-931d-a0c0fdc2c8b7 name=/runtime.v1.RuntimeService/CreateContainer +INFO[…] Retrieved OCI artifact seccomp profile of len: 18853 id=c1f22c59-e30e-4046-931d-a0c0fdc2c8b7 name=/runtime.v1.RuntimeService/CreateContainer +INFO[…] Created container 116a316cd9a11fe861dd04c43b94f45046d1ff37e2ed05a4e4194fcaab29ee63: default/pod/container id=c1f22c59-e30e-4046-931d-a0c0fdc2c8b7 name=/runtime.v1.RuntimeService/CreateContainer +``` + +```shell +export CONTAINER_ID=$(sudo crictl ps --name container -q) +sudo crictl inspect $CONTAINER_ID | jq .info.runtimeSpec.linux.seccomp | head +``` + +```yaml +{ + "defaultAction": "SCMP_ACT_ERRNO", + "defaultErrnoRet": 38, + "architectures": [ + "SCMP_ARCH_X86_64", + "SCMP_ARCH_X86", + "SCMP_ARCH_X32" + ], + "syscalls": [ + { +``` + +コンテナイメージの場合、アノテーション`seccomp-profile.kubernetes.cri-o.io`は`seccomp-profile.kubernetes.cri-o.io/POD`と同様に扱われ、Pod全体に適用されます。 +さらに、この機能は、イメージにコンテナ固有のアノテーションを使用する場合にも機能します。 +たとえば、コンテナの名前が`container1`の場合: + +```shell +skopeo inspect --raw docker://quay.io/crio/nginx-seccomp:v2-container | + jq '.annotations."seccomp-profile.kubernetes.cri-o.io/container1"' +``` + +```console +"quay.io/crio/seccomp:v2" +``` + +この機能の素晴らしい点は、ユーザーが特定のコンテナイメージ用のseccompプロファイルを作成し、同じレジストリ内に並べて保存できることです。 +イメージをプロファイルにリンクすることで、アプリケーション全体のライフサイクルを通じてそれらを維持する柔軟性が提供されます。 + +### ORASを使用してプロファイルをプッシュする + +OCIオブジェクトを作成してseccompプロファイルを含めるには、ORASを使用する場合、もう少し作業が必要です。 +将来的には、Podmanなどのツールが全体のプロセスをより簡略化することを期待しています。 +現時点では、コンテナレジストリが[OCI互換](https://oras.land/docs/compatible_oci_registries/#registries-supporting-oci-artifacts)である必要があります。 +これは[Quay.io](https://quay.io)の場合も同様です。 +CRI-Oは、seccompプロファイルオブジェクトがコンテナイメージメディアタイプ(`application/vnd.cncf.seccomp-profile.config.v1+json`)を持っていることを期待していますが、ORASはデフォルトで`application/vnd.oci.empty.v1+json`を使用します。 +これを実現するために、次のコマンドを実行できます: + +```shell +echo "{}" > config.json +oras push \ + --config config.json:application/vnd.cncf.seccomp-profile.config.v1+json \ + quay.io/crio/seccomp:v2 seccomp.json +``` + +結果として得られるイメージには、CRI-Oが期待する`mediaType`が含まれています。 +ORASは単一のレイヤー`seccomp.json` をレジストリにプッシュします。 +プロファイルの名前はあまり重要ではありません。 +CRI-Oは最初のレイヤーを選択し、それがseccompプロファイルとして機能するかどうかを確認します。 + +## 将来の作業 + +CRI-OはOCIアーティファクトを通常のファイルと同様に内部で管理しています。 +これにより、それらを移動したり、使用されなくなった場合に削除したり、seccompプロファイル以外のデータを利用したりする利点が得られます。 +これにより、OCIアーティファクトをベースにしたCRI-Oの将来の拡張が可能になります。 +また、OCIアーティファクトの中に複数のレイヤーを持つことを考える上で、seccompプロファイルの積層も可能になります。 +v1.30.xリリースでは`Unconfined`ワークロードのみがサポートされているという制限は、将来CRI-Oが解決したい課題です。 +セキュリティを損なうことなく、全体的なユーザーエクスペリエンスを簡素化することが、コンテナワークロードにおけるseccompの成功の鍵となるようです。 + +CRI-Oのメンテナーは、新機能に関するフィードバックや提案を歓迎します! +このブログ投稿を読んでいただき、ぜひKubernetesの[Slackチャンネル#crio](https://kubernetes.slack.com/messages/CAZH62UR1)を通じてメンテナーに連絡したり、[GitHubリポジトリ](https://github.com/cri-o/cri-o)でIssueを作成したりしてください。 diff --git a/content/ja/community/code-of-conduct.md b/content/ja/community/code-of-conduct.md index 971e25570b229..22186e03416ba 100644 --- a/content/ja/community/code-of-conduct.md +++ b/content/ja/community/code-of-conduct.md @@ -9,7 +9,7 @@ css: /css/community.css

            Kubernetesコミュニティ行動規範

            Kubernetesは、CNCF行動規範に従います。 -以下のCNCFの行動規範のテキストは、commit 214585eから複製したものです。この掲示が古くなっていることに気がついた場合には、issueを作成してください。 +以下のCNCFの行動規範のテキストは、commit c9a4849から複製したものです。この掲示が古くなっていることに気がついた場合には、issueを作成してください。 イベント、ミーティング、Slack、その他のコミュニケーション手段において行動規範の違反を見つけた場合には、Kubernetes Code of Conduct Committee(行動規範委員会)に連絡してください。連絡はメールアドレスconduct@kubernetes.ioから行えます。連絡者の匿名性は守られます。 diff --git a/content/ja/community/static/cncf-code-of-conduct.md b/content/ja/community/static/cncf-code-of-conduct.md index 61255d92d9a9f..659b552e40049 100644 --- a/content/ja/community/static/cncf-code-of-conduct.md +++ b/content/ja/community/static/cncf-code-of-conduct.md @@ -1,32 +1,84 @@ + https://github.com/cncf/foundation/blob/main/code-of-conduct-languages/jp.md --> -CNCF コミュニティ行動規範 v1.0 +CNCF コミュニティ行動規範 v1.3 ------------------------------ -### コントリビューター行動規範 +## コミュニティの行動規範 -本プロジェクトのコントリビューターおよびメンテナーとして、オープンかつ快適なコミュニティを促進するために、私たちは、問題の報告、機能要求の投稿、ドキュメントの更新、プル要求またはパッチの送信、および他の活動を通して貢献するすべての人々を尊重することを誓います。 +CNCFコミュニティのコントリビューター、メンテナ、および参加者は、オープンかつ快適なコミュニティを促進するために、問題の報告、機能要求の投稿、ドキュメントの更新、プルリクエストまたはパッチの送信、カンファレンスやイベントへの参加、または他のコミュニティ、プロジェクト活動を通して参加または貢献するすべての人々を尊重することを誓います。 -私たちは、経験レベル、性別、性の自認および表明、性的嗜好、障がい、個人的な外見、身体の大きさ、人種、民族、年齢、宗教、または国籍に関係なく、このプロジェクトへの参加を、全員にとってハラスメントがない経験にすることを約束します。 +私たちは、年齢、身体の大きさ、カースト、障害、民族性、経験レベル、家族構成、性別、性自認と性表現、配偶者の有無、軍人または退役軍人の地位、国籍、容姿、人種、宗教、性的指向、社会経済的地位、部族、またはその他あらゆる多様性の側面に関係なく、CNCFコミュニティへの参加を、全員にとってハラスメントがない経験にすることを約束します。 -認められない参加者の行動の例: +## 適用範囲 -- 性的な言語またはイメージの使用 -- 個人的な攻撃 -- 煽りや侮辱/軽蔑的なコメント -- 公開または非公開のハラスメント -- 明示的な許可なく、物理的な住所や電子アドレスなど、他者の個人情報を公開すること -- 他の倫理または職業倫理に反する行為。 +本行動規範の適用範囲: -プロジェクト メンテナーは、本行動規範に準拠していないコメント、コミット、コード、Wiki 編集、問題、他のコントリビューションを削除、編集、または却下する権利および責任を有しています。プロジェクト メンテナーは、本行動規範を採用することで、公正かつ一貫した方法で、これらの原則を本プロジェクトの管理におけるすべての要素に適用することに注力します。本行動規範を遵守または施行しないプロジェクト メンテナーは、永久的にプロジェクト チームから抹消される可能性があります。 -個人がプロジェクトまたはコミュニティを代表するときには、本行動規範は、プロジェクト スペースおよび公共のスペースの両方に適用されます。 -Kubernetesで虐待的、嫌がらせ、または許されない行動があった場合には、から[Kubernetes Code of Conduct Committee](https://git.k8s.io/community/committee-code-of-conduct)(行動規範委員会)にご連絡ください。その他のプロジェクトにつきましては、CNCFプロジェクト管理者または仲介者にご連絡ください。 +* プロジェクトやコミュニティのスペース内 +* CNCFコミュニティ参加者の言葉や行動が、CNCFプロジェクト、CNCFコミュニティ、または他のCNCFコミュニティ参加者に向けられる、またはそれらに関連する場合の他のスペース内 -本行動規範は、コントリビューターの合意 (https://contributor-covenant.org) バージョン 1.2.0 https://contributor-covenant.org/version/1/2/0/ から適応されています。 +## CNCFイベント -### CNCF イベント行動規範 +Linux Foundationのプロフェッショナルなイベントスタッフによって制作されるCNCFイベントに関しては、イベントページにあるLinux Foundationの[イベント行動規範](https://events.linuxfoundation.org/code-of-conduct/)に準拠します。これは、CNCF行動規範と併用されることを目的としています。 -CNCF イベントは、イベント ページにある Linux Foundation 行動規範 に準拠します。これは、前述のポリシーに対応し、インシデントへの対応に関する詳細を含めることを目的としています。 +## 規範 + +CNCFコミュニティはオープンであり、包括的であり、敬意をもって接されます。コミュニティのすべてのメンバーは、自分自身のアイデンティティが尊重される権利を持っています。 + +良い環境を構築するための参加者の行動の例は以下のようなものが含まれますが、これらに限定されるものではありません。 + + + +* 他人への共感と思いやりを表す +* 異なる意見、視点、経験を尊重する +* 建設的なフィードバックを心がけ、それを快く受け入れる +* ミスに対して責任感を持ち、その影響を受けた人々に謝罪し、その経験から学ぶこと +* 個人だけではなく、コミュニティ全体として何が最善策かを重視する +* 快適で包括的な言葉の使用 + +一方で、以下のような行動は受け入れられませんが、これらに限定されるものではありません。 + + + +* 性的な言語や描写の使用 +* 煽りや侮辱的、軽蔑的なコメント、および個人または政治的な攻撃 +* あらゆる形態の公開または非公開のハラスメント +* 明示的な許可なしに他人の個人情報(住所やメールアドレス)を公開すること +* 暴力、脅迫、またはこれらの行為を助長する行為 +* ストーカー行為やその人の意思に反した追跡行為をすること +* 望ましくない身体的な接触 +* 歓迎されない性的または恋愛的な注目や誘い +* その他、プロフェッショナルな場において不適切とみなされうる行為 + +また、次のような行動も禁止されています。 + + + +* 行動規範の調査に関連して故意に誤った情報や誤解を招く情報を提供する、あるいは調査を故意に妨害する。 +* インシデントを報告したり、証人としてインシデントに関する情報を提供したりした人へ対する報復行為。 + +プロジェクトのメンテナは、この行動規範に準拠していないコメント、コミット、コード、Wikiの編集、問題、他のコントリビューションを削除、編集、または却下する権利および責任を持っています。プロジェクトのメンテナは、本行動規範を採用することで、公正かつ一貫した方法で、これらの原則をCNCFプロジェクトの管理におけるすべての要素に適用することに注力します。本行動規範を遵守または施行しないプロジェクトのメンテナは、一時的あるいは永久的にプロジェクトのチームから抹消される可能性があります。 + +## 報告 + +Kubernetesコミュニティにて問題が発生した場合には、[conduct@kubernetes.io](mailto:conduct@kubernetes.io)から[Kubernetes Code of Conduct Committee](https://git.k8s.io/community/committee-code-of-conduct)(行動規範委員会)までご連絡ください。通常3営業日以内に返信致します。 + +その他のプロジェクトや複数のプロジェクトに影響を与えるインシデントにつきましては、[CNCFの行動規範委員会](https://www.cncf.io/conduct/committee/)(email: [conduct@cncf.io](mailto:conduct@cncf.io))までご連絡ください。あるいは、[CNCFの行動規範委員会](https://www.cncf.io/conduct/committee/)の個別のメンバーに報告することもできます。報告の手順や匿名での報告方法など、より詳細な情報は、[インシデント解決手順](https://github.com/cncf/foundation/blob/main/code-of-conduct/coc-incident-resolution-procedures.md)をご覧ください。通常3営業日以内に返信致します。 + +Linux Foundationが制作するCNCFイベントでのインシデントについては、[eventconduct@cncf.io](mailto:eventconduct@cncf.io)にご連絡ください。 + +## 施行 + +報告されたインシデントのレビューと調査の後、管轄するCoCの対応チームは、この行動規範と関連するドキュメントに基づいて、適切な行動を決定します。 + +プロジェクトリーダーシップが取り扱う行動規範のインシデント、CNCF行動規範委員会が取り扱うインシデント、およびLinux Foundation(そのイベントチームを含む)が取り扱うインシデントに関する情報には、私たちの[管轄ポリシー](https://github.com/cncf/foundation/blob/main/code-of-conduct/coc-committee-jurisdiction-policy.md)を参照してください。 + +## 改正 + +CNCFの憲章と一貫して、この行動規範に対する実質的な変更は、Technical Oversight Committeeの承認が必要です。 + +## 謝辞 + +本行動規範は、コントリビューター行動規範([http://contributor-covenant.org](http://contributor-covenant.org/))に基づいています。バージョン 2.0はこちらから参照可能です。[http://contributor-covenant.org/version/2/0/code_of_conduct/](http://contributor-covenant.org/version/2/0/code_of_conduct/) diff --git a/content/ja/docs/concepts/_index.md b/content/ja/docs/concepts/_index.md index 8075e3eb34e90..0e6e5af67ad47 100644 --- a/content/ja/docs/concepts/_index.md +++ b/content/ja/docs/concepts/_index.md @@ -15,7 +15,7 @@ weight: 40 ## 概要 -Kubernetesを機能させるには、*Kubernetes API オブジェクト* を使用して、実行したいアプリケーションやその他のワークロード、使用するコンテナイメージ、レプリカ(複製)の数、どんなネットワークやディスクリソースを利用可能にするかなど、クラスターの *desired state* (望ましい状態)を記述します。desired state (望ましい状態)をセットするには、Kubernetes APIを使用してオブジェクトを作成します。通常はコマンドラインインターフェイス `kubectl` を用いてKubernetes APIを操作しますが、Kubernetes APIを直接使用してクラスターと対話し、desired state (望ましい状態)を設定、または変更することもできます。 +Kubernetesを機能させるには、*Kubernetes API オブジェクト* を使用して、実行したいアプリケーションやその他のワークロード、使用するコンテナイメージ、レプリカ(複製)の数、どんなネットワークやディスクリソースを利用可能にするかなど、クラスターの *desired state* (望ましい状態)を記述します。desired state (望ましい状態)をセットするには、Kubernetes APIを使用してオブジェクトを作成します。通常はコマンドラインインターフェース `kubectl` を用いてKubernetes APIを操作しますが、Kubernetes APIを直接使用してクラスターと対話し、desired state (望ましい状態)を設定、または変更することもできます。 一旦desired state (望ましい状態)を設定すると、Pod Lifecycle Event Generator([PLEG](https://github.com/kubernetes/design-proposals-archive/blob/main/node/pod-lifecycle-event-generator.md))を使用した*Kubernetes コントロールプレーン*が機能し、クラスターの現在の状態をdesired state (望ましい状態)に一致させます。そのためにKubernetesはさまざまなタスク(たとえば、コンテナの起動または再起動、特定アプリケーションのレプリカ数のスケーリング等)を自動的に実行します。Kubernetesコントロールプレーンは、クラスターで実行されている以下のプロセスで構成されています。 @@ -51,7 +51,7 @@ Kubernetesマスターや kubeletプロセスといったKubernetesコントロ ### Kubernetesマスター -Kubernetesのマスターは、クラスターの望ましい状態を維持する責務を持ちます。`kubectl` コマンドラインインターフェイスを使用するなどしてKubernetesとやり取りするとき、ユーザーは実際にはクラスターにあるKubernetesのマスターと通信しています。 +Kubernetesのマスターは、クラスターの望ましい状態を維持する責務を持ちます。`kubectl` コマンドラインインターフェースを使用するなどしてKubernetesとやり取りするとき、ユーザーは実際にはクラスターにあるKubernetesのマスターと通信しています。 「マスター」とは、クラスター状態を管理するプロセスの集合を指します。通常これらのプロセスは、すべてクラスター内の単一ノードで実行されます。このノードはマスターとも呼ばれます。マスターは、可用性と冗長性のために複製することもできます。 diff --git a/content/ja/docs/concepts/architecture/_index.md b/content/ja/docs/concepts/architecture/_index.md index b8906ee100d9d..25a5698ebab61 100644 --- a/content/ja/docs/concepts/architecture/_index.md +++ b/content/ja/docs/concepts/architecture/_index.md @@ -1,4 +1,8 @@ --- title: "クラスターのアーキテクチャ" weight: 30 +description: > + Kubernetesの背後にあるアーキテクチャのコンセプト。 --- + +{{< figure src="/images/docs/kubernetes-cluster-architecture.svg" alt="Components of Kubernetes" caption="Kubernetesクラスターのアーキテクチャ" class="diagram-large" >}} diff --git a/content/ja/docs/concepts/architecture/control-plane-node-communication.md b/content/ja/docs/concepts/architecture/control-plane-node-communication.md index 674dee02ed487..c836b5bf34c82 100644 --- a/content/ja/docs/concepts/architecture/control-plane-node-communication.md +++ b/content/ja/docs/concepts/architecture/control-plane-node-communication.md @@ -31,7 +31,7 @@ APIサーバーに接続したい{{< glossary_tooltip text="Pod" term_id="pod" > コントロールプレーン(APIサーバー)からノードへの主要な通信経路は2つあります。 1つ目は、APIサーバーからクラスター内の各ノードで実行される{{< glossary_tooltip text="kubelet" term_id="kubelet" >}}プロセスへの通信経路です。 -2つ目は、APIサーバーの _プロキシー_ 機能を介した、APIサーバーから任意のノード、Pod、またはサービスへの通信経路です。 +2つ目は、APIサーバーの _プロキシ_ 機能を介した、APIサーバーから任意のノード、Pod、またはサービスへの通信経路です。 ### APIサーバーからkubeletへの通信 {#api-server-to-kubelet} @@ -67,7 +67,7 @@ SSHトンネルは現在非推奨であるため、自分が何をしている {{< feature-state for_k8s_version="v1.18" state="beta" >}} -SSHトンネルの代替として、Konnectivityサービスは、コントロールプレーンからクラスターへの通信に、TCPレベルのプロキシーを提供します。Konnectivityサービスは、コントロールプレーンネットワークのKonnectivityサーバーと、ノードネットワークのKonnectivityエージェントの、2つの部分で構成されています。 +SSHトンネルの代替として、Konnectivityサービスは、コントロールプレーンからクラスターへの通信に、TCPレベルのプロキシを提供します。Konnectivityサービスは、コントロールプレーンネットワークのKonnectivityサーバーと、ノードネットワークのKonnectivityエージェントの、2つの部分で構成されています。 Konnectivityエージェントは、Konnectivityサーバーへの接続を開始し、ネットワーク接続を維持します。 Konnectivityサービスを有効にすると、コントロールプレーンからノードへのトラフィックは、すべてこの接続を経由するようになります。 diff --git a/content/ja/docs/concepts/architecture/cri.md b/content/ja/docs/concepts/architecture/cri.md index 57c1345777308..b220afeffb1d7 100644 --- a/content/ja/docs/concepts/architecture/cri.md +++ b/content/ja/docs/concepts/architecture/cri.md @@ -1,12 +1,12 @@ --- -title: コンテナランタイムインターフェイス(CRI) +title: コンテナランタイムインターフェース(CRI) content_type: concept weight: 60 --- -CRIは、クラスターコンポーネントを再コンパイルすることなく、kubeletがさまざまなコンテナランタイムを使用できるようにするプラグインインターフェイスです。 +CRIは、クラスターコンポーネントを再コンパイルすることなく、kubeletがさまざまなコンテナランタイムを使用できるようにするプラグインインターフェースです。 {{< glossary_tooltip text="kubelet" term_id="kubelet" >}}が{{< glossary_tooltip text="Pod" term_id="pod" >}}とそのコンテナを起動できるように、クラスター内の各ノードで動作する{{}}が必要です。 diff --git a/content/ja/docs/concepts/cluster-administration/addons.md b/content/ja/docs/concepts/cluster-administration/addons.md index e22ca75da5a51..a2b0c95f37578 100644 --- a/content/ja/docs/concepts/cluster-administration/addons.md +++ b/content/ja/docs/concepts/cluster-administration/addons.md @@ -25,14 +25,14 @@ weight: 120 * [Contiv](https://contivpp.io/)は、さまざまなユースケースと豊富なポリシーフレームワーク向けに設定可能なネットワーク(BGPを使用したネイティブのL3、vxlanを使用したオーバーレイ、古典的なL2、Cisco-SDN/ACI)を提供します。Contivプロジェクトは完全に[オープンソース](https://github.com/contiv)です。[インストーラー](https://github.com/contiv/install)はkubeadmとkubeadm以外の両方をベースとしたインストールオプションがあります。 * [Contrail](https://www.juniper.net/us/en/products-services/sdn/contrail/contrail-networking/)は、[Tungsten Fabric](https://tungsten.io)をベースにしている、オープンソースでマルチクラウドに対応したネットワーク仮想化およびポリシー管理プラットフォームです。ContrailおよびTungsten Fabricは、Kubernetes、OpenShift、OpenStack、Mesosなどのオーケストレーションシステムと統合されており、仮想マシン、コンテナ/Pod、ベアメタルのワークロードに隔離モードを提供します。 * [Flannel](https://github.com/flannel-io/flannel#deploying-flannel-manually)は、Kubernetesで使用できるオーバーレイネットワークプロバイダーです。 -* [Knitter](https://github.com/ZTE/Knitter/)は、1つのKubernetes Podで複数のネットワークインターフェイスをサポートするためのプラグインです。 +* [Knitter](https://github.com/ZTE/Knitter/)は、1つのKubernetes Podで複数のネットワークインターフェースをサポートするためのプラグインです。 * [Multus](https://github.com/k8snetworkplumbingwg/multus-cni)は、すべてのCNIプラグイン(たとえば、Calico、Cilium、Contiv、Flannel)に加えて、SRIOV、DPDK、OVS-DPDK、VPPをベースとするKubernetes上のワークロードをサポートする、複数のネットワークサポートのためのマルチプラグインです。 * [OVN-Kubernetes](https://github.com/ovn-org/ovn-kubernetes/)は、Open vSwitch(OVS)プロジェクトから生まれた仮想ネットワーク実装である[OVN(Open Virtual Network)](https://github.com/ovn-org/ovn/)をベースとする、Kubernetesのためのネットワークプロバイダーです。OVN-Kubernetesは、OVSベースのロードバランサーおよびネットワークポリシーの実装を含む、Kubernetes向けのオーバーレイベースのネットワーク実装を提供します。 * [Nodus](https://github.com/akraino-edge-stack/icn-nodus)は、OVNベースのCNIコントローラープラグインで、クラウドネイティブベースのService function chaining(SFC)を提供します。 * [NSX-T](https://docs.vmware.com/en/VMware-NSX-T-Data-Center/index.html) Container Plug-in(NCP)は、VMware NSX-TとKubernetesなどのコンテナオーケストレーター間のインテグレーションを提供します。また、NSX-Tと、Pivotal Container Service(PKS)とOpenShiftなどのコンテナベースのCaaS/PaaSプラットフォームとのインテグレーションも提供します。 * [Nuage](https://github.com/nuagenetworks/nuage-kubernetes/blob/v5.1.1-1/docs/kubernetes-1-installation.rst)は、Kubernetes Podと非Kubernetes環境間で可視化とセキュリティモニタリングを使用してポリシーベースのネットワークを提供するSDNプラットフォームです。 * [Romana](https://github.com/romana)は、[NetworkPolicy](/ja/docs/concepts/services-networking/network-policies/) APIもサポートするPodネットワーク向けのL3のネットワークソリューションです。 -* [Weave Net](https://www.weave.works/docs/net/latest/kubernetes/kube-addon/)は、ネットワークパーティションの両面で機能し、外部データベースを必要とせずに、ネットワークとネットワークポリシーを提供します。 +* [Weave Net](https://github.com/rajch/weave#using-weave-on-kubernetes)は、ネットワークパーティションの両面で機能し、外部データベースを必要とせずに、ネットワークとネットワークポリシーを提供します。 ## サービスディスカバリー {#service-discovery} @@ -40,7 +40,7 @@ weight: 120 ## 可視化と制御 {#visualization-amp-control} -* [Dashboard](https://github.com/kubernetes/dashboard#kubernetes-dashboard)はKubernetes向けのダッシュボードを提供するウェブインターフェイスです。 +* [Dashboard](https://github.com/kubernetes/dashboard#kubernetes-dashboard)はKubernetes向けのダッシュボードを提供するウェブインターフェースです。 * [Weave Scope](https://www.weave.works/documentation/scope-latest-installing/#k8s)は、コンテナ、Pod、Serviceなどをグラフィカルに可視化するツールです。[Weave Cloud account](https://cloud.weave.works/)と組み合わせて使うか、UIを自分でホストして使います。 ## インフラストラクチャ {#infrastructure} diff --git a/content/ja/docs/concepts/cluster-administration/proxies.md b/content/ja/docs/concepts/cluster-administration/proxies.md index 5f815ed401b88..2aa313128d57b 100644 --- a/content/ja/docs/concepts/cluster-administration/proxies.md +++ b/content/ja/docs/concepts/cluster-administration/proxies.md @@ -1,47 +1,47 @@ --- -title: Kubernetesのプロキシー +title: Kubernetesのプロキシ content_type: concept weight: 100 --- -このページではKubernetesと併用されるプロキシーについて説明します。 +このページではKubernetesと併用されるプロキシについて説明します。 -## プロキシー +## プロキシ -Kubernetesを使用する際に、いくつかのプロキシーを使用する場面があります。 +Kubernetesを使用する際に、いくつかのプロキシを使用する場面があります。 -1. [kubectlのプロキシー](/docs/tasks/access-application-cluster/access-cluster/#directly-accessing-the-rest-api): +1. [kubectlのプロキシ](/docs/tasks/access-application-cluster/access-cluster/#directly-accessing-the-rest-api): - ユーザーのデスクトップ上かPod内で稼働します - - ローカルホストのアドレスからKubernetes apiserverへのプロキシーを行います - - クライアントからプロキシー間ではHTTPを使用します - - プロキシーからapiserverへはHTTPSを使用します + - ローカルホストのアドレスからKubernetes apiserverへのプロキシを行います + - クライアントからプロキシ間ではHTTPを使用します + - プロキシからapiserverへはHTTPSを使用します - apiserverの場所を示します - 認証用のヘッダーを追加します -1. [apiserverのプロキシー](/docs/tasks/access-application-cluster/access-cluster/#discovering-builtin-services): +1. [apiserverのプロキシ](/docs/tasks/access-application-cluster/access-cluster/#discovering-builtin-services): - apiserver内で動作する踏み台となります - これがなければ到達不可能であるクラスターIPへ、クラスターの外部からのユーザーを接続します - apiserverのプロセス内で稼働します - - クライアントからプロキシー間ではHTTPSを使用します(apiserverの設定により、HTTPを使用します) - - プロキシーからターゲット間では利用可能な情報を使用して、プロキシーによって選択されたHTTPかHTTPSのいずれかを使用します + - クライアントからプロキシ間ではHTTPSを使用します(apiserverの設定により、HTTPを使用します) + - プロキシからターゲット間では利用可能な情報を使用して、プロキシによって選択されたHTTPかHTTPSのいずれかを使用します - Node、Pod、Serviceへ到達するのに使えます - Serviceへ到達するときは負荷分散を行います 1. [kube proxy](/ja/docs/concepts/services-networking/service/#ips-and-vips): - 各ノード上で稼働します - - UDP、TCP、SCTPをプロキシーします + - UDP、TCP、SCTPをプロキシします - HTTPを解釈しません - 負荷分散機能を提供します - Serviceへ到達させるためのみに使用されます -1. apiserverの前段にあるプロキシー/ロードバランサー: +1. apiserverの前段にあるプロキシ/ロードバランサー: - 実際に存在するかどうかと実装はクラスターごとに異なります(例: nginx) - 全てのクライアントと、1つ以上のapiserverの間に位置します @@ -59,7 +59,7 @@ Kubernetesユーザーのほとんどは、最初の2つのタイプ以外に心 ## リダイレクトの要求 -プロキシーはリダイレクトの機能を置き換えました。リダイレクトの使用は非推奨となります。 +プロキシはリダイレクトの機能を置き換えました。リダイレクトの使用は非推奨となります。 diff --git a/content/ja/docs/concepts/configuration/organize-cluster-access-kubeconfig.md b/content/ja/docs/concepts/configuration/organize-cluster-access-kubeconfig.md index a182120c541a5..ed059c886fbf7 100644 --- a/content/ja/docs/concepts/configuration/organize-cluster-access-kubeconfig.md +++ b/content/ja/docs/concepts/configuration/organize-cluster-access-kubeconfig.md @@ -108,9 +108,9 @@ kubectl config view kubeconfigファイル内のファイルとパスのリファレンスは、kubeconfigファイルの位置からの相対パスで指定します。コマンドライン上のファイルのリファレンスは、現在のワーキングディレクトリからの相対パスです。`$HOME/.kube/config`内では、相対パスは相対のまま、絶対パスは絶対のまま保存されます。 -## プロキシー +## プロキシ -kubeconfigファイルで`proxy-url`を使用すると、以下のようにクラスターごとにプロキシーを使用するように`kubectl`を設定することができます。 +kubeconfigファイルで`proxy-url`を使用すると、以下のようにクラスターごとにプロキシを使用するように`kubectl`を設定することができます。 ```yaml apiVersion: v1 diff --git a/content/ja/docs/concepts/extend-kubernetes/api-extension/apiserver-aggregation.md b/content/ja/docs/concepts/extend-kubernetes/api-extension/apiserver-aggregation.md index d107478cca974..4d9501af0dee0 100644 --- a/content/ja/docs/concepts/extend-kubernetes/api-extension/apiserver-aggregation.md +++ b/content/ja/docs/concepts/extend-kubernetes/api-extension/apiserver-aggregation.md @@ -16,7 +16,7 @@ weight: 20 ## アグリゲーションレイヤー -アグリゲーションレイヤーは、kube-apiserverのプロセス内で動きます。拡張リソースが登録されるまでは、アグリゲーションレイヤーは何もしません。APIを登録するには、ユーザーはKubernetes APIで使われるURLのパスを"要求"した、_APIService_ オブジェクトを追加します。それを追加すると、アグリゲーションレイヤーはAPIパス(例、`/apis/myextension.mycompany.io/v1/…`)への全てのアクセスを、登録されたAPIServiceにプロキシーします。 +アグリゲーションレイヤーは、kube-apiserverのプロセス内で動きます。拡張リソースが登録されるまでは、アグリゲーションレイヤーは何もしません。APIを登録するには、ユーザーはKubernetes APIで使われるURLのパスを"要求"した、_APIService_ オブジェクトを追加します。それを追加すると、アグリゲーションレイヤーはAPIパス(例、`/apis/myextension.mycompany.io/v1/…`)への全てのアクセスを、登録されたAPIServiceにプロキシします。 APIServiceを実装する最も一般的な方法は、クラスター内で実行されるPodで*拡張APIサーバー* を実行することです。クラスター内のリソース管理に拡張APIサーバーを使用している場合、拡張APIサーバー("extension-apiserver"とも呼ばれます)は通常、1つ以上の{{< glossary_tooltip text="コントローラー" term_id="controller" >}}とペアになっています。apiserver-builderライブラリは、拡張APIサーバーと関連するコントローラーの両方にスケルトンを提供します。 diff --git a/content/ja/docs/concepts/extend-kubernetes/api-extension/custom-resources.md b/content/ja/docs/concepts/extend-kubernetes/api-extension/custom-resources.md index 1679d2929f0d0..1905ef1af1a27 100644 --- a/content/ja/docs/concepts/extend-kubernetes/api-extension/custom-resources.md +++ b/content/ja/docs/concepts/extend-kubernetes/api-extension/custom-resources.md @@ -99,7 +99,7 @@ Kubernetesは、クラスターへカスタムリソースを追加する2つの Kubernetesは、さまざまなユーザーのニーズを満たすためにこれら2つのオプションを提供しており、使いやすさや柔軟性が損なわれることはありません。 -アグリゲートAPIは、プロキシーとして機能するプライマリAPIサーバーの背後にある、下位のAPIServerです。このような配置は[APIアグリゲーション](/ja/docs/concepts/extend-kubernetes/api-extension/apiserver-aggregation/)(AA)と呼ばれています。ユーザーにとっては、単にAPIサーバーが拡張されているように見えます。 +アグリゲートAPIは、プロキシとして機能するプライマリAPIサーバーの背後にある、下位のAPIServerです。このような配置は[APIアグリゲーション](/ja/docs/concepts/extend-kubernetes/api-extension/apiserver-aggregation/)(AA)と呼ばれています。ユーザーにとっては、単にAPIサーバーが拡張されているように見えます。 CRDでは、APIサーバーの追加なしに、ユーザーが新しい種類のリソースを作成できます。CRDを使うには、APIアグリゲーションを理解する必要はありません。 diff --git a/content/ja/docs/concepts/extend-kubernetes/compute-storage-net/_index.md b/content/ja/docs/concepts/extend-kubernetes/compute-storage-net/_index.md new file mode 100644 index 0000000000000..68a9112b0a317 --- /dev/null +++ b/content/ja/docs/concepts/extend-kubernetes/compute-storage-net/_index.md @@ -0,0 +1,32 @@ +--- +title: コンピュート、ストレージ、ネットワーキングの拡張機能 +weight: 30 +no_list: true +--- + +このセクションでは、Kubernetes自体の一部としては提供されていない、クラスターへの拡張について説明します。 +これらの拡張を使用して、クラスター内のノードを強化したり、Pod同士をつなぐネットワークファブリックを提供したりすることができます。 + +* [CSI](/ja/docs/concepts/storage/volumes/#csi)および[FlexVolume](/ja/docs/concepts/storage/volumes/#flexvolume)ストレージプラグイン + + {{< glossary_tooltip text="Container Storage Interface" term_id="csi" >}} (CSI)プラグインは、新しい種類のボリュームをサポートするためのKubernetesの拡張方法を提供します。 + これらのボリュームは、永続性のある外部ストレージにバックアップすることができます。また、一時的なストレージを提供することも、ファイルシステムのパラダイムを使用して、情報への読み取り専用のインターフェースを提供することもできます。 + + Kubernetesには、Kubernetes v1.23から非推奨とされている(CSIに置き換えられる)[FlexVolume](/ja/docs/concepts/storage/volumes/#flexvolume)プラグインへのサポートも含まれています。 + + FlexVolumeプラグインは、Kubernetesがネイティブにサポートしていないボリュームタイプをマウントすることをユーザーに可能にします。 + FlexVolumeストレージに依存するPodを実行すると、kubeletはバイナリプラグインを呼び出してボリュームをマウントします。 + アーカイブされた[FlexVolume](https://git.k8s.io/design-proposals-archive/storage/flexvolume-deployment.md)デザインの提案には、このアプローチの詳細が記載されています。 + + [Kubernetes Volume Plugin FAQ for Storage Vendors](https://github.com/kubernetes/community/blob/master/sig-storage/volume-plugin-faq.md#kubernetes-volume-plugin-faq-for-storage-vendors)には、ストレージプラグインに関する一般的な情報が含まれています。 + +* [デバイスプラグイン](/docs/concepts/extend-kubernetes/compute-storage-net/device-plugins/) + + デバイスプラグインは、ノードが(`cpu`や`memory`などの組み込みノードリソースに加えて)新しいNode設備を発見し、これらのカスタムなノードローカル設備を要求するPodに提供することを可能にします。 + +* [ネットワークプラグイン](/docs/concepts/extend-kubernetes/compute-storage-net/network-plugins/) + + ネットワークプラグインにより、Kubernetesはさまざまなネットワーキングのトポロジーや技術を扱うことができます。 + 動作するPodネットワークを持ち、Kubernetesネットワークモデルの他の側面をサポートするためには、Kubernetesクラスターに _ネットワークプラグイン_ が必要です。 + + Kubernetes {{< skew currentVersion >}}は、{{< glossary_tooltip text="CNI" term_id="cni" >}}ネットワークプラグインと互換性があります。 diff --git a/content/ja/docs/concepts/overview/components.md b/content/ja/docs/concepts/overview/components.md index 784c84dd5b590..e4dbd89f1ff56 100644 --- a/content/ja/docs/concepts/overview/components.md +++ b/content/ja/docs/concepts/overview/components.md @@ -106,7 +106,7 @@ Kubernetesによって開始されたコンテナは、DNS検索にこのDNSサ ### クラスターレベルのロギング -[クラスターレベルのロギング](/ja/docs/concepts/cluster-administration/logging/)メカニズムは、コンテナのログを、検索/参照インターフェイスを備えた中央ログストアに保存します。 +[クラスターレベルのロギング](/ja/docs/concepts/cluster-administration/logging/)メカニズムは、コンテナのログを、検索/参照インターフェースを備えた中央ログストアに保存します。 ## {{% heading "whatsnext" %}} diff --git a/content/ja/docs/concepts/scheduling-eviction/_index.md b/content/ja/docs/concepts/scheduling-eviction/_index.md index b937c7e5e737d..9caad173f4e29 100644 --- a/content/ja/docs/concepts/scheduling-eviction/_index.md +++ b/content/ja/docs/concepts/scheduling-eviction/_index.md @@ -1,8 +1,33 @@ --- -title: "スケジューリングと退避" +title: "スケジューリング、プリエンプションと退避" weight: 95 description: > - Kubernetesにおいてスケジューリングとは、稼働させたいPodをNodeにマッチさせ、kubeletが実行できるようにすることを指します。 - 退避とは、リソース不足のNodeで1つ以上のPodを積極的に停止させるプロセスです。 + Kubernetesにおいてスケジューリングとは、稼働させたいPodをノードにマッチさせ、kubeletが実行できるようにすることを指します。 + プリエンプションは、優先度の低いPodを終了させて、より優先度の高いPodがノード上でスケジュールできるようにするプロセスです。 + 退避(eviction)とは、リソース不足のノードで1つ以上のPodを積極的に終了させるプロセスです。 +no_list: true --- +Kubernetesにおいてスケジューリングとは、稼働させたい{{}}を{{}}にマッチさせ、{{}}が実行できるようにすることを指します。 +プリエンプションは、{{}}の低いPodを終了させて、より優先度の高いPodがノード上でスケジュールできるようにするプロセスです。 +退避とは、リソース不足のノードで1つ以上のPodを積極的に終了させるプロセスです。 + +## スケジューリング + +* [Kubernetesのスケジューラー](/ja/docs/concepts/scheduling-eviction/kube-scheduler/) +* [Node上へのPodのスケジューリング](/ja/docs/concepts/scheduling-eviction/assign-pod-node/) +* [Podのオーバーヘッド](/ja/docs/concepts/scheduling-eviction/pod-overhead/) +* [Pod Topology Spread Constraints](/docs/concepts/scheduling-eviction/topology-spread-constraints/) +* [Taints and Tolerations](/docs/concepts/scheduling-eviction/taint-and-toleration/) +* [スケジューリングフレームワーク](/ja/docs/concepts/scheduling-eviction/scheduling-framework) +* [Dynamic Resource Allocation](/docs/concepts/scheduling-eviction/dynamic-resource-allocation) +* [スケジューラーのパフォーマンスチューニング](/ja/docs/concepts/scheduling-eviction/scheduler-perf-tuning/) +* [拡張リソースのリソースビンパッキング](/ja/docs/concepts/scheduling-eviction/resource-bin-packing/) +* [Pod Scheduling Readiness](/docs/concepts/scheduling-eviction/pod-scheduling-readiness/) +* [Descheduler](https://github.com/kubernetes-sigs/descheduler#descheduler-for-kubernetes) + +## Pod Disruption + +* [Podの優先度とプリエンプション](/ja/docs/concepts/scheduling-eviction/pod-priority-preemption/) +* [Node-pressure Eviction](/docs/concepts/scheduling-eviction/node-pressure-eviction/) +* [APIを起点とした退避](/ja/docs/concepts/scheduling-eviction/api-eviction/) diff --git a/content/ja/docs/concepts/services-networking/connect-applications-service.md b/content/ja/docs/concepts/services-networking/connect-applications-service.md index a6980f9e92361..90979a25685c8 100644 --- a/content/ja/docs/concepts/services-networking/connect-applications-service.md +++ b/content/ja/docs/concepts/services-networking/connect-applications-service.md @@ -60,7 +60,7 @@ kubectl get pods -l run=my-nginx -o yaml | grep podIP コンテナはノードでポート80を使用**していない**ことに注意してください。 また、Podにトラフィックをルーティングする特別なNATルールもありません。 つまり、同じcontainerPortを使用して同じノードで複数のnginx Podを実行し、IPを使用してクラスター内の他のPodやノードからそれらにアクセスできます。 -Dockerと同様に、ポートは引き続きホストノードのインターフェイスに公開できますが、ネットワークモデルにより、この必要性は根本的に減少します。 +Dockerと同様に、ポートは引き続きホストノードのインターフェースに公開できますが、ネットワークモデルにより、この必要性は根本的に減少します。 興味があれば、これを[どのように達成するか](/ja/docs/concepts/cluster-administration/networking/#how-to-achieve-this)について詳しく読むことができます。 @@ -138,7 +138,7 @@ my-nginx 10.244.2.5:80,10.244.3.4:80 1m クラスター内の任意のノードから、`:`でnginx Serviceにcurl接続できるようになりました。 Service IPは完全に仮想的なもので、ホスト側のネットワークには接続できないことに注意してください。 -この仕組みに興味がある場合は、[サービスプロキシー](/ja/docs/concepts/services-networking/service/#virtual-ips-and-service-proxies)の詳細をお読みください。 +この仕組みに興味がある場合は、[サービスプロキシ](/ja/docs/concepts/services-networking/service/#virtual-ips-and-service-proxies)の詳細をお読みください。 ## Serviceにアクセスする diff --git a/content/ja/docs/concepts/services-networking/dual-stack.md b/content/ja/docs/concepts/services-networking/dual-stack.md index cf6a48b7be5d3..c2bcdae0a74d4 100644 --- a/content/ja/docs/concepts/services-networking/dual-stack.md +++ b/content/ja/docs/concepts/services-networking/dual-stack.md @@ -24,14 +24,14 @@ KubernetesクラスターでIPv4/IPv6デュアルスタックを有効にする * デュアルスタックのPodネットワーク(PodごとにIPv4とIPv6のアドレスが1つずつ割り当てられます) * IPv4およびIPv6が有効化されたService(各Serviceは1つのアドレスファミリーでなければなりません) - * IPv4およびIPv6インターフェイスを経由したPodのクラスター外向きの(たとえば、インターネットへの)ルーティング + * IPv4およびIPv6インターフェースを経由したPodのクラスター外向きの(たとえば、インターネットへの)ルーティング ## 前提条件 IPv4/IPv6デュアルスタックのKubernetesクラスターを利用するには、以下の前提条件を満たす必要があります。 * Kubernetesのバージョンが1.16以降である - * プロバイダーがデュアルスタックのネットワークをサポートしている(クラウドプロバイダーなどが、ルーティング可能なIPv4/IPv6ネットワークインターフェイスが搭載されたKubernetesを提供可能である) + * プロバイダーがデュアルスタックのネットワークをサポートしている(クラウドプロバイダーなどが、ルーティング可能なIPv4/IPv6ネットワークインターフェースが搭載されたKubernetesを提供可能である) * ネットワークプラグインがデュアルスタックに対応している(KubenetやCalicoなど) ## IPv4/IPv6デュアルスタックを有効にする diff --git a/content/ja/docs/concepts/services-networking/ingress-controllers.md b/content/ja/docs/concepts/services-networking/ingress-controllers.md index c041d6eca9d7e..70728c15ac3ab 100644 --- a/content/ja/docs/concepts/services-networking/ingress-controllers.md +++ b/content/ja/docs/concepts/services-networking/ingress-controllers.md @@ -40,14 +40,14 @@ Ingressリソースが動作するためには、クラスターでIngressコン * [Istio Ingress](https://istio.io/latest/docs/tasks/traffic-management/ingress/kubernetes-ingress/)は、[Istio](https://istio.io/)ベースのIngressコントローラーです。 * [Kong Ingress Controller for Kubernetes](https://github.com/Kong/kubernetes-ingress-controller#readme)は、[Kong Gateway](https://konghq.com/kong/)向けのIngressコントローラーです。 * [Kusk Gateway](https://kusk.kubeshop.io/)は[Envoy](https://www.envoyproxy.io)をベースにしたOpenAPIドリブンのIngressコントローラーです。 -* [NGINX Ingress Controller for Kubernetes](https://www.nginx.com/products/nginx-ingress-controller/)は、[NGINX](https://www.nginx.com/resources/glossary/nginx/)ウェブサーバーで(プロキシーとして)動作します。 +* [NGINX Ingress Controller for Kubernetes](https://www.nginx.com/products/nginx-ingress-controller/)は、[NGINX](https://www.nginx.com/resources/glossary/nginx/)ウェブサーバーで(プロキシとして)動作します。 * [ngrok Kubernetes Ingress Controller](https://github.com/ngrok/kubernetes-ingress-controller)は、[ngrok platform](https://ngrok.com)を使用するK8sサービスに安全な公開アクセスを追加するためのオープンソースコントローラーです。 * [OCI Native Ingress Controller](https://github.com/oracle/oci-native-ingress-controller#readme)は、Oracle Cloud Infrastructure用のIngressコントローラーであり、[OCI Load Balancer](https://docs.oracle.com/ja-jp/iaas/Content/Balance/home.htm)を管理することができます。 * [Pomerium Ingress Controller](https://www.pomerium.com/docs/k8s/ingress.html)は[Pomerium](https://pomerium.com/)ベースのものであり、コンテキストを考慮したアクセスポリシーを提供します。 -* [Skipper](https://opensource.zalando.com/skipper/kubernetes/ingress-controller/)は、カスタムプロキシーを構築するためのライブラリーとして設計された、Kubernetes Ingressなどのユースケースを含む、サービス構成用のHTTPルーターとリバースプロキシーです。 +* [Skipper](https://opensource.zalando.com/skipper/kubernetes/ingress-controller/)は、カスタムプロキシを構築するためのライブラリーとして設計された、Kubernetes Ingressなどのユースケースを含む、サービス構成用のHTTPルーターとリバースプロキシです。 * [Traefik Kubernetes Ingress provider](https://doc.traefik.io/traefik/providers/kubernetes-ingress/)は、[Traefik](https://traefik.io/traefik/) proxy向けのIngressコントローラーです。 * [Tyk Operator](https://github.com/TykTechnologies/tyk-operator)はAPI管理機能をIngressに持たせるためにCustom ResourcesでAPIを拡張します。Tyk OperatorはOpen Source Tyk GatewayとTyk Cloudコントロールプレーンで動作します。 -* [Voyager](https://appscode.com/products/voyager)は、[HAProxy](https://www.haproxy.org/#desc)向けのIngressコントローラーです。 +* [Voyager](https://voyagermesh.com)は、[HAProxy](https://www.haproxy.org/#desc)向けのIngressコントローラーです。 * [Wallarm Ingress Controller](https://www.wallarm.com/solutions/waf-for-kubernetes)はWAAP(WAF)やAPIセキュリティ機能を提供するIngressコントローラーです。 ## 複数のIngressコントローラーの使用 {#using-multiple-ingress-controllers} diff --git a/content/ja/docs/concepts/services-networking/ingress.md b/content/ja/docs/concepts/services-networking/ingress.md index 0912bbbb5b0e7..e237742df1193 100644 --- a/content/ja/docs/concepts/services-networking/ingress.md +++ b/content/ja/docs/concepts/services-networking/ingress.md @@ -53,7 +53,7 @@ Ingressリソースの最小構成の例は以下のとおりです。 Ingressには`apiVersion`、`kind`、`metadata`や`spec`フィールドが必要です。Ingressオブジェクトの名前は、有効な[DNSサブドメイン名](/ja/docs/concepts/overview/working-with-objects/names#dns-subdomain-names)である必要があります。設定ファイルに関する一般的な情報は、[アプリケーションのデプロイ](/ja/docs/tasks/run-application/run-stateless-application-deployment/)、[コンテナの設定](/ja/docs/tasks/configure-pod-container/configure-pod-configmap/)、[リソースの管理](/ja/docs/concepts/cluster-administration/manage-deployment/)を参照してください。Ingressでは、Ingressコントローラーに依存しているいくつかのオプションの設定をするためにアノテーションを一般的に使用します。例としては、[rewrite-targetアノテーション](https://github.com/kubernetes/ingress-nginx/blob/main/docs/examples/rewrite/README.md)などがあります。[Ingressコントローラー](/ja/docs/concepts/services-networking/ingress-controllers)の種類が異なれば、サポートするアノテーションも異なります。サポートされているアノテーションについて学ぶためには、使用するIngressコントローラーのドキュメントを確認してください。 -Ingress [Spec](https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status)は、ロードバランサーやプロキシーサーバーを設定するために必要な全ての情報を持っています。最も重要なものとして、外部からくる全てのリクエストに対して一致したルールのリストを含みます。IngressリソースはHTTP(S)トラフィックに対してのルールのみサポートしています。 +Ingress [Spec](https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status)は、ロードバランサーやプロキシサーバーを設定するために必要な全ての情報を持っています。最も重要なものとして、外部からくる全てのリクエストに対して一致したルールのリストを含みます。IngressリソースはHTTP(S)トラフィックに対してのルールのみサポートしています。 `ingressClassName`が省略された場合、[デフォルトのIngressClass](#default-ingress-class)を定義する必要があります。 diff --git a/content/ja/docs/concepts/services-networking/service.md b/content/ja/docs/concepts/services-networking/service.md index f0959da26e172..6be79f4e3b4d0 100644 --- a/content/ja/docs/concepts/services-networking/service.md +++ b/content/ja/docs/concepts/services-networking/service.md @@ -70,7 +70,7 @@ spec: この定義では、"my-service"という名前のついた新しいServiceオブジェクトを作成します。これは`app=Myapp`ラベルのついた各Pod上でTCPの9376番ポートをターゲットとします。 -Kubernetesは、このServiceに対してIPアドレス("clusterIP"とも呼ばれます)を割り当てます。これはServiceのプロキシーによって使用されます(下記の[仮想IPとServiceプロキシー](#virtual-ips-and-service-proxies)を参照ください)。 +Kubernetesは、このServiceに対してIPアドレス("clusterIP"とも呼ばれます)を割り当てます。これはServiceのプロキシによって使用されます(下記の[仮想IPとServiceプロキシ](#virtual-ips-and-service-proxies)を参照ください)。 Serviceセレクターのコントローラーはセレクターに一致するPodを継続的にスキャンし、“my-service”という名前のEndpointsオブジェクトに対して変更をPOSTします。 @@ -151,35 +151,35 @@ ExternalName Serviceはセレクターの代わりにDNS名を使用する特殊 `AppProtocol`フィールドによってServiceの各ポートに対して特定のアプリケーションプロトコルを指定することができます。 この値は、対応するEndpointsオブジェクトとEndpointSliceオブジェクトに反映されます。 -## 仮想IPとサービスプロキシー {#virtual-ips-and-service-proxies} +## 仮想IPとサービスプロキシ {#virtual-ips-and-service-proxies} Kubernetesクラスターの各Nodeは`kube-proxy`を稼働させています。`kube-proxy`は[`ExternalName`](#externalname)タイプ以外の`Service`用に仮想IPを実装する責務があります。 ### なぜ、DNSラウンドロビンを使わないのでしょうか。 -ここで湧き上がる質問として、なぜKubernetesは内部のトラフィックをバックエンドへ転送するためにプロキシーに頼るのでしょうか。 +ここで湧き上がる質問として、なぜKubernetesは内部のトラフィックをバックエンドへ転送するためにプロキシに頼るのでしょうか。 他のアプローチはどうなのでしょうか。例えば、複数のAバリュー(もしくはIPv6用にAAAAバリューなど)をもつDNSレコードを設定し、ラウンドロビン方式で名前を解決することは可能でしょうか。 -Serviceにおいてプロキシーを使う理由はいくつかあります。 +Serviceにおいてプロキシを使う理由はいくつかあります。 * DNSの実装がレコードのTTLをうまく扱わず、期限が切れた後も名前解決の結果をキャッシュするという長い歴史がある。 * いくつかのアプリケーションではDNSルックアップを1度だけ行い、その結果を無期限にキャッシュする。 * アプリケーションとライブラリーが適切なDNS名の再解決を行ったとしても、DNSレコード上の0もしくは低い値のTTLがDNSに負荷をかけることがあり、管理が難しい。 -### user-spaceプロキシーモード {#proxy-mode-userspace} +### user-spaceプロキシモード {#proxy-mode-userspace} このモードでは、kube-proxyはServiceやEndpointsオブジェクトの追加・削除をチェックするために、Kubernetes Masterを監視します。 -各Serviceは、ローカルのNode上でポート(ランダムに選ばれたもの)を公開します。この"プロキシーポート"に対するどのようなリクエストも、そのServiceのバックエンドPodのどれか1つにプロキシーされます(Endpointsを介して通知されたPodに対して)。 +各Serviceは、ローカルのNode上でポート(ランダムに選ばれたもの)を公開します。この"プロキシポート"に対するどのようなリクエストも、そのServiceのバックエンドPodのどれか1つにプロキシされます(Endpointsを介して通知されたPodに対して)。 kube-proxyは、どのバックエンドPodを使うかを決める際にServiceの`SessionAffinity`項目の設定を考慮に入れます。 -最後に、user-spaceプロキシーはServiceの`clusterIP`(仮想IP)と`port`に対するトラフィックをキャプチャするiptablesルールをインストールします。 -そのルールは、トラフィックをバックエンドPodにプロキシーするためのプロキシーポートにリダイレクトします。 +最後に、user-spaceプロキシはServiceの`clusterIP`(仮想IP)と`port`に対するトラフィックをキャプチャするiptablesルールをインストールします。 +そのルールは、トラフィックをバックエンドPodにプロキシするためのプロキシポートにリダイレクトします。 デフォルトでは、user-spaceモードにおけるkube-proxyはラウンドロビンアルゴリズムによってバックエンドPodを選択します。 -![user-spaceプロキシーのService概要ダイアグラム](/images/docs/services-userspace-overview.svg) +![user-spaceプロキシのService概要ダイアグラム](/images/docs/services-userspace-overview.svg) -### `iptables`プロキシーモード {#proxy-mode-iptables} +### `iptables`プロキシモード {#proxy-mode-iptables} このモードでは、kube-proxyはServiceやEndpointsオブジェクトの追加・削除のチェックのためにKubernetesコントロールプレーンを監視します。 各Serviceでは、そのServiceの`clusterIP`と`port`に対するトラフィックをキャプチャするiptablesルールをインストールし、そのトラフィックをServiceのあるバックエンドのセットに対してリダイレクトします。 @@ -195,9 +195,9 @@ kube-proxyがiptablesモードで稼働し、最初に選択されたPodが応 iptablesモードのkube-proxyが正常なバックエンドPodのみをリダイレクト対象とするために、Podの[ReadinessProbe](/ja/docs/concepts/workloads/pods/pod-lifecycle/#container-probes)を使用してバックエンドPodが正常に動作しているか確認できます。これは、ユーザーがkube-proxyを介して、コネクションに失敗したPodに対してトラフィックをリダイレクトするのを除外することを意味します。 -![iptablesプロキシーのService概要ダイアグラム](/images/docs/services-iptables-overview.svg) +![iptablesプロキシのService概要ダイアグラム](/images/docs/services-iptables-overview.svg) -### IPVSプロキシーモード {#proxy-mode-ipvs} +### IPVSプロキシモード {#proxy-mode-ipvs} {{< feature-state for_k8s_version="v1.11" state="stable" >}} @@ -205,9 +205,9 @@ iptablesモードのkube-proxyが正常なバックエンドPodのみをリダ このコントロールループはIPVSのステータスが理想的な状態になることを保証します。 Serviceにアクセスするとき、IPVSはトラフィックをバックエンドのPodに向けます。 -IPVSプロキシーモードはiptablesモードと同様に、netfilterのフック関数に基づいています。ただし、基礎となるデータ構造としてハッシュテーブルを使っているのと、kernel-spaceで動作します。 -これは、IPVSモードにおけるkube-proxyはiptablesモードに比べてより低いレイテンシーでトラフィックをリダイレクトし、プロキシーのルールを同期する際にはよりパフォーマンスがよいことを意味します。 -他のプロキシーモードと比較して、IPVSモードはより高いネットワークトラフィックのスループットをサポートしています。 +IPVSプロキシモードはiptablesモードと同様に、netfilterのフック関数に基づいています。ただし、基礎となるデータ構造としてハッシュテーブルを使っているのと、kernel-spaceで動作します。 +これは、IPVSモードにおけるkube-proxyはiptablesモードに比べてより低いレイテンシーでトラフィックをリダイレクトし、プロキシのルールを同期する際にはよりパフォーマンスがよいことを意味します。 +他のプロキシモードと比較して、IPVSモードはより高いネットワークトラフィックのスループットをサポートしています。 IPVSはバックエンドPodに対するトラフィックのバランシングのために多くのオプションを下記のとおりに提供します。 @@ -225,9 +225,9 @@ kube-proxyはIPVSモードで起動する場合、IPVSカーネルモジュー もしIPVSカーネルモジュールが見つからなかった場合、kube-proxyはiptablesモードで稼働するようにフォールバックされます。 {{< /note >}} -![IPVSプロキシーのService概要ダイアグラム](/images/docs/services-ipvs-overview.svg) +![IPVSプロキシのService概要ダイアグラム](/images/docs/services-ipvs-overview.svg) -このダイアグラムのプロキシーモデルにおいて、ServiceのIP:Portに対するトラフィックは、クライアントがKubernetesのServiceやPodについて何も知ることなく適切にバックエンドにプロキシーされています。 +このダイアグラムのプロキシモデルにおいて、ServiceのIP:Portに対するトラフィックは、クライアントがKubernetesのServiceやPodについて何も知ることなく適切にバックエンドにプロキシされています。 特定のクライアントからのコネクションが、毎回同一のPodにリダイレクトされるようにするためには、`service.spec.sessionAffinity`に"ClientIP"を設定することにより、クライアントのIPアドレスに基づいたSessionAffinityを選択することができます(デフォルトは"None")。 また、`service.spec.sessionAffinityConfig.clientIP.timeoutSeconds`を適切に設定することにより、セッションのタイムアウト時間を設定できます(デフォルトではこの値は18,000で、3時間となります)。 @@ -326,7 +326,7 @@ KubernetesのDNSサーバーは`ExternalName` Serviceにアクセスする唯一 例えば、ユーザーはこのAPI上でカスタム{{< glossary_tooltip term_id="operator-pattern" text="オペレーター" >}}を実装することができます。 この`Service`においては、clusterIPは割り当てられず、kube-proxyはこのServiceをハンドリングしないのと、プラットフォームによって行われるはずの -ロードバランシングやプロキシーとしての処理は行われません。DNSがどのように自動で設定されるかは、定義されたServiceが定義されたラベルセレクターを持っているかどうかに依存します。 +ロードバランシングやプロキシとしての処理は行われません。DNSがどのように自動で設定されるかは、定義されたServiceが定義されたラベルセレクターを持っているかどうかに依存します。 ### ラベルセレクターの利用 @@ -352,7 +352,7 @@ Kubernetesの`ServiceTypes`によって、ユーザーがどのような種類 * `ClusterIP`: クラスター内部のIPでServiceを公開する。このタイプではServiceはクラスター内部からのみ疎通性があります。このタイプはデフォルトの`ServiceType`です。 * [`NodePort`](#nodeport): 各NodeのIPにて、静的なポート(`NodePort`)上でServiceを公開します。その`NodePort` のServiceが転送する先の`ClusterIP` Serviceが自動的に作成されます。`:`にアクセスすることによって`NodePort` Serviceにアクセスできるようになります。 * [`LoadBalancer`](#loadbalancer): クラウドプロバイダーのロードバランサーを使用して、Serviceを外部に公開します。クラスター外部にあるロードバランサーが転送する先の`NodePort`と`ClusterIP` Serviceは自動的に作成されます。 -* [`ExternalName`](#externalname): `CNAME`レコードを返すことにより、`externalName`フィールドに指定したコンテンツ(例: `foo.bar.example.com`)とServiceを紐づけます。しかし、いかなる種類のプロキシーも設定されません。 +* [`ExternalName`](#externalname): `CNAME`レコードを返すことにより、`externalName`フィールドに指定したコンテンツ(例: `foo.bar.example.com`)とServiceを紐づけます。しかし、いかなる種類のプロキシも設定されません。 {{< note >}} `ExternalName`タイプのServiceを利用するためには、kube-dnsのバージョン1.7かCoreDNSのバージョン0.0.8以上が必要となります。 {{< /note >}} @@ -567,9 +567,9 @@ metadata: 2つ目のアノテーションはPodが利用するプロトコルを指定するものです。HTTPSとSSLの場合、ELBはそのPodが証明書を使って暗号化されたコネクションを介して自分自身のPodを認証すると推測します。 -HTTPとHTTPSでは、レイヤー7でのプロキシーを選択します。ELBはユーザーとのコネクションを切断し、リクエストを転送するときにリクエストヘッダーをパースして、`X-Forwarded-For`ヘッダーにユーザーのIPを追加します(Podは接続相手のELBのIPアドレスのみ確認可能です)。 +HTTPとHTTPSでは、レイヤー7でのプロキシを選択します。ELBはユーザーとのコネクションを切断し、リクエストを転送するときにリクエストヘッダーをパースして、`X-Forwarded-For`ヘッダーにユーザーのIPを追加します(Podは接続相手のELBのIPアドレスのみ確認可能です)。 -TCPとSSLでは、レイヤー4でのプロキシーを選択します。ELBはヘッダーの値を変更せずにトラフィックを転送します。 +TCPとSSLでは、レイヤー4でのプロキシを選択します。ELBはヘッダーの値を変更せずにトラフィックを転送します。 いくつかのポートがセキュアに保護され、他のポートではセキュアでないような混合した環境において、下記のようにアノテーションを使うことができます。 @@ -581,7 +581,7 @@ TCPとSSLでは、レイヤー4でのプロキシーを選択します。ELBは service.beta.kubernetes.io/aws-load-balancer-ssl-ports: "443,8443" ``` -上記の例では、もしServiceが`80`、`443`、`8443`と3つのポートを含んでいる場合、`443`と`8443`はSSL証明書を使いますが、`80`では単純にHTTPでのプロキシーとなります。 +上記の例では、もしServiceが`80`、`443`、`8443`と3つのポートを含んでいる場合、`443`と`8443`はSSL証明書を使いますが、`80`では単純にHTTPでのプロキシとなります。 Kubernetes v1.9以降のバージョンからは、Serviceのリスナー用にHTTPSやSSLと[事前定義されたAWS SSLポリシー](https://docs.aws.amazon.com/elasticloadbalancing/latest/classic/elb-security-policy-table.html)を使用できます。 どのポリシーが使用できるかを確認するために、`aws`コマンドラインツールを使用できます。 @@ -611,7 +611,7 @@ AWS上で稼働するクラスターで[PROXY protocol](https://www.haproxy.org/ service.beta.kubernetes.io/aws-load-balancer-proxy-protocol: "*" ``` -Kubernetesバージョン1.3.0からは、このアノテーションを使用するとELBによってプロキシーされた全てのポートが対象になり、そしてそれ以外の場合は構成されません。 +Kubernetesバージョン1.3.0からは、このアノテーションを使用するとELBによってプロキシされた全てのポートが対象になり、そしてそれ以外の場合は構成されません。 #### AWS上でのELBのアクセスログ @@ -809,7 +809,7 @@ IPアドレスをハードコードする場合、[Headless Service](#headless-s {{< /note >}} `my-service.prod.svc.cluster.local`というホストをルックアップするとき、クラスターのDNS Serviceは`my.database.example.com`という値をもつ`CNAME`レコードを返します。 -`my-service`へのアクセスは、他のServiceと同じ方法ですが、再接続する際はプロキシーや転送を介して行うよりも、DNSレベルで行われることが決定的に異なる点となります。 +`my-service`へのアクセスは、他のServiceと同じ方法ですが、再接続する際はプロキシや転送を介して行うよりも、DNSレベルで行われることが決定的に異なる点となります。 後にユーザーが使用しているデータベースをクラスター内に移行することになった場合は、Podを起動させ、適切なラベルセレクターやEndpointsを追加し、Serviceの`type`を変更します。 {{< warning >}} @@ -851,12 +851,12 @@ spec: ## Serviceの欠点 -仮想IP用にuserspaceモードのプロキシーを使用すると、小規模もしくは中規模のスケールでうまく稼働できますが、1000以上のServiceがあるようなとても大きなクラスターではうまくスケールしません。 +仮想IP用にuserspaceモードのプロキシを使用すると、小規模もしくは中規模のスケールでうまく稼働できますが、1000以上のServiceがあるようなとても大きなクラスターではうまくスケールしません。 これについては、[Serviceのデザインプロポーザル](https://github.com/kubernetes/kubernetes/issues/1107)にてさらなる詳細を確認できます。 -userspaceモードのプロキシーの使用は、Serviceにアクセスするパケットの送信元IPアドレスが不明瞭になります。 +userspaceモードのプロキシの使用は、Serviceにアクセスするパケットの送信元IPアドレスが不明瞭になります。 これは、いくつかの種類のネットワークフィルタリング(ファイアウォールによるフィルタリング)を不可能にします。 -iptablesプロキシーモードはクラスター内の送信元IPを不明瞭にはしませんが、依然としてロードバランサーやNodePortへ疎通するクライアントに影響があります。 +iptablesプロキシモードはクラスター内の送信元IPを不明瞭にはしませんが、依然としてロードバランサーやNodePortへ疎通するクライアントに影響があります。 `Type`フィールドはネストされた機能としてデザインされています。 - 各レベルの値は前のレベルに対して追加します。 これは全てのクラウドプロバイダーにおいて厳密に要求されていません(例: Google Compute Engineは`LoadBalancer`を動作させるために`NodePort`を割り当てる必要はありませんが、AWSではその必要があります)が、現在のAPIでは要求しています。 @@ -886,7 +886,7 @@ Kubernetesは各Serviceに、それ自身のIPアドレスを割り当てるこ クライアントがVIPに接続する時、そのトラフィックは自動的に適切なEndpointsに転送されます。 Service用の環境変数とDNSは、Serviceの仮想IPアドレス(とポート)の面において、自動的に生成されます。 -kube-proxyは3つの微妙に異なった動作をするプロキシーモード— userspace、iptablesとIPVS — をサポートしています。 +kube-proxyは3つの微妙に異なった動作をするプロキシモード— userspace、iptablesとIPVS — をサポートしています。 #### Userspace @@ -895,8 +895,8 @@ kube-proxyは3つの微妙に異なった動作をするプロキシーモード そのServiceのポートが1234で、そのServiceはクラスター内の全てのkube-proxyインスタンスによって監視されていると仮定します。 kube-proxyが新しいServiceを見つけた時、kube-proxyは新しいランダムポートをオープンし、その仮想IPアドレスの新しいポートにリダイレクトするようにiptablesを更新し、そのポート上で新しい接続を待ち受けを開始します。 -クライアントがServiceの仮想IPアドレスに接続したとき、iptablesルールが有効になり、そのパケットをプロキシー自身のポートにリダイレクトします。 -その"Service プロキシー"はバックエンドPodの対象を選択し、クライアントのトラフィックをバックエンドPodに転送します。 +クライアントがServiceの仮想IPアドレスに接続したとき、iptablesルールが有効になり、そのパケットをプロキシ自身のポートにリダイレクトします。 +その"Service プロキシ"はバックエンドPodの対象を選択し、クライアントのトラフィックをバックエンドPodに転送します。 これはServiceのオーナーは、衝突のリスクなしに、求めるどのようなポートも選択できることを意味します。 クライアントは単純にそのIPとポートに対して接続すればよく、実際にどのPodにアクセスしているかを意識しません。 @@ -910,7 +910,7 @@ Service毎のルールは、トラフィックをバックエンドにリダイ クライアントがServiceの仮想IPアドレスに対して接続しているとき、そのiptablesルールが有効になります。 バックエンドのPodが選択され(SessionAffinityに基づくか、もしくはランダムで選択される)、パケットはバックエンドにリダイレクトされます。 -userspaceモードのプロキシーとは異なり、パケットは決してuserspaceにコピーされず、kube-proxyは仮想IPのために稼働される必要はなく、またNodeでは変更されていないクライアントIPからトラフィックがきます。 +userspaceモードのプロキシとは異なり、パケットは決してuserspaceにコピーされず、kube-proxyは仮想IPのために稼働される必要はなく、またNodeでは変更されていないクライアントIPからトラフィックがきます。 このように同じ基本的なフローは、NodePortまたはLoadBalancerを介してトラフィックがきた場合に、実行され、ただクライアントIPは変更されます。 @@ -936,7 +936,7 @@ ServiceはKubernetesのREST APIにおいてトップレベルのリソースで ### HTTP -もしクラウドプロバイダーがサポートしている場合、ServiceのEndpointsに転送される外部のHTTP/HTTPSでのリバースプロキシーをセットアップするために、LoadBalancerモードでServiceを作成可能です。 +もしクラウドプロバイダーがサポートしている場合、ServiceのEndpointsに転送される外部のHTTP/HTTPSでのリバースプロキシをセットアップするために、LoadBalancerモードでServiceを作成可能です。 {{< note >}} ユーザーはまた、HTTP/HTTPS Serviceを公開するために、Serviceの代わりに{{< glossary_tooltip term_id="ingress" >}}を利用することもできます。 diff --git a/content/ja/docs/concepts/storage/volumes.md b/content/ja/docs/concepts/storage/volumes.md index df385712b7a7b..a5545d53c4dcb 100644 --- a/content/ja/docs/concepts/storage/volumes.md +++ b/content/ja/docs/concepts/storage/volumes.md @@ -905,7 +905,7 @@ Portworxの`CSIMigration`機能が追加されましたが、Kubernetes 1.23で ## subPathの使用 {#using-subpath} 1つのPodで複数の用途に使用するために1つのボリュームを共有すると便利な場合があります。 -`volumeMounts.subPath`プロパティは、ルートではなく、参照されるボリューム内のサブパスを指定します。 +`volumeMounts[*].subPath`プロパティは、ルートではなく、参照されるボリューム内のサブパスを指定します。 次の例は、単一の共有ボリュームを使用してLAMPスタック(Linux Apache MySQL PHP)でPodを構成する方法を示しています。 このサンプルの`subPath`構成は、プロダクションでの使用にはお勧めしません。 @@ -1001,7 +1001,7 @@ CSIとFlexVolumeはどちらも、ボリュームプラグインをKubernetesコ ### csi -[Container Storage Interface](https://github.com/container-storage-interface/spec/blob/master/spec.md)(CSI)は、コンテナオーケストレーションシステム(Kubernetesなど)の標準インターフェイスを定義して、任意のストレージシステムをコンテナワークロードに公開します。 +[Container Storage Interface](https://github.com/container-storage-interface/spec/blob/master/spec.md)(CSI)は、コンテナオーケストレーションシステム(Kubernetesなど)の標準インターフェースを定義して、任意のストレージシステムをコンテナワークロードに公開します。 詳細については[CSI design proposal](https://github.com/kubernetes/community/blob/master/contributors/design-proposals/storage/container-storage-interface.md)を参照してください。 @@ -1081,7 +1081,7 @@ FlexVolumeドライバーのメンテナーは、CSIドライバーを実装し マウントの伝播により、コンテナによってマウントされたボリュームを、同じPod内の他のコンテナ、または同じノード上の他のPodに共有できます。 -ボリュームのマウント伝播は、`Container.volumeMounts`の`mountPropagation`フィールドによって制御されます。その値は次のとおりです。 +ボリュームのマウント伝播は、`containers[*].volumeMounts`の`mountPropagation`フィールドによって制御されます。その値は次のとおりです。 * `None` - このボリュームマウントは、ホストによってこのボリュームまたはそのサブディレクトリにマウントされる後続のマウントを受け取りません。同様に、コンテナによって作成されたマウントはホストに表示されません。これがデフォルトのモードです。 diff --git a/content/ja/docs/concepts/workloads/controllers/job.md b/content/ja/docs/concepts/workloads/controllers/job.md index c32b23db8353f..42180f95cc5c3 100644 --- a/content/ja/docs/concepts/workloads/controllers/job.md +++ b/content/ja/docs/concepts/workloads/controllers/job.md @@ -83,7 +83,7 @@ apiVersion: batch/v1 kind: Job metadata: annotations: batch.kubernetes.io/job-tracking: "" - ... + ... creationTimestamp: "2022-11-10T17:53:53Z" generation: 1 labels: @@ -334,12 +334,12 @@ Pod失敗ポリシーまたはPod失敗のバックオフポリシーのいず - `spec.podFailurePolicy.rules`で指定したPod失敗ポリシーのルールが順番に評価されます。あるPodの失敗がルールに一致すると、残りのルールは無視されます。Pod失敗に一致するルールがない場合は、デフォルトの処理が適用されます。 - `spec.podFailurePolicy.rules[*].onExitCodes.containerName`を指定することで、ルールを特定のコンテナに制限することができます。指定しない場合、ルールはすべてのコンテナに適用されます。指定する場合は、Pod テンプレート内のコンテナ名または`initContainer`名のいずれかに一致する必要があります。 - Pod失敗ポリシーが`spec.podFailurePolicy.rules[*].action`にマッチしたときに実行されるアクションを指定できます。指定可能な値は以下のとおりです。 - - `FailJob`: PodのJobを`Failed`としてマークし、実行中の Pod をすべて終了させる必要があることを示します。 + - `FailJob`: PodのJobを`Failed`としてマークし、実行中の Pod をすべて終了させる必要があることを示します。 - `Ignore`: `.spec.backoffLimit`のカウンターは加算されず、代替のPodが作成すべきであることを示します。 - `Count`: Podがデフォルトの方法で処理されるべきであることを示します。`.spec.backoffLimit`のカウンターが加算されます。 {{< note >}} -`PodFailurePolicy`を使用すると、Jobコントローラは`Failed`フェーズのPodのみにマッチします。削除タイムスタンプを持つPodで、終了フェーズ(`Failed`または`Succeeded`)にないものは、まだ終了中と見なされます。これは、終了中Podは終了フェーズに達するまで[追跡ファイナライザー](#job-tracking-with-finalizers)を保持することを意味します。Kubernetes 1.27以降、Kubeletは削除されたPodを終了フェーズに遷移させます(参照:[Podのフェーズ](/ja/docs/concepts/workloads/pods/pod-lifecycle/#pod-phase))。これにより、削除されたPodはJobコントローラーによってファイナライザーが削除されます。 +`PodFailurePolicy`を使用すると、Jobコントローラーは`Failed`フェーズのPodのみにマッチします。削除タイムスタンプを持つPodで、終了フェーズ(`Failed`または`Succeeded`)にないものは、まだ終了中と見なされます。これは、終了中Podは終了フェーズに達するまで[追跡ファイナライザー](#job-tracking-with-finalizers)を保持することを意味します。Kubernetes 1.27以降、Kubeletは削除されたPodを終了フェーズに遷移させます(参照:[Podのフェーズ](/ja/docs/concepts/workloads/pods/pod-lifecycle/#pod-phase))。これにより、削除されたPodはJobコントローラーによってファイナライザーが削除されます。 {{< /note >}} ## Jobの終了とクリーンアップ {#job-termination-and-cleanup} @@ -574,7 +574,7 @@ Events: この機能により、Jobが開始する前にスケジューリング命令を更新でき、カスタムキューコントローラーがPodの配置に影響を与えることができるようになります。同時に実際のPodからNodeへの割り当てをkube-schedulerにオフロードする能力を提供します。これは一時停止されたJobの中で、一度も一時停止解除されたことのないJobに対してのみ許可されます。 -JobのPodテンプレートで更新可能なフィールドはnodeAffinity、nodeSelector、tolerations、labelsとannotations、[スケジューリングゲート](/docs/concepts/scheduling-eviction/pod-scheduling-readiness/)です。 +JobのPodテンプレートで更新可能なフィールドはnodeAffinity、nodeSelector、tolerations、labelsとannotations、[スケジューリングゲート](/docs/concepts/scheduling-eviction/pod-scheduling-readiness/)です。 ### 独自のPodセレクターを指定 {#specifying-your-own-pod-selector} @@ -634,9 +634,9 @@ spec: `JobTrackingWithFinalizers`機能が無効になっている時に作成されたJobについては、コントロールプレーンを1.26にアップグレードしても、ファイナライザーを使用してJobを追跡しません。 {{< /note >}} -コントロールプレーンは任意のJobに属するPodを追跡し、そのPodがAPIサーバーから削除されたかどうか認識します。そのためJobコントローラはファイナライザー`batch.kubernetes.io/job-tracking`を持つPodを作成します。コントローラーがファイナライザーを削除するのは、PodがJobステータスに反映された後なので、他のコントローラーやユーザがPodを削除することができます。 +コントロールプレーンは任意のJobに属するPodを追跡し、そのPodがAPIサーバーから削除されたかどうか認識します。そのためJobコントローラーはファイナライザー`batch.kubernetes.io/job-tracking`を持つPodを作成します。コントローラーがファイナライザーを削除するのは、PodがJobステータスに反映された後なので、他のコントローラーやユーザがPodを削除することができます。 -Kubernetes 1.26にアップグレードする前、またはフィーチャーゲート`JobTrackingWithFinalizers`が有効になる前に作成されたJobは、Podファイナライザーを使用せずに追跡されます。Job{{< glossary_tooltip term_id="controller" text="コントローラー" >}}は、クラスタに存在するPodのみに基づいて、`succeeded`Podと`failed`Podのステータスカウンタを更新します。クラスタからPodが削除されると、コントロールプレーンはJobの進捗を見失う可能性があります。 +Kubernetes 1.26にアップグレードする前、またはフィーチャーゲート`JobTrackingWithFinalizers`が有効になる前に作成されたJobは、Podファイナライザーを使用せずに追跡されます。Job{{< glossary_tooltip term_id="controller" text="コントローラー" >}}は、クラスターに存在するPodのみに基づいて、`succeeded`Podと`failed`Podのステータスカウンタを更新します。クラスターからPodが削除されると、コントロールプレーンはJobの進捗を見失う可能性があります。 Jobが`batch.kubernetes.io/job-tracking`というアノテーションを持っているかどうかをチェックすることで、コントロールプレーンがPodファイナライザーを使ってJobを追跡しているかどうかを判断できます。Jobからこのアノテーションを手動で追加したり削除したりしては**いけません**。代わりに、JobがPodファイナライザーを使用して追跡されていることを確認するために、Jobを再作成することができます。 @@ -652,7 +652,7 @@ Jobが`batch.kubernetes.io/job-tracking`というアノテーションを持っ ### 単なるPod {#bare-pods} -Podが動作しているノードが再起動または故障した場合、Podは終了し、再起動されません。しかし、終了したPodを置き換えるため、Jobが新しいPodを作成します。このため、たとえアプリケーションが1つのPodしか必要としない場合でも、単なるPodではなくJobを使用することをお勧めします。 +Podが動作しているノードが再起動または故障した場合、Podは終了し、再起動されません。しかし、終了したPodを置き換えるため、Jobが新しいPodを作成します。このため、たとえアプリケーションが1つのPodしか必要としない場合でも、単なるPodではなくJobを使用することをお勧めします。 ### Replication Controller {#replication-controller} diff --git a/content/ja/docs/concepts/workloads/pods/disruptions.md b/content/ja/docs/concepts/workloads/pods/disruptions.md new file mode 100644 index 0000000000000..49a8a2e1f880e --- /dev/null +++ b/content/ja/docs/concepts/workloads/pods/disruptions.md @@ -0,0 +1,270 @@ +--- +title: Disruption +content_type: concept +weight: 70 +--- + + + +このガイドは、高可用性アプリケーションを構築したいと考えており、そのために、Podに対してどのような種類のDisruptionが発生する可能性があるか理解する必要がある、アプリケーション所有者を対象としたものです。 + +また、クラスターのアップグレードやオートスケーリングなどのクラスターの操作を自動化したいクラスター管理者も対象にしています。 + + + +## 自発的なDisruptionと非自発的なDisruption + +Podは誰か(人やコントローラー)が破壊するか、避けることができないハードウェアまたはシステムソフトウェアエラーが発生するまで、消えることはありません。 + +これらの不可避なケースをアプリケーションに対する*非自発的なDisruption*と呼びます。 +例えば: + +- ノードのバックエンドの物理マシンのハードウェア障害 +- クラスター管理者が誤ってVM(インスタンス)を削除した +- クラウドプロバイダーまたはハイパーバイザーの障害によってVMが消えた +- カーネルパニック +- クラスターネットワークパーティションが原因でクラスターからノードが消えた +- ノードの[リソース不足](/docs/concepts/scheduling-eviction/node-pressure-eviction/)によるPodの退避 + +リソース不足を除いて、これら条件は全て、大半のユーザーにとって馴染みのあるものでしょう。 +これらはKubernetesに固有のものではありません。 + +それ以外のケースのことを*自発的なDisruption*と呼びます。 +これらはアプリケーションの所有者によって起こされたアクションと、クラスター管理者によって起こされたアクションの両方を含みます。 +典型的なアプリケーションの所有者によるアクションには次のものがあります: + +- Deploymentやその他のPodを管理するコントローラーの削除 +- 再起動を伴うDeployment内のPodのテンプレートの更新 +- Podの直接削除(例:アクシデントによって) + +クラスター管理者のアクションには、次のようなものが含まれます: + +- 修復やアップグレードのための[ノードのドレイン](/docs/tasks/administer-cluster/safely-drain-node/)。 +- クラスターのスケールダウンのためにクラスターからノードをドレインする([クラスター自動スケーリング](https://github.com/kubernetes/autoscaler/#readme)について学ぶ)。 +- そのノードに別のものを割り当てることができるように、ノードからPodを削除する。 + +これらのアクションはクラスター管理者によって直接実行されるか、クラスター管理者やクラスターをホスティングしているプロバイダーによって自動的に実行される可能性があります。 + +クラスターに対して自発的なDisruptionの要因となるものが有効になっているかどうかについては、クラスター管理者に聞くか、クラウドプロバイダーに相談または配布文書を参照してください。 +有効になっているものが何もなければ、Pod Disruption Budgetの作成はスキップすることができます。 + +{{< caution >}} +全ての自発的なDisruptionがPod Disruption Budgetによる制約を受けるわけではありません。 +例えばDeploymentやPodの削除はPod Disruption Budgetをバイパスします。 +{{< /caution >}} + +## Disruptionへの対応 + +非自発的なDisruptionを軽減する方法をいくつか紹介します: + +- Podは必要な[リソースを要求](/ja/docs/tasks/configure-pod-container/assign-memory-resource)するようにする。 +- 高可用性が必要な場合はアプリケーションをレプリケートする。(レプリケートされた[ステートレス](/ja/docs/tasks/run-application/run-stateless-application-deployment/)および[ステートフル](/ja/docs/tasks/run-application/run-replicated-stateful-application/)アプリケーションの実行について学ぶ。) +- レプリケートされたアプリケーションを実行する際にさらに高い可用性を得るには、([アンチアフィニティ](/ja/docs/concepts/scheduling-eviction/assign-pod-node/#affinity-and-anti-affinity)を使って)ラックを横断して、または([マルチゾーンクラスター](/ja/docs/setup/multiple-zones)を使用している場合には)ゾーンを横断してアプリケーションを分散させる。 + +自発的なDisruptionの頻度は様々です。 +基本的なKubernetesクラスターでは、自動で発生する自発的なDisruptionはありません(ユーザーによってトリガーされたものだけです)。 +しかし、クラスター管理者やホスティングプロバイダーが何か追加のサービスを実行して自発的なDisruptionが発生する可能性があります。 +例えば、ノード上のソフトウェアアップデートのロールアウトは自発的なDisruptionの原因となります。 +また、クラスター(ノード)自動スケーリングの実装の中には、ノードのデフラグとコンパクト化のために自発的なDisruptionを伴うものがあります。 +クラスタ管理者やホスティングプロバイダーは、自発的なDisruptionがある場合、どの程度のDisruptionが予想されるかを文書化しているはずです。 +Podのspecの中で[PriorityClassesを使用している](/ja/docs/concepts/scheduling-eviction/pod-priority-preemption/)場合など、特定の設定オプションによっても自発的(および非自発的)なDisruptionを引き起こす可能性があります。 + + +## Pod Disruption Budget + +{{< feature-state for_k8s_version="v1.21" state="stable" >}} + +Kubernetesは、自発的なDisruptionが頻繁に発生する場合でも、可用性の高いアプリケーションの運用を支援する機能を提供しています。 + +アプリケーションの所有者として、各アプリケーションに対してPodDisruptionBudget (PDB)を作成することができます。 +PDBは、レプリカを持っているアプリケーションのうち、自発的なDisruptionによって同時にダウンするPodの数を制限します。 +例えば、クォーラムベースのアプリケーションでは、実行中のレプリカの数がクォーラムに必要な数を下回らないようにする必要があります。 +Webフロントエンドは、負荷に対応するレプリカの数が、全体に対して一定の割合を下回らないようにしたいかもしれません。 + +クラスター管理者やホスティングプロバイダーは、直接PodやDeploymentを削除するのではなく、[Eviction API](/docs/tasks/administer-cluster/safely-drain-node/#eviction-api)を呼び出す、PodDisruptionBudgetsに配慮したツールを使用すべきです。 + +例えば、`kubectl drain`サブコマンドはノードを休止中とマークします。 +`kubectl drain`を実行すると、ツールは休止中としたノード上の全てのPodを退避しようとします。 +`kubectl`があなたの代わりに送信する退避要求は一時的に拒否される可能性があるため、ツールは対象のノード上の全てのPodが終了するか、設定可能なタイムアウト時間に達するまで、全ての失敗した要求を定期的に再試行します。 + +PDBはアプリケーションの意図したレプリカ数に対して、許容できるレプリカの数を指定します。 +例えば`.spec.replicas: 5`を持つDeploymentは常に5つのPodを持つことが想定されます。 +PDBが同時に4つまでを許容する場合、Eviction APIは1度に(2つではなく)1つのPodの自発的なDisruptionを許可します。 + +アプリケーションを構成するPodのグループは、アプリケーションのコントローラー(Deployment、StatefulSetなど)が使用するものと同じラベルセレクターを使用して指定されます。 + +"意図した"Podの数は、これらのPodを管理するワークロードリソースの`.spec.replicas`から計算されます。 +コントロールプレーンはPodの`.metadata.ownerReferences`を調べることで、所有しているワークロードリソースを見つけます。 + +[非自発的なDisruption](#voluntary-and-involuntary-disruptions)はPDBによって防ぐことができません; +しかし、予算にはカウントされます。 + +アプリケーションのローリングアップデートによって削除または利用できなくなったPodはDisruptionの予算にカウントされますが、ローリングアップグレードを実行している時は(DeploymentやStatefulSetなどの)ワークロードリソースはPDBによって制限されません。 +代わりに、アプリケーションのアップデート中の障害のハンドリングは、個々のワークロードリソースに対するspecで設定されます。 + +ノードのドレイン中に動作がおかしくなったアプリケーションの退避をサポートするために、[Unhealthy Pod Eviction Policy](/docs/tasks/run-application/configure-pdb/#unhealthy-pod-eviction-policy)に`AlwaysAllow`を設定することを推奨します。 +既定の動作は、ドレインを継続する前にアプリケーションPodが[healthy](/docs/tasks/run-application/configure-pdb/#healthiness-of-a-pod)な状態になるまで待機します。 + +Eviction APIを使用してPodを退避した場合、[PodSpec](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#podspec-v1-core)で設定した`terminationGracePeriodSeconds`に従って正常に[終了](/ja/docs/concepts/workloads/pods/pod-lifecycle/#pod-termination)します。 + +## PodDisruptionBudgetの例 {#pdb-example} + +`node-1`から`node-3`まで3つのノードがあるクラスターを考えます。 +クラスターにはいくつかのアプリケーションが動いています。 +それらのうちの1つは3つのレプリカを持ち、最初は`pod-a`、`pod-b`そして`pod-c`と名前が付いています。 +もう一つ、これとは独立したPDBなしの`pod-x`と呼ばれるものもあります。 +初期状態ではPodは次のようにレイアウトされています: + +| node-1 | node-2 | node-3 | +|:--------------------:|:-------------------:|:------------------:| +| pod-a *available* | pod-b *available* | pod-c *available* | +| pod-x *available* | | | + +3つのPodはすべてDeploymentの一部で、これらはまとめて1つのPDBを持ち、3つのPodのうちの少なくとも2つが常に存在していることを要求します。 + +例えばクラスター管理者がカーネルのバグを修正するために、再起動して新しいカーネルバージョンにしたいとします。 +クラスター管理者はまず、`kubectl drain`コマンドを使って`node-1`をドレインしようとします。 +ツールは`pod-a`と`pod-x`を退避しようとします。 +これはすぐに成功します。 +2つのPodは同時に`terminating`状態になります。 +これにより、クラスターは次のような状態になります: + +| node-1 *draining* | node-2 | node-3 | +|:--------------------:|:-------------------:|:------------------:| +| pod-a *terminating* | pod-b *available* | pod-c *available* | +| pod-x *terminating* | | | + +DeploymentはPodの1つが終了中であることに気づき、`pod-d`という代わりのPodを作成します。 +`node-1`はcordonされたため、別のノードに展開されます。 +また、`pod-x`の代わりとして`pod-y`も作られました。 + +(備考: StatefulSetの場合、`pod-a`は`pod-0`のように呼ばれ、代わりのPodが作成される前に完全に終了する必要があります。 +この代わりのPodは、UIDは異なりますが、同じ`pod-0`という名前になります。 +それを除けば、本例はStatefulSetにも当てはまります。) + +現在、クラスターは次のような状態になっています: + +| node-1 *draining* | node-2 | node-3 | +|:--------------------:|:-------------------:|:------------------:| +| pod-a *terminating* | pod-b *available* | pod-c *available* | +| pod-x *terminating* | pod-d *starting* | pod-y | + +ある時点でPodは終了し、クラスターはこのようになります: + +| node-1 *drained* | node-2 | node-3 | +|:--------------------:|:-------------------:|:------------------:| +| | pod-b *available* | pod-c *available* | +| | pod-d *starting* | pod-y | + +この時点で、せっかちなクラスター管理者が`node-2`か`node-3`をドレインしようとすると、Deploymentの利用可能なPodは2つしかなく、また、PDBによって最低2つのPodが要求されているため、drainコマンドはブロックされます。 +しばらくすると、`pod-d`が使用可能になります。 + +クラスターの状態はこのようになります: + +| node-1 *drained* | node-2 | node-3 | +|:--------------------:|:-------------------:|:------------------:| +| | pod-b *available* | pod-c *available* | +| | pod-d *available* | pod-y | + +ここでクラスター管理者が`node-2`をドレインしようとします。 +drainコマンドは2つのPodをなんらかの順番で退避しようとします。 +例えば最初に`pod-b`、次に`pod-d`とします。 +`pod-b`については退避に成功します。 +しかし`pod-d`を退避しようとすると、Deploymentに対して利用可能なPodは1つしか残らないため、退避は拒否されます。 + +Deploymentは`pod-b`の代わりとして`pod-e`を作成します。 +クラスターには`pod-e`をスケジューリングする十分なリソースがないため、ドレインは再びブロックされます。 +クラスターは次のような状態になります: + +| node-1 *drained* | node-2 | node-3 | *no node* | +|:--------------------:|:-------------------:|:------------------:|:------------------:| +| | pod-b *terminating* | pod-c *available* | pod-e *pending* | +| | pod-d *available* | pod-y | | + +この時点で、クラスター管理者はアップグレードを継続するためにクラスターにノードを追加する必要があります。 + +KubernetesがどのようにDisruptionの発生率を変化させているかについては、次のようなものから知ることができます: + +- いくつのレプリカをアプリケーションが必要としているか +- インスタンスのグレースフルシャットダウンにどれくらいの時間がかかるか +- 新しいインスタンスのスタートアップにどれくらいの時間がかかるか +- コントローラーの種類 +- クラスターリソースのキャパシティ + +## Pod Disruption Condition {#pod-disruption-conditions} + +{{< feature-state for_k8s_version="v1.26" state="beta" >}} + +{{< note >}} +この機能を使用するためには、クラスターで[フィーチャーゲート](/ja/docs/reference/command-line-tools-reference/feature-gates/)`PodDisruptionConditions`を有効にする必要があります。 +{{< /note >}} + +有効にすると、専用のPod `DisruptionTarget` [Condition](/ja/docs/concepts/workloads/pods/pod-lifecycle/#pod-conditions)が追加されます。 +これはPodが{{}}によって削除されようとしていることを示すものです。 +Conditionの`reason`フィールドにて、追加で以下のいずれかをPodの終了の理由として示します: + +`PreemptionByScheduler` +: Podはより高い優先度を持つ新しいPodを収容するために、スケジューラーによって{{}}予定です。 +詳細については[Podの優先度とプリエンプション](/ja/docs/concepts/scheduling-eviction/pod-priority-preemption/)を参照してください。 + +`DeletionByTaintManager` +: Podが許容しない`NoExecute` taintによって、Podは(`kube-controller-manager`の中のノードライフサイクルコントローラーである)Taintマネージャーによって削除される予定です。 +{{}}ベースの退避を参照してください。 + +`EvictionByEvictionAPI` +: Podは{{}}マークされました。 + +`DeletionByPodGC` +: すでに存在しないノードに紐づいているPodのため、[Podのガベージコレクション](/ja/docs/concepts/workloads/pods/pod-lifecycle/#pod-garbage-collection)によって削除される予定です。 + +`TerminationByKubelet` +: {{}}または[Graceful Node Shutdown](/ja/docs/concepts/architecture/nodes/#graceful-node-shutdown)のため、Podはkubeletによって終了させられました。 + +{{< note >}} +PodのDisruptionは一時停止する場合があります。 +コントロールプレーンは同じPodに対するDisruptionを継続するために再試行するかもしれませんが、保証はされていません。 +その結果、`DisruptionTarget` ConditionはPodに付与されるかもしれませんが、実際にはPodは削除されていない可能性があります。 +そのような状況の場合、しばらくすると、Pod Disruption Conditionはクリアされます。 +{{< /note >}} + +フィーチャーゲート`PodDisruptionConditions`を有効にすると、Podのクリーンアップと共に、Podガベージコレクタ(PodGC)が非終了フェーズにあるPodを失敗とマークします。 +([Podガベージコレクション](/ja/docs/concepts/workloads/pods/pod-lifecycle/#pod-garbage-collection)も参照してください)。 + +Job(またはCronJob)を使用している場合、Jobの[Pod失敗ポリシー](/ja/docs/concepts/workloads/controllers/job#pod-failure-policy)の一部としてこれらのPod Disruption Conditionを使用したいと思うかもしれません。 + +## クラスターオーナーとアプリケーションオーナーロールの分離 + +多くの場合、クラスター管理者とアプリケーションオーナーは、互いの情報を一部しか持たない別の役割であると考えるのが便利です。 +このような責任の分離は、次のようなシナリオで意味を持つことがあります: + +- 多くのアプリケーションチームでKubernetesクラスターを共有していて、役割の専門化が自然に行われている場合 +- クラスター管理を自動化するためにサードパーティのツールやサービスを使用している場合 + +Pod Disruption Budgetはロール間のインターフェースを提供することによって、この役割の分離をサポートします。 + +もしあなたの組織でこのような責任の分担がなされていない場合は、Pod Disruption Budgetを使用する必要はないかもしれません。 + +## クラスターで破壊的なアクションを実行する方法 + +あなたがクラスターの管理者で、ノードやシステムソフトウェアのアップグレードなど、クラスター内のすべてのノードに対して破壊的なアクションを実行する必要がある場合、次のような選択肢があります: + +- アップグレードの間のダウンタイムを許容する。 +- もう一つの完全なレプリカクラスターにフェールオーバーする。 + - ダウンタイムはありませんが、重複するノードと、切り替えを調整する人的労力の両方のコストがかかる可能性があります。 +- Disruptionに耐性のあるアプリケーションを書き、PDBを使用する。 + - ダウンタイムはありません。 + - リソースの重複は最小限です。 + - クラスター管理をより自動化できます。 + - Disruptionに耐えうるアプリケーションを書くことは大変ですが、自発的なDisruptionに耐えうるようにするための作業は、非自発的なDisruptionに耐えうるために必要な作業とほぼ重複しています。 + + + + +## {{% heading "whatsnext" %}} + + +* [Pod Disruption Budgeを構成して](/docs/tasks/run-application/configure-pdb/)アプリケーションを保護する手順にしたがってください。 + +* [ノードのドレイン](/docs/tasks/administer-cluster/safely-drain-node/)について学んでください。 + +* ロールアウト中の可用性を維持するためのステップなど、[Deploymentの更新](/ja/docs/concepts/workloads/controllers/deployment/#updating-a-deployment)について学んでください。 diff --git a/content/ja/docs/concepts/workloads/pods/pod-lifecycle.md b/content/ja/docs/concepts/workloads/pods/pod-lifecycle.md index a975102d76207..85829d3e31d39 100644 --- a/content/ja/docs/concepts/workloads/pods/pod-lifecycle.md +++ b/content/ja/docs/concepts/workloads/pods/pod-lifecycle.md @@ -286,7 +286,7 @@ Podは、クラスター内のNodeで実行中のプロセスを表すため、 {{< note >}} Pod内のすべてのコンテナが同時にTERMシグナルを受信するわけではなく、シャットダウンの順序が問題になる場合はそれぞれに`preStop`フックを使用して同期することを検討する。 {{< /note >}} -1. kubeletが正常な終了を開始すると同時に、コントロールプレーンは、終了中のPodをEndpointSlice(およびEndpoints)オブジェクトから削除します。これらのオブジェクトは、{{< glossary_tooltip text="selector" term_id="selector" >}}が設定された{{< glossary_tooltip term_id="service" text="Service" >}}を表します。{{< glossary_tooltip text="ReplicaSets" term_id="replica-set" >}}とその他のワークロードリソースは、終了中のPodを有効なサービス中のReplicaSetとして扱いません。ゆっくりと終了するPodは、(サービスプロキシーのような)ロードバランサーが終了猶予期間が*始まる*とエンドポイントからそれらのPodを削除するので、トラフィックを継続して処理できません。 +1. kubeletが正常な終了を開始すると同時に、コントロールプレーンは、終了中のPodをEndpointSlice(およびEndpoints)オブジェクトから削除します。これらのオブジェクトは、{{< glossary_tooltip text="selector" term_id="selector" >}}が設定された{{< glossary_tooltip term_id="service" text="Service" >}}を表します。{{< glossary_tooltip text="ReplicaSets" term_id="replica-set" >}}とその他のワークロードリソースは、終了中のPodを有効なサービス中のReplicaSetとして扱いません。ゆっくりと終了するPodは、(サービスプロキシのような)ロードバランサーが終了猶予期間が*始まる*とエンドポイントからそれらのPodを削除するので、トラフィックを継続して処理できません。 1. 猶予期間が終了すると、kubeletは強制削除を開始する。コンテナランタイムは、Pod内でまだ実行中のプロセスに`SIGKILL`を送信する。kubeletは、コンテナランタイムが非表示の`pause`コンテナを使用している場合、そのコンテナをクリーンアップします。 1. kubeletは猶予期間を0(即時削除)に設定することでAPI server上のPodの削除を終了する。 1. API serverはPodのAPIオブジェクトを削除し、クライアントからは見えなくなります。 diff --git a/content/ja/docs/concepts/workloads/pods/sidecar-containers.md b/content/ja/docs/concepts/workloads/pods/sidecar-containers.md new file mode 100644 index 0000000000000..ee8a7aee3834c --- /dev/null +++ b/content/ja/docs/concepts/workloads/pods/sidecar-containers.md @@ -0,0 +1,93 @@ +--- +title: サイドカーコンテナ +content_type: concept +weight: 50 +--- + + +{{< feature-state for_k8s_version="v1.29" state="beta" >}} + +サイドカーコンテナは、メインのアプリケーションコンテナと同じ{{< glossary_tooltip text="Pod" term_id="pod" >}}内で実行されるセカンダリーコンテナです。 +これらのコンテナは、主要なアプリケーションコードを直接変更することなく、ロギング、モニタリング、セキュリティ、データの同期などの追加サービスや機能を提供することにより、アプリケーションコンテナの機能を強化または拡張するために使用されます。 + + + +## サイドカーコンテナの有効化 + +Kubernetes 1.29でデフォルトで有効化された`SidecarContainers`という名前の [フィーチャーゲート](/docs/reference/command-line-tools-reference/feature-gates/)により、 +Podの`initContainers`フィールドに記載されているコンテナの`restartPolicy`を指定することができます。 +これらの再起動可能な _サイドカー_ コンテナは、同じポッド内の他の[initコンテナ](/docs/concepts/workloads/pods/init-containers/)やメインのアプリケーションコンテナとは独立しています。 +これらは、メインアプリケーションコンテナや他のinitコンテナに影響を与えることなく、開始、停止、または再起動することができます。 + +## サイドカーコンテナとPodのライフサイクル + +もしinitコンテナが`restartPolicy`を`Always`に設定して作成された場合、それはPodのライフサイクル全体にわたって起動し続けます。 +これは、メインアプリケーションコンテナから分離されたサポートサービスを実行するのに役立ちます。 + +このinitコンテナに`readinessProbe`が指定されている場合、その結果はPodの`ready`状態を決定するために使用されます。 + +これらのコンテナはinitコンテナとして定義されているため、他のinitコンテナと同様に順序に関する保証を受けることができ、複雑なPodの初期化フローに他のinitコンテナと混在させることができます。 + +通常のinitコンテナと比較して、`initContainers`内で定義されたサイドカーは、開始した後も実行を続けます。 +これは、`.spec.initContainers`にPod用の複数のエントリーがある場合に重要です。 +サイドカースタイルのinitコンテナが実行中になった後(kubeletがそのinitコンテナの`started`ステータスをtrueに設定した後)、kubeletは順序付けられた`.spec.initContainers`リストから次のinitコンテナを開始します。 +そのステータスは、コンテナ内でプロセスが実行されておりStartup Probeが定義されていない場合、あるいはその`startupProbe`が成功するとtrueになります。 + +以下は、サイドカーを含む2つのコンテナを持つDeploymentの例です: + +{{% code_sample language="yaml" file="application/deployment-sidecar.yaml" %}} + +この機能は、サイドカーコンテナがメインコンテナが終了した後もジョブが完了するのを妨げないため、サイドカーを持つジョブを実行するのにも役立ちます。 + +以下は、サイドカーを含む2つのコンテナを持つJobの例です: + +{{% code_sample language="yaml" file="application/job/job-sidecar.yaml" %}} + +## 通常のコンテナとの違い + +サイドカーコンテナは、同じPod内の通常のコンテナと並行して実行されます。 +しかし、主要なアプリケーションロジックを実行するわけではなく、メインのアプリケーションにサポート機能を提供します。 + +サイドカーコンテナは独自の独立したライフサイクルを持っています。 +通常のコンテナとは独立して開始、停止、再起動することができます。 +これは、メインアプリケーションに影響を与えることなく、サイドカーコンテナを更新、スケール、メンテナンスできることを意味します。 + +サイドカーコンテナは、メインのコンテナと同じネットワークおよびストレージの名前空間を共有します。 +このような配置により、密接に相互作用し、リソースを共有することができます。 + +## initコンテナとの違い + +サイドカーコンテナは、メインのコンテナと並行して動作し、その機能を拡張し、追加サービスを提供します。 + +サイドカーコンテナは、メインアプリケーションコンテナと並行して実行されます。 +Podのライフサイクル全体を通じてアクティブであり、メインコンテナとは独立して開始および停止することができます。 +[Initコンテナ](/docs/concepts/workloads/pods/init-containers/)とは異なり、サイドカーコンテナはライフサイクルを制御するための[Probe](/docs/concepts/workloads/pods/pod-lifecycle/#types-of-probe)をサポートしています。 + +これらのコンテナは、メインアプリケーションコンテナと直接相互作用することができ、同じネットワーク名前空間、ファイルシステム、環境変数を共有します。追加の機能を提供するために緊密に連携して動作します。 + +## コンテナ内のリソース共有 + +{{< comment >}} +このセクションは[Initコンテナ](/docs/concepts/workloads/pods/init-containers/)ページにも存在します。 +このセクションを編集する場合は、その両方を変更してください。 +{{< /comment >}} + +Initコンテナ、サイドカーコンテナ、アプリケーションコンテナの順序と実行を考えるとき、リソースの使用に関して下記のルールが適用されます。 + +* 全てのInitコンテナの中で定義された最も高いリソースリクエストとリソースリミットが、*有効なinitリクエスト/リミット* になります。いずれかのリソースでリミットが設定されていない場合、これが最上級のリミットとみなされます。 +* Podのリソースの*有効なリクエスト/リミット* は、[Podのオーバーヘッド](/ja/docs/concepts/scheduling-eviction/pod-overhead/)と次のうち大きい方の合計になります。 + * リソースに対する全てのアプリケーションコンテナとサイドカーコンテナのリクエスト/リミットの合計 + * リソースに対する有効なinitリクエスト/リミット +* スケジューリングは有効なリクエスト/リミットに基づいて実行されます。つまり、InitコンテナはPodの生存中には使用されない初期化用のリソースを確保することができます。 +* Podの*有効なQoS(quality of service)ティアー* は、Initコンテナ、サイドカーコンテナ、アプリケーションコンテナで同様です。 + +クォータとリミットは有効なPodリクエストとリミットに基づいて適用されます。 + +Podレベルのコントロールグループ(cgroups)は、スケジューラーと同様に、有効なPodリクエストとリミットに基づいています。 + +## {{% heading "whatsnext" %}} + +* [ネイティブサイドカーコンテナ](/blog/2023/08/25/native-sidecar-containers/)に関するブログ投稿を読む。 +* [Initコンテナを持つPodを作成する方法](/docs/tasks/configure-pod-container/configure-pod-initialization/#create-a-pod-that-has-an-init-container)について読む。 +* [Probeの種類](/docs/concepts/workloads/pods/pod-lifecycle/#types-of-probe)について学ぶ: Liveness, Readiness, Startup Probe。 +* [Podのオーバーヘッド](/docs/concepts/scheduling-eviction/pod-overhead/)について学ぶ。 diff --git a/content/ja/docs/contribute/_index.md b/content/ja/docs/contribute/_index.md index 0289383cf256d..fc2c031829e2c 100644 --- a/content/ja/docs/contribute/_index.md +++ b/content/ja/docs/contribute/_index.md @@ -1,166 +1,26 @@ --- content_type: concept -title: K8sのドキュメントに貢献する -linktitle: 貢献 +title: Kubernetesに貢献する +linkTitle: 貢献 main_menu: true no_list: true weight: 80 card: name: 貢献 weight: 10 - title: K8sへの貢献を始める + title: Kubernetesに貢献する --- -*Kubernetesは初心者でも経験者でも、全てのコントリビューターからの改善を歓迎しています!* +Kubernetesに貢献する方法はたくさんあります。 +新機能の設計に取り組むこともできますし、既存のコードにドキュメントを追加することも、[ブログ](/ja/blog)で記事を書くこともできます。 +それだけではありません。新機能を実装したり、バグを修正したりすることもできます。 +貢献者コミュニティへの参加を支援することも、既存の貢献者をサポートすることもできます。 -{{< note >}} -Kubernetesへの貢献について総合的に知りたい場合は、[contributor documentation](https://www.kubernetes.dev/docs/)を参照してください。 +様々な方法でプロジェクトに貢献することができるため、Kubernetesは https://k8s.dev/ という専用のウェブサイトを作成しました。 +Kubernetesへの貢献についてもっと学ぶために、参照することができます。 -また、Kubernetesへの貢献については、{{< glossary_tooltip text="CNCF" term_id="cncf" >}}の[ページ](https://contribute.cncf.io/contributors/projects/#kubernetes)を参照することもできます。 -{{< /note >}} - ---- - -このウェブサイトは[Kubernetes SIG Docs](/docs/contribute/#get-involved-with-sig-docs)が管理しています。 - -Kubernetesドキュメントコントリビューターは - -- 既存のコンテンツを改善します -- 新しいコンテンツを作成します -- ドキュメントを翻訳します -- Kubernetesリリースサイクルの一部としてドキュメントを管理・公開します - - - -## はじめに - -どなたでも、問題を説明するissueや、ドキュメントの改善を求めるissueを作成し、[`kubernetes/website` GitHub リポジトリ](https://github.com/kubernetes/website)に対するプルリクエスト(PR)を用いて変更に貢献することができます。 -Kubernetesコミュニティで効果的に働くためには、[git](https://git-scm.com/)と[GitHub](https://skills.github.com/)を基本的に使いこなせる必要があります。 - -ドキュメンテーションに関わるには: - -1. CNCFの[Contributor License Agreement](https://github.com/kubernetes/community/blob/master/CLA.md)にサインしてください。 -2. [ドキュメンテーションのリポジトリー](https://github.com/kubernetes/website)と、ウェブサイトの[静的サイトジェネレーター](https://gohugo.io)に慣れ親しんでください。 -3. [プルリクエストのオープン](/docs/contribute/new-content/open-a-pr/)と[変更レビュー](/ja/docs/contribute/review/reviewing-prs/)の基本的なプロセスを理解していることを確認してください。 - - - - -{{< mermaid >}} -flowchart TB -subgraph third[プルリクエストのオープン] -direction TB -U[ ] -.- -Q[コンテンツを改善する] --- N[コンテンツを作成する] -N --- O[ドキュメントを翻訳する] -O --- P[k8sリリースサイクルの
            ドキュメントを管理する] - -end - -subgraph second[レビュー] -direction TB - T[ ] -.- - D[kubernetes/website
            リポジトリを確認する] --- E[静的サイトジェネレータ
            Hugoを確認する] - E --- F[基本的なGitHubの
            コマンドを理解する] - F --- G[オープンした
            プルリクエストを確認し
            レビュープロセスを見直す] -end - -subgraph first[サインアップ] - direction TB - S[ ] -.- - B[CNCFの
            貢献者ライセンス
            契約に署名する] --- C[Slackチャンネル
            sig-docs に
            参加する] - C --- V[kubernetes-sig-docsの
            メーリングリストに
            参加する] - V --- M[毎週開催している
            sig-docs callsや
            slack callsに
            参加する] -end - -A([fa:fa-user 新たな
            貢献者]) --> first -A --> second -A --> third -A --> H[質問をする!!!] - - -classDef grey fill:#dddddd,stroke:#ffffff,stroke-width:px,color:#000000, font-size:15px; -classDef white fill:#ffffff,stroke:#000,stroke-width:px,color:#000,font-weight:bold -classDef spacewhite fill:#ffffff,stroke:#fff,stroke-width:0px,color:#000 -class A,B,C,D,E,F,G,H,M,Q,N,O,P,V grey -class S,T,U spacewhite -class first,second,third white -{{}} -図1. 新たな貢献者のためのスタートガイド。 - -図1は新たな貢献者のためのロードマップを概説しています。`サインアップ`や`レビュー`のステップのいくつか、またはその全てに従えばよいです。これで、`プルリクエストのオープン`の下にリストされているいくつかの貢献目標を達成するためのプルリクエストを開く準備が整いました。また、質問はいつでも歓迎です! +もし _この_ ドキュメントへの貢献について特に学びたい場合は、[Kubernetesドキュメントへの貢献](/ja/docs/contribute/docs/)を参照してください。 -一部のタスクでは、Kubernetes organizationで、より多くの信頼とアクセス権限が必要です。 -役割と権限についての詳細は、[SIG Docsへの参加](/ja/docs/contribute/participate/)を参照してください。 - -## はじめての貢献 - -あらかじめいくつかのステップを見直すことで、最初の貢献に備えることができます。図2はそれらのステップの概説で、詳細は次のとおりです。 - - - - -{{< mermaid >}} -flowchart LR - subgraph second[はじめての貢献] - direction TB - S[ ] -.- - G[K8sメンバーからの
            PRレビューを受ける] --> - A[最初のPRを作成するための
            良いissueを
            kubernetes/websiteから探す] --> B[PRをオープンする!!] - end - subgraph first[推奨される準備] - direction TB - T[ ] -.- - D[貢献者の概要を読む] -->E[K8sのコンテンツと
            スタイルガイドを読む] - E --> F[Hugoのページコンテンツタイプと
            ショートコードについて学ぶ] - end - - - first ----> second - - -classDef grey fill:#dddddd,stroke:#ffffff,stroke-width:px,color:#000000, font-size:15px; -classDef white fill:#ffffff,stroke:#000,stroke-width:px,color:#000,font-weight:bold -classDef spacewhite fill:#ffffff,stroke:#fff,stroke-width:0px,color:#000 -class A,B,D,E,F,G grey -class S,T spacewhite -class first,second white -{{}} -図2. はじめての貢献のための準備。 - -- 貢献のための複数の方法について学ぶために[貢献の概要](/ja/docs/contribute/new-content/overview/)を読んでください。 -- 良い開始地点を探すために[`kubernetes/website` issueリスト](https://github.com/kubernetes/website/issues/)を確認してください。 -- 既存のドキュメントに対して[GitHubを使ってプルリクエストをオープン](/docs/contribute/new-content/open-a-pr/#changes-using-github)し、GitHubへのissueの登録について学んでください。 -- 正確さと言語の校正のため、他のKubernetesコミュニティメンバーから[プルリクエストのレビュー](/docs/contribute/review/reviewing-prs/)を受けてください。 -- 見識のあるコメントを残せるようにするため、Kubernetesの[コンテンツ](/ja/docs/contribute/style/content-guide/)と[スタイルガイド](/docs/contribute/style/style-guide/)を読んでください。 -- [ページコンテンツの種類](/docs/contribute/style/page-content-types/)と[Hugoショートコード](/docs/contribute/style/hugo-shortcodes/)について勉強してください。 - -## 貢献時の支援の受け方 - -はじめて貢献を行うのは大変なことかもしれません。[新規貢献者のためのアンバサダー](https://github.com/kubernetes/website#new-contributor-ambassadors)は、最初の数回の貢献を行う手助けをしてくれます。[Kubernetes Slack](https://slack.k8s.io/)で、特に`#sig-docs`チャンネルを用いて連絡を取ることができます。また毎月第一火曜日に行われる[新規貢献者のための歓迎会](https://www.kubernetes.dev/resources/calendar/)もあります。ここで新規貢献者のアンバサダーと交流し、質問に答えてもらうことができます。 - -## 次のステップ - -- リポジトリの[ローカルクローンでの作業](/docs/contribute/new-content/open-a-pr/#fork-the-repo)について学んでください。 -- [リリース機能](/docs/contribute/new-content/new-features/)について記載してください。 -- [SIG Docs](/ja/docs/contribute/participate/)に参加し、[memberやreviewer](/docs/contribute/participate/roles-and-responsibilities/)になってください。 -- [国際化](/ja/docs/contribute/localization/)を始めたり、支援したりしてください。 - -## SIG Docsに参加する - -[SIG Docs](/ja/docs/contribute/participate/)はKubernetesのドキュメントとウェブサイトを公開・管理するコントリビューターのグループです。SIG Docsに参加することはKubernetesコントリビューター(機能開発でもそれ以外でも)にとってKubernetesプロジェクトに大きな影響を与える素晴らしい方法の一つです。 - -SIG Docsは複数の方法でコミュニケーションをとっています。 - -- [Kubernetes Slackインスタンスの`#sig-docs`に参加してください](https://slack.k8s.io/)。自己紹介を忘れずに! -- [`kubernetes-sig-docs`メーリングリストに参加してください](https://groups.google.com/forum/#!forum/kubernetes-sig-docs)。ここでは幅広い議論が起こり、公式な決定が記録されます。 -- [毎週のSIG Docsビデオミーティング](https://github.com/kubernetes/community/tree/master/sig-docs)に参加してください。ミーティングは `#sig-docs`でアナウンスされ、[Kubernetesコミュニティミーティングカレンダー](https://calendar.google.com/calendar/embed?src=cgnt364vd8s86hr2phapfjc6uk%40group.calendar.google.com&ctz=America/Los_Angeles)に追加されます。[Zoomクライアント](https://zoom.us/download)をダウンロードするか、電話を使って通話する必要があります。 - -## その他の貢献方法 - -- [Kubernetesコミュニティサイト](/community/)を訪問してください。TwitterやStack Overflowに参加したり、Kubernetesの集会やイベントについて学んだりしてください。 -- 機能開発に貢献したい方は、まずはじめに[Kubernetesコントリビューターチートシート](https://github.com/kubernetes/community/tree/master/contributors/guide/contributor-cheatsheet)を読んでください。 -- [Kubernetesの貢献者](https://www.kubernetes.dev/)や[追加の貢献者向けリソース](https://www.kubernetes.dev/resources/)についてもっと学ぶために、貢献者サイトを読んでください。 -- [ブログ記事やケーススタディ](/docs/contribute/new-content/blogs-case-studies/)を投稿してください。 +また、Kubernetesへの貢献については、{{< glossary_tooltip text="CNCF" term_id="cncf" >}}の[ページ](https://contribute.cncf.io/contributors/projects/#kubernetes)を参照することもできます。 diff --git a/content/ja/docs/contribute/docs.md b/content/ja/docs/contribute/docs.md new file mode 100644 index 0000000000000..503853685b57a --- /dev/null +++ b/content/ja/docs/contribute/docs.md @@ -0,0 +1,162 @@ +--- +content_type: concept +title: Kubernetesのドキュメントに貢献する +weight: 09 +card: + name: 貢献 + weight: 11 + title: Kubernetesのドキュメントに貢献する +--- + + +このウェブサイトは[Kubernetes SIG Docs](/docs/contribute/#get-involved-with-sig-docs)が管理しています。 +Kubernetesプロジェクトは初心者でも経験者でも、全てのコントリビューターからの改善を歓迎しています! + +Kubernetesドキュメントコントリビューターは + +- 既存のコンテンツを改善します +- 新しいコンテンツを作成します +- ドキュメントを翻訳します +- Kubernetesリリースサイクルの一部としてドキュメントを管理・公開します + +--- + +{{< note >}} +Kubernetesへの貢献について総合的に知りたい場合は、[contributor documentation](https://www.kubernetes.dev/docs/)を参照してください。 +{{< /note >}} + + + +## はじめに + +どなたでも、問題を説明するissueや、ドキュメントの改善を求めるissueを作成し、[`kubernetes/website` GitHubリポジトリ](https://github.com/kubernetes/website)に対するプルリクエスト(PR)を用いて変更に貢献することができます。 +Kubernetesコミュニティで効果的に働くためには、[git](https://git-scm.com/)と[GitHub](https://skills.github.com/)を基本的に使いこなせる必要があります。 + +ドキュメンテーションに関わるには: + +1. CNCFの[Contributor License Agreement](https://github.com/kubernetes/community/blob/master/CLA.md)にサインしてください。 +2. [ドキュメンテーションのリポジトリ](https://github.com/kubernetes/website)と、ウェブサイトの[静的サイトジェネレーター](https://gohugo.io)に慣れ親しんでください。 +3. [プルリクエストのオープン](/docs/contribute/new-content/open-a-pr/)と[変更レビュー](/ja/docs/contribute/review/reviewing-prs/)の基本的なプロセスを理解していることを確認してください。 + + + + +{{< mermaid >}} +flowchart TB +subgraph third[プルリクエストのオープン] +direction TB +U[ ] -.- +Q[コンテンツを改善する] --- N[コンテンツを作成する] +N --- O[ドキュメントを翻訳する] +O --- P[k8sリリースサイクルの
            ドキュメントを管理する] + +end + +subgraph second[レビュー] +direction TB + T[ ] -.- + D[kubernetes/website
            リポジトリを確認する] --- E[静的サイトジェネレーター
            Hugoを確認する] + E --- F[基本的なGitHubの
            コマンドを理解する] + F --- G[オープンした
            プルリクエストを確認し
            レビュープロセスを見直す] +end + +subgraph first[サインアップ] + direction TB + S[ ] -.- + B[CNCFの
            コントリビューターライセンス
            サインに署名する] --- C[Slackチャンネル
            sig-docs に
            参加する] + C --- V[kubernetes-sig-docsの
            メーリングリストに
            参加する] + V --- M[毎週開催している
            sig-docs callsや
            slack callsに
            参加する] +end + +A([fa:fa-user 新たな
            コントリビューター]) --> first +A --> second +A --> third +A --> H[質問をする!!!] + + +classDef grey fill:#dddddd,stroke:#ffffff,stroke-width:px,color:#000000, font-size:15px; +classDef white fill:#ffffff,stroke:#000,stroke-width:px,color:#000,font-weight:bold +classDef spacewhite fill:#ffffff,stroke:#fff,stroke-width:0px,color:#000 +class A,B,C,D,E,F,G,H,M,Q,N,O,P,V grey +class S,T,U spacewhite +class first,second,third white +{{}} +図1. 新たなコントリビューターのためのスタートガイド。 + +図1は新たなコントリビューターのためのロードマップを概説しています。`サインアップ`や`レビュー`のステップのいくつか、またはその全てに従えばよいです。これで、`プルリクエストのオープン`の下にリストされているいくつかの貢献目標を達成するためのプルリクエストを開く準備が整いました。また、質問はいつでも歓迎です! + +一部のタスクでは、Kubernetes organizationで、より多くの信頼とアクセス権限が必要です。 +役割と権限についての詳細は、[SIG Docsへの参加](/ja/docs/contribute/participate/)を参照してください。 + +## はじめての貢献 + +あらかじめいくつかのステップを見直すことで、最初の貢献に備えることができます。図2はそれらのステップの概説で、詳細は次のとおりです。 + + + + +{{< mermaid >}} +flowchart LR + subgraph second[はじめての貢献] + direction TB + S[ ] -.- + G[K8sメンバーからの
            PRレビューを受ける] --> + A[最初のPRを作成するための
            良いissueを
            kubernetes/websiteから探す] --> B[PRをオープンする!!] + end + subgraph first[推奨される準備] + direction TB + T[ ] -.- + D[コントリビューターの概要を読む] -->E[K8sのコンテンツと
            スタイルガイドを読む] + E --> F[Hugoのページコンテンツタイプと
            ショートコードについて学ぶ] + end + + + first ----> second + + +classDef grey fill:#dddddd,stroke:#ffffff,stroke-width:px,color:#000000, font-size:15px; +classDef white fill:#ffffff,stroke:#000,stroke-width:px,color:#000,font-weight:bold +classDef spacewhite fill:#ffffff,stroke:#fff,stroke-width:0px,color:#000 +class A,B,D,E,F,G grey +class S,T spacewhite +class first,second white +{{}} +図2. はじめての貢献のための準備。 + +- 貢献のための複数の方法について学ぶために[貢献の概要](/ja/docs/contribute/new-content/)を読んでください。 +- 良い開始地点を探すために[`kubernetes/website` のissueリスト](https://github.com/kubernetes/website/issues/)を確認してください。 +- 既存のドキュメントに対して[GitHubを使ってプルリクエストを作成](/docs/contribute/new-content/open-a-pr/#changes-using-github)し、GitHubへのissueの登録について学んでください。 +- 正確さと言語の校正のため、他のKubernetesコミュニティメンバーから[プルリクエストのレビュー](/docs/contribute/review/reviewing-prs/)を受けてください。 +- 見識のあるコメントを残せるようにするため、Kubernetesの[コンテンツ](/ja/docs/contribute/style/content-guide/)と[スタイルガイド](/docs/contribute/style/style-guide/)を読んでください。 +- [ページコンテンツの種類](/docs/contribute/style/page-content-types/)と[Hugoショートコード](/docs/contribute/style/hugo-shortcodes/)について勉強してください。 + +## 貢献時の支援の受け方 + +はじめて貢献を行うのは大変なことかもしれません。[新規コントリビューターのためのアンバサダー](https://github.com/kubernetes/website#new-contributor-ambassadors)は、最初の数回の貢献を行う手助けをしてくれます。[Kubernetes Slack](https://slack.k8s.io/)で、特に`#sig-docs`チャンネルを用いて連絡を取ることができます。また毎月第一火曜日に行われる[新規コントリビューターのための歓迎会](https://www.kubernetes.dev/resources/calendar/)もあります。ここで新規コントリビューターのアンバサダーと交流し、質問に答えてもらうことができます。 + +訳注: 日本語ローカライゼーションに関しては、Slackの`kubernetes-docs-ja`チャンネルを利用してください。 + +## 次のステップ + +- リポジトリの[ローカルクローンでの作業](/docs/contribute/new-content/open-a-pr/#fork-the-repo)について学んでください。 +- [リリース機能](/docs/contribute/new-content/new-features/)について記載してください。 +- [SIG Docs](/ja/docs/contribute/participate/)に参加し、[memberやreviewer](/docs/contribute/participate/roles-and-responsibilities/)になってください。 +- [国際化](/ja/docs/contribute/localization/)を始めたり、支援したりしてください。 + +## SIG Docsに参加する + +[SIG Docs](/ja/docs/contribute/participate/)はKubernetesのドキュメントとウェブサイトを公開・管理するコントリビューターのグループです。SIG Docsに参加することはKubernetesコントリビューター(機能開発でもそれ以外でも)にとってKubernetesプロジェクトに大きな影響を与える素晴らしい方法の一つです。 + +SIG Docsは複数の方法でコミュニケーションをとっています。 + +- [Kubernetes Slackインスタンスの`#sig-docs`に参加してください](https://slack.k8s.io/)。自己紹介を忘れずに! + - 訳注: 日本語ローカライゼーションに関しては、Slackの`kubernetes-docs-ja`チャンネルを利用してください。 +- [`kubernetes-sig-docs`メーリングリストに参加してください](https://groups.google.com/forum/#!forum/kubernetes-sig-docs)。ここでは幅広い議論が起こり、公式な決定が記録されます。 +- [毎週のSIG Docsビデオミーティング](https://github.com/kubernetes/community/tree/master/sig-docs)に参加してください。ミーティングは `#sig-docs`でアナウンスされ、[Kubernetesコミュニティミーティングカレンダー](https://calendar.google.com/calendar/embed?src=cgnt364vd8s86hr2phapfjc6uk%40group.calendar.google.com&ctz=America/Los_Angeles)に追加されます。[Zoomクライアント](https://zoom.us/download)をダウンロードするか、電話を使って通話する必要があります。 + +## その他の貢献方法 + +- [Kubernetesコミュニティサイト](/community/)を訪問してください。TwitterやStack Overflowに参加したり、Kubernetesの集会やイベントについて学んだりしてください。 +- 機能開発に貢献したい方は、まずはじめに[Kubernetesコントリビューターチートシート](https://github.com/kubernetes/community/blob/master/contributors/guide/contributor-cheatsheet/README-ja.md)を読んでください。 +- [Kubernetesのコントリビューター](https://www.kubernetes.dev/)や[追加のコントリビューター向けリソース](https://www.kubernetes.dev/resources/)についてもっと学ぶために、コントリビューターサイトを読んでください。 +- [ブログ記事やケーススタディ](/docs/contribute/new-content/blogs-case-studies/)を投稿してください。 diff --git a/content/ja/docs/contribute/localization.md b/content/ja/docs/contribute/localization.md index c97e48d52242c..649ae5065f42f 100644 --- a/content/ja/docs/contribute/localization.md +++ b/content/ja/docs/contribute/localization.md @@ -14,19 +14,19 @@ card: -## ドキュメントを日本語に翻訳するまでの流れ +## ドキュメントを日本語に翻訳するまでの流れ {#translate-flow} 翻訳を行うための基本的な流れについて説明します。不明点がある場合は[Kubernetes公式Slack](http://slack.kubernetes.io/)の`#kubernetes-docs-ja`チャンネルにてお気軽にご質問ください。 -### 前提知識 +### 前提知識 {#prerequisite} 翻訳作業は全て[GitHubのIssue](https://github.com/kubernetes/website/issues?q=is%3Aissue+is%3Aopen+label%3Alanguage%2Fja)によって管理されています。翻訳作業を行いたい場合は、Issueの一覧をまず最初にご確認ください。 また、Kubernetes傘下のリポジトリでは`CLA`と呼ばれる同意書に署名しないと、Pull Requestをマージすることができません。詳しくは[英語のドキュメント](https://github.com/kubernetes/community/blob/master/CLA.md)や、[Qiitaに有志の方が書いてくださった日本語のまとめ](https://qiita.com/jlandowner/items/d14d9bc8797a62b65e67)をご覧ください。 -### 翻訳を始めるまで +### 翻訳を始めるまで {#start-translation} -#### 翻訳を希望するページのIssueが存在しない場合 +#### 翻訳を希望するページのIssueが存在しない場合 {#no-issue} 1. [こちらのサンプル](https://github.com/kubernetes/website/issues/22340)に従う形でIssueを作成する 2. 自分自身を翻訳作業に割り当てたい場合は、Issueのメッセージまたはコメントに`/assign`と書く @@ -34,12 +34,12 @@ card: **不明点がある場合は[Kubernetes公式Slack](http://slack.kubernetes.io/)の`#kubernetes-docs-ja`チャンネルにてお気軽にご質問ください。** -#### 翻訳を希望するページのIssueが存在する場合 +#### 翻訳を希望するページのIssueが存在する場合 {#exist-issue} 1. 自分自身を翻訳作業に割り当てるために、Issueのコメントに`/assign`と書く 2. [新規ページを翻訳する場合](#translate-new-page)のステップに進む -### Pull Requestを送るまで +### Pull Requestを送るまで {#create-pull-request} #### 新規ページを翻訳する場合の手順 {#translate-new-page} @@ -48,95 +48,82 @@ card: 3. `content/en`のディレクトリから必要なファイルを`content/ja`にコピーし、翻訳する 4. `main`ブランチに向けてPull Requestを作成する -#### 既存のページの誤字脱字や古い記述を修正する場合の手順 +#### 既存のページの誤字脱字や古い記述を修正する場合の手順 {#fix-existing-page} 1. `kubernetes/website`リポジトリをフォークする 2. `main`から任意の名前でブランチを作成する 3. `content/ja`のディレクトリから必要なファイルを編集する 4. `main`ブランチに向けてPull Requestを作成する -## 翻訳スタイルガイド +## 翻訳スタイルガイド {#style-guide} -### 基本方針 +### 基本方針 {#basic-policy} -- 本文を、敬体(ですます調)で統一 +- 本文を、敬体(ですます調)で統一 - 特に、「〜になります」「〜となります」という表現は「〜です」の方が適切な場合が多いため注意 - 句読点は「、」と「。」を使用 - 漢字、ひらがな、カタカナは全角で表記 - 数字とアルファベットは半角で表記 -- スペースと括弧 `()` 、コロン `:` は半角、それ以外の記号類は全角で表記 +- 記号類は感嘆符「!」と疑問符「?」のみ全角、それ以外は半角で表記 - 英単語と日本語の間に半角スペースは不要 +- 日本語文では、文章の途中で改行を行わない。句点「。」で改行する +- メタデータの`reviewer`の項目は削除する +- すでに日本語訳が存在するページにリンクを張る場合は、`/ja/`を含めたURLを使用する + - 例: `/path/to/page/`ではなく、`/ja/path/to/page/`を使用する -### 頻出単語 +### 用語の表記 {#terminology} -英語 | 日本語 ---------- | --------- -Addon/Add-on|アドオン -Aggregation Layer | アグリゲーションレイヤー -architecture | アーキテクチャ -binary | バイナリ -cluster|クラスター -community | コミュニティ -container | コンテナ -controller | コントローラー -Deployment/Deploy|KubernetesリソースとしてのDeploymentはママ表記、一般的な用語としてのdeployの場合は、デプロイ -directory | ディレクトリ -For more information|さらなる情報(一時的) -GitHub | GitHub (ママ表記) -Issue | Issue (ママ表記) -operator | オペレーター -orchestrate(動詞)|オーケストレーションする -Persistent Volume|KubernetesリソースとしてのPersistentVolumeはママ表記、一般的な用語としての場合は、永続ボリューム -prefix | プレフィックス -Pull Request | Pull Request (ママ表記) -Quota|クォータ -registry | レジストリ -secure | セキュア -a set of ~ | ~の集合 -stacked | 積層(例: stacked etcd clusterは積層etcdクラスター) - -### 備考 - -ServiceやDeploymentなどのKubernetesのAPIオブジェクトや技術仕様的な固有名詞は、無理に日本語訳せずそのまま書いてください。 - -また、日本語では名詞を複数形にする意味はあまりないので、英語の名詞を利用する場合は原則として単数形で表現してください。 - -例: - -- Kubernetes Service -- Node -- Pod - -外部サイトへの参照の記事タイトルは翻訳しましょう。(一時的) - -### 頻出表記(日本語) +Kubernetesのリソース名や技術用語などは、原則としてそのままの表記を使用します。 +例えば、PodやService、Deploymentなどは翻訳せずにそのまま表記してください。 + +ただし、ノード(Node)に関しては明確にKubernetesとしてのNodeリソース(例: `kind: Node`や`kubectl get nodes`)を指していないのであれば、「ノード」と表記してください。 + +またこれらの単語は、複数形ではなく単数形を用います。 +例えば、原文に"pods"と表記されている場合でも、日本語訳では"Pod"と表記してください。 + +### 頻出表記(日本語) {#frequent-phrases} よくある表記 | あるべき形 --------- | --------- 〜ので、〜から、〜だから| 〜のため 、〜ため -(あいうえお。)| (あいうえお)。 -〇,〇,〇|〇、〇、〇(※今回列挙はすべて読点で統一) +(あいうえお。)| (あいうえお)。 +〇,〇,〇|〇、〇、〇(※列挙はすべて読点で統一) + +### 長音の有無 {#long-vowel} -### 単語末尾に長音記号(「ー」)を付けるかどうか +カタカナ語に長音を付与するかどうかは、以下の原則に従ってください。 -「サーバー」「ユーザー」など英単語をカタカナに訳すときに、末尾の「ー」を付けるかどうか。 +- -er、-or、-ar、-cy、-gyで終わる単語は長音を付与する + - 例: 「クラスター」「セレクター」「サイドカー」「ポリシー」「トポロジー」 +- -ear、-eer、-re、-ty、-dy、-ryで終わる単語は長音を付与しない + - 例: 「クリア」「エンジニア」「アーキテクチャ」「セキュリティ」「スタディ」「ディレクトリ」 -- 「r」「re」「y」などで終わる単語については、原則付ける -- 上の頻出語のように、別途まとめたものは例外とする +ただし、「コンテナ」は例外的に長音を付与しないこととします。 -参考: https://kubernetes.slack.com/archives/CAG2M83S8/p1554096635015200 辺りのやりとり +この原則を作成するにあたって、[mozilla-japan/translation Editorial Guideline#カタカナ語の表記](https://github.com/mozilla-japan/translation/wiki/Editorial-Guideline#カタカナ語の表記)を参考にしました。 + +### その他の表記 {#other-notation} + +その他の表記については、以下の表を参考にしてください。 + +英語 | 日本語 +--------- | --------- +interface | インターフェース +proxy | プロキシ +quota|クォータ +stacked | 積層 -### cron jobの訳し方に関して +### cron jobの訳し方に関して {#cron-job} -混同を避けるため、cron jobはcronジョブと訳し、CronJobはリソース名としてのままにする。 -cron「の」ジョブは、「の」が続く事による解釈の難から基本的にはつけないものとする。 +混同を避けるため、cron jobはcronジョブと訳し、CronJobはリソース名としてそのまま表記します。 +cron「の」ジョブは、「の」が続く事による解釈の難から基本的にはつけないものとします。 -### その他基本方針など +### その他基本方針など {#other-basic-policy} - 意訳と直訳で迷った場合は「直訳」で訳す -- 訳で難しい・わからないと感じたらSlackの#kubernetes-docs-jaでみんなに聞く +- 訳で難しい・わからないと感じたらSlackの`#kubernetes-docs-ja`で相談する - できることを挙手制で、できないときは早めに報告 -## アップストリームのコントリビューター +## アップストリームのコントリビューター {#upstream-contributor} SIG Docsでは、英語のソースに対する[アップストリームへのコントリビュートや誤りの訂正](/docs/contribute/intermediate#localize-content)を歓迎しています。 diff --git a/content/ja/docs/home/_index.md b/content/ja/docs/home/_index.md index 610a35ea644f4..a8e47d0fbb370 100644 --- a/content/ja/docs/home/_index.md +++ b/content/ja/docs/home/_index.md @@ -47,9 +47,9 @@ cards: button_path: /docs/reference - name: contribute title: "ドキュメントにコントリビュートする" - description: "プロジェクトに不慣れでも、長い間関わっていたとしても、誰でもコントリビュートすることができます。" - button: "ドキュメントにコントリビュートする" - button_path: /docs/contribute + description: "Kubernetesをより良いものにするために、どのような貢献ができるかを見てみます。" + button: "貢献する方法を見る" + button_path: "/docs/contribute" - name: training title: "トレーニング" description: "Kubernetesの資格を取得して、クラウドネイティブプロジェクトを成功させます!" diff --git a/content/ja/docs/reference/access-authn-authz/authentication.md b/content/ja/docs/reference/access-authn-authz/authentication.md index c1cd132e56f15..3533f1814f8f5 100644 --- a/content/ja/docs/reference/access-authn-authz/authentication.md +++ b/content/ja/docs/reference/access-authn-authz/authentication.md @@ -29,7 +29,7 @@ APIリクエストは、通常のユーザーかサービスアカウントに ## 認証戦略 -Kubernetesは、クライアント証明書、Bearerトークン、認証プロキシー、HTTP Basic認証を使い、認証プラグインを通してAPIリクエストを認証します。APIサーバーにHTTPリクエストが送信されると、プラグインは以下の属性をリクエストに関連付けようとします。 +Kubernetesは、クライアント証明書、Bearerトークン、認証プロキシ、HTTP Basic認証を使い、認証プラグインを通してAPIリクエストを認証します。APIサーバーにHTTPリクエストが送信されると、プラグインは以下の属性をリクエストに関連付けようとします。 * ユーザー名: エンドユーザーを識別する文字列です。一般的にな値は、`kube-admin`や`jane@example.com`です。 * UID: エンドユーザーを識別する文字列であり、ユーザー名よりも一貫性と一意性を持たせようとするものです。 @@ -48,7 +48,7 @@ Kubernetesは、クライアント証明書、Bearerトークン、認証プロ `system:authenticated`グループには、すべての認証済みユーザーのグループのリストが含まれます。 -他の認証プロトコル(LDAP、SAML、Kerberos、X509スキームなど)との統合は、[認証プロキシー](#authenticating-proxy)や[認証Webhook](#webhook-token-authentication)を使用して実施できます。 +他の認証プロトコル(LDAP、SAML、Kerberos、X509スキームなど)との統合は、[認証プロキシ](#authenticating-proxy)や[認証Webhook](#webhook-token-authentication)を使用して実施できます。 ### X509クライアント証明書 @@ -211,7 +211,7 @@ Secretは常にbase64でエンコードされるため、これらの値もbase6 1. Kubernetesには、認証プロセスを起動するための"Webインターフェース"がありません。クレデンシャルを収集するためのブラウザやインターフェースがないため、まずIDプロバイダに認証を行う必要があります。 2. `id_token`は、取り消すことができません。これは証明書のようなもので、有効期限が短い(数分のみ)必要があるので、数分ごとに新しいトークンを取得しなければならないのは非常に面倒です。 -3. Kubernetesダッシュボードへの認証において、`kubectl proxy`コマンドや`id_token`を注入するリバースプロキシーを使う以外に、簡単な方法はありません。 +3. Kubernetesダッシュボードへの認証において、`kubectl proxy`コマンドや`id_token`を注入するリバースプロキシを使う以外に、簡単な方法はありません。 #### APIサーバーの設定 @@ -402,10 +402,10 @@ POSTボディは、以下の形式になります。 HTTPステータスコードは、追加のエラーコンテキストを提供するために使うことができます。 -### 認証プロキシー {#authenticating-proxy} +### 認証プロキシ {#authenticating-proxy} APIサーバーは、`X-Remote-User`のようにリクエストヘッダの値からユーザーを識別するように設定することができます。 -これは、リクエストヘッダの値を設定する認証プロキシーと組み合わせて使用するために設計です。 +これは、リクエストヘッダの値を設定する認証プロキシと組み合わせて使用するために設計です。 * `--requestheader-username-headers`: 必須であり、大文字小文字を区別しません。ユーザーのIDをチェックするためのヘッダー名を順番に指定します。値を含む最初のヘッダーが、ユーザー名として使われます。 * `--requestheader-group-headers`: バージョン1.6以降で任意であり、大文字小文字を区別しません。"X-Remote-Group"を推奨します。ユーザーのグループをチェックするためのヘッダー名を順番に指定します。指定されたヘッダーの全ての値が、グループ名として使われます。 @@ -450,7 +450,7 @@ extra: - profile ``` -ヘッダーのスプーフィングを防ぐため、認証プロキシーはリクエストヘッダーがチェックされる前に、指定された認証局に対する検証のために有効なクライアント証明書をAPIサーバーへ提示する必要があります。 +ヘッダーのスプーフィングを防ぐため、認証プロキシはリクエストヘッダーがチェックされる前に、指定された認証局に対する検証のために有効なクライアント証明書をAPIサーバーへ提示する必要があります。 * `--requestheader-client-ca-file`: 必須です。PEMエンコードされた証明書バンドルです。有効なクライアント証明書を提示し、リクエストヘッダーでユーザー名がチェックされる前に、指定されたファイル内の認証局に対して検証する必要があります。 diff --git a/content/ja/docs/reference/command-line-tools-reference/feature-gates/index.md b/content/ja/docs/reference/command-line-tools-reference/feature-gates/index.md index d833d8def5e7c..1d9f9723854ef 100644 --- a/content/ja/docs/reference/command-line-tools-reference/feature-gates/index.md +++ b/content/ja/docs/reference/command-line-tools-reference/feature-gates/index.md @@ -444,7 +444,7 @@ GAになってからさらなる変更を加えることは現実的ではない - `StorageObjectInUseProtection`: PersistentVolumeまたはPersistentVolumeClaimオブジェクトがまだ使用されている場合、それらの削除を延期します。 - `StorageVersionHash`: apiserversがディスカバリーでストレージのバージョンハッシュを公開できるようにします。 - `StreamingProxyRedirects`: ストリーミングリクエストのバックエンド(kubelet)からのリダイレクトをインターセプト(およびフォロー)するようAPIサーバーに指示します。ストリーミングリクエストの例には`exec`、`attach`、`port-forward`リクエストが含まれます。 -- `SupportIPVSProxyMode`: IPVSを使用したクラスター内サービスの負荷分散の提供を有効にします。詳細は[サービスプロキシー](/ja/docs/concepts/services-networking/service/#virtual-ips-and-service-proxies)で確認できます。 +- `SupportIPVSProxyMode`: IPVSを使用したクラスター内サービスの負荷分散の提供を有効にします。詳細は[サービスプロキシ](/ja/docs/concepts/services-networking/service/#virtual-ips-and-service-proxies)で確認できます。 - `SupportPodPidsLimit`: PodのPID制限のサポートを有効にします。 - `Sysctls`: 各Podに設定できる名前空間付きのカーネルパラメーター(sysctl)のサポートを有効にします。詳細は[sysctls](/docs/tasks/administer-cluster/sysctl-cluster/)で確認できます。 - `TaintBasedEvictions`: ノードのTaintとPodのTolerationに基づいてノードからPodを排除できるようにします。。詳細は[TaintとToleration](/docs/concepts/scheduling-eviction/taint-and-toleration/)で確認できます。 diff --git a/content/ja/docs/reference/glossary/cadvisor.md b/content/ja/docs/reference/glossary/cadvisor.md new file mode 100644 index 0000000000000..7c4670bed2ac9 --- /dev/null +++ b/content/ja/docs/reference/glossary/cadvisor.md @@ -0,0 +1,16 @@ +--- +title: cAdvisor +id: cadvisor +date: 2021-12-09 +full_link: https://github.com/google/cadvisor/ +short_description: > + コンテナのリソース使用量とパフォーマンス特性を理解するためのツール +aka: +tags: +- tool +--- +cAdvisor(Container Advisor)は、コンテナユーザーに実行中の{{< glossary_tooltip text="コンテナ" term_id="container" >}}のリソース使用量とパフォーマンス特性を理解させることができます。 + + + +これは、実行中のコンテナに関する情報を収集、集約、処理、エクスポートするデーモンです。具体的には、コンテナごとにリソース分離パラメーター、リソース使用量の履歴、完全なリソース使用量の履歴のヒストグラム、およびネットワーク統計を保持します。このデータは、コンテナごととマシン全体でエクスポートされます。 diff --git a/content/ja/docs/reference/glossary/certificate.md b/content/ja/docs/reference/glossary/certificate.md new file mode 100644 index 0000000000000..2c72009eb764f --- /dev/null +++ b/content/ja/docs/reference/glossary/certificate.md @@ -0,0 +1,17 @@ +--- +title: 証明書 +id: certificate +date: 2018-04-12 +full_link: /docs/tasks/tls/managing-tls-in-a-cluster/ +short_description: > + Kubernetesクラスターへのアクセスを検証するために使用される暗号化されたセキュアなファイル。 + +aka: +tags: +- security +--- + Kubernetesクラスターへのアクセスを検証するために使用される暗号化されたセキュアなファイル。 + + + +証明書により、Kubernetesクラスター内のアプリケーションがKubernetes APIに安全にアクセスできるようになります。証明書は、クライアントがAPIへのアクセスを許可されていることを検証します。 diff --git a/content/ja/docs/reference/glossary/cgroup.md b/content/ja/docs/reference/glossary/cgroup.md new file mode 100644 index 0000000000000..cd523615b6799 --- /dev/null +++ b/content/ja/docs/reference/glossary/cgroup.md @@ -0,0 +1,17 @@ +--- +title: cgroup (control group) +id: cgroup +date: 2019-06-25 +full_link: +short_description: > + リソースの分離、使用状況の監視、制限を行うLinuxプロセスのグループ。 + +aka: +tags: +- fundamental +--- +リソースの分離、使用状況の監視、制限を行うLinuxプロセスのグループ。 + + + +cgroupはLinuxカーネルの機能であり、一連のプロセスに対して、リソース使用量(CPU、メモリー、ディスクI/O、ネットワーク)を制限、監視、分離するものです。 diff --git a/content/ja/docs/reference/glossary/cluster-architect.md b/content/ja/docs/reference/glossary/cluster-architect.md new file mode 100644 index 0000000000000..f168e1fc6b1b4 --- /dev/null +++ b/content/ja/docs/reference/glossary/cluster-architect.md @@ -0,0 +1,17 @@ +--- +title: クラスターアーキテクト +id: cluster-architect +date: 2018-04-12 +full_link: +short_description: > + 一つ以上のKubernetesクラスターで構成されるインフラストラクチャーを設計する人。 + +aka: +tags: +- user-type +--- + 一つ以上のKubernetesクラスターで構成されるインフラストラクチャーを設計する人。 + + + +クラスターアーキテクトは、高可用性やセキュリティといった、分散システムにおけるベストプラクティスに関心を持ちます。 diff --git a/content/ja/docs/reference/glossary/cluster-operations.md b/content/ja/docs/reference/glossary/cluster-operations.md new file mode 100644 index 0000000000000..7a4ddd2f80461 --- /dev/null +++ b/content/ja/docs/reference/glossary/cluster-operations.md @@ -0,0 +1,17 @@ +--- +title: クラスター管理 +id: cluster-operations +date: 2019-05-12 +full_link: +short_description: > + Kubernetesクラスターの管理に関連する作業です。 + +aka: +tags: +- operation +--- + Kubernetesクラスターの管理に関連する作業です。日々の運用管理とアップグレードの調整が含まれます。 + + + + クラスター管理作業の例は以下の通りです。クラスターをスケールするために新しいノードをデプロイすること、ソフトウェアのアップグレードを実行すること、セキュリティコントロールを実装すること、ストレージの追加または削除を行うこと、クラスターのネットワークを構成すること、クラスター全体のオブザーバビリティを管理すること、イベントに対応することです。 diff --git a/content/ja/docs/reference/glossary/cni.md b/content/ja/docs/reference/glossary/cni.md new file mode 100644 index 0000000000000..0cb941ee7d51b --- /dev/null +++ b/content/ja/docs/reference/glossary/cni.md @@ -0,0 +1,18 @@ +--- +title: コンテナネットワークインターフェース(CNI) +id: cni +date: 2018-05-25 +full_link: /ja/docs/concepts/extend-kubernetes/compute-storage-net/network-plugins/ +short_description: > + コンテナネットワークインターフェース(CNI)プラグインは、appc/CNI仕様に準拠したネットワークプラグインの一種です。 + + +aka: +tags: +- networking +--- + コンテナネットワークインターフェイス(CNI)プラグインは、appc/CNI仕様に準拠したネットワークプラグインの一種です。 + + + +* KubernetesとCNIについては、[**ネットワークプラグイン**](/docs/concepts/extend-kubernetes/compute-storage-net/network-plugins/)を参照してください。 diff --git a/content/ja/docs/reference/glossary/container-lifecycle-hooks.md b/content/ja/docs/reference/glossary/container-lifecycle-hooks.md new file mode 100644 index 0000000000000..59175762bedd0 --- /dev/null +++ b/content/ja/docs/reference/glossary/container-lifecycle-hooks.md @@ -0,0 +1,17 @@ +--- +title: コンテナライフサイクルフック +id: container-lifecycle-hooks +date: 2018-10-08 +full_link: /ja/docs/concepts/containers/container-lifecycle-hooks/ +short_description: > + ライフサイクルフックは、コンテナ管理のライフサイクルにおけるイベントを公開し、イベントが発生したときにユーザーがコードを実行できるようにします。 + +aka: +tags: +- extension +--- + ライフサイクルフックは、{{< glossary_tooltip text="コンテナ" term_id="container" >}}管理のライフサイクルにおけるイベントを公開し、イベントが発生したときにユーザーがコードを実行できるようにします。 + + + +コンテナには2つのフックが公開されています。PostStartはコンテナが作成された直後に実行され、PreStopはコンテナが終了する直前に呼ばれるブロッキングです。 diff --git a/content/ja/docs/reference/glossary/containerd.md b/content/ja/docs/reference/glossary/containerd.md new file mode 100644 index 0000000000000..0f2b4e9adaac1 --- /dev/null +++ b/content/ja/docs/reference/glossary/containerd.md @@ -0,0 +1,17 @@ +--- +title: containerd +id: containerd +date: 2019-05-14 +full_link: https://containerd.io/docs/ +short_description: > + シンプルさ、堅牢性、移植性を重視したコンテナランタイムです。 + +aka: +tags: +- tool +--- + シンプルさ、堅牢性、移植性を重視したコンテナランタイムです。 + + + +containerdはLinuxやWindows上でデーモンとして実行される{{< glossary_tooltip text="コンテナ" term_id="container" >}}ランタイムです。containerdはコンテナイメージの取得や保存、コンテナの実行、ネットワークアクセスの提供などを行います。 diff --git a/content/ja/docs/reference/glossary/control-plane.md b/content/ja/docs/reference/glossary/control-plane.md index 00fd3ab3e3da3..645f3d8254ef2 100644 --- a/content/ja/docs/reference/glossary/control-plane.md +++ b/content/ja/docs/reference/glossary/control-plane.md @@ -4,13 +4,13 @@ id: control-plane date: 2019-05-12 full_link: short_description: > - コンテナのライフサイクルを定義、展開、管理するためのAPIとインターフェイスを公開するコンテナオーケストレーションレイヤーです。 + コンテナのライフサイクルを定義、展開、管理するためのAPIとインターフェースを公開するコンテナオーケストレーションレイヤーです。 aka: tags: - fundamental --- - コンテナのライフサイクルを定義、展開、管理するためのAPIとインターフェイスを公開するコンテナオーケストレーションレイヤーです。 + コンテナのライフサイクルを定義、展開、管理するためのAPIとインターフェースを公開するコンテナオーケストレーションレイヤーです。 diff --git a/content/ja/docs/reference/glossary/csi.md b/content/ja/docs/reference/glossary/csi.md index f3dfd24442752..81046689fc300 100644 --- a/content/ja/docs/reference/glossary/csi.md +++ b/content/ja/docs/reference/glossary/csi.md @@ -1,17 +1,17 @@ --- -title: コンテナストレージインターフェイス(CSI) +title: コンテナストレージインターフェース(CSI) id: csi date: 2018-06-25 full_link: /docs/concepts/storage/volumes/#csi short_description: > - コンテナストレージインターフェイス(CSI)はストレージシステムをコンテナに公開するための標準インターフェイスを定義します。 + コンテナストレージインターフェース(CSI)はストレージシステムをコンテナに公開するための標準インターフェースを定義します。 aka: tags: - storage --- -コンテナストレージインターフェイス(CSI)はストレージシステムをコンテナに公開するための標準インターフェイスを定義します。 +コンテナストレージインターフェース(CSI)はストレージシステムをコンテナに公開するための標準インターフェースを定義します。 diff --git a/content/ja/docs/reference/kubectl/_index.md b/content/ja/docs/reference/kubectl/_index.md index 6d2f2d7a47c44..ce7a97423fdde 100644 --- a/content/ja/docs/reference/kubectl/_index.md +++ b/content/ja/docs/reference/kubectl/_index.md @@ -131,7 +131,7 @@ kubectl config set-context --current --namespace= `patch` | kubectl patch (-f FILENAME | TYPE NAME | TYPE/NAME) --patch PATCH [flags] | Strategic Merge Patchの処理を使用して、リソースの1つ以上のフィールドを更新します。 `plugin` | `kubectl plugin [flags] [options]` | プラグインと対話するためのユーティリティを提供します。 `port-forward` | `kubectl port-forward POD [LOCAL_PORT:]REMOTE_PORT [...[LOCAL_PORT_N:]REMOTE_PORT_N] [flags]` | 1つ以上のローカルポートを、Podに転送します。 -`proxy` | `kubectl proxy [--port=PORT] [--www=static-dir] [--www-prefix=prefix] [--api-prefix=prefix] [flags]` | Kubernetes APIサーバーへのプロキシーを実行します。 +`proxy` | `kubectl proxy [--port=PORT] [--www=static-dir] [--www-prefix=prefix] [--api-prefix=prefix] [flags]` | Kubernetes APIサーバーへのプロキシを実行します。 `replace` | `kubectl replace -f FILENAME` | ファイルや標準出力から、リソースを置き換えます。 `rollout` | `kubectl rollout SUBCOMMAND [options]` | リソースのロールアウトを管理します。有効なリソースには、Deployment、DaemonSetとStatefulSetが含まれます。 `run` | kubectl run NAME --image=image [--env="key=value"] [--port=port] [--dry-run=server|client|none] [--overrides=inline-json] [flags] | 指定したイメージを、クラスター上で実行します。 diff --git a/content/ja/docs/reference/node/kubelet-checkpoint-api.md b/content/ja/docs/reference/node/kubelet-checkpoint-api.md index 085b223f3ce43..1f6a05c77089f 100644 --- a/content/ja/docs/reference/node/kubelet-checkpoint-api.md +++ b/content/ja/docs/reference/node/kubelet-checkpoint-api.md @@ -26,7 +26,7 @@ weight: 10 指定したPodから指定したコンテナのチェックポイントを作成するようにkubeletに指示します。 -kubeletチェックポイントインターフェイスへのアクセスの制御方法についての詳細な情報は、[Kubelet authentication/authorization reference](/docs/reference/access-authn-authz/kubelet-authn-authz)を参照してください。 +kubeletチェックポイントインターフェースへのアクセスの制御方法についての詳細な情報は、[Kubelet authentication/authorization reference](/docs/reference/access-authn-authz/kubelet-authn-authz)を参照してください。 kubeletは基礎となる{{}}実装にチェックポイントをリクエストします。 チェックポイントリクエストでは、kubeletが`checkpoint---.tar`のようなチェックポイントアーカイブの名前を指定します。 diff --git a/content/ja/docs/reference/tools.md b/content/ja/docs/reference/tools.md index 09b757375b1cc..394c586a03bb3 100644 --- a/content/ja/docs/reference/tools.md +++ b/content/ja/docs/reference/tools.md @@ -17,7 +17,7 @@ Kubernetesには、Kubernetesシステムの操作に役立ついくつかの組 [`minikube`](https://minikube.sigs.k8s.io/docs/)は、開発やテストのためにワークステーション上でシングルノードのKubernetesクラスターをローカルで実行するツールです。 ## Dashboard -[`Dashboard`](/ja/docs/tasks/access-application-cluster/web-ui-dashboard/)は、KubernetesのWebベースのユーザインタフェースで、コンテナ化されたアプリケーションをKubernetesクラスターにデプロイしたり、トラブルシューティングしたり、クラスターとそのリソース自体を管理したりすることが出来ます。 +[`Dashboard`](/ja/docs/tasks/access-application-cluster/web-ui-dashboard/)は、KubernetesのWebベースのユーザインターフェースで、コンテナ化されたアプリケーションをKubernetesクラスターにデプロイしたり、トラブルシューティングしたり、クラスターとそのリソース自体を管理したりすることが出来ます。 ## Helm [`Kubernetes Helm`](https://github.com/helm/helm)は、事前に設定されたKubernetesリソースのパッケージ、別名Kubernetes chartsを管理するためのツールです。 diff --git a/content/ja/docs/setup/best-practices/certificates.md b/content/ja/docs/setup/best-practices/certificates.md index a499631875a05..816295c696b08 100644 --- a/content/ja/docs/setup/best-practices/certificates.md +++ b/content/ja/docs/setup/best-practices/certificates.md @@ -11,15 +11,14 @@ Kubernetesでは、TLS認証のためにPKI証明書が必要です。 自身で証明書を作成することも可能です。例えば、秘密鍵をAPIサーバーに保持しないことで、管理をよりセキュアにする場合が挙げられます。 本ページでは、クラスターに必要な証明書について説明します。 - - ## クラスターではどのように証明書が使われているのか -Kubernetesは下記の用途でPKIを必要とします: +Kubernetesは下記の用途でPKIを必要とします: * kubeletがAPIサーバーの認証をするためのクライアント証明書 +* APIサーバーがkubeletと通信するためのkubeletの[サーバー証明書](/docs/reference/access-authn-authz/kubelet-tls-bootstrapping/#client-and-serving-certificates) * APIサーバーのエンドポイント用サーバー証明書 * クラスターの管理者がAPIサーバーの認証を行うためのクライアント証明書 * APIサーバーがkubeletと通信するためのクライアント証明書 @@ -36,11 +35,14 @@ Kubernetesは下記の用途でPKIを必要とします: ## 証明書の保存場所 -kubeadmを使用してKubernetesをインストールする場合、証明書は`/etc/kubernetes/pki`に保存されます。このドキュメントの全てのパスは、そのディレクトリの相対パスを表します。 +kubeadmを使用してKubernetesをインストールする場合、ほとんどの証明書は`/etc/kubernetes/pki`に保存されます。このドキュメントの全てのパスは、そのディレクトリの相対パスを表します。 +ただしユーザーアカウントの証明書に関しては、kubeadmは`/etc/kubernetes`に配置します。 ## 手動で証明書を設定する -kubeadmで証明書を生成したくない場合は、下記の方法のいずれかで手動で生成可能です。 +もしkubeadmに必要な証明書の生成を望まない場合、それらを単一ルート認証局を使って作成するか、全ての証明書を提供することで作成できます。 +自身の認証局を作成する詳細については、[証明書を手動で生成する](/ja/docs/tasks/administer-cluster/certificates/)を参照してください。 +証明書の管理についての詳細は、[kubeadmによる証明書管理](/ja/docs/tasks/administer-cluster/kubeadm/kubeadm-certs/)を参照してください。 ### 単一ルート認証局 @@ -55,6 +57,16 @@ kubeadmで証明書を生成したくない場合は、下記の方法のいず | front-proxy-ca.crt,key | kubernetes-front-proxy-ca | [front-end proxy](/docs/tasks/extend-kubernetes/configure-aggregation-layer/)用    | 上記の認証局に加えて、サービスアカウント管理用に公開鍵/秘密鍵のペア(`sa.key`と`sa.pub`)を取得する事が必要です。 +次の例は、前の表で示されたCAのキーと証明書を示しています: + +``` +/etc/kubernetes/pki/ca.crt +/etc/kubernetes/pki/ca.key +/etc/kubernetes/pki/etcd/ca.crt +/etc/kubernetes/pki/etcd/ca.key +/etc/kubernetes/pki/front-proxy-ca.crt +/etc/kubernetes/pki/front-proxy-ca.key +``` ### 全ての証明書 @@ -72,9 +84,14 @@ CAの秘密鍵をクラスターにコピーしたくない場合、自身で全 | kube-apiserver-kubelet-client | kubernetes-ca | system:masters | client | | | front-proxy-client | kubernetes-front-proxy-ca | | client | | +{{< note >}} +`kube-apiserver-kubelet-client`にスーパーユーザーグループ`system:masters`を使用する代わりに、より権限の低いグループを使用することができます。 +そのために、kubeadmは`kubeadm:cluster-admins`グループを使用します。 +{{< /note >}} + [1]: クラスターに接続するIPおよびDNS名( [kubeadm](/docs/reference/setup-tools/kubeadm/kubeadm/)を使用する場合と同様、ロードバランサーのIPおよびDNS名、`kubernetes`、`kubernetes.default`、`kubernetes.default.svc`、`kubernetes.default.svc.cluster`、`kubernetes.default.svc.cluster.local`) -`kind`は下記の[x509の鍵用途](https://pkg.go.dev/k8s.io/api/certificates/v1beta1#KeyUsage)のタイプにマッピングされます: +ここで`種類`は、一つまたは複数のx509の鍵用途にマッピングされており、これは[CertificateSigningRequest](/docs/reference/kubernetes-api/authentication-resources/certificate-signing-request-v1#CertificateSigningRequest)の`.spec.usages`にも記載されています: | 種類 | 鍵の用途     | |--------|---------------------------------------------------------------------------------| @@ -87,14 +104,14 @@ CAの秘密鍵をクラスターにコピーしたくない場合、自身で全 {{< /note >}} {{< note >}} -kubeadm利用者のみ: +kubeadm利用者のみ: * 秘密鍵なしでCA証明書をクラスターにコピーするシナリオは、kubeadmドキュメントの外部認証局の項目で言及されています。 * kubeadmでPKIを生成すると、`kube-etcd`、`kube-etcd-peer`および `kube-etcd-healthcheck-client`証明書は外部etcdを利用するケースでは生成されない事に留意してください。 {{< /note >}} -### 証明書のパス +### 証明書のパス {#certificate-paths} 証明書は推奨パスに配置するべきです([kubeadm](/docs/reference/setup-tools/kubeadm/kubeadm/)を使用する場合と同様)。 パスは場所に関係なく与えられた引数で特定されます。 @@ -123,24 +140,67 @@ kubeadm利用者のみ: | sa.key | | kube-controller-manager | service-account-private | | | sa.pub | kube-apiserver | service-account-key | -## ユーザアカウント用に証明書を設定する +次の例は、自分自身で全てのキーと証明書を生成している場合に提供する必要があるファイルパスを[前の表](#certificate-paths)から示しています: + +``` +/etc/kubernetes/pki/etcd/ca.key +/etc/kubernetes/pki/etcd/ca.crt +/etc/kubernetes/pki/apiserver-etcd-client.key +/etc/kubernetes/pki/apiserver-etcd-client.crt +/etc/kubernetes/pki/ca.key +/etc/kubernetes/pki/ca.crt +/etc/kubernetes/pki/apiserver.key +/etc/kubernetes/pki/apiserver.crt +/etc/kubernetes/pki/apiserver-kubelet-client.key +/etc/kubernetes/pki/apiserver-kubelet-client.crt +/etc/kubernetes/pki/front-proxy-ca.key +/etc/kubernetes/pki/front-proxy-ca.crt +/etc/kubernetes/pki/front-proxy-client.key +/etc/kubernetes/pki/front-proxy-client.crt +/etc/kubernetes/pki/etcd/server.key +/etc/kubernetes/pki/etcd/server.crt +/etc/kubernetes/pki/etcd/peer.key +/etc/kubernetes/pki/etcd/peer.crt +/etc/kubernetes/pki/etcd/healthcheck-client.key +/etc/kubernetes/pki/etcd/healthcheck-client.crt +/etc/kubernetes/pki/sa.key +/etc/kubernetes/pki/sa.pub +``` + +## ユーザーアカウント用に証明書を設定する 管理者アカウントおよびサービスアカウントは手動で設定しなければなりません。 -| ファイル名 | クレデンシャル名 | デフォルトCN | 組織       | -|-------------------------|----------------------------|--------------------------------|----------------| -| admin.conf | default-admin | kubernetes-admin | system:masters | -| kubelet.conf | default-auth | system:node:`` (see note) | system:nodes | -| controller-manager.conf | default-controller-manager | system:kube-controller-manager | | -| scheduler.conf | default-scheduler | system:kube-scheduler | | +| ファイル名 | クレデンシャル名 | デフォルトCN | O (in Subject) | +|-------------------------|----------------------------|-------------------------------------|------------------------| +| admin.conf | default-admin | kubernetes-admin | `` | +| super-admin.conf | default-super-admin | kubernetes-super-admin | system:masters | +| kubelet.conf | default-auth | system:node:`` (備考を参照) | system:nodes | +| controller-manager.conf | default-controller-manager | system:kube-controller-manager | | +| scheduler.conf | default-scheduler | system:kube-scheduler | | {{< note >}} `kubelet.conf`における``の値は**必ず**APIサーバーに登録されたkubeletのノード名と一致しなければなりません。詳細は、[Node Authorization](/docs/reference/access-authn-authz/node/)を参照してください。 {{< /note >}} +{{< note >}} +上記の例での``は実装に依存します。 +一部のツールはデフォルトの`admin.conf`内の証明書に`system:masters`グループの一部として署名します。 +`system:masters`は緊急用のスーパーユーザーグループであり、RBACのようなKubernetesの認証レイヤーをバイパスすることができます。 +また、一部のツールはこのスーパーユーザーグループに紐づけられた証明書を含む`super-admin.conf`を生成しません。 + +kubeadmはkubeconfigファイル内に2つの別々の管理者証明書を生成します。 +一つは`admin.conf`内にあり、`Subject: O = kubeadm:cluster-admins, CN = kubernetes-admin`となっています。 +`kubeadm:cluster-admins`は`cluster-admin` ClusterRoleに紐づけられたカスタムグループです。 +このファイルは、kubeadmが管理する全てのコントロールプレーンマシン上で生成されます。 + +もう一つは`super-admin.conf`内にあり、`Subject: O = system:masters, CN = kubernetes-super-admin`となっています。 +このファイルは`kubeadm init`が呼び出されたノード上でのみ生成されます。 +{{< /note >}} + 1. 各コンフィグ毎に、CN名と組織を指定してx509証明書と鍵ペアを生成してください。 -1. 以下のように、各コンフィグで`kubectl`を実行してください。 +2. 以下のように、各コンフィグで`kubectl`を実行してください。 ```shell KUBECONFIG= kubectl config set-cluster default-cluster --server=https://:6443 --certificate-authority --embed-certs @@ -158,5 +218,12 @@ KUBECONFIG= kubectl config use-context default-system | controller-manager.conf | kube-controller-manager | `manifests/kube-controller-manager.yaml`のマニフェストファイルに追記する必要があります。 | | scheduler.conf | kube-scheduler | `manifests/kube-scheduler.yaml`のマニフェストファイルに追記する必要があります。 | +以下のファイルは、前の表に挙げたファイルへの絶対パスを示しています: - +``` +/etc/kubernetes/admin.conf +/etc/kubernetes/super-admin.conf +/etc/kubernetes/kubelet.conf +/etc/kubernetes/controller-manager.conf +/etc/kubernetes/scheduler.conf +``` diff --git a/content/ja/docs/setup/best-practices/enforcing-pod-security-standards.md b/content/ja/docs/setup/best-practices/enforcing-pod-security-standards.md new file mode 100644 index 0000000000000..5fa7bf25b2b90 --- /dev/null +++ b/content/ja/docs/setup/best-practices/enforcing-pod-security-standards.md @@ -0,0 +1,59 @@ +--- +title: Podセキュリティ標準の強制 +weight: 40 +--- + + + +このページでは、[Podセキュリティの標準](/ja/docs/concepts/security/pod-security-standards)を強制する際のベストプラクティスの概要を説明します。 + + + +## ビルトインPodセキュリティアドミッションコントローラーの使用 + +{{< feature-state for_k8s_version="v1.25" state="stable" >}} + +[Podセキュリティアドミッションコントローラー](/docs/reference/access-authn-authz/admission-controllers/#podsecurity)は、非推奨のPodSecurityPolicyを置き換えます。 + +### すべてのNamespaceに設定する + +設定が全く無いNamespaceは、クラスターのセキュリティモデルにおいて重大な弱点とみなすべきです。 +各Namespaceで発生するワークロードのタイプを時間をかけて分析し、Podセキュリティ標準を参照しながら、それぞれに適切なレベルを決定することを推奨します。 +また、ラベルのないNamespaceは、まだ評価されていないことだけを示すべきです。 + +すべてのNamespaceのワークロードが同じセキュリティ要件を持つというシナリオでは、PodSecurityラベルを一括適用する方法を[例](/docs/tasks/configure-pod-container/enforce-standards-namespace-labels/#applying-to-all-namespaces)で説明しています。 + +### 最小特権の原則を採用する + +理想的な世界では、すべてのNamespaceのPodが`restricted`ポリシーの要件を満たすでしょう。 +しかし、ワークロードの中には正当な理由で昇格した特権を必要とするものもあるため、それは不可能であり、現実的でもありません。 + +- `privileged`ワークロードを許可するNamespaceは、適切なアクセス制御を確立し、実施すべきである。 +- 最小権限のNamespaceで実行されるワークロードについては、そのワークロードのセキュリティ要件に関するドキュメントを整備する。可能であれば、それらの要件がどのように制約される可能性があるのかを考慮する。 + +### マルチモード戦略の採用 + +Podセキュリティアドミッションコントローラーの`audit`と`warn`モードを使用すると、既存のワークロードを破壊することなく、Podに関する重要なセキュリティインサイトを簡単に収集できます。 + +すべてのNamespaceでこれらのモードを有効にし、最終的に`enforce`したいレベルやバージョンに設定するのがよい方法です。 +このフェーズで生成される警告と監査注釈は、その状態への指針となります。 +ワークロード作成者が希望のレベルに収まるように変更することを期待している場合は、`warn`モードを有効にしてください。 +監査ログを使用して、希望のレベルに収まるように変更を監視/推進することを期待している場合は、`audit`モードを有効にしてください。 + +`enforce`モードが希望通りの値に設定されている場合でも、これらのモードはいくつかの異なる方法で役立ちます。 + +- `warn`を`enforce`と同じレベルに設定すると、バリデーションを通過しないPod(またはPodテンプレートを持つリソース)を作成しようとしたときに、クライアントが警告を受け取るようになります。これにより、対象のリソースを更新して準拠させることができます。 +- `enforce`を特定の最新バージョンではないに固定するNamespaceでは、`audit`と`warn`モードを`enforce`と同じレベルに設定するが、最新バージョンに対して設定することで、以前のバージョンでは許可されていたが、現在のベストプラクティスでは許可されていない設定を可視化することができます。 + +## サードパーティによる代替案 + +{{% thirdparty-content %}} + +Kubernetesエコシステムでは、セキュリティプロファイルを強制するための他の選択肢も開発されています。 + +- [Kubewarden](https://github.com/kubewarden) +- [Kyverno](https://kyverno.io/policies/) +- [OPA Gatekeeper](https://github.com/open-policy-agent/gatekeeper) + +ビルトインソリューション(PodSecurityアドミッションコントローラーなど)とサードパーティツールのどちらを選ぶかは、あなたの状況次第です。 +どのようなソリューションを評価する場合でも、サプライチェーンの信頼が非常に重要です。最終的には、前述のアプローチのどれを使っても、何もしないよりはましでしょう。 diff --git a/content/ja/docs/setup/learning-environment/minikube.md b/content/ja/docs/setup/learning-environment/minikube.md index 70dedbfee6768..42f7e1afe7fb9 100644 --- a/content/ja/docs/setup/learning-environment/minikube.md +++ b/content/ja/docs/setup/learning-environment/minikube.md @@ -201,7 +201,7 @@ MinikubeのサポートするKubernetesの機能: また、このクラスターと通信する[kubectl](/ja/docs/reference/kubectl/)のインストールも設定します。 {{< note >}} -もしWebプロキシーを通している場合、そのプロキシー情報を`minikube start`コマンドに渡す必要があります: +もしWebプロキシを通している場合、そのプロキシ情報を`minikube start`コマンドに渡す必要があります: ```shell https_proxy= minikube start --docker-env http_proxy= --docker-env https_proxy= --docker-env no_proxy=192.168.99.0/24 @@ -484,7 +484,7 @@ Minikubeで起動したいアドオンを `~/.minikube/addons` ディレクト MinikubeはKubernetesとDockerデーモンを含む仮想マシンを作成します。 KubernetesがDockerを使用してコンテナをスケジュールしようとする際、Dockerデーモンはコンテナをプルするために外部ネットワークを必要とする場合があります。 -HTTPプロキシーを通している場合には、プロキシー設定をDockerに提供する必要があります。 +HTTPプロキシを通している場合には、プロキシ設定をDockerに提供する必要があります。 これを行うには、`minikube start` に必要な環境変数をフラグとして渡します。 例: @@ -494,8 +494,8 @@ minikube start --docker-env http_proxy=http://$YOURPROXY:PORT \ --docker-env https_proxy=https://$YOURPROXY:PORT ``` -仮想マシンのアドレスが192.168.99.100の場合、プロキシーの設定により `kubectl` が直接アクセスできない可能性があります。 -このIPアドレスのプロキシー設定を迂回するには、以下のようにno_proxy設定を変更する必要があります。 +仮想マシンのアドレスが192.168.99.100の場合、プロキシの設定により `kubectl` が直接アクセスできない可能性があります。 +このIPアドレスのプロキシ設定を迂回するには、以下のようにno_proxy設定を変更する必要があります。 ```shell export no_proxy=$no_proxy,$(minikube ip) diff --git a/content/ja/docs/setup/production-environment/container-runtimes.md b/content/ja/docs/setup/production-environment/container-runtimes.md index 171b2994bbcc6..d85a3ce0957ba 100644 --- a/content/ja/docs/setup/production-environment/container-runtimes.md +++ b/content/ja/docs/setup/production-environment/container-runtimes.md @@ -93,7 +93,7 @@ cgroupとインターフェースするために、kubeletおよびコンテナ ### cgroupfsドライバー {#cgroupfs-cgroup-driver} `cgroupfs`ドライバーは、kubeletのデフォルトのcgroupドライバーです。 -`cgroupfs`ドライバーを使用すると、kubeletとコンテナランタイムはcgroupファイルシステムと直接インターフェイスし、cgroupを設定します。 +`cgroupfs`ドライバーを使用すると、kubeletとコンテナランタイムはcgroupファイルシステムと直接インターフェースし、cgroupを設定します。 [systemd](https://www.freedesktop.org/wiki/Software/systemd/)がinitシステムである場合、`cgroupfs`ドライバーは推奨**されません**。 なぜなら、systemdはシステム上のcgroupマネージャーが単一であると想定しているからです。 diff --git a/content/ja/docs/setup/production-environment/tools/kubeadm/create-cluster-kubeadm.md b/content/ja/docs/setup/production-environment/tools/kubeadm/create-cluster-kubeadm.md index 55bf57fbc8def..38a9b0b414c6d 100644 --- a/content/ja/docs/setup/production-environment/tools/kubeadm/create-cluster-kubeadm.md +++ b/content/ja/docs/setup/production-environment/tools/kubeadm/create-cluster-kubeadm.md @@ -63,7 +63,7 @@ kubeadmツールの全体の機能の状態は、一般利用可能(GA)です。 1. (推奨)シングルコントロールプレーンの`kubeadm`クラスターを高可用性クラスターにアップグレードする予定がある場合、`--control-plane-endpoint`を指定して、すべてのコントロールプレーンノードとエンドポイントを共有する必要があります。エンドポイントにはDNSネームやロードバランサーのIPアドレスが使用できます。 1. Podネットワークアドオンを選んで、`kubeadm init`に引数を渡す必要があるかどうか確認してください。選んだサードパーティーのプロバイダーによっては、`--pod-network-cidr`をプロバイダー固有の値に設定する必要がある場合があります。詳しくは、[Podネットワークアドオンのインストール](#pod-network)を参照してください。 1. (オプション)バージョン1.14から、`kubeadm`はよく知られたドメインソケットのパスリストを用いて、Linux上のコンテナランタイムの検出を試みます。異なるコンテナランタイムを使用する場合やプロビジョニングするノードに2つ以上のランタイムがインストールされている場合、`kubeadm init`に`--cri-socket`引数を指定してください。詳しくは、[ランタイムのインストール](/ja/docs/setup/production-environment/tools/kubeadm/install-kubeadm/#installing-runtime)を読んでください。 -1. (オプション)明示的に指定しない限り、`kubeadm`はデフォルトゲートウェイに関連付けられたネットワークインターフェイスを使用して、この特定のコントロールプレーンノードのAPIサーバーのadvertise addressを設定します。異なるネットワークインターフェイスを使用するには、`kubeadm init`に`--apiserver-advertise-address=`引数を指定してください。IPv6アドレスを使用するIPv6 Kubernetesクラスターをデプロイするには、たとえば`--apiserver-advertise-address=fd00::101`のように、IPv6アドレスを指定する必要があります。 +1. (オプション)明示的に指定しない限り、`kubeadm`はデフォルトゲートウェイに関連付けられたネットワークインターフェースを使用して、この特定のコントロールプレーンノードのAPIサーバーのadvertise addressを設定します。異なるネットワークインターフェースを使用するには、`kubeadm init`に`--apiserver-advertise-address=`引数を指定してください。IPv6アドレスを使用するIPv6 Kubernetesクラスターをデプロイするには、たとえば`--apiserver-advertise-address=fd00::101`のように、IPv6アドレスを指定する必要があります。 1. (オプション)`kubeadm init`を実行する前に`kubeadm config images pull`を実行して、gcr.ioコンテナイメージレジストリに接続できるかどうかを確認します。 コントロールプレーンノードを初期化するには、次のコマンドを実行します。 diff --git a/content/ja/docs/setup/production-environment/tools/kubeadm/install-kubeadm.md b/content/ja/docs/setup/production-environment/tools/kubeadm/install-kubeadm.md index 0efeb9daccc43..ecdd9c1de3131 100644 --- a/content/ja/docs/setup/production-environment/tools/kubeadm/install-kubeadm.md +++ b/content/ja/docs/setup/production-environment/tools/kubeadm/install-kubeadm.md @@ -51,10 +51,10 @@ card: ## 必須ポートの確認 Kubernetesのコンポーネントが互いに通信するためには、これらの[必要なポート](/ja/docs/reference/networking/ports-and-protocols/)が開いている必要があります。 -netcatなどのツールを使用することで、下記のようにポートが開いているかどうかを確認することが可能です。 +[netcat](https://netcat.sourceforge.net)などのツールを使用することで、下記のようにポートが開いているかどうかを確認することが可能です。 ```shell -nc 127.0.0.1 6443 +nc 127.0.0.1 6443 -v ``` 使用するPodネットワークプラグインによっては、特定のポートを開く必要がある場合もあります。 @@ -122,23 +122,31 @@ kubeadmは`kubelet`や`kubectl`をインストールまたは管理**しない** {{< tabs name="k8s_install" >}} {{% tab name="Ubuntu、Debian、またはHypriotOS" %}} -1. `apt`のパッケージ一覧を更新し、Kubernetesの`apt`リポジトリを利用するのに必要なパッケージをインストールします: +1. `apt`のパッケージ一覧を更新し、Kubernetesの`apt`リポジトリーを利用するのに必要なパッケージをインストールします: ```shell sudo apt-get update + # apt-transport-httpsはダミーパッケージの可能性があります。その場合、そのパッケージはスキップできます sudo apt-get install -y apt-transport-https ca-certificates curl gpg ``` -2. Google Cloudの公開鍵をダウンロードします: +2. Kubernetesパッケージリポジトリーの公開署名キーをダウンロードします。すべてのリポジトリーに同じ署名キーが使用されるため、URL内のバージョンは無視できます: ```shell - curl -fsSL https://dl.k8s.io/apt/doc/apt-key.gpg | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-archive-keyring.gpg + # `/etc/apt/keyrings`フォルダーが存在しない場合は、curlコマンドの前に作成する必要があります。下記の備考を参照してください。 + # sudo mkdir -p -m 755 /etc/apt/keyrings + curl -fsSL https://pkgs.k8s.io/core:/stable:/{{< param "version" >}}/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg ``` -3. Kubernetesの`apt`リポジトリを追加します: +{{< note >}} +Debian 12とUbuntu 22.04より古いリリースでは、`/etc/apt/keyrings`フォルダーはデフォルトでは存在しないため、curlコマンドの前に作成する必要があります。 +{{< /note >}} + +3. 適切なKubernetes `apt`リポジトリーを追加します。このリポジトリーには、Kubernetes {{< skew currentVersion >}}用のパッケージのみがあることに注意してください。他のKubernetesマイナーバージョンの場合は、目的のマイナーバージョンに一致するようにURL内のKubernetesマイナーバージョンを変更する必要があります(インストールする予定のKubernetesバージョンのドキュメントも読んでください): ```shell - echo "deb [signed-by=/etc/apt/keyrings/kubernetes-archive-keyring.gpg] https://apt.kubernetes.io/ kubernetes-xenial main" | sudo tee /etc/apt/sources.list.d/kubernetes.list + # これにより、/etc/apt/sources.list.d/kubernetes.listにある既存の設定が上書きされます + echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/{{< param "version" >}}/deb/ /' | sudo tee /etc/apt/sources.list.d/kubernetes.list ``` 4. `apt`のパッケージ一覧を更新し、kubelet、kubeadm、kubectlをインストールします。そしてバージョンを固定します: @@ -148,10 +156,6 @@ kubeadmは`kubelet`や`kubectl`をインストールまたは管理**しない** sudo apt-get install -y kubelet kubeadm kubectl sudo apt-mark hold kubelet kubeadm kubectl ``` -{{< note >}} -Debian 12やUbuntu 22.04より古いリリースでは、`/etc/apt/keyrings`はデフォルトでは存在しません。 -必要に応じてこのディレクトリを作成し、誰でも読み取り可能で、管理者のみ書き込み可能にすることができます。 -{{< /note >}} {{% /tab %}} {{% tab name="CentOS、RHEL、またはFedora" %}} diff --git a/content/ja/docs/setup/production-environment/tools/kubeadm/troubleshooting-kubeadm.md b/content/ja/docs/setup/production-environment/tools/kubeadm/troubleshooting-kubeadm.md index 94f34654f1bcb..47334150d7014 100644 --- a/content/ja/docs/setup/production-environment/tools/kubeadm/troubleshooting-kubeadm.md +++ b/content/ja/docs/setup/production-environment/tools/kubeadm/troubleshooting-kubeadm.md @@ -194,7 +194,7 @@ Error from server (NotFound): the server could not find the requested resource Vagrantは通常、2つのインターフェースを全てのVMに割り当てます。1つ目は全てのホストにIPアドレス`10.0.2.15`が割り当てられており、NATされる外部トラフィックのためのものです。 - これは、ホストの最初のインターフェイスをデフォルトにしているflannelの問題につながるかもしれません。これは、すべてのホストが同じパブリックIPアドレスを持っていると考えます。これを防ぐには、2番目のインターフェイスが選択されるように `--iface eth1`フラグをflannelに渡してください。 + これは、ホストの最初のインターフェースをデフォルトにしているflannelの問題につながるかもしれません。これは、すべてのホストが同じパブリックIPアドレスを持っていると考えます。これを防ぐには、2番目のインターフェースが選択されるように `--iface eth1`フラグをflannelに渡してください。 ## 公開されていないIPがコンテナに使われている diff --git a/content/ja/docs/setup/production-environment/windows/user-guide-windows-containers.md b/content/ja/docs/setup/production-environment/windows/user-guide-windows-containers.md index 5ea749f98a381..b9c29a4eacd55 100644 --- a/content/ja/docs/setup/production-environment/windows/user-guide-windows-containers.md +++ b/content/ja/docs/setup/production-environment/windows/user-guide-windows-containers.md @@ -20,7 +20,7 @@ Windowsアプリケーションは、多くの組織で実行されるサービ ## 始める前に * [Windows Serverを実行するマスターノードとワーカーノード](/ja/docs/tasks/administer-cluster/kubeadm/adding-windows-nodes)を含むKubernetesクラスターを作成します -* Kubernetes上にServiceとワークロードを作成してデプロイすることは、LinuxコンテナとWindowsコンテナ共に、ほぼ同じように動作することに注意してください。クラスターとのインタフェースとなる[Kubectlコマンド](/ja/docs/reference/kubectl/)も同じです。Windowsコンテナをすぐに体験できる例を以下セクションに用意しています。 +* Kubernetes上にServiceとワークロードを作成してデプロイすることは、LinuxコンテナとWindowsコンテナ共に、ほぼ同じように動作することに注意してください。クラスターとのインターフェースとなる[Kubectlコマンド](/ja/docs/reference/kubectl/)も同じです。Windowsコンテナをすぐに体験できる例を以下セクションに用意しています。 ## はじめに:Windowsコンテナのデプロイ diff --git a/content/ja/docs/setup/release/_index.md b/content/ja/docs/setup/release/_index.md deleted file mode 100644 index 8c812f72def53..0000000000000 --- a/content/ja/docs/setup/release/_index.md +++ /dev/null @@ -1,4 +0,0 @@ ---- -title: "リリースノートおよびバージョンスキュー" -weight: 10 ---- diff --git a/content/ja/docs/tasks/access-application-cluster/communicate-containers-same-pod-shared-volume.md b/content/ja/docs/tasks/access-application-cluster/communicate-containers-same-pod-shared-volume.md index dd616dc3920b7..06f7326fe3672 100644 --- a/content/ja/docs/tasks/access-application-cluster/communicate-containers-same-pod-shared-volume.md +++ b/content/ja/docs/tasks/access-application-cluster/communicate-containers-same-pod-shared-volume.md @@ -119,7 +119,7 @@ Hello from the debian container Podが複数のコンテナを持つことができる主な理由は、プライマリアプリケーションを支援するヘルパーアプリケーションをサポートするためです。 ヘルパーアプリケーションの典型的な例は、データプラー、データプッシャー、およびプロキシです。 多くの場合、ヘルパーアプリケーションとプライマリアプリケーションは互いに通信する必要があります。 -通常、これは、この演習に示すように共有ファイルシステムを介して、またはループバックネットワークインターフェイスであるlocalhostを介して行われます。 +通常、これは、この演習に示すように共有ファイルシステムを介して、またはループバックネットワークインターフェースであるlocalhostを介して行われます。 このパターンの例は、新しい更新のためにGitリポジトリをポーリングするヘルパープログラムを伴うWebサーバーです。 この演習のボリュームは、コンテナがポッドの寿命中に通信する方法を提供します。 diff --git a/content/ja/docs/tasks/access-application-cluster/web-ui-dashboard.md b/content/ja/docs/tasks/access-application-cluster/web-ui-dashboard.md index 7c5cd69cec200..dcf084bc61f1a 100644 --- a/content/ja/docs/tasks/access-application-cluster/web-ui-dashboard.md +++ b/content/ja/docs/tasks/access-application-cluster/web-ui-dashboard.md @@ -10,7 +10,7 @@ card: -ダッシュボードは、WebベースのKubernetesユーザーインターフェイスです。 +ダッシュボードは、WebベースのKubernetesユーザーインターフェースです。 ダッシュボードを使用して、コンテナ化されたアプリケーションをKubernetesクラスターにデプロイしたり、 コンテナ化されたアプリケーションをトラブルシューティングしたり、クラスターリソースを管理したりすることができます。 ダッシュボードを使用して、クラスター上で実行されているアプリケーションの概要を把握したり、 @@ -46,7 +46,7 @@ kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.0.0/a チュートリアルで作成されたサンプルユーザーには管理者権限が与えられ、教育目的のみに使用されます。 {{< /warning >}} -### コマンドラインプロキシー +### コマンドラインプロキシ 以下のコマンドを実行することで、kubectlコマンドラインツールを使ってダッシュボードにアクセスすることができます: ``` diff --git a/content/ja/docs/tasks/administer-cluster/configure-upgrade-etcd.md b/content/ja/docs/tasks/administer-cluster/configure-upgrade-etcd.md new file mode 100644 index 0000000000000..ce6d3ff188ef6 --- /dev/null +++ b/content/ja/docs/tasks/administer-cluster/configure-upgrade-etcd.md @@ -0,0 +1,350 @@ +--- +title: Kubernetes向けetcdクラスターの運用 +content_type: task +weight: 270 +--- + + + +{{< glossary_definition term_id="etcd" length="all" prepend="etcdは">}} + +## {{% heading "prerequisites" %}} + +Kubernetesクラスターが必要で、kubectlコマンドラインツールがクラスターと通信できるように設定されている必要があります。 +コントロールプレーンノード以外に少なくとも2つのノードを持つクラスターで、このガイドに従うことを推奨します。 +まだクラスターを用意していない場合は、[minikube](https://minikube.sigs.k8s.io/docs/tutorials/multi_node/)を使用して作成することができます。 + + + +## 前提条件 + +* etcdは、奇数のメンバーを持つクラスターとして実行します。 + +* etcdはリーダーベースの分散システムです。リーダーが定期的に全てのフォロワーにハートビートを送信し、クラスターの安定性を維持するようにします。 + +* リソース不足が発生しないようにします。 + + クラスターのパフォーマンスと安定性は、ネットワークとディスクのI/Oに敏感です。 + リソース不足はハートビートのタイムアウトを引き起こし、クラスターの不安定化につながる可能性があります。 + 不安定なetcdは、リーダーが選出されていないことを意味します。 + そのような状況では、クラスターは現在の状態に変更を加えることができません。 + これは、新しいPodがスケジュールされないことを意味します。 + +* Kubernetesクラスターの安定性には、etcdクラスターの安定性が不可欠です。 + したがって、etcdクラスターは専用のマシンまたは[保証されたリソース要件](https://etcd.io/docs/current/op-guide/hardware/)を持つ隔離された環境で実行してください。 + +* 本番環境で実行するために推奨される最低限のetcdバージョンは、`3.4.22`以降あるいは`3.5.6`以降です。 + +## リソース要件 + +限られたリソースでetcdを運用するのはテスト目的にのみ適しています。 +本番環境へのデプロイには、高度なハードウェア構成が必要です。 +本番環境へetcdをデプロイする前に、[リソース要件](https://etcd.io/docs/current/op-guide/hardware/#example-hardware-configurations)を確認してください。 + +## etcdクラスターの起動 + +このセクションでは、単一ノードおよびマルチノードetcdクラスターの起動について説明します。 + +### 単一ノードetcdクラスター + +単一ノードetcdクラスターは、テスト目的でのみ使用してください。 + +1. 以下を実行します: + + ```sh + etcd --listen-client-urls=http://$PRIVATE_IP:2379 \ + --advertise-client-urls=http://$PRIVATE_IP:2379 + ``` + +2. Kubernetes APIサーバーをフラグ`--etcd-servers=$PRIVATE_IP:2379`で起動します。 + + `PRIVATE_IP`がetcdクライアントIPに設定されていることを確認してください。 + +### マルチノードetcdクラスター + +耐久性と高可用性のために、本番環境ではマルチノードクラスターとしてetcdを実行し、定期的にバックアップを取ります。 +本番環境では5つのメンバーによるクラスターが推奨されます。 +詳細は[FAQドキュメント](https://etcd.io/docs/current/faq/#what-is-failure-tolerance)を参照してください。 + +etcdクラスターは、静的なメンバー情報、または動的な検出によって構成されます。 +クラスタリングに関する詳細は、[etcdクラスタリングドキュメント](https://etcd.io/docs/current/op-guide/clustering/)を参照してください。 + +例として、次のクライアントURLで実行される5つのメンバーによるetcdクラスターを考えてみます。 +5つのURLは、`http://$IP1:2379`、`http://$IP2:2379`、`http://$IP3:2379`、`http://$IP4:2379`、および`http://$IP5:2379`です。Kubernetes APIサーバーを起動するには、 + +1. 以下を実行します: + + ```shell + etcd --listen-client-urls=http://$IP1:2379,http://$IP2:2379,http://$IP3:2379,http://$IP4:2379,http://$IP5:2379 --advertise-client-urls=http://$IP1:2379,http://$IP2:2379,http://$IP3:2379,http://$IP4:2379,http://$IP5:2379 + ``` + +2. フラグ`--etcd-servers=$IP1:2379,$IP2:2379,$IP3:2379,$IP4:2379,$IP5:2379`を使ってKubernetes APIサーバーを起動します。 + + `IP`変数がクライアントのIPアドレスに設定されていることを確認してください。 + +### ロードバランサーを使用したマルチノードetcdクラスター + +ロードバランシングされたetcdクラスターを実行するには、次の手順に従います。 + +1. etcdクラスターを設定します。 +2. etcdクラスターの前にロードバランサーを設定します。 + 例えば、ロードバランサーのアドレスを`$LB`とします。 +3. フラグ`--etcd-servers=$LB:2379`を使ってKubernetes APIサーバーを起動します。 + +## etcdクラスターのセキュリティ確保 + +etcdへのアクセスはクラスター内でのルート権限に相当するため、理想的にはAPIサーバーのみがアクセスできるようにするべきです。 +データの機密性を考慮して、etcdクラスターへのアクセス権を必要とするノードのみに付与することが推奨されます。 + +etcdをセキュアにするためには、ファイアウォールのルールを設定するか、etcdによって提供されるセキュリティ機能を使用します。 +etcdのセキュリティ機能はx509公開鍵基盤(PKI)に依存します。 +この機能を使用するには、キーと証明書のペアを生成して、セキュアな通信チャンネルを確立します。 +例えば、etcdメンバー間の通信をセキュアにするために`peer.key`と`peer.cert`のキーペアを使用し、etcdとそのクライアント間の通信をセキュアにするために`client.key`と`client.cert`を使用します。 +クライアント認証用のキーペアとCAファイルを生成するには、etcdプロジェクトによって提供されている[サンプルスクリプト](https://github.com/coreos/etcd/tree/master/hack/tls-setup)を参照してください。 + +### 通信のセキュリティ確保 + +セキュアなピア通信を持つetcdを構成するためには、`--peer-key-file=peer.key`および`--peer-cert-file=peer.cert`フラグを指定し、URLスキーマとしてHTTPSを使用します。 + +同様に、セキュアなクライアント通信を持つetcdを構成するためには、`--key-file=k8sclient.key`および`--cert-file=k8sclient.cert`フラグを指定し、URLスキーマとしてHTTPSを使用します。 +セキュアな通信を使用するクライアントコマンドの例は以下の通りです: + +``` +ETCDCTL_API=3 etcdctl --endpoints 10.2.0.9:2379 \ + --cert=/etc/kubernetes/pki/etcd/server.crt \ + --key=/etc/kubernetes/pki/etcd/server.key \ + --cacert=/etc/kubernetes/pki/etcd/ca.crt \ + member list +``` + +### etcdクラスターへのアクセス制限 + +セキュアな通信を構成した後、TLS認証を使用して、etcdクラスターへのアクセスをKubernetes APIサーバーのみに制限します。 + +例えば、CA `etcd.ca`によって信頼されるキーペア`k8sclient.key`と`k8sclient.cert`を考えてみます。 +`--client-cert-auth`とTLSを使用してetcdが構成されている場合、etcdは`--trusted-ca-file`フラグで渡されたCAまたはシステムのCAを使用してクライアントからの証明書を検証します。 +`--client-cert-auth=true`および`--trusted-ca-file=etcd.ca`フラグを指定することで、証明書`k8sclient.cert`を持つクライアントのみにアクセスを制限します。 + +etcdが正しく構成されると、有効な証明書を持つクライアントのみがアクセスできます。 +Kubernetes APIサーバーにアクセス権を与えるためには、`--etcd-certfile=k8sclient.cert`、`--etcd-keyfile=k8sclient.key`および`--etcd-cafile=ca.cert`フラグで構成します。 + +{{< note >}} +etcd認証は、Kubernetesでは現在サポートされていません。 +{{< /note >}} + +## 障害が発生したetcdメンバーの交換 + +etcdクラスターは、一部のメンバーの障害を許容することで高可用性を実現します。 +しかし、クラスターの全体的な状態を改善するためには、障害が発生したメンバーを直ちに交換することが重要です。 +複数のメンバーに障害が発生した場合は、1つずつ交換します。 +障害が発生したメンバーを交換するには、メンバーを削除し、新しいメンバーを追加するという2つのステップがあります。 + +etcdは内部でユニークなメンバーIDを保持していますが、人的なミスを避けるためにも各メンバーにはユニークな名前を使用することが推奨されます。 +例えば、3つのメンバーのetcdクラスターを考えてみましょう。 +URLが`member1=http://10.0.0.1`、`member2=http://10.0.0.2`、そして`member3=http://10.0.0.3`だとします。 +`member1`に障害が発生した場合、`member4=http://10.0.0.4`で交換します。 + +1. 障害が発生した`member1`のメンバーIDを取得します: + + ```shell + etcdctl --endpoints=http://10.0.0.2,http://10.0.0.3 member list + ``` + + 次のメッセージが表示されます: + + ```console + 8211f1d0f64f3269, started, member1, http://10.0.0.1:2380, http://10.0.0.1:2379 + 91bc3c398fb3c146, started, member2, http://10.0.0.2:2380, http://10.0.0.2:2379 + fd422379fda50e48, started, member3, http://10.0.0.3:2380, http://10.0.0.3:2379 + ``` + +1. 以下のいずれかを行います: + + 1. 各Kubernetes APIサーバーが全てのetcdメンバーと通信するように構成されている場合、`--etcd-servers`フラグから障害が発生したメンバーを削除し、各Kubernetes APIサーバーを再起動します。 + 1. 各Kubernetes APIサーバーが単一のetcdメンバーと通信している場合、障害が発生したetcdと通信しているKubernetes APIサーバーを停止します。 + +1. 壊れたノード上のetcdサーバーを停止します。 + Kubernetes APIサーバー以外のクライアントからetcdにトラフィックが流れている可能性があり、データディレクトリへの書き込みを防ぐためにすべてのトラフィックを停止することが望ましいです。 + +1. メンバーを削除します: + + ```shell + etcdctl member remove 8211f1d0f64f3269 + ``` + + 次のメッセージが表示されます: + + ```console + Removed member 8211f1d0f64f3269 from cluster + ``` + +1. 新しいメンバーを追加します: + + ```shell + etcdctl member add member4 --peer-urls=http://10.0.0.4:2380 + ``` + + 次のメッセージが表示されます: + + ```console + Member 2be1eb8f84b7f63e added to cluster ef37ad9dc622a7c4 + ``` + +1. IP `10.0.0.4`のマシン上で新たに追加されたメンバーを起動します: + + ```shell + export ETCD_NAME="member4" + export ETCD_INITIAL_CLUSTER="member2=http://10.0.0.2:2380,member3=http://10.0.0.3:2380,member4=http://10.0.0.4:2380" + export ETCD_INITIAL_CLUSTER_STATE=existing + etcd [flags] + ``` + +1. 以下のいずれかを行います: + + 1. 各Kubernetes APIサーバーが全てのetcdメンバーと通信するように構成されている場合、`--etcd-servers`フラグに新たに追加されたメンバーを加え、各Kubernetes APIサーバーを再起動します。 + 1. 各Kubernetes APIサーバーが単一のetcdメンバーと通信している場合、ステップ2で停止したKubernetes APIサーバーを起動します。 + その後、Kubernetes APIサーバークライアントを再度構成して、停止されたKubernetes APIサーバーへのリクエストをルーティングします。 + これは多くの場合、ロードバランサーを構成することで行われます。 + +クラスターの再構成に関する詳細については、[etcd再構成ドキュメント](https://etcd.io/docs/current/op-guide/runtime-configuration/#remove-a-member)を参照してください。 + +## etcdクラスターのバックアップ + +すべてのKubernetesオブジェクトはetcdに保存されています。 +定期的にetcdクラスターのデータをバックアップすることは、すべてのコントロールプレーンノードを失うなどの災害シナリオでKubernetesクラスターを復旧するために重要です。 +スナップショットファイルには、すべてのKubernetesの状態と重要な情報が含まれています。 +機密性の高いKubernetesデータを安全に保つために、スナップショットファイルを暗号化してください。 + +etcdクラスターのバックアップは、etcdのビルトインスナップショットとボリュームスナップショットの2つの方法で実現できます。 + +### ビルトインスナップショット + +etcdはビルトインスナップショットをサポートしています。 +スナップショットは、`etcdctl snapshot save`コマンドを使用してライブメンバーから、あるいはetcdプロセスによって現在使用されていない[データディレクトリ](https://etcd.io/docs/current/op-guide/configuration/#--data-dir)から`member/snap/db`ファイルをコピーして作成できます。 +スナップショットを作成しても、メンバーのパフォーマンスに影響はありません。 + +以下は、`$ENDPOINT`によって提供されるキースペースのスナップショットを`snapshot.db`ファイルに作成する例です: + +```shell +ETCDCTL_API=3 etcdctl --endpoints $ENDPOINT snapshot save snapshot.db +``` + +スナップショットを確認します: + +```shell +ETCDCTL_API=3 etcdctl --write-out=table snapshot status snapshot.db +``` + +```console ++----------+----------+------------+------------+ +| HASH | REVISION | TOTAL KEYS | TOTAL SIZE | ++----------+----------+------------+------------+ +| fe01cf57 | 10 | 7 | 2.1 MB | ++----------+----------+------------+------------+ +``` + +### ボリュームスナップショット + +etcdがAmazon Elastic Block Storeのようなバックアップをサポートするストレージボリューム上で実行されている場合、ストレージボリュームのスナップショットを作成することによってetcdデータをバックアップします。 + +### etcdctlオプションを使用したスナップショット + +etcdctlによって提供されるさまざまなオプションを使用してスナップショットを作成することもできます。例えば + +```shell +ETCDCTL_API=3 etcdctl -h +``` + +はetcdctlから利用可能なさまざまなオプションを一覧表示します。 +例えば、以下のようにエンドポイント、証明書、キーを指定してスナップショットを作成することができます: + +```shell +ETCDCTL_API=3 etcdctl --endpoints=https://127.0.0.1:2379 \ + --cacert= --cert= --key= \ + snapshot save +``` + +ここで、`trusted-ca-file`、`cert-file`、`key-file`はetcd Podの説明から取得できます。 + +## etcdクラスターのスケールアウト + +etcdクラスターのスケールアウトは、パフォーマンスとのトレードオフで可用性を高めます。 +スケーリングはクラスターのパフォーマンスや能力を高めるものではありません。 +一般的なルールとして、etcdクラスターをスケールアウトまたはスケールインすることはありません。 +etcdクラスターに自動スケーリンググループを設定しないでください。 +公式にサポートされるどんなスケールの本番環境のKubernetesクラスターにおいても、常に静的な5つのメンバーのetcdクラスターを運用することを強く推奨します。 + +合理的なスケーリングは、より高い信頼性が求められる場合に、3つのメンバーで構成されるクラスターを5つのメンバーにアップグレードすることです。 +既存のクラスターにメンバーを追加する方法については、[etcdの再構成ドキュメント](https://etcd.io/docs/current/op-guide/runtime-configuration/#remove-a-member)を参照してください。 + +## etcdクラスターの復元 + +etcdは、[major.minor](http://semver.org/)バージョンのetcdプロセスから取得されたスナップショットからの復元をサポートしています。 +異なるパッチバージョンのetcdからのバージョン復元もサポートされています。 +復元操作は、障害が発生したクラスターのデータを回復するために用いられます。 + +復元操作を開始する前に、スナップショットファイルが存在している必要があります。 +これは、以前のバックアップ操作からのスナップショットファイルでも、残っている[データディレクトリ](https://etcd.io/docs/current/op-guide/configuration/#--data-dir)からのスナップショットファイルでも構いません。 + +クラスターを復元する場合は、`--data-dir`オプションを使用して、クラスターをどのフォルダーに復元するかを指定します: +```shell +ETCDCTL_API=3 etcdctl --data-dir snapshot restore snapshot.db +``` + +ここで、``は復元プロセス中に作成されるディレクトリです。 + +もう一つの例としては、まず`ETCDCTL_API`環境変数をエクスポートします: + +```shell +export ETCDCTL_API=3 +etcdctl --data-dir snapshot restore snapshot.db +``` +``が以前と同じフォルダーである場合は、クラスターを復元する前にそれを削除してetcdプロセスを停止します。そうでない場合は、etcdの構成を変更し、復元後にetcdプロセスを再起動して新しいデータディレクトリを使用するようにします。 + +スナップショットファイルからクラスターを復元する方法と例についての詳細は、[etcd災害復旧ドキュメント](https://etcd.io/docs/current/op-guide/recovery/#restoring-a-cluster)を参照してください。 + +復元されたクラスターのアクセスURLが前のクラスターと異なる場合、Kubernetes APIサーバーをそれに応じて再設定する必要があります。 +この場合、`--etcd-servers=$OLD_ETCD_CLUSTER`のフラグの代わりに、`--etcd-servers=$NEW_ETCD_CLUSTER`のフラグでKubernetes APIサーバーを再起動します。 +`$NEW_ETCD_CLUSTER`と`$OLD_ETCD_CLUSTER`をそれぞれのIPアドレスに置き換えてください。 +etcdクラスターの前にロードバランサーを使用している場合、代わりにロードバランサーを更新する必要があるかもしれません。 + +etcdメンバーの過半数に永続的な障害が発生した場合、etcdクラスターは故障したと見なされます。 +このシナリオでは、Kubernetesは現在の状態に対して変更を加えることができません。 +スケジュールされたPodは引き続き実行されるかもしれませんが、新しいPodはスケジュールできません。 +このような場合、etcdクラスターを復旧し、必要に応じてKubernetes APIサーバーを再設定して問題を修正します。 + +{{< note >}} +クラスター内でAPIサーバーが実行されている場合、etcdのインスタンスを復元しようとしないでください。 +代わりに、以下の手順に従ってetcdを復元してください: + +- **すべての**APIサーバーインスタンスを停止 +- すべてのetcdインスタンスで状態を復元 +- すべてのAPIサーバーインスタンスを再起動 + +また、`kube-scheduler`、`kube-controller-manager`、`kubelet`などのコンポーネントを再起動することもお勧めします。 +これは、これらが古いデータに依存していないことを確認するためです。実際には、復元には少し時間がかかります。 +復元中、重要なコンポーネントはリーダーロックを失い、自動的に再起動します。 +{{< /note >}} + +## etcdクラスターのアップグレード + +etcdのアップグレードに関する詳細は、[etcdアップグレード](https://etcd.io/docs/latest/upgrades/)のドキュメントを参照してください。 + +{{< note >}} +アップグレードを開始する前に、まずetcdクラスターをバックアップしてください。 +{{< /note >}} + +## etcdクラスターのメンテナンス + +etcdのメンテナンスに関する詳細は、[etcdメンテナンス](https://etcd.io/docs/latest/op-guide/maintenance/)のドキュメントを参照してください。 + +{{% thirdparty-content single="true" %}} + +{{< note >}} +デフラグメンテーションはコストがかかる操作のため、できるだけ頻繁に実行しないようにしてください。 +一方で、etcdメンバーがストレージのクォータを超えないようにする必要もあります。 +Kubernetesプロジェクトでは、デフラグメンテーションを行う際には、[etcd-defrag](https://github.com/ahrtr/etcd-defrag)などのツールを使用することを推奨しています。 + +また、デフラグメンテーションを定期的に実行するために、KubernetesのCronJobとしてデフラグメンテーションツールを実行することもできます。 +詳細は[`etcd-defrag-cronjob.yaml`](https://github.com/ahrtr/etcd-defrag/blob/main/doc/etcd-defrag-cronjob.yaml)を参照してください。 +{{< /note >}} diff --git a/content/ja/docs/tasks/administer-cluster/coredns.md b/content/ja/docs/tasks/administer-cluster/coredns.md index 45e52d6b289ba..2aab87bc38b39 100644 --- a/content/ja/docs/tasks/administer-cluster/coredns.md +++ b/content/ja/docs/tasks/administer-cluster/coredns.md @@ -24,7 +24,7 @@ weight: 380 ## CoreDNSのインストール {#installing-coredns} -kube-dnsの手動デプロイや置き換えについては、[CoreDNS GitHub project](https://github.com/coredns/deployment/tree/master/kubernetes)のドキュメントを参照してください。 +kube-dnsの手動デプロイや置き換えについては、[CoreDNS website](https://coredns.io/manual/installation/)のドキュメントを参照してください。 ## CoreDNSへの移行 {#migrating-to-coredns} diff --git a/content/ja/docs/tasks/administer-cluster/extended-resource-node.md b/content/ja/docs/tasks/administer-cluster/extended-resource-node.md index c55f3d0a71d7f..829f49da27064 100644 --- a/content/ja/docs/tasks/administer-cluster/extended-resource-node.md +++ b/content/ja/docs/tasks/administer-cluster/extended-resource-node.md @@ -43,7 +43,7 @@ Host: k8s-master:8080 Kubernetesは、ドングルとは何かも、ドングルが何に利用できるのかを知る必要もないことに注意してください。上のPATCHリクエストは、ただNodeが4つのドングルと呼ばれるものを持っているとKubernetesに教えているだけです。 -Kubernetes APIサーバーに簡単にリクエストを送れるように、プロキシーを実行します。 +Kubernetes APIサーバーに簡単にリクエストを送れるように、プロキシを実行します。 ```shell kubectl proxy @@ -132,7 +132,7 @@ Host: k8s-master:8080 ] ``` -Kubernetes APIサーバーに簡単にリクエストを送れるように、プロキシーを実行します。 +Kubernetes APIサーバーに簡単にリクエストを送れるように、プロキシを実行します。 ```shell kubectl proxy diff --git a/content/ja/docs/tasks/administer-cluster/migrating-from-dockershim/check-if-dockershim-removal-affects-you.md b/content/ja/docs/tasks/administer-cluster/migrating-from-dockershim/check-if-dockershim-removal-affects-you.md index 3a719e29d710b..5535d10b03f18 100644 --- a/content/ja/docs/tasks/administer-cluster/migrating-from-dockershim/check-if-dockershim-removal-affects-you.md +++ b/content/ja/docs/tasks/administer-cluster/migrating-from-dockershim/check-if-dockershim-removal-affects-you.md @@ -33,7 +33,7 @@ Kubernetesの組み込みコンポーネントである`dockershim`はリリー [コンテナランタイム](/ja/docs/concepts/containers/#container-runtimes)とは、Kubernetes Podを構成するコンテナを実行できるソフトウェアです。 -KubernetesはPodのオーケストレーションとスケジューリングを担当し、各ノードでは{{< glossary_tooltip text="kubelet" term_id="kubelet" >}}がコンテナランタイムインターフェイスを抽象化して使用するので、互換性があればどのコンテナランタイムでも使用することができます。 +KubernetesはPodのオーケストレーションとスケジューリングを担当し、各ノードでは{{< glossary_tooltip text="kubelet" term_id="kubelet" >}}がコンテナランタイムインターフェースを抽象化して使用するので、互換性があればどのコンテナランタイムでも使用することができます。 初期のリリースでは、Kubernetesは1つのコンテナランタイムと互換性を提供していました: Dockerです。 その後、Kubernetesプロジェクトの歴史の中で、クラスター運用者は追加のコンテナランタイムを採用することを希望しました。 CRIはこのような柔軟性を可能にするために設計され、kubeletはCRIのサポートを開始しました。 diff --git a/content/ja/docs/tasks/administer-cluster/running-cloud-controller.md b/content/ja/docs/tasks/administer-cluster/running-cloud-controller.md index 52fc426f68b9f..7b5b8c6a068a6 100644 --- a/content/ja/docs/tasks/administer-cluster/running-cloud-controller.md +++ b/content/ja/docs/tasks/administer-cluster/running-cloud-controller.md @@ -64,7 +64,7 @@ Kubernetesのコアリポジトリにないクラウドコントローラーマ ### ボリュームのサポート -ボリュームの統合にはkubeletとの調整も必要になるためクラウドコントローラーマネージャーは`kube-controller-manager`にあるボリュームコントローラーを実装しません。CSI(コンテナストレージインターフェイス)が進化してFlexボリュームプラグインの強力なサポートが追加されるにつれ、クラウドがボリュームと完全に統合できるようクラウドコントローラーマネージャーに必要なサポートが追加されます。Kubernetesリポジトリの外部にあるCSIボリュームプラグインの詳細については[こちら](https://github.com/kubernetes/features/issues/178)をご覧ください。 +ボリュームの統合にはkubeletとの調整も必要になるためクラウドコントローラーマネージャーは`kube-controller-manager`にあるボリュームコントローラーを実装しません。CSI(コンテナストレージインターフェース)が進化してFlexボリュームプラグインの強力なサポートが追加されるにつれ、クラウドがボリュームと完全に統合できるようクラウドコントローラーマネージャーに必要なサポートが追加されます。Kubernetesリポジトリの外部にあるCSIボリュームプラグインの詳細については[こちら](https://github.com/kubernetes/features/issues/178)をご覧ください。 ### スケーラビリティ diff --git a/content/ja/docs/tasks/administer-cluster/securing-a-cluster.md b/content/ja/docs/tasks/administer-cluster/securing-a-cluster.md index e5cfd0d2dbc52..21e7bbe9976f8 100644 --- a/content/ja/docs/tasks/administer-cluster/securing-a-cluster.md +++ b/content/ja/docs/tasks/administer-cluster/securing-a-cluster.md @@ -35,7 +35,7 @@ Kubernetesは、クラスター内のすべてのAPI通信がデフォルトでT 例えば、シングルユーザーの小規模なクラスターでは、シンプルな証明書や静的なBearerトークンを使用することができます。 大規模なクラスターでは、ユーザーをグループに細分化できる既存のOIDCまたはLDAPサーバーを統合することができます。 -ノード、プロキシー、スケジューラー、ボリュームプラグインなど、インフラの一部であるものも含めて、すべてのAPIクライアントを認証する必要があります。 +ノード、プロキシ、スケジューラー、ボリュームプラグインなど、インフラの一部であるものも含めて、すべてのAPIクライアントを認証する必要があります。 これらのクライアントは通常、[service accounts](/docs/reference/access-authn-authz/service-accounts-admin/)であるか、またはx509クライアント証明書を使用しており、クラスター起動時に自動的に作成されるか、クラスターインストールの一部として設定されます。 詳細については、[認証](/ja/docs/reference/access-authn-authz/authentication/)を参照してください。 diff --git a/content/ja/docs/tasks/administer-cluster/use-cascading-deletion.md b/content/ja/docs/tasks/administer-cluster/use-cascading-deletion.md index ba8c6cc88e434..191e757275c01 100644 --- a/content/ja/docs/tasks/administer-cluster/use-cascading-deletion.md +++ b/content/ja/docs/tasks/administer-cluster/use-cascading-deletion.md @@ -56,7 +56,7 @@ kubectl delete deployment nginx-deployment --cascade=foreground **Kubernetes APIを使用する** -1. ローカルプロキシーセッションを開始します: +1. ローカルプロキシセッションを開始します: ```shell kubectl proxy --port=8080 @@ -107,7 +107,7 @@ kubectl delete deployment nginx-deployment --cascade=background **Kubernetes APIを使用する** -1. ローカルプロキシーセッションを開始します: +1. ローカルプロキシセッションを開始します: ```shell kubectl proxy --port=8080 @@ -151,7 +151,7 @@ kubectl delete deployment nginx-deployment --cascade=orphan **Kubernetes APIを使用する** -1. ローカルプロキシーセッションを開始します: +1. ローカルプロキシセッションを開始します: ```shell kubectl proxy --port=8080 diff --git a/content/ja/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes.md b/content/ja/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes.md index 1abc1b62d12c7..c93807f742fd9 100644 --- a/content/ja/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes.md +++ b/content/ja/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes.md @@ -117,7 +117,7 @@ liveness-exec 1/1 Running 1 1m ## HTTPリクエストによるLiveness Probeを定義する {#define-a-liveness-http-request} 別の種類のLiveness Probeでは、HTTP GETリクエストを使用します。 -次の構成ファイルは、`registry.k8s.io/liveness`イメージを使用したコンテナを起動するPodを作成します。 +次の構成ファイルは、`registry.k8s.io/e2e-test-images/agnhost`イメージを使用したコンテナを起動するPodを作成します。 {{% codenew file="pods/probe/http-liveness.yaml" %}} @@ -209,7 +209,6 @@ HTTPまたはTCPによるProbeにおいて、[ContainerPort](/docs/reference/gen ports: - name: liveness-port containerPort: 8080 - hostPort: 8080 livenessProbe: httpGet: @@ -231,7 +230,6 @@ livenessProbe: ports: - name: liveness-port containerPort: 8080 - hostPort: 8080 livenessProbe: httpGet: diff --git a/content/ja/docs/tasks/configure-pod-container/configure-pod-initialization.md b/content/ja/docs/tasks/configure-pod-container/configure-pod-initialization.md new file mode 100644 index 0000000000000..0ef6b45555d8e --- /dev/null +++ b/content/ja/docs/tasks/configure-pod-container/configure-pod-initialization.md @@ -0,0 +1,88 @@ +--- +title: Pod初期化の設定 +content_type: task +weight: 170 +--- + + + +このページでは、アプリケーションコンテナが実行される前に、Initコンテナを使用してPodを初期化する方法を示します。 + +## {{% heading "prerequisites" %}} + +{{< include "task-tutorial-prereqs.md" >}} {{< version-check >}} + + + +## Initコンテナを持つPodを作成する + +この演習では、アプリケーションコンテナが1つ、Initコンテナが1つのPodを作成します。 +Initコンテナはアプリケーションコンテナが実行される前に完了します。 + +Podの設定ファイルは次の通りです: + +{{% code_sample file="pods/init-containers.yaml" %}} + +設定ファイルを確認すると、PodはInitコンテナとアプリケーションコンテナが共有するボリュームを持っています。 + +Initコンテナは共有ボリュームを`/work-dir`にマウントし、アプリケーションコンテナは共有ボリュームを`/usr/share/nginx/html`にマウントします。 +Initコンテナは以下のコマンドを実行してから終了します: + +```shell +wget -O /work-dir/index.html http://info.cern.ch +``` + +Initコンテナは、nginxサーバーのルートディレクトリの`index.html`ファイルに書き込むことに注意してください。 + +Podを作成します: + +```shell +kubectl apply -f https://k8s.io/examples/pods/init-containers.yaml +``` + +nginxコンテナが実行中であることを確認します: + +```shell +kubectl get pod init-demo +``` + +次の出力はnginxコンテナが実行中であることを示します: + +``` +NAME READY STATUS RESTARTS AGE +init-demo 1/1 Running 0 1m +``` + +init-demo Podで実行中のnginxコンテナのシェルを取得します: + +```shell +kubectl exec -it init-demo -- /bin/bash +``` + +シェルで、nginxサーバーにGETリクエストを送信します: + +``` +root@nginx:~# apt-get update +root@nginx:~# apt-get install curl +root@nginx:~# curl localhost +``` + +出力は、Initコンテナが書き込んだウェブページをnginxが提供していることを示します: + +```html +
            +http://info.cern.ch +
            + +

            http://info.cern.ch - home of the first website

            + ... +
          • Browse the first website
          • + ... +``` + +## {{% heading "whatsnext" %}} + +* [同じPod内で実行されているコンテナ間の通信](/ja/docs/tasks/access-application-cluster/communicate-containers-same-pod-shared-volume/)についてもっと学ぶ。 +* [Initコンテナ](/ja/docs/concepts/workloads/pods/init-containers/)についてもっと学ぶ。 +* [ボリューム](/ja/docs/concepts/storage/volumes/)についてもっと学ぶ。 +* [Initコンテナのデバッグ](/ja/docs/tasks/debug/debug-application/debug-init-containers/)についてもっと学ぶ。 diff --git a/content/ja/docs/tasks/debug/debug-application/debug-service.md b/content/ja/docs/tasks/debug/debug-application/debug-service.md index 24c98eee1684f..a9f8cd2158deb 100644 --- a/content/ja/docs/tasks/debug/debug-application/debug-service.md +++ b/content/ja/docs/tasks/debug/debug-application/debug-service.md @@ -416,7 +416,7 @@ Endpointsリスト内の各Podは、それぞれの自身のホスト名を返 ## kube-proxyは機能しているか? {#is-the-kube-proxy-working} -ここに到達したのなら、Serviceは実行され、Endpointsがあり、Podが実際にサービスを提供しています。この時点で、Serviceのプロキシーメカニズム全体が疑わしいです。ひとつひとつ確認しましょう。 +ここに到達したのなら、Serviceは実行され、Endpointsがあり、Podが実際にサービスを提供しています。この時点で、Serviceのプロキシメカニズム全体が疑わしいです。ひとつひとつ確認しましょう。 Serviceのデフォルト実装、およびほとんどのクラスターで使用されるものは、kube-proxyです。kube-proxyはそれぞれのノードで実行され、Serviceの抽象化を提供するための小さなメカニズムセットの1つを構成するプログラムです。クラスターがkube-proxyを使用しない場合、以下のセクションは適用されず、使用しているServiceの実装を調査する必要があります。 @@ -494,7 +494,7 @@ TCP 10.0.1.175:80 rr 各Serviceの各ポートに加えて、NodePort、External IP、およびLoad Balancer IPに対して、kube-proxyは仮想サーバーを作成します。Pod endpointごとに、対応する実サーバーが作成されます。この例では、サービスhostnames(`10.0.1.175:80`)は3つのendpoints(`10.244.0.5:9376`、`10.244.0.6:9376`、`10.244.0.7:9376`)を持っています。 -IPVSプロキシーは、各Serviceアドレス(Cluster IP、External IP、NodePort IP、Load Balancer IPなど)毎の仮想サーバーと、Serviceのエンドポイントが存在する場合に対応する実サーバーを作成します。この例では、hostnames Service(`10.0.1.175:80`)は3つのエンドポイント(`10.244.0.5:9376`、`10.244.0.6:9376`、`10.244.0.7:9376`)を持ち、上と似た結果が得られるはずです。 +IPVSプロキシは、各Serviceアドレス(Cluster IP、External IP、NodePort IP、Load Balancer IPなど)毎の仮想サーバーと、Serviceのエンドポイントが存在する場合に対応する実サーバーを作成します。この例では、hostnames Service(`10.0.1.175:80`)は3つのエンドポイント(`10.244.0.5:9376`、`10.244.0.6:9376`、`10.244.0.7:9376`)を持ち、上と似た結果が得られるはずです。 #### Userspace mode @@ -525,7 +525,7 @@ curl 10.0.1.175:80 hostnames-632524106-bbpiw ``` -もしこれが失敗し、あなたがuserspaceプロキシーを使用している場合、プロキシーへの直接アクセスを試してみてください。もしiptablesプロキシーを使用している場合、このセクションはスキップしてください。 +もしこれが失敗し、あなたがuserspaceプロキシを使用している場合、プロキシへの直接アクセスを試してみてください。もしiptablesプロキシを使用している場合、このセクションはスキップしてください。 上記の`iptables-save`の出力を振り返り、`kube-proxy`がServiceに使用しているポート番号を抽出します。上記の例では"48577"です。このポートに接続してください。 diff --git a/content/ja/docs/tasks/debug/debug-application/determine-reason-pod-failure.md b/content/ja/docs/tasks/debug/debug-application/determine-reason-pod-failure.md index d977eba3f15d7..7f55a228c075f 100644 --- a/content/ja/docs/tasks/debug/debug-application/determine-reason-pod-failure.md +++ b/content/ja/docs/tasks/debug/debug-application/determine-reason-pod-failure.md @@ -90,11 +90,12 @@ spec: ## {{% heading "whatsnext" %}} - * [コンテナ](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#container-v1-core)の`terminationMessagePath`フィールド参照 -* [ログ取得](/docs/concepts/cluster-administration/logging/)について +* [イメージ](/ja/docs/concepts/containers/images/)の[ImagePullBackOff](/ja/docs/concepts/containers/images/#imagepullbackoff)を参照 +* [ログ取得](/ja/docs/concepts/cluster-administration/logging/)について * [Goテンプレート](https://pkg.go.dev/text/template)について - +* [Podのステータス](/ja/docs/tasks/debug/debug-application/debug-init-containers/#understanding-pod-status)と[Podのフェーズ](/ja/docs/concepts/workloads/pods/pod-lifecycle/#pod-phase)について +* [コンテナのステータス](/ja/docs/concepts/workloads/pods/pod-lifecycle/#container-states)について diff --git a/content/ja/docs/tasks/debug/debug-cluster/_index.md b/content/ja/docs/tasks/debug/debug-cluster/_index.md index feae8fbb33047..adb94d8eb7028 100644 --- a/content/ja/docs/tasks/debug/debug-cluster/_index.md +++ b/content/ja/docs/tasks/debug/debug-cluster/_index.md @@ -9,7 +9,9 @@ no_list: true このドキュメントはクラスターのトラブルシューティングに関するもので、あなたが経験している問題の根本原因として、アプリケーションをすでに除外していることを前提としています。 アプリケーションのデバッグのコツは、[アプリケーションのトラブルシューティングガイド](/ja/docs/tasks/debug/debug-application/)をご覧ください。 -また、[トラブルシューティングドキュメント](/ja/docs/tasks/debug/debug)にも詳しい情報があります。 +また、[トラブルシューティングドキュメント](/docs/tasks/debug/)にも詳しい情報があります。 + +{{}}のトラブルシューティングについては、[kubectlのトラブルシューティング](/docs/tasks/debug/debug-cluster/troubleshoot-kubectl/)を参照してください。 @@ -17,6 +19,8 @@ no_list: true クラスターで最初にデバッグするのは、ノードがすべて正しく登録されているかどうかです。 +以下を実行します。 + ```shell kubectl get nodes ``` @@ -28,22 +32,207 @@ kubectl get nodes ```shell kubectl cluster-info dump ``` + +### 例: ダウンあるいは到達不能なノードのデバッグ + +デバッグを行う際、ノードの状態を見ることが有用なことがあります。 +たとえば、そのノード上で動作しているPodが奇妙な挙動を示している場合や、なぜPodがそのノードにスケジュールされないのかを知りたい場合などです。 +Podと同様に、`kubectl describe node`や`kubectl get node -o yaml`を使用してノードに関する詳細情報を取得できます。 +例えば、ノードがダウンしている(ネットワークから切断されている、またはkubeletが停止して再起動しないなど)場合に見られる状況は以下の通りです。 +ノードがNotReadyであることを示すイベントに注意し、また、Podが動作していないことにも注意してください(NotReady状態が5分間続くとPodは追い出されます)。 + +```shell +kubectl get nodes +``` + +```none +NAME STATUS ROLES AGE VERSION +kube-worker-1 NotReady 1h v1.23.3 +kubernetes-node-bols Ready 1h v1.23.3 +kubernetes-node-st6x Ready 1h v1.23.3 +kubernetes-node-unaj Ready 1h v1.23.3 +``` + +```shell +kubectl describe node kube-worker-1 +``` + +```none +Name: kube-worker-1 +Roles: +Labels: beta.kubernetes.io/arch=amd64 + beta.kubernetes.io/os=linux + kubernetes.io/arch=amd64 + kubernetes.io/hostname=kube-worker-1 + kubernetes.io/os=linux +Annotations: kubeadm.alpha.kubernetes.io/cri-socket: /run/containerd/containerd.sock + node.alpha.kubernetes.io/ttl: 0 + volumes.kubernetes.io/controller-managed-attach-detach: true +CreationTimestamp: Thu, 17 Feb 2022 16:46:30 -0500 +Taints: node.kubernetes.io/unreachable:NoExecute + node.kubernetes.io/unreachable:NoSchedule +Unschedulable: false +Lease: + HolderIdentity: kube-worker-1 + AcquireTime: + RenewTime: Thu, 17 Feb 2022 17:13:09 -0500 +Conditions: + Type Status LastHeartbeatTime LastTransitionTime Reason Message + ---- ------ ----------------- ------------------ ------ ------- + NetworkUnavailable False Thu, 17 Feb 2022 17:09:13 -0500 Thu, 17 Feb 2022 17:09:13 -0500 WeaveIsUp Weave pod has set this + MemoryPressure Unknown Thu, 17 Feb 2022 17:12:40 -0500 Thu, 17 Feb 2022 17:13:52 -0500 NodeStatusUnknown Kubelet stopped posting node status. + DiskPressure Unknown Thu, 17 Feb 2022 17:12:40 -0500 Thu, 17 Feb 2022 17:13:52 -0500 NodeStatusUnknown Kubelet stopped posting node status. + PIDPressure Unknown Thu, 17 Feb 2022 17:12:40 -0500 Thu, 17 Feb 2022 17:13:52 -0500 NodeStatusUnknown Kubelet stopped posting node status. + Ready Unknown Thu, 17 Feb 2022 17:12:40 -0500 Thu, 17 Feb 2022 17:13:52 -0500 NodeStatusUnknown Kubelet stopped posting node status. +Addresses: + InternalIP: 192.168.0.113 + Hostname: kube-worker-1 +Capacity: + cpu: 2 + ephemeral-storage: 15372232Ki + hugepages-2Mi: 0 + memory: 2025188Ki + pods: 110 +Allocatable: + cpu: 2 + ephemeral-storage: 14167048988 + hugepages-2Mi: 0 + memory: 1922788Ki + pods: 110 +System Info: + Machine ID: 9384e2927f544209b5d7b67474bbf92b + System UUID: aa829ca9-73d7-064d-9019-df07404ad448 + Boot ID: 5a295a03-aaca-4340-af20-1327fa5dab5c + Kernel Version: 5.13.0-28-generic + OS Image: Ubuntu 21.10 + Operating System: linux + Architecture: amd64 + Container Runtime Version: containerd://1.5.9 + Kubelet Version: v1.23.3 + Kube-Proxy Version: v1.23.3 +Non-terminated Pods: (4 in total) + Namespace Name CPU Requests CPU Limits Memory Requests Memory Limits Age + --------- ---- ------------ ---------- --------------- ------------- --- + default nginx-deployment-67d4bdd6f5-cx2nz 500m (25%) 500m (25%) 128Mi (6%) 128Mi (6%) 23m + default nginx-deployment-67d4bdd6f5-w6kd7 500m (25%) 500m (25%) 128Mi (6%) 128Mi (6%) 23m + kube-system kube-proxy-dnxbz 0 (0%) 0 (0%) 0 (0%) 0 (0%) 28m + kube-system weave-net-gjxxp 100m (5%) 0 (0%) 200Mi (10%) 0 (0%) 28m +Allocated resources: + (Total limits may be over 100 percent, i.e., overcommitted.) + Resource Requests Limits + -------- -------- ------ + cpu 1100m (55%) 1 (50%) + memory 456Mi (24%) 256Mi (13%) + ephemeral-storage 0 (0%) 0 (0%) + hugepages-2Mi 0 (0%) 0 (0%) +Events: +... +``` + +```shell +kubectl get node kube-worker-1 -o yaml +``` + +```yaml +apiVersion: v1 +kind: Node +metadata: + annotations: + kubeadm.alpha.kubernetes.io/cri-socket: /run/containerd/containerd.sock + node.alpha.kubernetes.io/ttl: "0" + volumes.kubernetes.io/controller-managed-attach-detach: "true" + creationTimestamp: "2022-02-17T21:46:30Z" + labels: + beta.kubernetes.io/arch: amd64 + beta.kubernetes.io/os: linux + kubernetes.io/arch: amd64 + kubernetes.io/hostname: kube-worker-1 + kubernetes.io/os: linux + name: kube-worker-1 + resourceVersion: "4026" + uid: 98efe7cb-2978-4a0b-842a-1a7bf12c05f8 +spec: {} +status: + addresses: + - address: 192.168.0.113 + type: InternalIP + - address: kube-worker-1 + type: Hostname + allocatable: + cpu: "2" + ephemeral-storage: "14167048988" + hugepages-2Mi: "0" + memory: 1922788Ki + pods: "110" + capacity: + cpu: "2" + ephemeral-storage: 15372232Ki + hugepages-2Mi: "0" + memory: 2025188Ki + pods: "110" + conditions: + - lastHeartbeatTime: "2022-02-17T22:20:32Z" + lastTransitionTime: "2022-02-17T22:20:32Z" + message: Weave pod has set this + reason: WeaveIsUp + status: "False" + type: NetworkUnavailable + - lastHeartbeatTime: "2022-02-17T22:20:15Z" + lastTransitionTime: "2022-02-17T22:13:25Z" + message: kubelet has sufficient memory available + reason: KubeletHasSufficientMemory + status: "False" + type: MemoryPressure + - lastHeartbeatTime: "2022-02-17T22:20:15Z" + lastTransitionTime: "2022-02-17T22:13:25Z" + message: kubelet has no disk pressure + reason: KubeletHasNoDiskPressure + status: "False" + type: DiskPressure + - lastHeartbeatTime: "2022-02-17T22:20:15Z" + lastTransitionTime: "2022-02-17T22:13:25Z" + message: kubelet has sufficient PID available + reason: KubeletHasSufficientPID + status: "False" + type: PIDPressure + - lastHeartbeatTime: "2022-02-17T22:20:15Z" + lastTransitionTime: "2022-02-17T22:15:15Z" + message: kubelet is posting ready status. AppArmor enabled + reason: KubeletReady + status: "True" + type: Ready + daemonEndpoints: + kubeletEndpoint: + Port: 10250 + nodeInfo: + architecture: amd64 + bootID: 22333234-7a6b-44d4-9ce1-67e31dc7e369 + containerRuntimeVersion: containerd://1.5.9 + kernelVersion: 5.13.0-28-generic + kubeProxyVersion: v1.23.3 + kubeletVersion: v1.23.3 + machineID: 9384e2927f544209b5d7b67474bbf92b + operatingSystem: linux + osImage: Ubuntu 21.10 + systemUUID: aa829ca9-73d7-064d-9019-df07404ad448 +``` + ## ログの確認 今のところ、クラスターをより深く掘り下げるには、関連するマシンにログインする必要があります。 以下は、関連するログファイルの場所です。 -(systemdベースのシステムでは、代わりに `journalctl` を使う必要があるかもしれないことに注意してください) +(systemdベースのシステムでは、代わりに`journalctl`を使う必要があるかもしれないことに注意してください) -### マスターノード +### コントロールプレーンノード - * `/var/log/kube-apiserver.log` - APIの提供を担当するAPIサーバーのログ - * `/var/log/kube-scheduler.log` - スケジューリング決定責任者であるスケジューラーのログ - * `/var/log/kube-controller-manager.log` - レプリケーションコントローラーを管理するコントローラーのログ +* `/var/log/kube-apiserver.log` - APIの提供を担当するAPIサーバーのログ +* `/var/log/kube-scheduler.log` - スケジューリング決定責任者であるスケジューラーのログ +* `/var/log/kube-controller-manager.log` - スケジューリングを除く、ほとんどのKubernetes組み込みの{{}}を実行するコンポーネントのログ(スケジューリングはkube-schedulerが担当します) ### ワーカーノード - * `/var/log/kubelet.log` - ノード上でコンテナの実行を担当するKubeletのログ - * `/var/log/kube-proxy.log` - サービスのロードバランシングを担うKube Proxyのログ +* `/var/log/kubelet.log` - ノード上でコンテナの実行を担当するKubeletのログ +* `/var/log/kube-proxy.log` - サービスのロードバランシングを担うKube Proxyのログ ## クラスター障害モードの一般的な概要 @@ -51,36 +240,41 @@ kubectl cluster-info dump ### 根本的な原因 - - VMのシャットダウン - - クラスター内、またはクラスターとユーザー間のネットワークパーティション - - Kubernetesソフトウェアのクラッシュ - - データの損失や永続的ストレージ(GCE PDやAWS EBSボリュームなど)の使用不能 - - Kubernetesソフトウェアやアプリケーションソフトウェアの設定ミスなど、オペレーターのミス +- VMのシャットダウン +- クラスター内、またはクラスターとユーザー間のネットワークパーティション +- Kubernetesソフトウェアのクラッシュ +- データの損失や永続的ストレージ(GCE PDやAWS EBSボリュームなど)の使用不能 +- Kubernetesソフトウェアやアプリケーションソフトウェアの設定ミスなど、オペレーターのミス ### 具体的なシナリオ - - apiserver VMのシャットダウンまたはapiserverのクラッシュ +- apiserver VMのシャットダウンまたはapiserverのクラッシュ + - その結果 - 新しいPod、サービス、レプリケーションコントローラーの停止、更新、起動ができない - Kubernetes APIに依存していない限り、既存のPodやサービスは正常に動作し続けるはずです - - apiserverのバックアップストレージが失われた +- apiserverのバックアップストレージが失われた + - その結果 - apiserverが立ち上がらない - - kubeletsは到達できなくなりますが、同じPodを実行し、同じサービスのプロキシを提供し続けます + - kubeletは到達できなくなりますが、同じPodを実行し、同じサービスのプロキシを提供し続けます - apiserverを再起動する前に、手動でapiserverの状態を回復または再現する必要がある - - サポートサービス(ノードコントローラー、レプリケーションコントローラーマネージャー、スケジューラーなど)VMのシャットダウンまたはクラッシュ - - 現在、これらはapiserverとコロケーションしており、使用できない場合はapiserverと同様の影響があります - - 将来的には、これらも複製されるようになり、同じ場所に配置されない可能性があります - - 独自の永続的な状態を持っていない。 - - - 個別ノード(VMまたは物理マシン)のシャットダウン +- サポートサービス(ノードコントローラー、レプリケーションコントローラーマネージャー、スケジューラーなど)VMのシャットダウンまたはクラッシュ + - 現在、これらはapiserverとコロケーションしており、使用できない場合はapiserverと同様の影響があります + - 将来的には、これらも複製されるようになり、同じ場所に配置されない可能性があります + - 独自の永続的な状態を持っていない +- 個別ノード(VMまたは物理マシン)のシャットダウン + - その結果 - そのノード上のPodの実行を停止 - - ネットワークパーティション +- ネットワークパーティション + - その結果 - パーティションAはパーティションBのノードがダウンしていると考え、パーティションBはapiserverがダウンしていると考えています。(マスターVMがパーティションAで終了したと仮定) - - Kubeletソフトウェア障害 +- Kubeletソフトウェア障害 + - その結果 - クラッシュしたkubeletがノード上で新しいPodを起動できない - kubeletがPodを削除するかどうか - ノードが不健全と判定される - レプリケーションコントローラーが別の場所で新しいPodを起動する - - クラスターオペレーターエラー +- クラスターオペレーターエラー + - その結果 - PodやServiceなどの損失 - apiserverのバックエンドストレージの紛失 - ユーザーがAPIを読めなくなる @@ -99,10 +293,10 @@ kubectl cluster-info dump - 異常: コントロールプレーンノードのシャットダウンまたはコントロールプレーンコンポーネント(スケジューラー、APIサーバー、コントローラーマネージャー)のクラッシュ - 1つ以上のノードまたはコンポーネントの同時故障に耐えることができる - 異常: APIサーバーのバックアップストレージ(etcdのデータディレクトリーなど)が消失 - - HA(高可用性) etcdの構成を想定しています + - HA(高可用性)etcdの構成を想定しています - 対処法: apiserver PDs/EBS-volumesを定期的にスナップショットする - - 異常: Apiserver のバックエンドストレージが失われる + - 異常: Apiserverのバックエンドストレージが失われる - 異常: 操作ミスが発生する場合がある - 異常: Kubernetesのソフトウェアに障害が発生する場合がある @@ -113,3 +307,13 @@ kubectl cluster-info dump - 対処法: 予期せぬ再起動に耐えられるように設計されたアプリケーション(コンテナ) - 異常: ノードのシャットダウン - 異常: Kubeletソフトウェア障害 + +## {{% heading "whatsnext" %}} + +* [リソースメトリクスパイプライン](/ja/docs/tasks/debug/debug-cluster/resource-metrics-pipeline/)で利用可能なメトリクスについて学ぶ +* [リソース使用状況の監視](/ja/docs/tasks/debug/debug-cluster/resource-usage-monitoring/)に役立つ追加ツールを探す +* Node Problem Detectorを使用して[ノードの健康状態を監視する](/ja/docs/tasks/debug/debug-cluster/monitor-node-health/) +* `kubectl debug node`を使用して[Kubernetesノードをデバッグする](/docs/tasks/debug/debug-cluster/kubectl-node-debug) +* `crictl`を使用して[Kubernetesノードをデバッグする](/ja/docs/tasks/debug/debug-cluster/crictl/) +* [Kubernetesの監査](/ja/docs/tasks/debug/debug-cluster/audit/)に関する詳細な情報を得る +* `telepresence`を使用して[ローカルでサービスを開発・デバッグする](/ja/docs/tasks/debug/debug-cluster/local-debugging/) diff --git a/content/ja/docs/tasks/debug/debug-cluster/crictl.md b/content/ja/docs/tasks/debug/debug-cluster/crictl.md index 2fa6d030cb304..068af5a5bb32b 100644 --- a/content/ja/docs/tasks/debug/debug-cluster/crictl.md +++ b/content/ja/docs/tasks/debug/debug-cluster/crictl.md @@ -9,7 +9,7 @@ weight: 30 {{< feature-state for_k8s_version="v1.11" state="stable" >}} -`crictl`はCRI互換のコンテナランタイム用のコマンドラインインターフェイスです。 +`crictl`はCRI互換のコンテナランタイム用のコマンドラインインターフェースです。 これを使って、Kubernetesノード上のコンテナランタイムやアプリケーションの検査やデバッグを行うことができます。 `crictl`とそのソースコードは[cri-tools](https://github.com/kubernetes-sigs/cri-tools)リポジトリにホストされています。 diff --git a/content/ja/docs/tasks/debug/debug-cluster/kubectl-node-debug.md b/content/ja/docs/tasks/debug/debug-cluster/kubectl-node-debug.md new file mode 100644 index 0000000000000..ec3e4d27314d2 --- /dev/null +++ b/content/ja/docs/tasks/debug/debug-cluster/kubectl-node-debug.md @@ -0,0 +1,102 @@ +--- +title: Kubectlを用いたKubernetesノードのデバッグ +content_type: task +min-kubernetes-server-version: 1.20 +--- + + +このページでは、Kubernetesクラスター上で動作している[ノード](/ja/docs/concepts/architecture/nodes/)を`kubectl debug`コマンドを使用してデバッグする方法について説明します。 + +## {{% heading "prerequisites" %}} + +{{< include "task-tutorial-prereqs.md" >}} {{< version-check >}} + +Podを作成し、それらの新しいPodを任意のノードに割り当てる権限が必要です。 +また、ホストのファイルシステムにアクセスするPodを作成する権限も必要です。 + + + +## `kubectl debug node`を用いてノードをデバッグする + +`kubectl debug node`コマンドを使用して、トラブルシューティングしたいノードにPodをデプロイします。 +このコマンドは、SSH接続を使用してノードにアクセスできないシナリオで役に立ちます。 +Podが作成されると、そのPodはノード上で対話型シェルを開きます。 +mynodeという名前のノード上で対話型シェルを作成するには、次のように実行します。 + +```shell +kubectl debug node/mynode -it --image=ubuntu +``` + +```console +ノードmynode上に、コンテナデバッガーを持つデバッグ用Pod、node-debugger-mynode-pdx84を作成します。 +コマンドプロンプトが表示されない場合は、エンターキーを押してみてください。 +root@mynode:/# +``` + +デバッグコマンドは、情報を収集し、問題をトラブルシューティングするのに役立ちます。 +使用する可能性のあるコマンドには、`ip`、`ifconfig`、`nc`、`ping`、`ps`などがあります。 +また、`mtr`、`tcpdump`、`curl`などの他のツールもそれぞれのパッケージマネージャーからインストールすることができます。 + +{{< note >}} + +デバッグコマンドは、デバッグ用のPodが使用しているイメージに基づいて異なる場合があり、これらのコマンドをインストールする必要があるかもしれません。 + +{{< /note >}} + +デバッグ用のPodは、Pod内の`/host`にマウントされたノードのルートファイルシステムにアクセスできます。 +kubeletをファイルシステムのネームスペースで実行している場合、デバッグ用のPodはそのネームスペースのルートを見ることになり、ノード全体のルートではありません。 +典型的なLinuxノードの場合、関連するログを見つけるために以下のパスを確認できます。 + +`/host/var/log/kubelet.log` +: ノード上でコンテナを実行する責任がある`kubelet`からのログです。 + +`/host/var/log/kube-proxy.log` +: サービスのエンドポイントへのトラフィックを指示する責任がある`kube-proxy`からのログです。 + +`/host/var/log/containerd.log` +: ノード上で実行されている`containerd`プロセスからのログです。 + +`/host/var/log/syslog` +: システムに関する一般的なメッセージや情報です。 + +`/host/var/log/kern.log` +: カーネルログです。 + +ノード上でデバッグセッションを作成する際には、以下の点を考慮してください。 + +* `kubectl debug`は、新しいPodの名前をノードの名前に基づいて自動的に生成します。 +* ノードのルートファイルシステムは`/host`にマウントされます。 +* コンテナはホストのIPC、ネットワーク、PID Namespaceで実行されますが、Podは特権を持っていません。 + これは、一部のプロセス情報の読み取りが失敗する可能性があることを意味します。 + その情報へのアクセスはスーパーユーザーに制限されているためです。 + 例えば、`chroot /host`は失敗します。 + 特権Podが必要な場合は、手動で作成してください。 + +## {{% heading "cleanup" %}} + +デバッグ用のPodの使用が終了したら、それを削除してください。 + +```shell +kubectl get pods +``` + +```none +NAME READY STATUS RESTARTS AGE +node-debugger-mynode-pdx84 0/1 Completed 0 8m1s +``` + +```shell +# Podの名前は適宜変更してください +kubectl delete pod node-debugger-mynode-pdx84 --now +``` + +```none +pod "node-debugger-mynode-pdx84" deleted +``` + +{{< note >}} + +ノードがダウンしている場合(ネットワークから切断されている、kubeletが停止して再起動しないなど)、`kubectl debug node`コマンドは機能しません。 +その場合は、[ダウンあるいは到達不能なノードのデバッグ](/ja/docs/tasks/debug/debug-cluster/#example-debugging-a-down-unreachable-node)を確認してください。 + +{{< /note >}} diff --git a/content/ja/docs/tasks/debug/debug-cluster/local-debugging.md b/content/ja/docs/tasks/debug/debug-cluster/local-debugging.md index 624d52b972137..2f73c26ecd3b4 100644 --- a/content/ja/docs/tasks/debug/debug-cluster/local-debugging.md +++ b/content/ja/docs/tasks/debug/debug-cluster/local-debugging.md @@ -7,7 +7,7 @@ content_type: task Kubernetesアプリケーションは通常、複数の独立したサービスから構成され、それぞれが独自のコンテナで動作しています。これらのサービスをリモートのKubernetesクラスター上で開発・デバッグするには、[実行中のコンテナへのシェルを取得](/ja/docs/tasks/debug/debug-application/get-shell-running-container/)してリモートシェル内でツールを実行しなければならず面倒な場合があります。 -`telepresence`は、リモートKubernetesクラスターにサービスをプロキシーしながら、ローカルでサービスを開発・デバッグするプロセスを容易にするためのツールです。 +`telepresence`は、リモートKubernetesクラスターにサービスをプロキシしながら、ローカルでサービスを開発・デバッグするプロセスを容易にするためのツールです。 `telepresence` を使用すると、デバッガーやIDEなどのカスタムツールをローカルサービスで使用でき、ConfigMapやsecret、リモートクラスター上で動作しているサービスへのフルアクセスをサービスに提供します。 このドキュメントでは、リモートクラスター上で動作しているサービスをローカルで開発・デバッグするために`telepresence`を使用する方法を説明します。 @@ -36,7 +36,7 @@ Kubernetes上でアプリケーションを開発する場合、通常は1つの そのサービスは、テストやデバッグのために他のサービスへのアクセスを必要とする場合があります。 継続的なデプロイメントパイプラインを使用することも一つの選択肢ですが、最速のデプロイメントパイプラインでさえ、プログラムやデバッグサイクルに遅延が発生します。 -既存のデプロイメントとtelepresenceプロキシーを交換するには、`--swap-deployment` オプションを使用します。 +既存のデプロイメントとtelepresenceプロキシを交換するには、`--swap-deployment` オプションを使用します。 スワップすることで、ローカルでサービスを実行し、リモートのKubernetesクラスターに接続することができます。 リモートクラスター内のサービスは、ローカルで実行されているインスタンスにアクセスできるようになりました。 diff --git a/content/ja/docs/tasks/debug/debug-cluster/windows.md b/content/ja/docs/tasks/debug/debug-cluster/windows.md new file mode 100644 index 0000000000000..0ceb1f00a5779 --- /dev/null +++ b/content/ja/docs/tasks/debug/debug-cluster/windows.md @@ -0,0 +1,152 @@ +--- +title: WindowsデバッグTips +content_type: concept +--- + + + + + +## ノードレベルのトラブルシューティング{#troubleshooting-node} + +1. Podが"Container Creating"と表示されたまま動かなくなったり、何度も再起動を繰り返します + + pauseイメージがWindows OSのバージョンと互換性があることを確認してください。 + 最新/推奨のpauseイメージや詳細情報については、[Pauseコンテナ](/docs/concepts/windows/intro/#pause-container)を参照してください。 + + {{< note >}} + コンテナランタイムとしてcontainerdを使用している場合、pauseイメージはconfig.toml設定ファイルの`plugins.plugins.cri.sandbox_image`フィールドで指定されます。 + {{< /note >}} + +1. Podが`ErrImgPull`または`ImagePullBackOff`のステータスを表示します + + Podが[互換性](https://learn.microsoft.com/ja-jp/virtualization/windowscontainers/deploy-containers/version-compatibility)のあるWindowsノードにスケジュールされていることを確認してください。 + + Podに対して互換性のあるノードを指定する方法の詳細については、[このガイド](/docs/concepts/windows/user-guide/#ensuring-os-specific-workloads-land-on-the-appropriate-container-host)を参照してください。 + +## ネットワークのトラブルシューティング{#troubleshooting-network} + +1. Windows Podがネットワークに接続できません + + 仮想マシンを使用している場合は、すべてのVMのネットワークアダプターでMACスプーフィングが**有効**になっていることを確認してください。 + +1. Windows Podから外部リソースにpingできません + + Windows Podには、ICMPプロトコル用にプログラムされたアウトバウンドルールはありません。ただし、TCP/UDPはサポートされています。 + クラスター外のリソースへの接続を実証する場合は、`ping `を対応する`curl `コマンドに置き換えてください。 + + それでも問題が解決しない場合は、[cni.conf](https://github.com/Microsoft/SDN/blob/master/Kubernetes/flannel/l2bridge/cni/config/cni.conf)のネットワーク設定に問題がある可能性が高いです。 + この静的ファイルはいつでも編集できます。 + 設定の更新は、新しく作成されたすべてのKubernetesリソースに適用されます。 + + Kubernetesのネットワーク要件の1つ([Kubernetesモデル](/ja/docs/concepts/cluster-administration/networking/)を参照)は、内部でNATせずにクラスター通信が行われることです。 + この要件を満たすために、アウトバウンドのNATを発生させたくないすべての通信のための[ExceptionList](https://github.com/Microsoft/SDN/blob/master/Kubernetes/flannel/l2bridge/cni/config/cni.conf#L20)があります。 + ただしこれは、クエリしようとしている外部IPを`ExceptionList`から除外する必要があることも意味します。 + そうして初めて、Windows Podからのトラフィックが正しくSNATされ、外部からの応答を受信できるようになります。 + この点について、`cni.conf`の`ExceptionList`は次のようになります: + + ```conf + "ExceptionList": [ + "10.244.0.0/16", # クラスターのサブネット + "10.96.0.0/12", # Serviceのサブネット + "10.127.130.0/24" # 管理(ホスト)のサブネット + ] + ``` + +1. Windowsノードが`NodePort`タイプのServiceにアクセスできません + + ノード自身からのローカルNodePortへのアクセスは失敗します。 + これは既知の制限です。 + NodePortへのアクセスは、他のノードや外部のクライアントからは動作します。 + +1. コンテナのvNICとHNSエンドポイントが削除されています + + この問題は`hostname-override`パラメーターが[kube-proxy](/docs/reference/command-line-tools-reference/kube-proxy/) + に渡されていない場合に発生する可能性があります。 + これを解決するためには、ユーザーは次のようにkube-proxyにホスト名を渡す必要があります: + + ```powershell + C:\k\kube-proxy.exe --hostname-override=$(hostname) + ``` + +1. WindowsノードがService IPを使用してサービスにアクセスできません + + これはWindows上のネットワークスタックの既知の制限です。 + ただし、Windows PodはService IPにアクセスできます。 + +1. kubeletの起動時にネットワークアダプターが見つかりません + + Windowsのネットワーキングスタックでは、Kubernetesネットワーキングが動作するために仮想アダプターが必要です。 + (管理者シェルで)次のコマンドを実行しても結果が返されない場合、kubeletが動作するために必要な前提条件である仮想ネットワークの作成に失敗しています。 + + ```powershell + Get-HnsNetwork | ? Name -ieq "cbr0" + Get-NetAdapter | ? Name -Like "vEthernet (Ethernet*" + ``` + + ホストのネットワークアダプターが"Ethernet"ではない場合、`start.ps1`スクリプトの[InterfaceName](https://github.com/microsoft/SDN/blob/master/Kubernetes/flannel/start.ps1#L7)パラメーターを修正することが有益です。 + それ以外の場合は、`start-kubelet.ps1`スクリプトの出力結果を参照して、仮想ネットワークの作成中にエラーが発生していないか確認します。 + +1. DNS名前解決が正しく動作しません + + この[セクション](/ja/docs/concepts/services-networking/dns-pod-service/#dns-windows)のWindowsにおけるDNSの制限について確認してください。 + +1. `kubectl port-forward`が"unable to do port forwarding: wincat not found"で失敗します + + これは、pauseインフラコンテナ`mcr.microsoft.com/oss/kubernetes/pause:3.6`に`wincat.exe`を含める形で、Kubernetes 1.15にて実装されました。 + 必ずサポートされたKubernetesのバージョンを使用してください。 + 独自のpauseインフラコンテナをビルドしたい場合は、必ず[wincat](https://github.com/kubernetes/kubernetes/tree/master/build/pause/windows/wincat)を含めるようにしてください。 + +1. Windows Serverノードがプロキシの背後にあるため、Kubernetesのインストールに失敗しています + + プロキシの背後にある場合は、次のPowerShell環境変数が定義されている必要があります: + + ```PowerShell + [Environment]::SetEnvironmentVariable("HTTP_PROXY", "http://proxy.example.com:80/", [EnvironmentVariableTarget]::Machine) + [Environment]::SetEnvironmentVariable("HTTPS_PROXY", "http://proxy.example.com:443/", [EnvironmentVariableTarget]::Machine) + ``` + +### Flannelのトラブルシューティング + +1. Flannelを使用すると、クラスターに再参加した後にノードに問題が発生します + + 以前に削除したノードがクラスターに再参加すると、flanneldはノードに新しいPodサブネットを割り当てようとします。 + ユーザーは、次のパスにある古いPodサブネットの設定ファイルを削除する必要があります: + + ```powershell + Remove-Item C:\k\SourceVip.json + Remove-Item C:\k\SourceVipRequest.json + ``` + +1. Flanneldが"Waiting for the Network to be created"と表示されたままになります + + この[Issue](https://github.com/coreos/flannel/issues/1066)に関する多数の報告があります; + 最も可能性が高いのは、flannelネットワークの管理IPが設定されるタイミングの問題です。 + 回避策は、`start.ps1`を再度実行するか、次のように手動で再起動することです: + + ```powershell + [Environment]::SetEnvironmentVariable("NODE_NAME", "") + C:\flannel\flanneld.exe --kubeconfig-file=c:\k\config --iface= --ip-masq=1 --kube-subnet-mgr=1 + ``` + +1. `/run/flannel/subnet.env`が見つからないためにWindows Podが起動しません + + これはFlannelが正常に起動できなかったことを示しています。 + `flanneld.exe`を再起動するか、Kubernetesマスター上の`/run/flannel/subnet.env`をWindowsワーカーノード上の`C:\run\flannel\subnet.env`に手動でコピーして、`FLANNEL_SUBNET`行を異なる数値に変更します。 + 例えば、ノードのサブネットを10.244.4.1/24としたい場合は次のようにします: + + ```env + FLANNEL_NETWORK=10.244.0.0/16 + FLANNEL_SUBNET=10.244.4.1/24 + FLANNEL_MTU=1500 + FLANNEL_IPMASQ=true + ``` + +### さらなる調査 + +これらの手順で問題が解決しない場合は、下記からKubernetesのWindowsノード上でWindowsコンテナを実行するためのヘルプを得ることができます: + +* StackOverflowの[Windows Server Container](https://stackoverflow.com/questions/tagged/windows-server-container)トピック +* Kubernetesの公式フォーラム[discuss.kubernetes.io](https://discuss.kubernetes.io/) +* Kubernetes Slack [#SIG-Windowsチャンネル](https://kubernetes.slack.com/messages/sig-windows) + diff --git a/content/ja/docs/tasks/inject-data-application/define-command-argument-container.md b/content/ja/docs/tasks/inject-data-application/define-command-argument-container.md new file mode 100644 index 0000000000000..b37f6ce2e9bcf --- /dev/null +++ b/content/ja/docs/tasks/inject-data-application/define-command-argument-container.md @@ -0,0 +1,97 @@ +--- +title: コンテナにコマンドと引数を定義する +content_type: task +weight: 10 +--- + + + +このページでは、{{< glossary_tooltip term_id="pod" >}}でコンテナを実行するときにコマンドと引数を定義する方法を説明します。 + + + + +## {{% heading "prerequisites" %}} + + +{{< include "task-tutorial-prereqs.md" >}} {{< version-check >}} + + + + + + +## Podの作成時にコマンドと引数を定義する + +Podを作成するときに、Pod内で実行するコンテナのコマンドと引数を定義できます。コマンドを定義するには、設定ファイルに`command`フィールドを記述します。コマンドの引数を定義するには、設定ファイルに`args`フィールドを記述します。定義したコマンドと引数はPodの作成後に変更することはできません。 + +設定ファイルで定義したコマンドと引数は、コンテナイメージが提供するデフォルトのコマンドと引数を上書きします。引数を定義し、コマンドを定義しなかった場合、デフォルトのコマンドと新しい引数が使用されます。 + +{{< note >}} +`command`フィールドは、いくつかのコンテナランタイムではエントリポイントに相当します。 +{{< /note >}} + +この演習では、1つのコンテナを実行するPodを作成します。Podの設定ファイルには、コマンドと2つの引数を定義します。 + +{{% code_sample file="pods/commands.yaml" %}} + +1. YAMLの設定ファイルに基づいてPodを作成 + + ```shell + kubectl apply -f https://k8s.io/examples/pods/commands.yaml + ``` + +1. 実行中のPodをリストアップ + + ```shell + kubectl get pods + ``` + + 出力は、command-demo Podで実行されたコンテナが完了したことを示します。 + +1. コンテナ内で実行されたコマンドの出力を確認するためにPodのログを見る + + ```shell + kubectl logs command-demo + ``` + + 出力は、HOSTNAMEとKUBERNETES_PORT環境変数の値を示します。 + + ```text + command-demo + tcp://10.3.240.1:443 + ``` + +## 環境変数を使って引数を定義する + +前述の例では、文字列を指定して引数を直接定義しました。文字列を直接指定する代わりに、環境変数を使用して引数を定義することもできます。 + + +```yaml +env: +- name: MESSAGE + value: "hello world" +command: ["/bin/echo"] +args: ["$(MESSAGE)"] +``` + +つまり、[ConfigMap](/ja/docs/tasks/configure-pod-container/configure-pod-configmap/)や[Secret](/ja/docs/concepts/configuration/secret/)など、環境変数を定義するために利用可能な技術のどれを使っても、Podの引数を定義できるということです。 + +{{< note >}} +環境変数は`"$(VAR)"`という括弧で囲まれて表示されます。これは、`command`や`args`フィールドで変数を展開するために必要です。 +{{< /note >}} + +## シェルでコマンドを実行する + +シェルでコマンドを実行する必要がある場合もあります。例えば、コマンドが複数のコマンドをパイプでつないだものであったり、シェルスクリプトであったりします。コマンドをシェルで実行するには、次のように記述します。 + +```shell +command: ["/bin/sh"] +args: ["-c", "while true; do echo hello; sleep 10;done"] +``` + +## {{% heading "whatsnext" %}} + +* [Podとコンテナの設定](/ja/docs/tasks/)についてもっとよく知る +* [コンテナ内でのコマンド実行](/ja/docs/tasks/debug/debug-application/get-shell-running-container/)についてもっとよく知る +* [コンテナのAPI](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#container-v1-core)を確認する diff --git a/content/ja/docs/tasks/network/validate-dual-stack.md b/content/ja/docs/tasks/network/validate-dual-stack.md index 829086870e25a..1e282d0269227 100644 --- a/content/ja/docs/tasks/network/validate-dual-stack.md +++ b/content/ja/docs/tasks/network/validate-dual-stack.md @@ -11,7 +11,7 @@ content_type: task ## {{% heading "prerequisites" %}} -* プロバイダーがデュアルスタックのネットワークをサポートしていること (クラウドプロバイダーか、ルーティングできるIPv4/IPv6ネットワークインターフェイスを持つKubernetesノードが提供できること) +* プロバイダーがデュアルスタックのネットワークをサポートしていること (クラウドプロバイダーか、ルーティングできるIPv4/IPv6ネットワークインターフェースを持つKubernetesノードが提供できること) * (KubenetやCalicoなど)デュアルスタックをサポートする[ネットワークプラグイン](/docs/concepts/extend-kubernetes/compute-storage-net/network-plugins/) * [デュアルスタックを有効化](/ja/docs/concepts/services-networking/dual-stack/)したクラスター @@ -37,7 +37,7 @@ kubectl get nodes k8s-linuxpool1-34450317-0 -o go-template --template='{{range . IPv4ブロックとIPv6ブロックがそれぞれ1つずつ割り当てられているはずです。 -ノードが検出されたIPv4とIPv6のインターフェイスを持っていることを検証します。ノード名は自分のクラスター内の有効なノード名に置換してください。この例では、ノード名は`k8s-linuxpool1-34450317-0`になっています。 +ノードが検出されたIPv4とIPv6のインターフェースを持っていることを検証します。ノード名は自分のクラスター内の有効なノード名に置換してください。この例では、ノード名は`k8s-linuxpool1-34450317-0`になっています。 ```shell kubectl get nodes k8s-linuxpool1-34450317-0 -o go-template --template='{{range .status.addresses}}{{printf "%s: %s\n" .type .address}}{{end}}' diff --git a/content/ja/docs/tasks/run-application/delete-stateful-set.md b/content/ja/docs/tasks/run-application/delete-stateful-set.md index 81142068ed6f9..724757cd37459 100644 --- a/content/ja/docs/tasks/run-application/delete-stateful-set.md +++ b/content/ja/docs/tasks/run-application/delete-stateful-set.md @@ -6,17 +6,12 @@ weight: 60 -このタスクでは、StatefulSetを削除する方法を説明します。 - - +このタスクでは、{{< glossary_tooltip term_id="StatefulSet" >}}を削除する方法を説明します。 ## {{% heading "prerequisites" %}} - * このタスクは、クラスター上で、StatefulSetで表現されるアプリケーションが実行されていることを前提としています。 - - ## StatefulSetの削除 @@ -43,10 +38,10 @@ kubectlを使ってStatefulSetを削除すると0にスケールダウンされ kubectl delete -f --cascade=orphan ``` -`--cascade=orphan`を`kubectl delete`に渡すことで、StatefulSetオブジェクト自身が削除された後でも、StatefulSetによって管理されていたPodは残ります。Podに`app=myapp`というラベルが付いている場合は、次のようにして削除できます: +`--cascade=orphan`を`kubectl delete`に渡すことで、StatefulSetオブジェクト自身が削除された後でも、StatefulSetによって管理されていたPodは残ります。Podに`app.kubernetes.io/name=MyApp`というラベルが付いている場合は、次のようにして削除できます: ```shell -kubectl delete pods -l app=myapp +kubectl delete pods -l app.kubernetes.io/name=MyApp ``` ### 永続ボリューム @@ -63,25 +58,17 @@ StatefulSet内のPodを削除しても、関連付けられているボリュー ```shell grace=$(kubectl get pods --template '{{.spec.terminationGracePeriodSeconds}}') -kubectl delete statefulset -l app=myapp +kubectl delete statefulset -l app.kubernetes.io/name=MyApp sleep $grace -kubectl delete pvc -l app=myapp - +kubectl delete pvc -l app.kubernetes.io/name=MyApp ``` -上の例では、Podは`app=myapp`というラベルを持っています。必要に応じてご利用のラベルに置き換えてください。 +上の例では、Podは`app.kubernetes.io/name=MyApp`というラベルを持っています。必要に応じてご利用のラベルに置き換えてください。 ### StatefulSet Podの強制削除 StatefulSet内の一部のPodが長期間`Terminating`または`Unknown`状態のままになっていることが判明した場合は、手動でapiserverからPodを強制的に削除する必要があります。これは潜在的に危険な作業です。詳細は[StatefulSet Podの強制削除](/ja/docs/tasks/run-application/force-delete-stateful-set-pod/)を参照してください。 - - ## {{% heading "whatsnext" %}} - -[StatefulSet Podの強制削除](/ja/docs/tasks/run-application/force-delete-stateful-set-pod/)の詳細 - - - - +[StatefulSet Podの強制削除](/ja/docs/tasks/run-application/force-delete-stateful-set-pod/)の詳細。 diff --git a/content/ja/docs/tasks/tools/_index.md b/content/ja/docs/tasks/tools/_index.md index 0d78f6ccd82e1..21bc70b1404e8 100644 --- a/content/ja/docs/tasks/tools/_index.md +++ b/content/ja/docs/tasks/tools/_index.md @@ -1,6 +1,6 @@ --- title: "ツールのインストール" -description: Kubernetesのツールをローカルのコンピュータ上にセットアップします。 +description: Kubernetesのツールをローカルのコンピューター上にセットアップします。 weight: 10 no_list: true --- diff --git a/content/ja/docs/tasks/tools/included/_index.md b/content/ja/docs/tasks/tools/included/_index.md new file mode 100644 index 0000000000000..f1954c95c7b2f --- /dev/null +++ b/content/ja/docs/tasks/tools/included/_index.md @@ -0,0 +1,10 @@ +--- +title: "Tools Included" +description: "メインのkubectl-installs-*.mdページに含まれるスニペット。" +headless: true +toc_hide: true +_build: + list: never + render: never + publishResources: false +--- \ No newline at end of file diff --git a/content/ja/docs/tasks/tools/included/kubectl-convert-overview.md b/content/ja/docs/tasks/tools/included/kubectl-convert-overview.md new file mode 100644 index 0000000000000..149b00c2298f5 --- /dev/null +++ b/content/ja/docs/tasks/tools/included/kubectl-convert-overview.md @@ -0,0 +1,14 @@ +--- +title: "kubectl-convertの概要" +description: >- + Kubernetes APIのあるバージョンから別のバージョンにマニフェストを変換することができるkubectlプラグイン。 +headless: true +_build: + list: never + render: never + publishResources: false +--- + +異なるAPIバージョン間でマニフェストを変換できる、Kubernetesコマンドラインツール`kubectl`のプラグインです。 +これは特に、新しいKubernetesのリリースで、非推奨ではないAPIバージョンにマニフェストを移行する場合に役に立ちます。 +詳細については[非推奨ではないAPIへの移行](/docs/reference/using-api/deprecation-guide/#migrate-to-non-deprecated-apis)を参照してください。 diff --git a/content/ja/docs/tasks/tools/included/kubectl-whats-next.md b/content/ja/docs/tasks/tools/included/kubectl-whats-next.md new file mode 100644 index 0000000000000..bde814e28946f --- /dev/null +++ b/content/ja/docs/tasks/tools/included/kubectl-whats-next.md @@ -0,0 +1,15 @@ +--- +title: "次の項目" +description: "kubectlをインストールした後の次の項目。" +headless: true +_build: + list: never + render: never + publishResources: false +--- + +* [Minikubeをインストールする](https://minikube.sigs.k8s.io/docs/start/) +* クラスターの作成に関する詳細を[スタートガイド](/ja/docs/setup/)で確認する。 +* [アプリケーションを起動して公開する方法を学ぶ。](/ja/docs/tasks/access-application-cluster/service-access-application-cluster/) +* あなたが作成していないクラスターにアクセスする必要がある場合は、[クラスターアクセスドキュメントの共有](/ja/docs/tasks/access-application-cluster/configure-access-multiple-clusters/)を参照してください。 +* [kubectlリファレンスドキュメント](/docs/reference/kubectl/kubectl/)を参照する diff --git a/content/ja/docs/tasks/tools/included/optional-kubectl-configs-bash-linux.md b/content/ja/docs/tasks/tools/included/optional-kubectl-configs-bash-linux.md new file mode 100644 index 0000000000000..bec8d42277599 --- /dev/null +++ b/content/ja/docs/tasks/tools/included/optional-kubectl-configs-bash-linux.md @@ -0,0 +1,73 @@ +--- +title: "bash auto-completion on Linux" +description: "Some optional configuration for bash auto-completion on Linux." +headless: true +_build: + list: never + render: never + publishResources: false +--- + +### Introduction + +The kubectl completion script for Bash can be generated with the command `kubectl completion bash`. +Sourcing the completion script in your shell enables kubectl autocompletion. + +However, the completion script depends on +[**bash-completion**](https://github.com/scop/bash-completion), +which means that you have to install this software first +(you can test if you have bash-completion already installed by running `type _init_completion`). + +### Install bash-completion + +bash-completion is provided by many package managers +(see [here](https://github.com/scop/bash-completion#installation)). +You can install it with `apt-get install bash-completion` or `yum install bash-completion`, etc. + +The above commands create `/usr/share/bash-completion/bash_completion`, +which is the main script of bash-completion. Depending on your package manager, +you have to manually source this file in your `~/.bashrc` file. + +To find out, reload your shell and run `type _init_completion`. +If the command succeeds, you're already set, otherwise add the following to your `~/.bashrc` file: + +```bash +source /usr/share/bash-completion/bash_completion +``` + +Reload your shell and verify that bash-completion is correctly installed by typing `type _init_completion`. + +### Enable kubectl autocompletion + +#### Bash + +You now need to ensure that the kubectl completion script gets sourced in all +your shell sessions. There are two ways in which you can do this: + +{{< tabs name="kubectl_bash_autocompletion" >}} +{{< tab name="User" codelang="bash" >}} +echo 'source <(kubectl completion bash)' >>~/.bashrc +{{< /tab >}} +{{< tab name="System" codelang="bash" >}} +kubectl completion bash | sudo tee /etc/bash_completion.d/kubectl > /dev/null +sudo chmod a+r /etc/bash_completion.d/kubectl +{{< /tab >}} +{{< /tabs >}} + +If you have an alias for kubectl, you can extend shell completion to work with that alias: + +```bash +echo 'alias k=kubectl' >>~/.bashrc +echo 'complete -o default -F __start_kubectl k' >>~/.bashrc +``` + +{{< note >}} +bash-completion sources all completion scripts in `/etc/bash_completion.d`. +{{< /note >}} + +Both approaches are equivalent. After reloading your shell, kubectl autocompletion should be working. +To enable bash autocompletion in current session of shell, source the ~/.bashrc file: + +```bash +source ~/.bashrc +``` diff --git a/content/ja/docs/tasks/tools/included/optional-kubectl-configs-bash-mac.md b/content/ja/docs/tasks/tools/included/optional-kubectl-configs-bash-mac.md new file mode 100644 index 0000000000000..5aabe6197862b --- /dev/null +++ b/content/ja/docs/tasks/tools/included/optional-kubectl-configs-bash-mac.md @@ -0,0 +1,103 @@ +--- +title: "macOS上でのbashの自動補完" +description: "macOS上でのbashの自動補完に対するいくつかの補助的な設定。" +headless: true +_build: + list: never + render: never + publishResources: false +--- + +### はじめに + +Bashにおけるkubectlの補完スクリプトは`kubectl completion bash`コマンドで生成できます。 +シェル内で補完スクリプトをsourceすることでkubectlの自動補完が有効になります。 + +ただし、補完スクリプトは[**bash-completion**](https://github.com/scop/bash-completion)に依存しているため、事前にインストールしておく必要があります。 + +{{< warning>}} +bash-completionにはv1とv2の2つのバージョンがあります。 +v1はBash 3.2(macOSのデフォルト)用で、v2はBash 4.1以降向けです。 +kubectlの補完スクリプトはbash-completionのv1とBash 3.2では正しく**動作しません**。 +**bash-completion v2**と**Bash 4.1以降**が必要になります。 +したがって、macOSで正常にkubectlの補完を使用するには、Bash 4.1以降をインストールする必要があります([*手順*](https://itnext.io/upgrading-bash-on-macos-7138bd1066ba))。 +以下の手順では、Bash4.1以降(Bashのバージョンが4.1またはそれより新しいことを指します)を使用することを前提とします。 +{{< /warning >}} + +### Bashのアップグレード + +ここではBash 4.1以降の使用を前提としています。 +Bashのバージョンは下記のコマンドで調べることができます: + +```bash +echo $BASH_VERSION +``` + +バージョンが古い場合、Homebrewを使用してインストールもしくはアップグレードできます: + +```bash +brew install bash +``` + +シェルをリロードし、希望するバージョンを使用していることを確認してください: + +```bash +echo $BASH_VERSION $SHELL +``` + +Homebrewは通常、`/usr/local/bin/bash`にインストールします。 + +### bash-completionをインストールする + +{{< note >}} +前述のとおり、この手順ではBash 4.1以降であることが前提のため、bash-completion v2をインストールすることになります(これとは逆に、Bash 3.2およびbash-completion v1の場合ではkubectlの補完は動作しません)。 +{{< /note >}} + + +`type _init_completion`を実行することで、bash-completionがすでにインストールされていることを確認できます。 +ない場合は、Homebrewを使用してインストールすることができます: + +```bash +brew install bash-completion@2 +``` + +このコマンドの出力で示されたように、`~/.bash_profile`に以下を追記してください: + +```bash +brew_etc="$(brew --prefix)/etc" && [[ -r "${brew_etc}/profile.d/bash_completion.sh" ]] && . "${brew_etc}/profile.d/bash_completion.sh" +``` + +シェルをリロードし、`type _init_completion`を実行してbash-completion v2が正しくインストールされていることを検証してください。 + +### kubectlの自動補完を有効にする + +すべてのシェルセッションにてkubectlの補完スクリプトをsourceできるようにしなければなりません。 +これを行うには複数の方法があります: + +- 補完スクリプトを`~/.bash_profile`内でsourceする: + + ```bash + echo 'source <(kubectl completion bash)' >>~/.bash_profile + ``` + +- 補完スクリプトを`/usr/local/etc/bash_completion.d`ディレクトリに追加する: + + ```bash + kubectl completion bash >/usr/local/etc/bash_completion.d/kubectl + ``` + +- kubectlにエイリアスを張っている場合は、エイリアスでも動作するようにシェルの補完を拡張することができます: + + ```bash + echo 'alias k=kubectl' >>~/.bash_profile + echo 'complete -o default -F __start_kubectl k' >>~/.bash_profile + ``` + +- kubectlをHomebrewでインストールした場合([前述](/ja/docs/tasks/tools/install-kubectl-macos/#install-with-homebrew-on-macos)の通り)、kubectlの補完スクリプトはすでに`/usr/local/etc/bash_completion.d/kubectl`に格納されているでしょうか。 + この場合、なにも操作する必要はありません。 + + {{< note >}} + Homebrewでインストールしたbash-completion v2は`BASH_COMPLETION_COMPAT_DIR`ディレクトリ内のすべてのファイルをsourceするため、後者の2つの方法が機能します。 + {{< /note >}} + +どの場合でも、シェルをリロードしたあとに、kubectlの自動補完が機能するはずです。 diff --git a/content/ja/docs/tasks/tools/included/optional-kubectl-configs-fish.md b/content/ja/docs/tasks/tools/included/optional-kubectl-configs-fish.md new file mode 100644 index 0000000000000..d6dacaa67ba12 --- /dev/null +++ b/content/ja/docs/tasks/tools/included/optional-kubectl-configs-fish.md @@ -0,0 +1,24 @@ +--- +title: "fishの自動補完" +description: "fishシェルの自動補完を有効にする補助的な設定。" +headless: true +_build: + list: never + render: never + publishResources: false +--- + +{{< note >}} +Fishに対する自動補完はkubectl 1.23以降が必要です。 +{{< /note >}} + +Fishにおけるkubectlの補完スクリプトは`kubectl completion fish`コマンドで生成できます。 +シェル内で補完スクリプトをsourceすることでkubectlの自動補完が有効になります。 + +すべてのシェルセッションで使用するには、`~/.config/fish/config.fish`に以下を追記してください: + +```shell +kubectl completion fish | source +``` + +シェルをリロードしたあとに、kubectlの自動補完が機能するはずです。 diff --git a/content/ja/docs/tasks/tools/included/optional-kubectl-configs-pwsh.md b/content/ja/docs/tasks/tools/included/optional-kubectl-configs-pwsh.md new file mode 100644 index 0000000000000..e6140ba608b2d --- /dev/null +++ b/content/ja/docs/tasks/tools/included/optional-kubectl-configs-pwsh.md @@ -0,0 +1,28 @@ +--- +title: "PowerShellの自動補完" +description: "PowerShellの自動補完に対するいくつかの補助的な設定。" +headless: true +_build: + list: never + render: never + publishResources: false +--- + +PowerShellにおけるkubectlの補完スクリプトは`kubectl completion powershell`コマンドで生成できます。 + +すべてのシェルセッションでこれを行うには、次の行を`$PROFILE`ファイルに追加します。 + +```powershell +kubectl completion powershell | Out-String | Invoke-Expression +``` + +このコマンドは、PowerShellを起動する度に自動補完のスクリプトを再生成します。 +生成されたスクリプトを直接`$PROFILE`ファイルに追加することもできます。 + +生成されたスクリプトを`$PROFILE`ファイルに追加するためには、PowerShellのプロンプトで次の行を実行します: + +```powershell +kubectl completion powershell >> $PROFILE +``` + +シェルをリロードした後、kubectlの自動補完が機能します。 diff --git a/content/ja/docs/tasks/tools/included/optional-kubectl-configs-zsh.md b/content/ja/docs/tasks/tools/included/optional-kubectl-configs-zsh.md new file mode 100644 index 0000000000000..98597649ae767 --- /dev/null +++ b/content/ja/docs/tasks/tools/included/optional-kubectl-configs-zsh.md @@ -0,0 +1,29 @@ +--- +title: "zshの自動補完" +description: "zshの自動補完に対するいくつかの補助的な設定。" +headless: true +_build: + list: never + render: never + publishResources: false +--- + +Zshにおけるkubectlの補完スクリプトは`kubectl completion zsh`コマンドで生成できます。 +シェル内で補完スクリプトをsourceすることでkubectlの自動補完が有効になります。 + +すべてのシェルセッションで使用するには、`~/.zshrc`に以下を追記してください: + +```zsh +source <(kubectl completion zsh) +``` + +kubectlにエイリアスを張っている場合でも、kubectlの自動補完は自動的に機能します。 + +シェルをリロードしたあとに、kubectlの自動補完が機能するはずです。 + +`2: command not found: compdef`のようなエラーが出力された場合は、以下を`~/.zshrc`の先頭に追記してください: + +```zsh +autoload -Uz compinit +compinit +``` \ No newline at end of file diff --git a/content/ja/docs/tasks/tools/included/verify-kubectl.md b/content/ja/docs/tasks/tools/included/verify-kubectl.md new file mode 100644 index 0000000000000..043796a587974 --- /dev/null +++ b/content/ja/docs/tasks/tools/included/verify-kubectl.md @@ -0,0 +1,46 @@ +--- +title: "kubectlの設定を検証する" +description: "kubectlを検証する方法。" +headless: true +_build: + list: never + render: never + publishResources: false +--- + +kubectlがKubernetesクラスターを探索し接続するために、[kubeconfigファイル](/ja/docs/concepts/configuration/organize-cluster-access-kubeconfig/)が必要です。 +これは、[kube-up.sh](https://github.com/kubernetes/kubernetes/blob/master/cluster/kube-up.sh)によりクラスターを作成した際や、Minikubeクラスターを正常にデプロイした際に自動生成されます。 +デフォルトでは、kubectlの設定は`~/.kube/config`に格納されています。 + +クラスターの状態を取得し、kubectlが適切に設定されていることを確認してください: + +```shell +kubectl cluster-info +``` + +URLのレスポンスが表示されている場合は、kubectlはクラスターに接続するよう正しく設定されています。 + +以下のようなメッセージが表示されている場合は、kubectlは正しく設定されていないか、Kubernetesクラスターに接続できていません。 + +``` +The connection to the server was refused - did you specify the right host or port? +``` + +たとえば、ラップトップ上(ローカル環境)でKubernetesクラスターを起動するような場合、[Minikube](https://minikube.sigs.k8s.io/docs/start/)などのツールを最初にインストールしてから、上記のコマンドを再実行する必要があります。 + +`kubectl cluster-info`がURLレスポンスを返したにもかかわらずクラスターにアクセスできない場合は、次のコマンドで設定が正しいことを確認してください: + +```shell +kubectl cluster-info dump +``` + +### エラーメッセージ'No Auth Provider Found'のトラブルシューティング{#no-auth-provider-found} + +Kubernetes 1.26にて、kubectlは以下のクラウドプロバイダーが提供するマネージドKubernetesのビルトイン認証を削除しました。 +これらのプロバイダーは、クラウド固有の認証を提供するkubectlプラグインをリリースしています。 +手順については以下のプロバイダーのドキュメントを参照してください: + +* Azure AKS: [kubelogin plugin](https://azure.github.io/kubelogin/) +* Google Kubernetes Engine: [gke-gcloud-auth-plugin](https://cloud.google.com/kubernetes-engine/docs/how-to/cluster-access-for-kubectl?hl=ja#install_plugin) + +(この変更とは関係なく、他の理由で同じエラーメッセージが表示される可能性もあります。) diff --git a/content/ja/docs/tasks/tools/install-kubectl-linux.md b/content/ja/docs/tasks/tools/install-kubectl-linux.md new file mode 100644 index 0000000000000..48a1eaef87868 --- /dev/null +++ b/content/ja/docs/tasks/tools/install-kubectl-linux.md @@ -0,0 +1,350 @@ +--- +title: Install and Set Up kubectl on Linux +content_type: task +weight: 10 +--- + +## {{% heading "prerequisites" %}} + +You must use a kubectl version that is within one minor version difference of +your cluster. For example, a v{{< skew currentVersion >}} client can communicate +with v{{< skew currentVersionAddMinor -1 >}}, v{{< skew currentVersionAddMinor 0 >}}, +and v{{< skew currentVersionAddMinor 1 >}} control planes. +Using the latest compatible version of kubectl helps avoid unforeseen issues. + +## Install kubectl on Linux + +The following methods exist for installing kubectl on Linux: + +- [Install kubectl binary with curl on Linux](#install-kubectl-binary-with-curl-on-linux) +- [Install using native package management](#install-using-native-package-management) +- [Install using other package management](#install-using-other-package-management) + +### Install kubectl binary with curl on Linux + +1. Download the latest release with the command: + + {{< tabs name="download_binary_linux" >}} + {{< tab name="x86-64" codelang="bash" >}} + curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl" + {{< /tab >}} + {{< tab name="ARM64" codelang="bash" >}} + curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/arm64/kubectl" + {{< /tab >}} + {{< /tabs >}} + + {{< note >}} + To download a specific version, replace the `$(curl -L -s https://dl.k8s.io/release/stable.txt)` + portion of the command with the specific version. + + For example, to download version {{< skew currentPatchVersion >}} on Linux x86-64, type: + + ```bash + curl -LO https://dl.k8s.io/release/v{{< skew currentPatchVersion >}}/bin/linux/amd64/kubectl + ``` + + And for Linux ARM64, type: + + ```bash + curl -LO https://dl.k8s.io/release/v{{< skew currentPatchVersion >}}/bin/linux/arm64/kubectl + ``` + + {{< /note >}} + +1. Validate the binary (optional) + + Download the kubectl checksum file: + + {{< tabs name="download_checksum_linux" >}} + {{< tab name="x86-64" codelang="bash" >}} + curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl.sha256" + {{< /tab >}} + {{< tab name="ARM64" codelang="bash" >}} + curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/arm64/kubectl.sha256" + {{< /tab >}} + {{< /tabs >}} + + Validate the kubectl binary against the checksum file: + + ```bash + echo "$(cat kubectl.sha256) kubectl" | sha256sum --check + ``` + + If valid, the output is: + + ```console + kubectl: OK + ``` + + If the check fails, `sha256` exits with nonzero status and prints output similar to: + + ```console + kubectl: FAILED + sha256sum: WARNING: 1 computed checksum did NOT match + ``` + + {{< note >}} + Download the same version of the binary and checksum. + {{< /note >}} + +1. Install kubectl + + ```bash + sudo install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl + ``` + + {{< note >}} + If you do not have root access on the target system, you can still install + kubectl to the `~/.local/bin` directory: + + ```bash + chmod +x kubectl + mkdir -p ~/.local/bin + mv ./kubectl ~/.local/bin/kubectl + # and then append (or prepend) ~/.local/bin to $PATH + ``` + + {{< /note >}} + +1. Test to ensure the version you installed is up-to-date: + + ```bash + kubectl version --client + ``` + + Or use this for detailed view of version: + + ```cmd + kubectl version --client --output=yaml + ``` + +### Install using native package management + +{{< tabs name="kubectl_install" >}} +{{% tab name="Debian-based distributions" %}} + +1. Update the `apt` package index and install packages needed to use the Kubernetes `apt` repository: + + ```shell + sudo apt-get update + # apt-transport-https may be a dummy package; if so, you can skip that package + sudo apt-get install -y apt-transport-https ca-certificates curl + ``` + +2. Download the public signing key for the Kubernetes package repositories. The same signing key is used for all repositories so you can disregard the version in the URL: + + ```shell + # If the folder `/etc/apt/keyrings` does not exist, it should be created before the curl command, read the note below. + # sudo mkdir -p -m 755 /etc/apt/keyrings + curl -fsSL https://pkgs.k8s.io/core:/stable:/{{< param "version" >}}/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg + ``` + +{{< note >}} +In releases older than Debian 12 and Ubuntu 22.04, folder `/etc/apt/keyrings` does not exist by default, and it should be created before the curl command. +{{< /note >}} + +3. Add the appropriate Kubernetes `apt` repository. If you want to use Kubernetes version different than {{< param "version" >}}, + replace {{< param "version" >}} with the desired minor version in the command below: + + ```shell + # This overwrites any existing configuration in /etc/apt/sources.list.d/kubernetes.list + echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/{{< param "version" >}}/deb/ /' | sudo tee /etc/apt/sources.list.d/kubernetes.list + ``` + +{{< note >}} +To upgrade kubectl to another minor release, you'll need to bump the version in `/etc/apt/sources.list.d/kubernetes.list` before running `apt-get update` and `apt-get upgrade`. This procedure is described in more detail in [Changing The Kubernetes Package Repository](/docs/tasks/administer-cluster/kubeadm/change-package-repository/). +{{< /note >}} + +4. Update `apt` package index, then install kubectl: + + ```shell + sudo apt-get update + sudo apt-get install -y kubectl + ``` + +{{% /tab %}} + +{{% tab name="Red Hat-based distributions" %}} + +1. Add the Kubernetes `yum` repository. If you want to use Kubernetes version + different than {{< param "version" >}}, replace {{< param "version" >}} with + the desired minor version in the command below. + + ```bash + # This overwrites any existing configuration in /etc/yum.repos.d/kubernetes.repo + cat <}}/rpm/ + enabled=1 + gpgcheck=1 + gpgkey=https://pkgs.k8s.io/core:/stable:/{{< param "version" >}}/rpm/repodata/repomd.xml.key + EOF + ``` + +{{< note >}} +To upgrade kubectl to another minor release, you'll need to bump the version in `/etc/yum.repos.d/kubernetes.repo` before running `yum update`. This procedure is described in more detail in [Changing The Kubernetes Package Repository](/docs/tasks/administer-cluster/kubeadm/change-package-repository/). +{{< /note >}} + +2. Install kubectl using `yum`: + + ```bash + sudo yum install -y kubectl + ``` + +{{% /tab %}} + +{{% tab name="SUSE-based distributions" %}} + +1. Add the Kubernetes `zypper` repository. If you want to use Kubernetes version + different than {{< param "version" >}}, replace {{< param "version" >}} with + the desired minor version in the command below. + + ```bash + # This overwrites any existing configuration in /etc/zypp/repos.d/kubernetes.repo + cat <}}/rpm/ + enabled=1 + gpgcheck=1 + gpgkey=https://pkgs.k8s.io/core:/stable:/{{< param "version" >}}/rpm/repodata/repomd.xml.key + EOF + ``` + +{{< note >}} +To upgrade kubectl to another minor release, you'll need to bump the version in `/etc/zypp/repos.d/kubernetes.repo` +before running `zypper update`. This procedure is described in more detail in +[Changing The Kubernetes Package Repository](/docs/tasks/administer-cluster/kubeadm/change-package-repository/). +{{< /note >}} + + 2. Install kubectl using `zypper`: + + ```bash + sudo zypper install -y kubectl + ``` + +{{% /tab %}} +{{< /tabs >}} + +### Install using other package management + +{{< tabs name="other_kubectl_install" >}} +{{% tab name="Snap" %}} +If you are on Ubuntu or another Linux distribution that supports the +[snap](https://snapcraft.io/docs/core/install) package manager, kubectl +is available as a [snap](https://snapcraft.io/) application. + +```shell +snap install kubectl --classic +kubectl version --client +``` + +{{% /tab %}} + +{{% tab name="Homebrew" %}} +If you are on Linux and using [Homebrew](https://docs.brew.sh/Homebrew-on-Linux) +package manager, kubectl is available for [installation](https://docs.brew.sh/Homebrew-on-Linux#install). + +```shell +brew install kubectl +kubectl version --client +``` + +{{% /tab %}} + +{{< /tabs >}} + +## Verify kubectl configuration + +{{< include "included/verify-kubectl.md" >}} + +## Optional kubectl configurations and plugins + +### Enable shell autocompletion + +kubectl provides autocompletion support for Bash, Zsh, Fish, and PowerShell, +which can save you a lot of typing. + +Below are the procedures to set up autocompletion for Bash, Fish, and Zsh. + +{{< tabs name="kubectl_autocompletion" >}} +{{< tab name="Bash" include="included/optional-kubectl-configs-bash-linux.md" />}} +{{< tab name="Fish" include="included/optional-kubectl-configs-fish.md" />}} +{{< tab name="Zsh" include="included/optional-kubectl-configs-zsh.md" />}} +{{< /tabs >}} + +### Install `kubectl convert` plugin + +{{< include "included/kubectl-convert-overview.md" >}} + +1. Download the latest release with the command: + + {{< tabs name="download_convert_binary_linux" >}} + {{< tab name="x86-64" codelang="bash" >}} + curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl-convert" + {{< /tab >}} + {{< tab name="ARM64" codelang="bash" >}} + curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/arm64/kubectl-convert" + {{< /tab >}} + {{< /tabs >}} + +1. Validate the binary (optional) + + Download the kubectl-convert checksum file: + + {{< tabs name="download_convert_checksum_linux" >}} + {{< tab name="x86-64" codelang="bash" >}} + curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl-convert.sha256" + {{< /tab >}} + {{< tab name="ARM64" codelang="bash" >}} + curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/arm64/kubectl-convert.sha256" + {{< /tab >}} + {{< /tabs >}} + + Validate the kubectl-convert binary against the checksum file: + + ```bash + echo "$(cat kubectl-convert.sha256) kubectl-convert" | sha256sum --check + ``` + + If valid, the output is: + + ```console + kubectl-convert: OK + ``` + + If the check fails, `sha256` exits with nonzero status and prints output similar to: + + ```console + kubectl-convert: FAILED + sha256sum: WARNING: 1 computed checksum did NOT match + ``` + + {{< note >}} + Download the same version of the binary and checksum. + {{< /note >}} + +1. Install kubectl-convert + + ```bash + sudo install -o root -g root -m 0755 kubectl-convert /usr/local/bin/kubectl-convert + ``` + +1. Verify plugin is successfully installed + + ```shell + kubectl convert --help + ``` + + If you do not see an error, it means the plugin is successfully installed. + +1. After installing the plugin, clean up the installation files: + + ```bash + rm kubectl-convert kubectl-convert.sha256 + ``` + +## {{% heading "whatsnext" %}} + +{{< include "included/kubectl-whats-next.md" >}} diff --git a/content/ja/docs/tasks/tools/install-kubectl-macos.md b/content/ja/docs/tasks/tools/install-kubectl-macos.md new file mode 100644 index 0000000000000..3c1595a5d6ddb --- /dev/null +++ b/content/ja/docs/tasks/tools/install-kubectl-macos.md @@ -0,0 +1,300 @@ +--- +title: macOS上でのkubectlのインストールおよびセットアップ +content_type: task +weight: 10 +--- + +## {{% heading "prerequisites" %}} + +kubectlのバージョンは、クラスターのマイナーバージョンとの差分が1つ以内でなければなりません。 +たとえば、クライアントがv{{< skew currentVersion >}}であれば、v{{< skew currentVersionAddMinor -1 >}}、v{{< skew currentVersionAddMinor 0 >}}、v{{< skew currentVersionAddMinor 1 >}}のコントロールプレーンと通信できます。 +最新の互換性のあるバージョンのkubectlを使うことで、不測の事態を避けることができるでしょう。 + + +## macOSへkubectlをインストールする{#install-kubectl-on-macos} + +macOSへkubectlをインストールするには、次の方法があります: + +- [macOSへkubectlをインストールする](#install-kubectl-on-macos) + - [curlを使用してmacOSへkubectlのバイナリをインストールする](#install-kubectl-binary-with-curl-on-macos) + - [Homebrewを使用してmacOSへインストールする](#install-with-homebrew-on-macos) + - [MacPortsを使用してmacOSへインストールする](#install-with-macports-on-macos) +- [kubectlの設定を検証する](#verify-kubectl-configuration) +- [オプションのkubectlの設定とプラグイン](#optional-kubectl-configurations-and-plugins) + - [シェルの自動補完を有効にする](#enable-shell-autocompletion) + - [`kubectl convert`プラグインをインストールする](#install-kubectl-convert-plugin) + +### curlを使用してmacOSへkubectlのバイナリをインストールする{#install-kubectl-binary-with-curl-on-macos} + +1. 最新リリースをダウンロードしてください: + + {{< tabs name="download_binary_macos" >}} + {{< tab name="Intel" codelang="bash" >}} + curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/darwin/amd64/kubectl" + {{< /tab >}} + {{< tab name="Appleシリコン" codelang="bash" >}} + curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/darwin/arm64/kubectl" + {{< /tab >}} + {{< /tabs >}} + + {{< note >}} + 特定のバージョンをダウンロードする場合、コマンドの`$(curl -L -s https://dl.k8s.io/release/stable.txt)`の部分を特定のバージョンに置き換えてください。 + + 例えば、Intel macOSへ{{< skew currentPatchVersion >}}のバージョンをダウンロードするには、次のコマンドを入力します: + + ```bash + curl -LO "https://dl.k8s.io/release/v{{< skew currentPatchVersion >}}/bin/darwin/amd64/kubectl" + ``` + + Appleシリコン上のmacOSに対しては、次を入力します: + + ```bash + curl -LO "https://dl.k8s.io/release/v{{< skew currentPatchVersion >}}/bin/darwin/arm64/kubectl" + ``` + + {{< /note >}} + +1. バイナリを検証してください(オプション) + + kubectlのチェックサムファイルをダウンロードします: + + {{< tabs name="download_checksum_macos" >}} + {{< tab name="Intel" codelang="bash" >}} + curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/darwin/amd64/kubectl.sha256" + {{< /tab >}} + {{< tab name="Appleシリコン" codelang="bash" >}} + curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/darwin/arm64/kubectl.sha256" + {{< /tab >}} + {{< /tabs >}} + + チェックサムファイルに対してkubectlバイナリを検証します: + + ```bash + echo "$(cat kubectl.sha256) kubectl" | shasum -a 256 --check + ``` + + 正しければ、出力は次のようになります: + + ```console + kubectl: OK + ``` + + チェックに失敗すると、`shasum`は0以外のステータスで終了し、次のような出力を表示します: + + ```console + kubectl: FAILED + shasum: WARNING: 1 computed checksum did NOT match + ``` + + {{< note >}} + 同じバージョンのバイナリとチェックサムをダウンロードしてください。 + {{< /note >}} + +1. kubectlバイナリを実行可能にしてください。 + + ```bash + chmod +x ./kubectl + ``` + +1. kubectlバイナリを`PATH`の中に移動させてください。 + + ```bash + sudo mv ./kubectl /usr/local/bin/kubectl + sudo chown root: /usr/local/bin/kubectl + ``` + + {{< note >}} + `/usr/local/bin`がPATH環境変数の中に含まれるようにしてください。 + {{< /note >}} + +1. インストールしたバージョンが最新であることを確認してください: + + ```bash + kubectl version --client + ``` + + または、バージョンの詳細を表示するために次を使用します: + + ```cmd + kubectl version --client --output=yaml + ``` + +1. kubectlをインストールし、検証した後は、チェックサムファイルを削除してください: + + ```bash + rm kubectl.sha256 + ``` + +### Homebrewを使用してmacOSへインストールする{#install-with-homebrew-on-macos} + +macOSで[Homebrew](https://brew.sh/)パッケージマネージャーを使用していれば、Homebrewでkubectlをインストールできます。 + +1. インストールコマンドを実行してください: + + ```bash + brew install kubectl + ``` + + または + + ```bash + brew install kubernetes-cli + ``` + +1. インストールしたバージョンが最新であることを確認してください: + + ```bash + kubectl version --client + ``` + +### MacPortsを使用してmacOSへインストールする{#install-with-macports-on-macos} + +macOSで[MacPorts](https://macports.org/)パッケージマネージャーを使用していれば、MacPortsでkubectlをインストールできます。 + +1. インストールコマンドを実行してください: + + ```bash + sudo port selfupdate + sudo port install kubectl + ``` + +1. インストールしたバージョンが最新であることを確認してください: + + ```bash + kubectl version --client + ``` + +## kubectlの設定を検証する{#verify-kubectl-configuration} + +{{< include "included/verify-kubectl.md" >}} + +## オプションのkubectlの設定とプラグイン{#optional-kubectl-configurations-and-plugins} + +### シェルの自動補完を有効にする{#enable-shell-autocompletion} + +kubectlはBash、Zsh、Fish、PowerShellの自動補完を提供しています。 +これにより、入力を大幅に削減することができます。 + +以下にBash、Fish、Zshの自動補完の設定手順を示します。 + +{{< tabs name="kubectl_autocompletion" >}} +{{< tab name="Bash" include="included/optional-kubectl-configs-bash-mac.md" />}} +{{< tab name="Fish" include="included/optional-kubectl-configs-fish.md" />}} +{{< tab name="Zsh" include="included/optional-kubectl-configs-zsh.md" />}} +{{< /tabs >}} + +### `kubectl convert`プラグインをインストールする{#install-kubectl-convert-plugin} + +{{< include "included/kubectl-convert-overview.md" >}} + +1. 次のコマンドを使用して最新リリースをダウンロードしてください: + + {{< tabs name="download_convert_binary_macos" >}} + {{< tab name="Intel" codelang="bash" >}} + curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/darwin/amd64/kubectl-convert" + {{< /tab >}} + {{< tab name="Appleシリコン" codelang="bash" >}} + curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/darwin/arm64/kubectl-convert" + {{< /tab >}} + {{< /tabs >}} + +1. バイナリを検証してください(オプション) + + kubectl-convertのチェックサムファイルをダウンロードします: + + {{< tabs name="download_convert_checksum_macos" >}} + {{< tab name="Intel" codelang="bash" >}} + curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/darwin/amd64/kubectl-convert.sha256" + {{< /tab >}} + {{< tab name="Appleシリコン" codelang="bash" >}} + curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/darwin/arm64/kubectl-convert.sha256" + {{< /tab >}} + {{< /tabs >}} + + チェックサムファイルに対してkubectl-convertバイナリを検証します: + + ```bash + echo "$(cat kubectl-convert.sha256) kubectl-convert" | shasum -a 256 --check + ``` + + 正しければ、出力は次のようになります: + + ```console + kubectl-convert: OK + ``` + + チェックに失敗すると、`shasum`は0以外のステータスで終了し、次のような出力を表示します: + + ```console + kubectl-convert: FAILED + shasum: WARNING: 1 computed checksum did NOT match + ``` + + {{< note >}} + 同じバージョンのバイナリとチェックサムをダウンロードしてください。 + {{< /note >}} + +1. kubectl-convertバイナリを実行可能にしてください。 + + ```bash + chmod +x ./kubectl-convert + ``` + +1. kubectl-convertバイナリを`PATH`の中に移動してください。 + + ```bash + sudo mv ./kubectl-convert /usr/local/bin/kubectl-convert + sudo chown root: /usr/local/bin/kubectl-convert + ``` + + {{< note >}} + `/usr/local/bin`がPATH環境変数の中に含まれるようにしてください。 + {{< /note >}} + +1. インストールしたバージョンが最新であることを確認してください + + ```shell + kubectl convert --help + ``` + + 何もエラーが表示されない場合は、プラグインが正常にインストールされたことを示しています。 + +1. プラグインのインストール後、インストールファイルを削除してください: + + ```bash + rm kubectl-convert kubectl-convert.sha256 + ``` + +### macOS上のkubectlをアンインストールする + +`kubectl`のインストール方法に応じて、次の方法を使用してください。 + +### コマンドラインを使用してkubectlをアンインストールする + +1. システム上の`kubectl`バイナリの場所を特定してください: + + ```bash + which kubectl + ``` + +1. `kubectl`バイナリを削除してください: + + ```bash + sudo rm + ``` + ``を前のステップの`kubectl`バイナリのパスに置き換えてください。 + 例えば`sudo rm /usr/local/bin/kubectl`。 + +### Homebrewを使用してkubectlをアンインストールする + +Homebrewを使用して`kubectl`をインストールした場合は、次のコマンドを実行してください: + +```bash +brew remove kubectl +``` + +## {{% heading "whatsnext" %}} + +{{< include "included/kubectl-whats-next.md" >}} + + diff --git a/content/ja/docs/tasks/tools/install-kubectl-windows.md b/content/ja/docs/tasks/tools/install-kubectl-windows.md new file mode 100644 index 0000000000000..8f4e18faf3158 --- /dev/null +++ b/content/ja/docs/tasks/tools/install-kubectl-windows.md @@ -0,0 +1,203 @@ +--- +title: Windows上でのkubectlのインストールおよびセットアップ +content_type: task +weight: 10 +--- + +## {{% heading "prerequisites" %}} + +kubectlのバージョンは、クラスターのマイナーバージョンとの差分が1つ以内でなければなりません。 +たとえば、クライアントがv{{< skew currentVersion >}}であれば、v{{< skew currentVersionAddMinor -1 >}}、v{{< skew currentVersionAddMinor 0 >}}、v{{< skew currentVersionAddMinor 1 >}}のコントロールプレーンと通信できます。 +最新の互換性のあるバージョンのkubectlを使うことで、不測の事態を避けることができるでしょう。 + +## Windowsへkubectlをインストールする + +Windowsへkubectlをインストールするには、次の方法があります: + +- [curlを使用してWindowsへkubectlのバイナリをインストールする](#install-kubectl-binary-with-curl-on-windows) +- [Chocolatey、Scoopまたはwingetを使用してWindowsへインストールする](#install-nonstandard-package-tools) + +### curlを使用してWindowsへkubectlのバイナリをインストールする{#install-kubectl-binary-with-curl-on-windows} + +1. 最新の{{< skew currentVersion >}}のパッチリリースをダウンロードしてください: + [kubectl {{< skew currentPatchVersion >}}](https://dl.k8s.io/release/v{{< skew currentPatchVersion >}}/bin/windows/amd64/kubectl.exe)。 + + または、`curl`がインストールされていれば、次のコマンドも使用できます: + + ```powershell + curl.exe -LO "https://dl.k8s.io/release/v{{< skew currentPatchVersion >}}/bin/windows/amd64/kubectl.exe" + ``` + + {{< note >}} + 最新の安定版を入手する際は(たとえばスクリプトで使用する場合)、[https://dl.k8s.io/release/stable.txt](https://dl.k8s.io/release/stable.txt)を参照してください。 + {{< /note >}} + +1. バイナリを検証してください(オプション) + + `kubectl`のチェックサムファイルをダウンロードします: + + ```powershell + curl.exe -LO "https://dl.k8s.io/v{{< skew currentPatchVersion >}}/bin/windows/amd64/kubectl.exe.sha256" + ``` + + チェックサムファイルに対して`kubectl`バイナリを検証します: + + - コマンドプロンプトを使用して、`CertUtil`の出力とダウンロードしたチェックサムファイルを手動で比較します: + + ```cmd + CertUtil -hashfile kubectl.exe SHA256 + type kubectl.exe.sha256 + ``` + + - PowerShellにて`-eq`オペレーターを使用して自動で検証を行い、`True`または`False`で結果を取得します: + + ```powershell + $(Get-FileHash -Algorithm SHA256 .\kubectl.exe).Hash -eq $(Get-Content .\kubectl.exe.sha256) + ``` + +1. `kubectl`バイナリのフォルダーを`PATH`環境変数に追加します。 + +1. `kubectl`のバージョンがダウンロードしたものと同じであることを確認してください: + + ```cmd + kubectl version --client + ``` + + または、バージョンの詳細を表示するために次を使用します: + + ```cmd + kubectl version --client --output=yaml + ``` + + + +{{< note >}} +[Docker Desktop for Windows](https://docs.docker.com/docker-for-windows/#kubernetes)は、それ自身のバージョンの`kubectl`を`PATH`に追加します。 +Docker Desktopをすでにインストールしている場合、Docker Desktopインストーラーによって追加された`PATH`の前に追加するか、Docker Desktopの`kubectl`を削除してください。 +{{< /note >}} + +### Chocolatey、Scoopまたはwingetを使用してWindowsへインストールする{#install-nonstandard-package-tools} + +1. Windowsへkubectlをインストールするために、[Chocolatey](https://chocolatey.org)パッケージマネージャーや[Scoop](https://scoop.sh)コマンドラインインストーラー、[winget](https://learn.microsoft.com/en-us/windows/package-manager/winget/)パッケージマネージャーを使用することもできます。 + + {{< tabs name="kubectl_win_install" >}} + {{% tab name="choco" %}} + ```powershell + choco install kubernetes-cli + ``` + {{% /tab %}} + {{% tab name="scoop" %}} + ```powershell + scoop install kubectl + ``` + {{% /tab %}} + {{% tab name="winget" %}} + ```powershell + winget install -e --id Kubernetes.kubectl + ``` + {{% /tab %}} + {{< /tabs >}} + +1. インストールしたバージョンが最新であることを確認してください: + + ```powershell + kubectl version --client + ``` + +1. ホームディレクトリへ移動してください: + + ```powershell + # cmd.exeを使用している場合はcd %USERPROFILE%を実行してください。 + cd ~ + ``` + +1. `.kube`ディレクトリを作成してください: + + ```powershell + mkdir .kube + ``` + +1. 作成した`.kube`ディレクトリへ移動してください: + + ```powershell + cd .kube + ``` + +1. リモートのKubernetesクラスターを使うために、kubectlを設定してください: + + ```powershell + New-Item config -type file + ``` + +{{< note >}} +Notepadなどの選択したテキストエディターから設定ファイルを編集してください。 +{{< /note >}} + +## kubectlの設定を検証する + +{{< include "included/verify-kubectl.md" >}} + +## オプションのkubectlの設定とプラグイン + +### シェルの自動補完を有効にする + +kubectlはBash、Zsh、Fish、PowerShellの自動補完を提供しています。 +これにより、入力を大幅に削減することができます。 + +以下にPowerShellの自動補完の設定手順を示します。 + +{{< include "included/optional-kubectl-configs-pwsh.md" >}} + +### `kubectl convert`プラグインをインストールする + +{{< include "included/kubectl-convert-overview.md" >}} + +1. 次のコマンドを使用して最新リリースをダウンロードしてください: + + ```powershell + curl.exe -LO "https://dl.k8s.io/release/v{{< skew currentPatchVersion >}}/bin/windows/amd64/kubectl-convert.exe" + ``` + +1. バイナリを検証してください(オプション)。 + + `kubectl-convert`のチェックサムファイルをダウンロードします: + + ```powershell + curl.exe -LO "https://dl.k8s.io/v{{< skew currentPatchVersion >}}/bin/windows/amd64/kubectl-convert.exe.sha256" + ``` + + チェックサムファイルに対して`kubectl-convert`バイナリを検証します: + + - コマンドプロンプトを使用して、`CertUtil`の出力とダウンロードしたチェックサムファイルを手動で比較します: + + ```cmd + CertUtil -hashfile kubectl-convert.exe SHA256 + type kubectl-convert.exe.sha256 + ``` + + - PowerShellにて`-eq`オペレーターを使用して自動で検証を行い、`True`または`False`で結果を取得します: + + ```powershell + $($(CertUtil -hashfile .\kubectl-convert.exe SHA256)[1] -replace " ", "") -eq $(type .\kubectl-convert.exe.sha256) + ``` + +1. `kubectl-convert`バイナリのフォルダーを`PATH`環境変数に追加します。 + +1. プラグインが正常にインストールされたことを確認してください。 + + ```shell + kubectl convert --help + ``` + + 何もエラーが表示されない場合は、プラグインが正常にインストールされたことを示しています。 + +1. プラグインのインストール後、インストールファイルを削除してください: + + ```powershell + del kubectl-convert.exe + del kubectl-convert.exe.sha256 + ``` + +## {{% heading "whatsnext" %}} + +{{< include "included/kubectl-whats-next.md" >}} diff --git a/content/ja/docs/tasks/tools/install-kubectl.md b/content/ja/docs/tasks/tools/install-kubectl.md deleted file mode 100644 index b43da69edd30d..0000000000000 --- a/content/ja/docs/tasks/tools/install-kubectl.md +++ /dev/null @@ -1,509 +0,0 @@ ---- -title: kubectlのインストールおよびセットアップ -content_type: task -weight: 10 -card: - name: tasks - weight: 20 - title: kubectlのインストール ---- - - -Kubernetesのコマンドラインツールである[kubectl](/ja/docs/reference/kubectl/kubectl)を使用して、Kubernetesクラスターに対してコマンドを実行することができます。kubectlによってアプリケーションのデプロイや、クラスターのリソース管理、検査およびログの表示を行うことができます。kubectlの操作に関する完全なリストは、[kubectlリファレンスドキュメント](/ja/docs/reference/kubectl/)を参照してください。 - - -## {{% heading "prerequisites" %}} - -kubectlのバージョンは、クラスターのマイナーバージョンとの差分が1つ以内でなければなりません。たとえば、クライアントがv1.2であれば、v1.1、v1.2、v1.3のマスターで動作するはずです。最新バージョンのkubectlを使うことで、不測の事態を避けることができるでしょう。 - - - - -## Linuxへkubectlをインストールする {#install-kubectl-on-linux} - -### curlを使用してLinuxへkubectlのバイナリをインストールする - -1. 次のコマンドにより、最新リリースをダウンロードしてください: - - ``` - curl -LO "https://dl.k8s.io/release/$(curl -LS https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl" - ``` - - 特定のバージョンをダウンロードする場合、コマンドの`$(curl -LS https://dl.k8s.io/release/stable.txt)`の部分を特定のバージョンに書き換えてください。 - - たとえば、Linuxへ{{< skew currentPatchVersion >}}のバージョンをダウンロードするには、次のコマンドを入力します: - - ``` - curl -LO https://dl.k8s.io/release/v{{< skew currentPatchVersion >}}/bin/linux/amd64/kubectl - ``` - -2. kubectlバイナリを実行可能にしてください。 - - ``` - chmod +x ./kubectl - ``` - -3. バイナリをPATHの中に移動させてください。 - - ``` - sudo mv ./kubectl /usr/local/bin/kubectl - ``` - -4. インストールしたバージョンが最新であることを確認してください: - - ``` - kubectl version --client - ``` - -### ネイティブなパッケージマネージャーを使用してインストールする - -{{< tabs name="kubectl_install" >}} -{{< tab name="Ubuntu、DebianまたはHypriotOS" codelang="bash" >}} -sudo apt-get update && sudo apt-get install -y apt-transport-https gnupg2 -curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add - -echo "deb https://apt.kubernetes.io/ kubernetes-xenial main" | sudo tee -a /etc/apt/sources.list.d/kubernetes.list -sudo apt-get update -sudo apt-get install -y kubectl -{{< /tab >}} -{{< tab name="CentOS、RHELまたはFedora" codelang="bash" >}}cat < /etc/yum.repos.d/kubernetes.repo -[kubernetes] -name=Kubernetes -baseurl=https://packages.cloud.google.com/yum/repos/kubernetes-el7-x86_64 -enabled=1 -gpgcheck=1 -repo_gpgcheck=1 -gpgkey=https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg -EOF -yum install -y kubectl -{{< /tab >}} -{{< /tabs >}} - - -### 他のパッケージマネージャーを使用してインストールする - -{{< tabs name="other_kubectl_install" >}} -{{% tab name="Snap" %}} -Ubuntuまたは[snap](https://snapcraft.io/docs/core/install)パッケージマネージャーをサポートする別のLinuxディストリビューションを使用している場合、kubectlは[snap](https://snapcraft.io/)アプリケーションとして使用できます。 - -```shell -snap install kubectl --classic - -kubectl version --client -``` -{{% /tab %}} -{{% tab name="Homebrew" %}} -Linuxで[Homebrew](https://docs.brew.sh/Homebrew-on-Linux)パッケージマネージャーを使用している場合は、kubectlを[インストール](https://docs.brew.sh/Homebrew-on-Linux#install)することが可能です。 -```shell -brew install kubectl - -kubectl version --client -``` -{{% /tab %}} -{{< /tabs >}} - -## macOSへkubectlをインストールする {#install-kubectl-on-macos} - -### curlを使用してmacOSへkubectlのバイナリをインストールする - -1. 最新リリースをダウンロードしてください: - - ```bash - curl -LO "https://dl.k8s.io/release/$(curl -LS https://dl.k8s.io/release/stable.txt)/bin/darwin/amd64/kubectl" - ``` - - 特定のバージョンをダウンロードする場合、コマンドの`$(curl -LS https://dl.k8s.io/release/stable.txt)`の部分を特定のバージョンに書き換えてください。 - - たとえば、macOSへ{{< skew currentPatchVersion >}}のバージョンをダウンロードするには、次のコマンドを入力します: - - ```bash - curl -LO https://dl.k8s.io/release/v{{< skew currentPatchVersion >}}/bin/darwin/amd64/kubectl - ``` - -2. kubectlバイナリを実行可能にしてください。 - - ```bash - chmod +x ./kubectl - ``` - -3. バイナリをPATHの中に移動させてください。 - - ```bash - sudo mv ./kubectl /usr/local/bin/kubectl - ``` -4. インストールしたバージョンが最新であることを確認してください: - - ```bash - kubectl version --client - ``` - -### Homebrewを使用してmacOSへインストールする - -macOSで[Homebrew](https://brew.sh/)パッケージマネージャーを使用していれば、Homebrewでkubectlをインストールすることもできます。 - -1. インストールコマンドを実行してください: - - ```bash - brew install kubectl - ``` - または - - ```bash - brew install kubernetes-cli - ``` - -2. インストールしたバージョンが最新であることを確認してください: - - ```bash - kubectl version --client - ``` - -### MacPortsを使用してmacOSへインストールする - -macOSで[MacPorts](https://macports.org/)パッケージマネージャーを使用していれば、MacPortsでkubectlをインストールすることもできます。 - -1. インストールコマンドを実行してください: - - ```bash - sudo port selfupdate - sudo port install kubectl - ``` - -2. インストールしたバージョンが最新であることを確認してください: - - ```bash - kubectl version --client - ``` - -## Windowsへkubectlをインストールする {#install-kubectl-on-windows} - -### curlを使用してWindowsへkubectlのバイナリをインストールする - -1. [こちらのリンク](https://dl.k8s.io/release/v{{< skew currentPatchVersion >}}/bin/windows/amd64/kubectl.exe)から、最新リリースである{{< skew currentPatchVersion >}}をダウンロードしてください。 - - または、`curl`をインストールされていれば、次のコマンドも使用できます: - - ```bash - curl -LO https://dl.k8s.io/release/v{{< skew currentPatchVersion >}}/bin/windows/amd64/kubectl.exe - ``` - - 最新の安定版を入手する際は(たとえばスクリプトで使用する場合)、[https://dl.k8s.io/release/stable.txt](https://dl.k8s.io/release/stable.txt)を参照してください。 - -2. バイナリをPATHに追加します -3. `kubectl`のバージョンがダウンロードしたものと同じであることを確認してください: - - ```bash - kubectl version --client - ``` -{{< note >}} -[Docker Desktop for Windows](https://docs.docker.com/docker-for-windows/#kubernetes)は、それ自身のバージョンの`kubectl`をPATHに追加します。Docker Desktopをすでにインストールしている場合、Docker Desktopインストーラーによって追加されたPATHの前に追加するか、Docker Desktopの`kubectl`を削除してください。 -{{< /note >}} - -### PSGalleryからPowerShellを使用してインストールする - -Windowsで[Powershell Gallery](https://www.powershellgallery.com/)パッケージマネージャーを使用していれば、Powershellでkubectlをインストールおよびアップデートすることもできます。 - -1. インストールコマンドを実行してください(必ず`DownloadLocation`を指定してください): - - ```powershell - Install-Script -Name 'install-kubectl' -Scope CurrentUser -Force - install-kubectl.ps1 [-DownloadLocation ] - ``` - - {{< note >}} - `DownloadLocation`を指定しない場合、`kubectl`はユーザのTempディレクトリにインストールされます。 - {{< /note >}} - - インストーラーは`$HOME/.kube`を作成し、設定ファイルを作成します。 - -2. インストールしたバージョンが最新であることを確認してください: - - ```powershell - kubectl version --client - ``` - -{{< note >}} -アップデートする際は、手順1に示した2つのコマンドを再実行してください。 -{{< /note >}} - -### ChocolateyまたはScoopを使用してWindowsへインストールする - -1. Windowsへkubectlをインストールするために、[Chocolatey](https://chocolatey.org)パッケージマネージャーや[Scoop](https://scoop.sh)コマンドラインインストーラーを使用することもできます。 - - {{< tabs name="kubectl_win_install" >}} - {{% tab name="choco" %}} - ```powershell - choco install kubernetes-cli - ``` - {{% /tab %}} - {{% tab name="scoop" %}} - ```powershell - scoop install kubectl - ``` - {{% /tab %}} - {{< /tabs >}} - -2. インストールしたバージョンが最新であることを確認してください: - - ```powershell - kubectl version --client - ``` - -3. ホームディレクトリへ移動してください: - - ```powershell - # cmd.exeを使用している場合は cd %USERPROFILE% を実行してください。 - cd ~ - ``` -4. `.kube`ディレクトリを作成してください: - - ```powershell - mkdir .kube - ``` - -5. 作成した`.kube`ディレクトリへ移動してください: - - ```powershell - cd .kube - ``` - -6. リモートのKubernetesクラスターを使うために、kubectlを設定してください: - - ```powershell - New-Item config -type file - ``` - -{{< note >}} -Notepadなどの選択したテキストエディターから設定ファイルを編集してください。 -{{< /note >}} - -## Google Cloud SDKの一部としてダウンロードする - -Google Cloud SDKの一部として、kubectlをインストールすることもできます。 - -1. [Google Cloud SDK](https://cloud.google.com/sdk/)をインストールしてください。 -2. `kubectl`のインストールコマンドを実行してください: - - ```shell - gcloud components install kubectl - ``` - -3. インストールしたバージョンが最新であることを確認してください: - - ```shell - kubectl version --client - ``` - -## kubectlの設定を検証する - -kubectlがKubernetesクラスターを探索し接続するために、[kubeconfigファイル](/docs/concepts/configuration/organize-cluster-access-kubeconfig/)が必要になります。これは、[kube-up.sh](https://github.com/kubernetes/kubernetes/blob/master/cluster/kube-up.sh)によりクラスターを作成した際や、Minikubeクラスターを正常にデプロイした際に自動生成されます。デフォルトでは、kubectlの設定は`~/.kube/config`に格納されています。 - -クラスターの状態を取得し、kubectlが適切に設定されていることを確認してください: - -```shell -kubectl cluster-info -``` -URLのレスポンスが表示されている場合は、kubectlはクラスターに接続するよう正しく設定されています。 - -以下のようなメッセージが表示されている場合は、kubectlは正しく設定されていないか、Kubernetesクラスターに接続できていません。 - -``` -The connection to the server was refused - did you specify the right host or port? -``` - -たとえば、ラップトップ上(ローカル環境)でKubernetesクラスターを起動するような場合、Minikubeなどのツールを最初にインストールしてから、上記のコマンドを再実行する必要があります。 - -kubectl cluster-infoがURLレスポンスを返したにもかかわらずクラスターにアクセスできない場合は、次のコマンドで設定が正しいことを確認してください: - -```shell -kubectl cluster-info dump -``` - -## kubectlの任意の設定 - -### シェルの自動補完を有効にする - -kubectlはBashおよびZshの自動補完を提供しています。これにより、入力を大幅に削減することができます。 - -以下にBash(LinuxとmacOSの違いも含む)およびZshの自動補完の設定手順を示します。 - -{{< tabs name="kubectl_autocompletion" >}} - -{{% tab name="LinuxでのBash" %}} - -### はじめに - -Bashにおけるkubectlの補完スクリプトは`kubectl completion bash`コマンドで生成できます。シェル内で補完スクリプトをsourceすることでkubectlの自動補完が有効になります。 - -ただし、補完スクリプトは[**bash-completion**](https://github.com/scop/bash-completion)に依存しているため、このソフトウェアを最初にインストールしておく必要があります(`type _init_completion`を実行することで、bash-completionがすでにインストールされていることを確認できます)。 - -### bash-completionをインストールする - -bash-completionは多くのパッケージマネージャーから提供されています([こちら](https://github.com/scop/bash-completion#installation)を参照してください)。`apt-get install bash-completion`または`yum install bash-completion`などでインストールできます。 - -上記のコマンドでbash-completionの主要スクリプトである`/usr/share/bash-completion/bash_completion`が作成されます。パッケージマネージャーによっては、このファイルを`~/.bashrc`にて手動でsourceする必要があります。 - -これを調べるには、シェルをリロードしてから`type _init_completion`を実行してください。コマンドが成功していればすでに設定済みです。そうでなければ、`~/.bashrc`に以下を追記してください: - -```bash -source /usr/share/bash-completion/bash_completion -``` - -シェルをリロードし、`type _init_completion`を実行してbash-completionが正しくインストールされていることを検証してください。 - -### kubectlの自動補完を有効にする - -すべてのシェルセッションにてkubectlの補完スクリプトをsourceできるようにしなければなりません。これを行うには2つの方法があります: - -- 補完スクリプトを`~/.bashrc`内でsourceしてください: - - ```bash - echo 'source <(kubectl completion bash)' >>~/.bashrc - ``` - -- 補完スクリプトを`/etc/bash_completion.d`ディレクトリに追加してください: - - ```bash - kubectl completion bash >/etc/bash_completion.d/kubectl - ``` -- kubectlにエイリアスを張っている場合は、以下のようにシェルの補完を拡張して使うことができます: - -```bash -echo 'alias k=kubectl' >>~/.bashrc -echo 'complete -F __start_kubectl k' >>~/.bashrc -``` - -{{< note >}} -bash-completionは`/etc/bash_completion.d`内のすべての補完スクリプトをsourceします。 -{{< /note >}} - -どちらも同様の手法です。シェルをリロードしたあとに、kubectlの自動補完が機能するはずです。 - -{{% /tab %}} - - -{{% tab name="macOSでのBash" %}} - - -### はじめに - -Bashにおけるkubectlの補完スクリプトは`kubectl completion bash`コマンドで生成できます。シェル内で補完スクリプトをsourceすることでkubectlの自動補完が有効になります。 - -ただし、補完スクリプトは[**bash-completion**](https://github.com/scop/bash-completion)に依存しているため、事前にインストールする必要があります。 - -{{< warning>}} -bash-completionにはv1とv2のバージョンがあり、v1はBash 3.2(macOSのデフォルト)用で、v2はBash 4.1以降向けです。kubectlの補完スクリプトはbash-completionのv1とBash 3.2では正しく**動作しません**。**bash-completion v2**および**Bash 4.1**が必要になります。したがって、macOSで正常にkubectlの補完を使用するには、Bash 4.1以降をインストールする必要があります([*手順*](https://itnext.io/upgrading-bash-on-macos-7138bd1066ba))。以下の手順では、Bash4.1以降(Bashのバージョンが4.1またはそれより新しいことを指します)を使用することを前提とします。 -{{< /warning >}} - -### bashのアップグレード - -ここではBash 4.1以降の使用を前提としています。Bashのバージョンは下記のコマンドで調べることができます。 - -```bash -echo $BASH_VERSION -``` - -バージョンが古い場合、Homebrewを使用してインストールもしくはアップグレードできます。 - -```bash -brew install bash -``` - -シェルをリロードし、希望するバージョンを使用していることを確認してください。 - -```bash -echo $BASH_VERSION $SHELL -``` - -Homebrewは通常、`/usr/local/bin/bash`にインストールします。 - -### bash-completionをインストールする - -{{< note >}} -前述のとおり、この手順ではBash 4.1以降であることが前提のため、bash-completion v2をインストールすることになります(これとは逆に、Bash 3.2およびbash-completion v1の場合ではkubectlの補完は動作しません)。 -{{< /note >}} - -`type _init_completion`を実行することで、bash-completionがすでにインストールされていることを確認できます。ない場合は、Homebrewを使用してインストールすることもできます: - -```bash -brew install bash-completion@2 -``` - -このコマンドの出力で示されたように、`~/.bash_profile`に以下を追記してください: - -```bash -export BASH_COMPLETION_COMPAT_DIR="/usr/local/etc/bash_completion.d" -[[ -r "/usr/local/etc/profile.d/bash_completion.sh" ]] && . "/usr/local/etc/profile.d/bash_completion.sh" -``` - -シェルをリロードし、`type _init_completion`を実行してbash-completion v2が正しくインストールされていることを検証してください。 - -### kubectlの自動補完を有効にする - - -すべてのシェルセッションにてkubectlの補完スクリプトをsourceできるようにしなければなりません。これを行うには複数の方法があります: - -- 補完スクリプトを`~/.bash_profile`内でsourceする: - - ```bash - echo 'source <(kubectl completion bash)' >>~/.bash_profile - ``` - -- 補完スクリプトを`/usr/local/etc/bash_completion.d`ディレクトリに追加する: - - ```bash - kubectl completion bash >/usr/local/etc/bash_completion.d/kubectl - ``` - -- kubectlにエイリアスを張っている場合は、以下のようにシェルの補完を拡張して使うことができます: - - ```bash - echo 'alias k=kubectl' >>~/.bash_profile - echo 'complete -F __start_kubectl k' >>~/.bash_profile - ``` - -- kubectlをHomwbrewでインストールした場合([前述](#homebrewを使用してmacosへインストールする)のとおり)、kubectlの補完スクリプトはすでに`/usr/local/etc/bash_completion.d/kubectl`に格納されているでしょう。この場合、なにも操作する必要はありません。 - - {{< note >}} - Homebrewでインストールしたbash-completion v2は`BASH_COMPLETION_COMPAT_DIR`ディレクトリ内のすべてのファイルをsourceするため、後者の2つの方法が機能します。 - {{< /note >}} - -どの場合でも、シェルをリロードしたあとに、kubectlの自動補完が機能するはずです。 -{{% /tab %}} - -{{% tab name="Zsh" %}} - -Zshにおけるkubectlの補完スクリプトは`kubectl completion zsh`コマンドで生成できます。シェル内で補完スクリプトをsourceすることでkubectlの自動補完が有効になります。 - -すべてのシェルセッションで使用するには、`~/.zshrc`に以下を追記してください: - -```zsh -source <(kubectl completion zsh) -``` - -kubectlにエイリアスを張っている場合は、以下のようにシェルの補完を拡張して使うことができます: - -```zsh -echo 'alias k=kubectl' >>~/.zshrc -echo 'compdef __start_kubectl k' >>~/.zshrc -``` - -シェルをリロードしたあとに、kubectlの自動補完が機能するはずです。 - -`complete:13: command not found: compdef`のようなエラーが出力された場合は、以下を`~/.zshrc`の先頭に追記してください: - -```zsh -autoload -Uz compinit -compinit -``` -{{% /tab %}} -{{< /tabs >}} - - - -## {{% heading "whatsnext" %}} - -* [Minikubeをインストールする](https://minikube.sigs.k8s.io/docs/start/) -* クラスターの作成に関する詳細を[スタートガイド](/ja/docs/setup/)で確認する -* [アプリケーションを起動して公開する方法を学ぶ](/ja/docs/tasks/access-application-cluster/service-access-application-cluster/) -* あなたが作成していないクラスターにアクセスする必要がある場合は、[クラスターアクセスドキュメントの共有](/ja/docs/tasks/access-application-cluster/configure-access-multiple-clusters/)を参照してください -* [kubectlリファレンスドキュメント](/docs/reference/kubectl/kubectl/)を参照する diff --git a/content/ja/docs/tutorials/kubernetes-basics/create-cluster/cluster-intro.html b/content/ja/docs/tutorials/kubernetes-basics/create-cluster/cluster-intro.html index 42e373f3cb786..1097da6f408e6 100644 --- a/content/ja/docs/tutorials/kubernetes-basics/create-cluster/cluster-intro.html +++ b/content/ja/docs/tutorials/kubernetes-basics/create-cluster/cluster-intro.html @@ -27,7 +27,7 @@

            目標

            Kubernetesクラスター

            - Kubernetesは、単一のユニットとして機能するように接続された、可用性の高いコンピュータのクラスターをまとめあげます。Kubernetesの抽象化により、コンテナ化されたアプリケーションを個々のマシンに特に結び付けることなくクラスターにデプロイできます。この新しいデプロイモデルを利用するには、アプリケーションを個々のホストから切り離す方法でアプリケーションをパッケージ化(つまり、コンテナ化)する必要があります。コンテナ化されたアプリケーションは、アプリケーションがホストに深く統合されたパッケージとして特定のマシンに直接インストールされていた従来のデプロイモデルよりも柔軟で、より迅速に利用可能です。Kubernetesはより効率的な方法で、クラスター全体のアプリケーションコンテナの配布とスケジューリングを自動化します。Kubernetesはオープンソースのプラットフォームであり、プロダクションレディです。 + Kubernetesは、単一のユニットとして機能するように接続された、可用性の高いコンピューターのクラスターをまとめあげます。Kubernetesの抽象化により、コンテナ化されたアプリケーションを個々のマシンに特に結び付けることなくクラスターにデプロイできます。この新しいデプロイモデルを利用するには、アプリケーションを個々のホストから切り離す方法でアプリケーションをパッケージ化(つまり、コンテナ化)する必要があります。コンテナ化されたアプリケーションは、アプリケーションがホストに深く統合されたパッケージとして特定のマシンに直接インストールされていた従来のデプロイモデルよりも柔軟で、より迅速に利用可能です。Kubernetesはより効率的な方法で、クラスター全体のアプリケーションコンテナの配布とスケジューリングを自動化します。Kubernetesはオープンソースのプラットフォームであり、プロダクションレディです。

            Kubernetesクラスターは以下の2種類のリソースで構成されています:

              @@ -47,7 +47,7 @@

              まとめ:

            - Kubernetesは、コンピュータクラスター内およびコンピュータクラスター間でのアプリケーションコンテナの配置(スケジューリング)および実行を調整する、プロダクショングレードのオープンソースプラットフォームです。 + Kubernetesは、コンピュータークラスター内およびコンピュータークラスター間でのアプリケーションコンテナの配置(スケジューリング)および実行を調整する、プロダクショングレードのオープンソースプラットフォームです。

            diff --git a/content/ja/docs/tutorials/kubernetes-basics/deploy-app/deploy-intro.html b/content/ja/docs/tutorials/kubernetes-basics/deploy-app/deploy-intro.html index c917aa28af50d..600fa7ceac85e 100644 --- a/content/ja/docs/tutorials/kubernetes-basics/deploy-app/deploy-intro.html +++ b/content/ja/docs/tutorials/kubernetes-basics/deploy-app/deploy-intro.html @@ -68,7 +68,7 @@

            Kubernetes上にはじめてのアプリケーショ
            -

            Kubernetesのコマンドラインインターフェイスであるkubectlを使用して、Deploymentを作成、管理できます。kubectlはKubernetes APIを使用してクラスターと対話します。このモジュールでは、Kubernetesクラスターでアプリケーションを実行するDeploymentを作成するために必要な、最も一般的なkubectlコマンドについて学びます。

            +

            Kubernetesのコマンドラインインターフェースであるkubectlを使用して、Deploymentを作成、管理できます。kubectlはKubernetes APIを使用してクラスターと対話します。このモジュールでは、Kubernetesクラスターでアプリケーションを実行するDeploymentを作成するために必要な、最も一般的なkubectlコマンドについて学びます。

            Deploymentを作成するときは、アプリケーションのコンテナイメージと実行するレプリカの数を指定する必要があります。Deploymentを更新することで、あとでその情報を変更できます。チュートリアルのモジュール56では、Deploymentをどのようにスケール、更新できるかについて説明します。

            diff --git a/content/ja/docs/tutorials/security/cluster-level-pss.md b/content/ja/docs/tutorials/security/cluster-level-pss.md index 1ae584543846c..41cbd01822cdb 100644 --- a/content/ja/docs/tutorials/security/cluster-level-pss.md +++ b/content/ja/docs/tutorials/security/cluster-level-pss.md @@ -157,7 +157,7 @@ v{{< skew currentVersion >}}以外のKubernetesバージョンを実行してい 環境にPodセキュリティアドミッションを実装する際には、以下の点を考慮してください: 1. クラスターに適用されるリスク状況に基づくと、`restricted`のようにより厳格なPodセキュリティの標準のほうが、より良い選択肢かもしれません。 -1. `kube-ssytem`名前空間の免除は、Podがその名前空間で`privileged`として実行するのを許容することになります。 +1. `kube-system`名前空間の免除は、Podがその名前空間で`privileged`として実行するのを許容することになります。 実世界で使うにあたっては、以下の最小権限の原則に従って`kube-system`へのアクセスを制限する厳格なRBACポリシーを適用することを、Kubernetesプロジェクトは強く推奨します。 上記の標準を実装するには、次のようにします: 1. 目的のPodセキュリティの標準を実装するために、Podセキュリティアドミッションコントローラーで利用可能な設定ファイルを作成します: diff --git a/content/ja/docs/tutorials/services/connect-applications-service.md b/content/ja/docs/tutorials/services/connect-applications-service.md index 0c48332a06337..4d6ad1cf7515b 100644 --- a/content/ja/docs/tutorials/services/connect-applications-service.md +++ b/content/ja/docs/tutorials/services/connect-applications-service.md @@ -129,7 +129,7 @@ NAME ADDRESSTYPE PORTS ENDPOINTS AGE my-nginx-7vzhx IPv4 80 10.244.2.5,10.244.3.4 21s ``` -今や、あなたのクラスター内のどのノードからもnginx Serviceに`:`でcurlを使用してアクセスできるはずです。Service IPは完全に仮想であり、物理的なケーブルで接続されるものではありません。どのように動作しているのか興味があれば、さらなる詳細について[サービスプロキシー](/ja/docs/concepts/services-networking/service/#virtual-ips-and-service-proxies)を読んでください。 +今や、あなたのクラスター内のどのノードからもnginx Serviceに`:`でcurlを使用してアクセスできるはずです。Service IPは完全に仮想であり、物理的なケーブルで接続されるものではありません。どのように動作しているのか興味があれば、さらなる詳細について[サービスプロキシ](/ja/docs/concepts/services-networking/service/#virtual-ips-and-service-proxies)を読んでください。 ## Serviceへのアクセス diff --git a/content/ja/docs/tutorials/services/source-ip.md b/content/ja/docs/tutorials/services/source-ip.md index 44d6be6e06483..ce7c445ede35f 100644 --- a/content/ja/docs/tutorials/services/source-ip.md +++ b/content/ja/docs/tutorials/services/source-ip.md @@ -219,7 +219,7 @@ graph LR; class client plain; {{}} -クライアントのIPが失われることを回避するために、Kubernetesには[クライアントの送信元IPを保持する](/docs/tasks/access-application-cluster/create-external-load-balancer/#preserving-the-client-source-ip)機能があります。`service.spec.externalTrafficPolicy`の値を`Local`に設定すると、kube-proxyはローカルに存在するエンドポイントへのプロキシーリクエストだけをプロキシーし、他のノードへはトラフィックを転送しなくなります。このアプローチでは、オリジナルの送信元IPアドレスが保持されます。ローカルにエンドポイントが存在しない場合には、そのノードに送信されたパケットは損失します。そのため、エンドポイントに到達するパケットに適用する可能性のあるパケット処理ルールでは、送信元IPが正しいことを信頼できます。 +クライアントのIPが失われることを回避するために、Kubernetesには[クライアントの送信元IPを保持する](/docs/tasks/access-application-cluster/create-external-load-balancer/#preserving-the-client-source-ip)機能があります。`service.spec.externalTrafficPolicy`の値を`Local`に設定すると、kube-proxyはローカルに存在するエンドポイントへのプロキシリクエストだけをプロキシし、他のノードへはトラフィックを転送しなくなります。このアプローチでは、オリジナルの送信元IPアドレスが保持されます。ローカルにエンドポイントが存在しない場合には、そのノードに送信されたパケットは損失します。そのため、エンドポイントに到達するパケットに適用する可能性のあるパケット処理ルールでは、送信元IPが正しいことを信頼できます。 次のようにして`service.spec.externalTrafficPolicy`フィールドを設定します。 @@ -389,9 +389,9 @@ client_address=198.51.100.79 `Type=LoadBalancer`を使用したServiceで送信元IPを保持する機能を提供しているのは一部のクラウドプロバイダだけです。実行しているクラウドプロバイダによっては、以下のように異なる方法でリクエストを満たす場合があります。 -1. クライアントとのコネクションをプロキシーが終端し、ノードやエンドポイントとの接続には新しいコネクションが開かれる。このような場合、送信元IPは常にクラウドのロードバランサーのものになり、クライアントのIPにはなりません。 +1. クライアントとのコネクションをプロキシが終端し、ノードやエンドポイントとの接続には新しいコネクションが開かれる。このような場合、送信元IPは常にクラウドのロードバランサーのものになり、クライアントのIPにはなりません。 -2. クライアントからロードバランサーのVIPに送信されたリクエストが、中間のプロキシーではなく、クライアントの送信元IPとともにノードまで到達するようなパケット転送が使用される。 +2. クライアントからロードバランサーのVIPに送信されたリクエストが、中間のプロキシではなく、クライアントの送信元IPとともにノードまで到達するようなパケット転送が使用される。 1つめのカテゴリーのロードバランサーの場合、真のクライアントIPと通信するために、 HTTPの[Forwarded](https://tools.ietf.org/html/rfc7239#section-5.2)ヘッダーや[X-FORWARDED-FOR](https://ja.wikipedia.org/wiki/X-Forwarded-For)ヘッダー、[proxy protocol](https://www.haproxy.org/download/1.8/doc/proxy-protocol.txt)などの、ロードバランサーとバックエンドの間で合意されたプロトコルを使用する必要があります。2つ目のカテゴリーのロードバランサーの場合、Serviceの`service.spec.healthCheckNodePort`フィールドに保存されたポートを指すHTTPのヘルスチェックを作成することで、上記の機能を活用できます。 diff --git a/content/ja/docs/tutorials/stateless-application/guestbook.md b/content/ja/docs/tutorials/stateless-application/guestbook.md index 31b4b8fe70507..be980eba6c642 100644 --- a/content/ja/docs/tutorials/stateless-application/guestbook.md +++ b/content/ja/docs/tutorials/stateless-application/guestbook.md @@ -79,7 +79,7 @@ POD-NAMEの部分を実際のPodの名前に書き換えてください。 ### RedisのマスターのServiceを作成する -ゲストブックアプリケーションは、データを書き込むためにRedisのマスターと通信する必要があります。そのためには、[Service](/ja/docs/concepts/services-networking/service/)を適用して、トラフィックをRedisのマスターのPodへプロキシーしなければなりません。Serviceは、Podにアクセスするためのポリシーを指定します。 +ゲストブックアプリケーションは、データを書き込むためにRedisのマスターと通信する必要があります。そのためには、[Service](/ja/docs/concepts/services-networking/service/)を適用して、トラフィックをRedisのマスターのPodへプロキシしなければなりません。Serviceは、Podにアクセスするためのポリシーを指定します。 {{% codenew file="application/guestbook/redis-master-service.yaml" %}} diff --git a/content/ja/examples/application/deployment-sidecar.yaml b/content/ja/examples/application/deployment-sidecar.yaml new file mode 100644 index 0000000000000..3f1b841d31ebf --- /dev/null +++ b/content/ja/examples/application/deployment-sidecar.yaml @@ -0,0 +1,34 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: myapp + labels: + app: myapp +spec: + replicas: 1 + selector: + matchLabels: + app: myapp + template: + metadata: + labels: + app: myapp + spec: + containers: + - name: myapp + image: alpine:latest + command: ['sh', '-c', 'while true; do echo "logging" >> /opt/logs.txt; sleep 1; done'] + volumeMounts: + - name: data + mountPath: /opt + initContainers: + - name: logshipper + image: alpine:latest + restartPolicy: Always + command: ['sh', '-c', 'tail -F /opt/logs.txt'] + volumeMounts: + - name: data + mountPath: /opt + volumes: + - name: data + emptyDir: {} \ No newline at end of file diff --git a/content/ja/examples/application/job/job-sidecar.yaml b/content/ja/examples/application/job/job-sidecar.yaml new file mode 100644 index 0000000000000..f0fcef883cbab --- /dev/null +++ b/content/ja/examples/application/job/job-sidecar.yaml @@ -0,0 +1,27 @@ +apiVersion: batch/v1 +kind: Job +metadata: + name: myjob +spec: + template: + spec: + containers: + - name: myjob + image: alpine:latest + command: ['sh', '-c', 'echo "logging" > /opt/logs.txt'] + volumeMounts: + - name: data + mountPath: /opt + initContainers: + - name: logshipper + image: alpine:latest + restartPolicy: Always + command: ['sh', '-c', 'tail -F /opt/logs.txt'] + volumeMounts: + - name: data + mountPath: /opt + restartPolicy: Never + volumes: + - name: data + emptyDir: {} + diff --git a/content/ja/examples/pods/probe/http-liveness.yaml b/content/ja/examples/pods/probe/http-liveness.yaml index 48ca861c14271..ecc1a6ff2e12e 100644 --- a/content/ja/examples/pods/probe/http-liveness.yaml +++ b/content/ja/examples/pods/probe/http-liveness.yaml @@ -7,9 +7,9 @@ metadata: spec: containers: - name: liveness - image: registry.k8s.io/liveness + image: registry.k8s.io/e2e-test-images/agnhost:2.40 args: - - /server + - liveness livenessProbe: httpGet: path: /healthz diff --git a/content/ja/examples/pods/security/security-context-2.yaml b/content/ja/examples/pods/security/security-context-2.yaml index 0e3185341e94d..a2c4ba20af959 100644 --- a/content/ja/examples/pods/security/security-context-2.yaml +++ b/content/ja/examples/pods/security/security-context-2.yaml @@ -10,4 +10,4 @@ spec: image: gcr.io/google-samples/node-hello:1.0 securityContext: runAsUser: 2000 - allowPrivilegeEscalation: false + allowPrivilegeEscalation: false \ No newline at end of file diff --git a/content/ja/examples/pods/security/security-context-3.yaml b/content/ja/examples/pods/security/security-context-3.yaml index 05295e1a03800..926846081fb15 100644 --- a/content/ja/examples/pods/security/security-context-3.yaml +++ b/content/ja/examples/pods/security/security-context-3.yaml @@ -5,7 +5,4 @@ metadata: spec: containers: - name: sec-ctx-3 - image: gcr.io/google-samples/node-hello:1.0 - - - + image: gcr.io/google-samples/node-hello:1.0 \ No newline at end of file diff --git a/content/ja/examples/pods/security/security-context-4.yaml b/content/ja/examples/pods/security/security-context-4.yaml index d725308fecb56..3f222261fc965 100644 --- a/content/ja/examples/pods/security/security-context-4.yaml +++ b/content/ja/examples/pods/security/security-context-4.yaml @@ -8,4 +8,4 @@ spec: image: gcr.io/google-samples/node-hello:1.0 securityContext: capabilities: - add: ["NET_ADMIN", "SYS_TIME"] + add: ["NET_ADMIN", "SYS_TIME"] \ No newline at end of file diff --git a/content/ja/examples/pods/security/security-context.yaml b/content/ja/examples/pods/security/security-context.yaml index 86ca51d39a6f0..458dd59efd325 100644 --- a/content/ja/examples/pods/security/security-context.yaml +++ b/content/ja/examples/pods/security/security-context.yaml @@ -5,15 +5,17 @@ metadata: spec: securityContext: runAsUser: 1000 + runAsGroup: 3000 fsGroup: 2000 volumes: - name: sec-ctx-vol emptyDir: {} containers: - name: sec-ctx-demo - image: gcr.io/google-samples/node-hello:1.0 + image: busybox:1.28 + command: [ "sh", "-c", "sleep 1h" ] volumeMounts: - name: sec-ctx-vol mountPath: /data/demo securityContext: - allowPrivilegeEscalation: false + allowPrivilegeEscalation: false \ No newline at end of file diff --git a/content/ja/releases/_index.md b/content/ja/releases/_index.md new file mode 100644 index 0000000000000..81be852bf8ad4 --- /dev/null +++ b/content/ja/releases/_index.md @@ -0,0 +1,30 @@ +--- +linktitle: リリース履歴 +title: リリース +type: docs +layout: release-info +notoc: true +--- + + + +Kubernetesプロジェクトは、最新の3つのマイナーリリース({{< skew latestVersion >}}、{{< skew prevMinorVersion >}}、{{< skew oldestMinorVersion >}})のリリースブランチをメンテナンスしています。 +Kubernetes 1.19以降のバージョンは、[約1年間のパッチサポート](/releases/patch-releases/#support-period)を受け付けています。 +Kubernetes 1.18以前のバージョンは、約9ヶ月間のパッチサポートを受け付けていました。 + +Kubernetesのバージョンは、**x.y.z**と表されます。 +ここで、**x**はメジャーバージョン、**y**はマイナーバージョン、**z**はパッチバージョンを指し、これらは[セマンティックバージョニング](https://semver.org/)の用語に従います。 + +詳細は、[バージョンスキューポリシー](/releases/version-skew-policy/)のドキュメントで確認できます。 + + + +## リリース履歴 + +{{< release-data >}} + +## リリース予定 + +Kubernetes**{{< skew nextMinorVersion >}}**の[リリーススケジュール](https://github.com/kubernetes/sig-release/tree/master/releases/release-{{< skew nextMinorVersion >}})をチェックしてみてください! + +## リソース diff --git a/content/ja/releases/notes.md b/content/ja/releases/notes.md new file mode 100644 index 0000000000000..e3e5d2d9baae9 --- /dev/null +++ b/content/ja/releases/notes.md @@ -0,0 +1,15 @@ +--- +linktitle: リリースノート +title: ノート +type: docs +description: > + Kubernetesのリリースノート +sitemap: + priority: 0.5 +--- + +リリースノートは、使用しているKubernetesのバージョンに合った[Changelog](https://github.com/kubernetes/kubernetes/tree/master/CHANGELOG)を読むことで確認できます。 +{{< skew currentVersionAddMinor 0 >}}のchangelogを見るには[GitHub](https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG/CHANGELOG-{{< skew currentVersionAddMinor 0 >}}.md)を参照してください。 + +またリリースノートは、[relnotes.k8s.io](https://relnotes.k8s.io)上で検索してフィルタリングすることもできます。 +{{< skew currentVersionAddMinor 0 >}}のフィルタリングされたリリースノートを見るには[relnotes.k8s.io](https://relnotes.k8s.io/?releaseVersions={{< skew currentVersionAddMinor 0 >}}.0)を参照してください。 diff --git a/content/ja/docs/setup/release/version-skew-policy.md b/content/ja/releases/version-skew-policy.md similarity index 98% rename from content/ja/docs/setup/release/version-skew-policy.md rename to content/ja/releases/version-skew-policy.md index bd1875aa41942..2d85ae15f72d9 100644 --- a/content/ja/docs/setup/release/version-skew-policy.md +++ b/content/ja/releases/version-skew-policy.md @@ -1,7 +1,8 @@ --- -title: Kubernetesバージョンとバージョンスキューサポートポリシー -content_type: concept -weight: 30 +title: バージョンスキューポリシー +type: docs +description: > + さまざまなKubernetesコンポーネント間でサポートされる最大のバージョンスキュー。 --- diff --git a/content/ko/OWNERS b/content/ko/OWNERS index dc285aa06bb6b..cc97f542ea387 100644 --- a/content/ko/OWNERS +++ b/content/ko/OWNERS @@ -8,6 +8,14 @@ reviewers: approvers: - sig-docs-ko-owners +- sig-docs-website-owners # important due to no_parent_owners option labels: +- area/localization - language/ko + +# Disable inheritance so that the localization team don't end up as approvers for all +# languages. +# https://github.com/kubernetes/community/blob/master/communication/website-guidelines.md +options: + no_parent_owners: true diff --git a/content/ko/docs/reference/command-line-tools-reference/feature-gates-removed.md b/content/ko/docs/reference/command-line-tools-reference/feature-gates-removed/index.md similarity index 100% rename from content/ko/docs/reference/command-line-tools-reference/feature-gates-removed.md rename to content/ko/docs/reference/command-line-tools-reference/feature-gates-removed/index.md diff --git a/content/ko/docs/reference/command-line-tools-reference/feature-gates.md b/content/ko/docs/reference/command-line-tools-reference/feature-gates/index.md similarity index 100% rename from content/ko/docs/reference/command-line-tools-reference/feature-gates.md rename to content/ko/docs/reference/command-line-tools-reference/feature-gates/index.md diff --git a/content/ko/docs/tasks/administer-cluster/network-policy-provider/weave-network-policy.md b/content/ko/docs/tasks/administer-cluster/network-policy-provider/weave-network-policy.md index 9c99014c1ffb1..c032d941c7fbb 100644 --- a/content/ko/docs/tasks/administer-cluster/network-policy-provider/weave-network-policy.md +++ b/content/ko/docs/tasks/administer-cluster/network-policy-provider/weave-network-policy.md @@ -19,12 +19,12 @@ weight: 50 ## Weave Net 애드온을 설치한다 -[애드온을 통한 쿠버네티스 통합하기](https://www.weave.works/docs/net/latest/kubernetes/kube-addon/) 가이드를 따른다. +[애드온을 통한 쿠버네티스 통합하기](https://github.com/weaveworks/weave/blob/master/site/kubernetes/kube-addon.md#-installation) 가이드를 따른다. 쿠버네티스의 위브넷 애드온은 쿠버네티스의 모든 네임스페이스의 네크워크 정책 어노테이션을 자동으로 모니터링하며, 정책에 따라 트래픽을 허용하고 차단하는 `iptables` 규칙을 구성하는 -[네트워크 폴리시 컨트롤러](https://www.weave.works/docs/net/latest/kubernetes/kube-addon/#npc)와 함께 제공된다. +[네트워크 폴리시 컨트롤러](https://github.com/weaveworks/weave/blob/master/site/kubernetes/kube-addon.md#network-policy)와 함께 제공된다. ## 설치 시험 diff --git a/content/pl/OWNERS b/content/pl/OWNERS index f51cfd63f3e19..4ec40bfa1cb5e 100644 --- a/content/pl/OWNERS +++ b/content/pl/OWNERS @@ -8,6 +8,14 @@ reviewers: approvers: - sig-docs-pl-owners +- sig-docs-website-owners # important due to no_parent_owners option labels: +- area/localization - language/pl + +# Disable inheritance so that the localization team don't end up as approvers for all +# languages. +# https://github.com/kubernetes/community/blob/master/communication/website-guidelines.md +options: + no_parent_owners: true diff --git a/content/pt-br/OWNERS b/content/pt-br/OWNERS index db8529e3435a9..2fec5d46678f6 100644 --- a/content/pt-br/OWNERS +++ b/content/pt-br/OWNERS @@ -1,4 +1,4 @@ -# This is the localization project for Portuguese. +# This is the localization project for (Brazilian) Portuguese. # Teams and members are visible at https://github.com/orgs/kubernetes/teams. reviewers: @@ -6,6 +6,14 @@ reviewers: approvers: - sig-docs-pt-owners +- sig-docs-website-owners # important due to no_parent_owners option labels: +- area/localization - language/pt + +# Disable inheritance so that the localization team don't end up as approvers for all +# languages. +# https://github.com/kubernetes/community/blob/master/communication/website-guidelines.md +options: + no_parent_owners: true diff --git a/content/pt-br/docs/concepts/storage/persistent-volumes.md b/content/pt-br/docs/concepts/storage/persistent-volumes.md index ec27b23a44b49..8e219c97af5c4 100644 --- a/content/pt-br/docs/concepts/storage/persistent-volumes.md +++ b/content/pt-br/docs/concepts/storage/persistent-volumes.md @@ -192,7 +192,7 @@ spec: ... ``` -Isso é útil se você deseja utilizar PersistentVolumes que possuem suas `claimPolicy` configuradas para `Retain`, incluindo situações onde você estiver reutilizando um PV existente. +Isso é útil se você deseja utilizar PersistentVolumes que possuem suas `persistentVolumeReclaimPolicy` configuradas para `Retain`, incluindo situações onde você estiver reutilizando um PV existente. ### Expandindo Requisições de Volumes Persistentes diff --git a/content/pt-br/docs/concepts/storage/volumes.md b/content/pt-br/docs/concepts/storage/volumes.md index 7ed655567a5dd..42954fdc68328 100644 --- a/content/pt-br/docs/concepts/storage/volumes.md +++ b/content/pt-br/docs/concepts/storage/volumes.md @@ -808,7 +808,7 @@ O recurso `CSIMigration` para Portworx foi adicionado, mas desativado por padrã ## Utilizando subPath {#using-subpath} -Às vezes, é útil compartilhar um volume para múltiplos usos em um único pod. A propriedade `volumeMounts.subPath` especifica um sub caminho dentro do volume referenciado em vez de sua raiz. +Às vezes, é útil compartilhar um volume para múltiplos usos em um único pod. A propriedade `volumeMounts[*].subPath` especifica um sub caminho dentro do volume referenciado em vez de sua raiz. O exemplo a seguir mostra como configurar um Pod com um ambiente LAMP (Linux, Apache, MySQL e PHP) usando um único volume compartilhado. Esta exemplo de configuração `subPath` não é recomendada para uso em produção. @@ -972,7 +972,7 @@ Os mantenedores do driver FlexVolume devem implementar um driver CSI e ajudar a A propagação de montagem permite compartilhar volumes montados por um contêiner para outros contêineres no mesmo pod, ou mesmo para outros pods no mesmo nó. -A propagação de montagem de um volume é controlada pelo campo `mountPropagation` na propriedade `Container.volumeMounts`. Os seus valores são: +A propagação de montagem de um volume é controlada pelo campo `mountPropagation` na propriedade `containers[*].volumeMounts`. Os seus valores são: * `None` - Este volume de montagem não receberá do host nenhuma montagem posterior que seja montada para este volume ou qualquer um de seus subdiretórios. De forma semelhante, nenhum ponto de montagem criado pelo contêiner será visível no host. Este é o modo padrão. diff --git a/content/pt-br/docs/tasks/access-application-cluster/access-cluster.md b/content/pt-br/docs/tasks/access-application-cluster/access-cluster.md new file mode 100644 index 0000000000000..c062909e80956 --- /dev/null +++ b/content/pt-br/docs/tasks/access-application-cluster/access-cluster.md @@ -0,0 +1,269 @@ +--- +title: Acessando clusters +weight: 20 +content_type: concept +--- + + + +Esse tópico fala sobre diversas maneiras de interagir com clusters. + + + +## Acessando pela primeira vez com kubectl + +Se estiver acessando o Kubernetes API pela primeira vez, recomendamos usar a CLI do Kubernetes, `kubectl`. + +Para acessar um cluster, você precisa saber a localização do cluster e ter credenciais para acessá-lo. Geralmente, isso é configurado automaticamente quando você trabalha com um [Guia de instalação](/pt-br/docs/setup/) ou outra pessoa configurou o cluster e forneceu a você credenciais e uma localização. + +Verifique o local e as credenciais que o kubectl conhece com esse comando: + +```shell +kubectl config view +``` + +Muitos dos [exemplos](/docs/reference/kubectl/quick-reference/) fornecem uma introdução ao uso do `kubectl` e a documentação completa pode ser encontrada no [guia de referência do kubectl](/docs/reference/kubectl/). + +## Acessando diretamente a API REST {#directly-accessing-the-rest-api} + +O Kubectl lida com a localização e a autenticação no servidor de API. +Se você quiser acessar diretamente a API REST com um cliente http como +curl ou wget, ou um navegador, há várias maneiras de localizar e autenticar: + +- Executar o kubectl no modo proxy. + - Método recomendado. + - Usa a localização previamente armazenada do servidor da API. + - Verifica a identidade do apiserver usando um certificado autoassinado. Não há possibilidade de ataque MITM (_Man-In-The-Middle_). + - Autentica-se no servidor da API. + - No futuro, poderá fazer balanceamento de carga inteligente no lado do cliente, e transferência em caso de falha. +- Forneça o local e as credenciais diretamente para o cliente http. + - Método alternativo. + - Funciona com alguns tipos de código de cliente que são confundidos pelo uso de um proxy. + - É necessário importar um certificado raiz em seu navegador para se proteger contra ataque MITM (_Man-In-The-Middle_). + +### Usando o kubectl proxy + +O comando a seguir executa o kubectl em um modo em que ele atua como um proxy reverso. Ele lida com +localização do apiserver e da autenticação. +Execute-o desta forma: + +```shell +kubectl proxy --port=8080 +``` + +Consulte [kubectl proxy](/docs/reference/generated/kubectl/kubectl-commands/#proxy) para obter mais detalhes. + +Em seguida, você pode explorar a API com curl, wget ou um navegador, substituindo localhost +por [::1] para IPv6, da seguinte forma: + +```shell +curl http://localhost:8080/api/ +``` + +O resultado é semelhante a este: + +```json +{ + "kind": "APIVersions", + "versions": [ + "v1" + ], + "serverAddressByClientCIDRs": [ + { + "clientCIDR": "0.0.0.0/0", + "serverAddress": "10.0.1.149:443" + } + ] +} +``` + +### Sem kubectl proxy + +Use `kubectl apply` e `kubectl describe secret...` para criar um token para a conta de serviço padrão com grep/cut: + +Primeiro, crie o Secret, solicitando um token para a ServiceAccount padrão: + +```shell +kubectl apply -f - </dev/null; do + echo "waiting for token..." >&2 + sleep 1 +done +``` + +Recupere e use o token gerado: + +```shell +APISERVER=$(kubectl config view --minify | grep server | cut -f 2- -d ":" | tr -d " ") +TOKEN=$(kubectl describe secret default-token | grep -E '^token' | cut -f2 -d':' | tr -d " ") + +curl $APISERVER/api --header "Authorization: Bearer $TOKEN" --insecure +``` + +O resultado é semelhante a este: + +```json +{ + "kind": "APIVersions", + "versions": [ + "v1" + ], + "serverAddressByClientCIDRs": [ + { + "clientCIDR": "0.0.0.0/0", + "serverAddress": "10.0.1.149:443" + } + ] +} +``` + +Usando `jsonpath`: + +```shell +APISERVER=$(kubectl config view --minify -o jsonpath='{.clusters[0].cluster.server}') +TOKEN=$(kubectl get secret default-token -o jsonpath='{.data.token}' | base64 --decode) + +curl $APISERVER/api --header "Authorization: Bearer $TOKEN" --insecure +``` + +O resultado é semelhante a este: + +```json +{ + "kind": "APIVersions", + "versions": [ + "v1" + ], + "serverAddressByClientCIDRs": [ + { + "clientCIDR": "0.0.0.0/0", + "serverAddress": "10.0.1.149:443" + } + ] +} +``` + +Os exemplos acima usam a opção `--insecure`. Isso deixa o cluster sujeito a ataques MITM. +Quando o kubectl acessa o cluster, ele usa um certificado raiz guardado +e certificados de cliente para acessar o servidor. (Esses certificados são instalados no diretório +`~/.kube`). Como os certificados do cluster normalmente são autoassinados, pode ser necessária uma +configuração especial para que seu cliente http use o certificado raiz. + +Em alguns clusters, o servidor da API não requer autenticação; ele pode servir +no localhost ou estar protegido por um firewall. Não há um padrão +para isso. A página [Controlando Acesso à API do Kubernetes](/pt-br/docs/concepts/security/controlling-access) +descreve como um administrador de cluster pode configurar isso. + +## Acesso programático à API + +O Kubernetes suporta oficialmente as bibliotecas de clientes [Go](#go-client) e [Python](#python-client). + +### Cliente Go{#go-client} + +* Para obter a biblioteca, execute o seguinte comando: `go get k8s.io/client-go@kubernetes-`, + consulte [INSTALL.md](https://github.com/kubernetes/client-go/blob/master/INSTALL.md#for-the-casual-user) + para obter instruções detalhadas de instalação. Consulte + [https://github.com/kubernetes/client-go](https://github.com/kubernetes/client-go#compatibility-matrix) + para ver quais versões são compatíveis. +* Escreva um aplicativo utilizando o cliente Go. Observe que ela define seus próprios objetos de API, + portanto, se necessário, importe as definições de API do cliente Go em vez de importá-las do repositório principal. + Por exemplo, `import "k8s.io/client-go/kubernetes"` está correto. + +O cliente Go pode usar o mesmo arquivo [kubeconfig](/pt-br/docs/concepts/configuration/organize-cluster-access-kubeconfig/) +como a CLI do kubectl faz, para localizar e autenticar ao apiserver. Veja esse +[exemplo](https://git.k8s.io/client-go/examples/out-of-cluster-client-configuration/main.go). + +Se o aplicativo for disponibilizado como um pod no cluster, consulte a [próxima seção](#acessando-a-api-a-partir-de-um-pod). + +### Cliente Python{#python-client} + +Para usar o [cliente Python](https://github.com/kubernetes-client/python), execute o seguinte comando: +`pip install kubernetes`. Consulte [a página Python Client Library](https://github.com/kubernetes-client/python) +para obter mais opções de instalação. + +O cliente Python pode usar o mesmo arquivo [kubeconfig](/docs/concepts/configuration/organize-cluster-access-kubeconfig/) +que a ferramenta kubectl utiliza para localizar e autenticar ao servidor da API. Veja esse +[exemplo](https://github.com/kubernetes-client/python/tree/master/examples). + +### Outras bibliotecas + +Existem [bibliotecas de clientes](/docs/reference/using-api/client-libraries/) para acessar a API utilizando outras linguagens. +Consulte a documentação de outras bibliotecas para saber como elas se autenticam. + +## Acessando a API a partir de um pod + +Ao acessar a API a partir de um pod, a localização e a autenticação +para o servidor de API são um pouco diferentes. + +Consulte [Acessando a API a partir de um pod](/docs/tasks/run-application/access-api-from-pod/) +para obter mais detalhes. + +## Acessando serviços em execução no cluster + +A seção anterior descreve como se conectar ao servidor da API do Kubernetes. +Para obter informações sobre como se conectar a outros serviços em execução em um cluster do Kubernetes, consulte +[Acessando serviços em execução em clusters](/pt-br/docs/tasks/access-application-cluster/access-cluster-services/). + +## Solicitação de redirecionamentos + +Os recursos de redirecionamento foram descontinuados e removidos. Em vez disso, use um proxy (veja abaixo). + +## Tantos proxies + +Há vários proxies diferentes que você pode encontrar ao usar o Kubernetes: + +1. O [kubectl proxy](#directly-accessing-the-rest-api): + + - é executado no computador de um usuário ou em um pod + - cria um proxy de um endereço localhost para o servidor da API do Kubernetes + - a conexão do cliente para o proxy usa HTTP + - a conexão do proxy para o servidor da API usa HTTPS + - localiza o apiserver + - adiciona cabeçalhos de autenticação + +2. O [proxy do servidor da API](/pt-br/docs/tasks/access-application-cluster/access-cluster-services/#descobrindo-serviços-integrados): + + - é um bastião incorporado ao apiserver + - conecta um usuário fora do cluster aos IPs do cluster que, de outra forma, poderiam não ser acessíveis + - é executado no processo do servidor da API + - cliente para proxy usa HTTPS (ou http se o servidor da API estiver configurado dessa forma) + - a conexão do proxy para o destino pode usar HTTP ou HTTPS, conforme escolhido pelo proxy usando as informações disponíveis + - pode ser usado para acessar um Nó, Pod ou Serviço + - faz o balanceamento de carga quando usado para acessar um serviço + +3. O [kube proxy](/docs/concepts/services-networking/service/#ips-and-vips): + + - é executado em cada nó + - proxy de UDP e TCP + - não entende HTTP + - fornece balanceamento de carga + - é usado apenas para acessar serviços + +4. Um Proxy/balanceador de carga na frente do(s) servidor(es) da API: + + - a existência e a implementação variam de cluster para cluster (por exemplo, nginx) + - fica entre todos os clientes e um ou mais servidores da API + - atua como um balanceador de carga se houver vários servidores da API. + +6. Balanceadores de carga de provedor de nuvem em serviços externos: + + - são fornecidos por alguns provedores de nuvem computacional (por exemplo, AWS ELB, Google Cloud Load Balancer) + - são criados automaticamente quando o serviço Kubernetes tem o tipo `LoadBalancer` + - usam somente UDP/TCP + - a implementação varia de acordo com o provedor de nuvem. + +Normalmente, os usuários do Kubernetes não precisam se preocupar com nada além dos dois primeiros tipos. O administrador do cluster +normalmente garantirá que os últimos tipos sejam configurados corretamente. diff --git a/content/pt-br/docs/tasks/access-application-cluster/configure-access-multiple-clusters.md b/content/pt-br/docs/tasks/access-application-cluster/configure-access-multiple-clusters.md new file mode 100644 index 0000000000000..4c81fd63bdef3 --- /dev/null +++ b/content/pt-br/docs/tasks/access-application-cluster/configure-access-multiple-clusters.md @@ -0,0 +1,400 @@ +--- +title: Configurar o acesso a múltiplos clusters +content_type: task +weight: 30 +card: + name: tasks + weight: 25 + title: Configure access to clusters +--- + + + +Esta página mostra como configurar o acesso a vários clusters usando arquivos de configuração. Depois que os clusters, os usuários e os contextos forem definidos em um ou mais arquivos de configuração, você pode alternar rapidamente entre os clusters usando o comando `kubectl config use-context`. + +{{< note >}} +Um arquivo usado para configurar o acesso a um cluster às vezes é chamado de arquivo *kubeconfig*. Essa é uma forma genérica de se referir a arquivos de configuração. Isso não significa que exista um arquivo chamado `kubeconfig`. +{{< /note >}} + + +{{< warning >}} +Use somente arquivos kubeconfig de fontes confiáveis. O uso de um arquivo kubeconfig artificialmente criado, pode resultar em execução de código malicioso ou exposição de arquivos. Se você preciso usar um arquivo kubeconfig não-confiável, inspecione-o cuidadosamente antes, da mesma forma que faria com um script de shell. +{{< /warning>}} + + +## {{% heading "prerequisites" %}} + +{{< include "task-tutorial-prereqs.md" >}} + +Para verificar se {{< glossary_tooltip text="kubectl" term_id="kubectl" >}} está instalado, +execute `kubectl version --client`. A versão do kubectl deve ter [no máximo uma versão menor de diferença](/releases/version-skew-policy/#kubectl) da versão do servidor de API do seu cluster. + + + +## Defina clusters, usuários e contextos + +Suponha que você tenha dois clusters, um para o trabalho de desenvolvimento, chamado `development`, e outro para o trabalho de teste, chamado `test`. +No cluster `development`, seus desenvolvedores de front-end trabalham em um namespace chamado `frontend`, +e os desenvolvedores de armazenamento trabalham em um namespace chamado `storage`. Em seu cluster `test`, +os desenvolvedores trabalham no namespace padrão ou criam namespaces auxiliares conforme +acharem adequado. O acesso ao cluster de desenvolvimento requer autenticação por certificado. O acesso +ao cluster de teste requer autenticação por nome de usuário e senha. + +Crie um diretório chamado `config-exercise`. Em seu diretório +`config-exercise`, crie um arquivo chamado `config-demo` com este conteúdo: + +```yaml +apiVersion: v1 +kind: Config +preferences: {} + +clusters: +- cluster: + name: development +- cluster: + name: test + +users: +- name: developer +- name: experimenter + +contexts: +- context: + name: dev-frontend +- context: + name: dev-storage +- context: + name: exp-test +``` + +Um arquivo de configuração descreve clusters, usuários e contextos. Seu arquivo `config-demo` +tem a estrutura para descrever dois clusters, dois usuários e três contextos. + +Vá para o diretório `config-exercise`. Digite estes comandos para adicionar detalhes do cluster ao +seu arquivo de configuração: + +```shell +kubectl config --kubeconfig=config-demo set-cluster development --server=https://1.2.3.4 --certificate-authority=fake-ca-file +kubectl config --kubeconfig=config-demo set-cluster test --server=https://5.6.7.8 --insecure-skip-tls-verify +``` + +Adicione detalhes do usuário ao seu arquivo de configuração: + +{{< caution >}} +O armazenamento de senhas na configuração do cliente do Kubernetes é arriscado. Uma alternativa melhor seria usar um plug-in de credenciais e salvá-las separadamente. Veja: [plugins de credenciais client-go](/pt-br/docs/reference/access-authn-authz/authentication/#plugins-de-credenciais-client-go) +{{< /caution >}} + +```shell +kubectl config --kubeconfig=config-demo set-credentials developer --client-certificate=fake-cert-file --client-key=fake-key-seefile +kubectl config --kubeconfig=config-demo set-credentials experimenter --username=exp --password=some-password +``` + +{{< note >}} +- Para excluir um usuário, você pode executar `kubectl --kubeconfig=config-demo config unset users.` +- Para remover um cluster, você pode executar `kubectl --kubeconfig=config-demo config unset clusters.` +- Para remover um contexto, você pode executar `kubectl --kubeconfig=config-demo config unset contexts.` +{{< /note >}} + +Adicione detalhes de contexto ao seu arquivo de configuração: + +```shell +kubectl config --kubeconfig=config-demo set-context dev-frontend --cluster=development --namespace=frontend --user=developer +kubectl config --kubeconfig=config-demo set-context dev-storage --cluster=development --namespace=storage --user=developer +kubectl config --kubeconfig=config-demo set-context exp-test --cluster=test --namespace=default --user=experimenter +``` + +Abra seu arquivo `config-demo` para ver os detalhes adicionados. Como alternativa para abrir o arquivo `config-demo`, você pode usar o comando `config view` + +```shell +kubectl config --kubeconfig=config-demo view +``` + +O resultado mostra os dois clusters, dois usuários e três contextos: + +```yaml +apiVersion: v1 +clusters: +- cluster: + certificate-authority: fake-ca-file + server: https://1.2.3.4 + name: development +- cluster: + insecure-skip-tls-verify: true + server: https://5.6.7.8 + name: test +contexts: +- context: + cluster: development + namespace: frontend + user: developer + name: dev-frontend +- context: + cluster: development + namespace: storage + user: developer + name: dev-storage +- context: + cluster: test + namespace: default + user: experimenter + name: exp-test +current-context: "" +kind: Config +preferences: {} +users: +- name: developer + user: + client-certificate: fake-cert-file + client-key: fake-key-file +- name: experimenter + user: + # Nota de documentação (este comentário NÃO faz parte da saída do comando). + # Armazenar senhas na configuração do cliente Kubernetes é arriscado. + # Uma alternativa melhor seria usar um plugin de credenciais + # e armazenar as credenciais separadamente. + # Veja https://kubernetes.io/pt-br/docs/reference/access-authn-authz/authentication/#plugins-de-credenciais-client-go + password: some-password + username: exp +``` + +O `fake-ca-file`, o `fake-cert-file` e o `fake-key-file` acima são os espaços reservados +para a localização dos arquivos de certificado. Você precisa alterá-los para a localização real +dos arquivos de certificado em seu ambiente. + +Às vezes, você pode querer usar dados codificados em Base64 incorporados aqui, em vez de arquivos de certificado separados. +Nesse caso, é necessário adicionar o sufixo `data` às chaves, por exemplo, +`certificate-authority-data`, `client-certificate-data`, `client-key-data`. + +Cada contexto é uma tripla (cluster, usuário, namespace). Por exemplo, o contexto +`dev-frontend` diz: "Use as credenciais do usuário `developer` +para acessar o namespace `frontend` do cluster `development`". + +Define o contexto atual: + +```shell +kubectl config --kubeconfig=config-demo use-context dev-frontend +``` + +Agora, sempre que você use um comando `kubectl`, a ação será aplicada ao cluster, +e ao namespace listados no contexto `dev-frontend`. E o comando usará +as credenciais do usuário listado no contexto `dev-frontend`. + +Para ver apenas as informações de configuração associadas ao +o contexto atual, use a opção `--minify`. + +```shell +kubectl config --kubeconfig=config-demo view --minify +``` + +O resultado mostra as informações de configuração associadas ao contexto `dev-frontend`: + +```yaml +apiVersion: v1 +clusters: +- cluster: + certificate-authority: fake-ca-file + server: https://1.2.3.4 + name: development +contexts: +- context: + cluster: development + namespace: frontend + user: developer + name: dev-frontend +current-context: dev-frontend +kind: Config +preferences: {} +users: +- name: developer + user: + client-certificate: fake-cert-file + client-key: fake-key-file +``` + +Agora, suponha que você queira trabalhar por um tempo no cluster de teste. + +Altere o contexto atual para `exp-test`: + +```shell +kubectl config --kubeconfig=config-demo use-context exp-test +``` + +Agora, qualquer comando `kubectl` que você usar, será aplicado ao namespace padrão do cluster `test`. E o comando usará as credenciais do usuário +listado no contexto `exp-test`. + +Ver a configuração associada ao novo contexto atual, `exp-test`. + +```shell +kubectl config --kubeconfig=config-demo view --minify +``` + +Por fim, suponha que você queira trabalhar por um tempo no namespace `storage` do cluster `development`. + +Altere o contexto atual para `dev-storage`: + +```shell +kubectl config --kubeconfig=config-demo use-context dev-storage +``` + +Ver a configuração associada ao novo contexto atual, `dev-storage`. + +```shell +kubectl config --kubeconfig=config-demo view --minify +``` + +## Crie um segundo arquivo de configuração + +Em seu diretório `config-exercise`, crie um arquivo chamado `config-demo-2` com este conteúdo: + +```yaml +apiVersion: v1 +kind: Config +preferences: {} + +contexts: +- context: + cluster: development + namespace: ramp + user: developer + name: dev-ramp-up +``` + +O arquivo de configuração anterior define um novo contexto chamado `dev-ramp-up`. + +## Defina a variável de ambiente KUBECONFIG + +Verifique se você tem uma variável de ambiente chamada `KUBECONFIG`. Em caso afirmativo, salve o valor atual da variável de ambiente `KUBECONFIG` para que você possa restaurá-lo posteriormente. +Por exemplo: + +### Linux + +```shell +export KUBECONFIG_SAVED="$KUBECONFIG" +``` + +### Windows PowerShell + +```powershell +$Env:KUBECONFIG_SAVED=$ENV:KUBECONFIG +``` + + A variável de ambiente `KUBECONFIG` é uma lista de caminhos para arquivos de configuração. A lista é +delimitada por dois pontos para Linux e Mac, e delimitada por ponto e vírgula para Windows. Se você tiver +uma variável de ambiente `KUBECONFIG`, familiarize-se com os arquivos de configuração +na lista. + +Anexe temporariamente duas localizações à sua variável de ambiente `KUBECONFIG`. Por exemplo: + +### Linux + +```shell +export KUBECONFIG="${KUBECONFIG}:config-demo:config-demo-2" +``` + +### Windows PowerShell + +```powershell +$Env:KUBECONFIG=("config-demo;config-demo-2") +``` + +Em seu diretório `config-exercise`, digite este comando: + +```shell +kubectl config view +``` + +O resultado mostra informações mescladas de todos os arquivos listados em sua variável de ambiente `KUBECONFIG`. Em particular, observe que as informações mescladas têm o contexto `dev-ramp-up` do arquivo `config-demo-2` e os três contextos do arquivo `config-demo`: + +```yaml +contexts: +- context: + cluster: development + namespace: frontend + user: developer + name: dev-frontend +- context: + cluster: development + namespace: ramp + user: developer + name: dev-ramp-up +- context: + cluster: development + namespace: storage + user: developer + name: dev-storage +- context: + cluster: test + namespace: default + user: experimenter + name: exp-test +``` + +Para obter mais informações sobre como os arquivos kubeconfig são mesclados, consulte +[Organizando o acesso ao cluster usando arquivos kubeconfig](/pt-br/docs/concepts/configuration/organize-cluster-access-kubeconfig/) + +## Explore o diretório $HOME/.kube + +Se você já tiver um cluster e puder usar o `kubectl` para interagir com o +o cluster, então provavelmente você tem um arquivo chamado `config` no diretório `$HOME/.kube`. + +Vá para `$HOME/.kube` e veja quais arquivos estão lá. Normalmente, há um arquivo chamado +`config`. Também pode haver outros arquivos de configuração nesse diretório. Em um breve momento +familiarize-se com o conteúdo desses arquivos. + +## Acrescente $HOME/.kube/config à sua variável de ambiente KUBECONFIG + +Se você tiver um arquivo `$HOME/.kube/config` e ele ainda não estiver listado em sua variável de ambiente +`KUBECONFIG`, acrescente-o à sua variável de ambiente `KUBECONFIG` agora. +Por exemplo: + +### Linux + +```shell +export KUBECONFIG="${KUBECONFIG}:${HOME}/.kube/config" +``` + +### Windows Powershell + +```powershell +$Env:KUBECONFIG="$Env:KUBECONFIG;$HOME\.kube\config" +``` + +Visualize as informações de configuração mescladas de todos os arquivos que agora estão listados +em sua variável de ambiente `KUBECONFIG`. Em seu diretório config-exercise, digite: + +```shell +kubectl config view +``` + +## Limpar + +Retorne sua variável de ambiente `KUBECONFIG` ao seu valor original. Por exemplo:
            + +### Linux + +```shell +export KUBECONFIG="$KUBECONFIG_SAVED" +``` + +### Windows PowerShell + +```powershell +$Env:KUBECONFIG=$ENV:KUBECONFIG_SAVED +``` + +## Verificar o sujeito representado pelo kubeconfig + +Nem sempre é óbvio quais atributos (nome de usuário, grupos) você obterá após a autenticação no cluster. +Isso pode ser ainda mais desafiador se você estiver gerenciando mais de um cluster ao mesmo tempo. + +Há um subcomando de `kubectl` para verificar os atributos do sujeito, como o nome de usuário, para o Kubernetes contexto selecionado: `kubectl auth whoami`. + +Leia [Acesso da API às informações de autenticação de um cliente](/docs/reference/access-authn-authz/authentication/#self-subject-review) +para saber mais sobre isso em detalhes. + + +## {{% heading "whatsnext" %}} + +* [Organizando o acesso ao cluster usando arquivos kubeconfig](/pt-br/docs/concepts/configuration/organize-cluster-access-kubeconfig/) +* [kubectl config](/docs/reference/generated/kubectl/kubectl-commands#config) + diff --git a/content/pt-br/docs/tasks/access-application-cluster/ingress-minikube.md b/content/pt-br/docs/tasks/access-application-cluster/ingress-minikube.md new file mode 100644 index 0000000000000..6eeec27579687 --- /dev/null +++ b/content/pt-br/docs/tasks/access-application-cluster/ingress-minikube.md @@ -0,0 +1,285 @@ +--- +title: Configurando o Ingress no Minikube com o NGINX Ingress Controller Config +content_type: task +weight: 110 +min-kubernetes-server-version: 1.19 +--- + + + +O [Ingress](/pt-br/docs/concepts/services-networking/ingress/) é um objeto da API que define regras +que permitem acesso externo a serviços em um cluster. Um +[Ingress controller](/docs/concepts/services-networking/ingress-controllers/) +cumpre as regras estabelecidas no Ingress. + +Essa página mostra como configurar um Ingress simples que redireciona as requisições para o Service "web" ou "web2" dependendo do URI HTTP. + +## {{% heading "prerequisites" %}} + +Esse tutorial assume que você está usando `minikube` para rodar um cluster Kubernetes local. +Visite [Install tools](/pt-br/docs/tasks/tools/#minikube) para aprender como instalar o `minikube`. + +{{< include "task-tutorial-prereqs.md" >}} {{< version-check >}} +Se você estiver usando uma versão mais antiga do Kubernetes, veja a documentação para essa versão. + +### Criando um cluster minikube +Se você ainda não configurou um cluster local, rode `minikube start` para criar um cluster. + + + +## Ativando o Ingress controller + +1. Para ativar o NGINX Ingress controller, rode os seguintes comandos: + + ```shell + minikube addons enable ingress + ``` + +1. Verifique que o NGINX Ingress controller está rodando + + ```shell + kubectl get pods -n ingress-nginx + ``` + + {{< note >}} + Os pods podem levar até um minuto para estarem rodando corretamente. + {{< /note >}} + + O resultado deve ser similar a: + + ```none + NAME READY STATUS RESTARTS AGE + ingress-nginx-admission-create-g9g49 0/1 Completed 0 11m + ingress-nginx-admission-patch-rqp78 0/1 Completed 1 11m + ingress-nginx-controller-59b45fb494-26npt 1/1 Running 0 11m + ``` + +## Instale uma aplicação hello world + +1. Crie um Deployment usando o seguinte comando: + + ```shell + kubectl create deployment web --image=gcr.io/google-samples/hello-app:1.0 + ``` + + O resultado deve ser: + + ```none + deployment.apps/web created + ``` + +1. Exponha o Deployment: + + ```shell + kubectl expose deployment web --type=NodePort --port=8080 + ``` + + O resultado deve ser: + + ```none + service/web exposed + ``` + +1. Verifique que o Service está criado e disponível em uma porta do nó: + + ```shell + kubectl get service web + ``` + + O resultado deve ser similar: + + ```none + NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE + web NodePort 10.104.133.249 8080:31637/TCP 12m + ``` + +1. Visite o Service via NodePort: + + ```shell + minikube service web --url + ``` + + O resultado é similar a: + + ```none + http://172.17.0.15:31637 + ``` + + ```shell + curl http://172.17.0.15:31637 + ``` + + O resultado é similar a: + + ```none + Hello, world! + Version: 1.0.0 + Hostname: web-55b8c6998d-8k564 + ``` + + Você agora pode acessar a aplicação de exemplo através do endereço IP do Minikube e NodePort. + No próximo passo, você irá acessar a aplicação usando o recurso Ingress. + +## Criando um Ingress +O manifesto a seguir define um Ingress que envia tráfego para seu Serviço via +`hello-world.info`. + +1. crie `example-ingress.yaml` usando o arquivo: + + {{% code_sample file="service/networking/example-ingress.yaml" %}} + +1. Crie o objeto Ingress rodando o seguinte comando: + + ```shell + kubectl apply -f https://k8s.io/examples/service/networking/example-ingress.yaml + ``` + + O resultado deve ser: + + ```none + ingress.networking.k8s.io/example-ingress created + ``` + +1. Verifique se o endereço IP está configurado: + + ```shell + kubectl get ingress + ``` + + {{< note >}} + Isso pode demorar alguns minutos. + {{< /note >}} + + Você deve ver um endereçco IPv4 na coluna `ADDRESS`; por exemplo: + + ```none + NAME CLASS HOSTS ADDRESS PORTS AGE + example-ingress hello-world.info 172.17.0.15 80 38s + ``` + + +1. Verifique se o Ingress controller está direcionando o tráfego: + + ```shell + curl --resolve "hello-world.info:80:$( minikube ip )" -i http://hello-world.info + ``` + + Você deve ver: + + ```none + Hello, world! + Version: 1.0.0 + Hostname: web-55b8c6998d-8k564 + ``` + + Você também pode visitar `hello-world.info` no seu navegador. + + * **Opcionalmente** + Procure o endereço IP externo reportado pelo minikube: + ```shell + minikube ip + ``` + + Adicione uma linha semelhante à seguinte no final do arquivo `/etc/hosts` no seu computador (você vai precisar de acesso de administrador): + + ```none + 172.17.0.15 hello-world.info + ``` + + {{< note >}} + Altere o endereço IP para corresponder ao resultado de `minikube ip`. + {{< /note >}} + + Depois que você fizer essa mudança, seu navegador enviará solicitações da URL `hello-world.info` para o Minikube + +## Criando um segundo Deployment + +1. Crie outro Deployment usando o seguinte comando: + + ```shell + kubectl create deployment web2 --image=gcr.io/google-samples/hello-app:2.0 + ``` + + O resultado deve ser: + + ```none + deployment.apps/web2 created + ``` + +1. Expondo o segundo Deployment: + + ```shell + kubectl expose deployment web2 --port=8080 --type=NodePort + ``` + + O resultado deve ser: + + ```none + service/web2 exposed + ``` + +## Edite o Ingress existente {#edit-ingress} + +1. Edite o manifesto `example-ingress.yaml` existente, e adicione as seguintes linhas no final: + ```yaml + - path: /v2 + pathType: Prefix + backend: + service: + name: web2 + port: + number: 8080 + ``` + +1. Aplique as mudanças: + + ```shell + kubectl apply -f example-ingress.yaml + ``` + + Você deve ver: + + ```none + ingress.networking/example-ingress configured + ``` + +## Testando o seu Ingress + +1. Acesse a primeira versão da sua aplicação Hello World. + + ```shell + curl --resolve "hello-world.info:80:$( minikube ip )" -i http://hello-world.info + ``` + + O resultado deve ser similar a: + + ```none + Hello, world! + Version: 1.0.0 + Hostname: web-55b8c6998d-8k564 + ``` + +1. Acesse a segunda versão da sua aplicação Hello World. + + ```shell + curl --resolve "hello-world.info:80:$( minikube ip )" -i http://hello-world.info/v2 + ``` + + O resultado deve ser similar a: + + ```none + Hello, world! + Version: 2.0.0 + Hostname: web2-75cd47646f-t8cjk + ``` + + {{< note >}} + Se você fez o passo opcional para atualizar o arquivo `/etc/hosts`, você também pode visitar `hello-world.info` e `hello-world.info/v2` do seu navegador. + {{< /note >}} + +## {{% heading "whatsnext" %}} + +* Leia mais sobre [Ingress](/pt-br/docs/concepts/services-networking/ingress/) +* Leia mais sobre [Ingress Controllers](/docs/concepts/services-networking/ingress-controllers/) +* Leia mais sobre [Services](/docs/concepts/services-networking/service/) + diff --git a/content/pt-br/docs/tasks/administer-cluster/network-policy-provider/cilium-network-policy.md b/content/pt-br/docs/tasks/administer-cluster/network-policy-provider/cilium-network-policy.md new file mode 100644 index 0000000000000..edf608101bed6 --- /dev/null +++ b/content/pt-br/docs/tasks/administer-cluster/network-policy-provider/cilium-network-policy.md @@ -0,0 +1,105 @@ +--- +title: Utilize o Cilium para NetworkPolicy +content_type: task +weight: 30 +--- + + +Essa página mostra como utilizar o Cilium para NetworkPolicy. + +Para saber mais sobre o Cilium, leia o artigo [Introdução ao Cilium (em inglês)](https://docs.cilium.io/en/stable/overview/intro). + + +## {{% heading "prerequisites" %}} + + +{{< include "task-tutorial-prereqs.md" >}} {{< version-check >}} + + + + +## Fazendo o Deploy do Cilium no Minikube para Testes Básicos + +Para familiarizar-se com o Cilium você poderá seguir o guia [Guia de Primeiros Passos do Cilium no Kubernetes (em inglês)](https://docs.cilium.io/en/stable/gettingstarted/k8s-install-default/) e realizar uma instalação básica do Cilium através de um DaemonSet no minikube. + +Inicie o minikube, a versão mínima exigida é >= v1.5.2, com os seguintes argumentos: + +```shell +minikube version +``` +``` +minikube version: v1.5.2 +``` + +```shell +minikube start --network-plugin=cni +``` + +Para o minikube, você poderá instalar o Cilium utilizando a ferramenta de linha de comando (CLI). Para isso, primeiro faça o download da última versão do CLI com o seguinte comando: + +```shell +curl -LO https://github.com/cilium/cilium-cli/releases/latest/download/cilium-linux-amd64.tar.gz +``` + +Em seguida extraia o arquivo baixado para o diretório `/usr/local/bin` com os comandos: + +```shell +sudo tar xzvfC cilium-linux-amd64.tar.gz /usr/local/bin +rm cilium-linux-amd64.tar.gz +``` + +Após executar os passos acima, você poderá instalar o Cilium utilizando o comando abaixo: + +```shell +cilium install +``` + +O Cilium irá detectar as configurações do cluster automaticamente, criará e instalará os componentes apropriados para que a instalação seja bem sucedida. +Os componentes são: + +- Certificate Authority (CA) no Secret `cilium-ca` e os certificados para o Hubble (camada de observabilidade do Cilium). +- Service accounts. +- Cluster roles. +- ConfigMap. +- Um agente DaemonSet e um Operator Deployment. + +Após a instalação, você poderá visualizar o status geral do Deployment do Cilium com o comando `cilium status`. +Confira a saída esperada da opção `status` [aqui](https://docs.cilium.io/en/stable/gettingstarted/k8s-install-default/#validate-the-installation). + +O restante do guia de primeiros passos utiliza como base uma aplicação de exemplo para explicar como aplicar políticas de segurança tanto para L3/L4 (como endereço de IP + porta), quanto para L7 (como HTTP). + +## Fazendo o deploy do Cilium para uso em produção + +Para instruções detalhadas de como fazer o deploy do Cilium em produção, acesse: [Guia de Instalação do Cilium no Kubernetes (em inglês)](https://docs.cilium.io/en/stable/network/kubernetes/concepts/). + +Essa documentação inclui detalhes sobre os requisitos, instruções e exemplos de DaemonSet para produção. + + + + +## Entendendo os componentes do Cilium + +Ao realizar o deploy do Cilium no cluster, Pods são adicionados ao namespace `kube-system`. Para ver essa lista de Pods execute: + +```shell +kubectl get pods --namespace=kube-system -l k8s-app=cilium +``` + +Você verá uma lista de Pods similar a essa: + +```console +NAME READY STATUS RESTARTS AGE +cilium-kkdhz 1/1 Running 0 3m23s +... +``` + +Um Pod `cilium` roda em cada um dos nós do seu cluster e garante as políticas de rede no tráfego de/para Pods naquele nó usando o Linux BPF. + + + +## {{% heading "whatsnext" %}} + +Uma vez que seu cluster estiver rodando, você pode seguir o artigo [Declarar uma Network Policy (em inglês)](/docs/tasks/administer-cluster/declare-network-policy/) para testar as políticas de NetworkPolicy do Kubernetes com o Cilium. +Divirta-se! Se tiver dúvidas, nos contate usando o [Canal Slack do Cilium](https://cilium.herokuapp.com/). + + diff --git a/content/pt-br/docs/tutorials/kubernetes-basics/deploy-app/deploy-intro.html b/content/pt-br/docs/tutorials/kubernetes-basics/deploy-app/deploy-intro.html index e181a606b76ad..206c69dfaf2ff 100644 --- a/content/pt-br/docs/tutorials/kubernetes-basics/deploy-app/deploy-intro.html +++ b/content/pt-br/docs/tutorials/kubernetes-basics/deploy-app/deploy-intro.html @@ -275,7 +275,7 @@

            Visualize o aplicativo

            echo Nome do Pod: $POD_NAME

            Você pode acessar o Pod através da API encaminhada, rodando o comando:

            curl - http://localhost:8001/api/v1/namespaces/default/pods/$POD_NAME/ + http://localhost:8001/api/v1/namespaces/default/pods/$POD_NAME:8080/proxy/

            Para que o novo Deployment esteja acessível sem utilizar o proxy, um diff --git a/content/pt-br/examples/service/networking/example-ingress.yaml b/content/pt-br/examples/service/networking/example-ingress.yaml new file mode 100644 index 0000000000000..085c71324f71f --- /dev/null +++ b/content/pt-br/examples/service/networking/example-ingress.yaml @@ -0,0 +1,18 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: example-ingress + annotations: + nginx.ingress.kubernetes.io/rewrite-target: /$1 +spec: + rules: + - host: hello-world.info + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: web + port: + number: 8080 diff --git a/content/ru/OWNERS b/content/ru/OWNERS index 75da45a4b597b..fe933ae6c64d8 100644 --- a/content/ru/OWNERS +++ b/content/ru/OWNERS @@ -8,6 +8,14 @@ reviewers: approvers: - sig-docs-ru-owners +- sig-docs-website-owners # important due to no_parent_owners option labels: +- area/localization - language/ru + +# Disable inheritance so that the localization team don't end up as approvers for all +# languages. +# https://github.com/kubernetes/community/blob/master/communication/website-guidelines.md +options: + no_parent_owners: true diff --git a/content/ru/docs/concepts/_index.md b/content/ru/docs/concepts/_index.md index 19e42ed49e90b..8687e9ba21bd6 100644 --- a/content/ru/docs/concepts/_index.md +++ b/content/ru/docs/concepts/_index.md @@ -17,7 +17,7 @@ weight: 40 Чтобы работать с Kubernetes, вы используете *объекты API Kubernetes* для описания *желаемого состояния вашего кластера*: какие приложения или другие рабочие нагрузки вы хотите запустить, какие образы контейнеров они используют, количество реплик, какие сетевые и дисковые ресурсы вы хотите использовать и сделать доступными и многое другое. Вы устанавливаете желаемое состояние, создавая объекты с помощью API Kubernetes, обычно через интерфейс командной строки `kubectl`. Вы также можете напрямую использовать API Kubernetes для взаимодействия с кластером и установки или изменения желаемого состояния. -После того, как вы установили желаемое состояние, *Плоскость управления Kubernetes* заставляет текущее состояние кластера соответствовать желаемому состоянию с помощью генератора событий жизненного цикла подов ([Pod Lifecycle Event Generator, PLEG](https://github.com/kubernetes/design-proposals-archive/blob/main/node/pod-lifecycle-event-generator.md)). Для этого Kubernetes автоматически выполняет множество задач, таких как запуск или перезапуск контейнеров, масштабирование количества реплик данного приложения и многое другое. Плоскость управления Kubernetes состоит из набора процессов, запущенных в вашем кластере: +После того, как вы установили желаемое состояние, *Управляющий слой Kubernetes* (control plane) заставляет текущее состояние кластера соответствовать желаемому состоянию с помощью генератора событий жизненного цикла подов ([Pod Lifecycle Event Generator, PLEG](https://github.com/kubernetes/design-proposals-archive/blob/main/node/pod-lifecycle-event-generator.md)). Для этого Kubernetes автоматически выполняет множество задач, таких как запуск или перезапуск контейнеров, масштабирование количества реплик данного приложения и многое другое. Управляющий слой Kubernetes состоит из набора процессов, запущенных в вашем кластере: * **Мастер Kubernetes** — это коллекция из трех процессов, которые выполняются на одном узле в вашем кластере, который обозначен как главный узел. Это процессы: [kube-apiserver](/docs/admin/kube-apiserver/), [kube-controller-manager](/docs/admin/kube-controller-manager/) и [kube-scheduler](/docs/admin/kube-scheduler/). * Каждый отдельный неосновной узел в вашем кластере выполняет два процесса: @@ -43,11 +43,11 @@ Kubernetes также содержит абстракции более высо * [ReplicaSet](/docs/concepts/workloads/controllers/replicaset/) * [Job](/docs/concepts/workloads/controllers/jobs-run-to-completion/) -## Плоскость управления Kubernetes +## Управляющий слой Kubernetes -Различные части панели управления Kubernetes, такие как мастер Kubernetes и процессы kubelet, определяют, как Kubernetes взаимодействует с кластером. Плоскость управления поддерживает запись всех объектов Kubernetes в системе и запускает непрерывные циклы управления для обработки состояния этих объектов. В любое время циклы управления панели управления будут реагировать на изменения в кластере и работать, чтобы фактическое состояние всех объектов в системе соответствовало желаемому состоянию, которое вы указали. +Различные части управляющего слоя Kubernetes (control plane), такие как мастер Kubernetes и процессы kubelet, определяют, как Kubernetes взаимодействует с кластером. Управляющий слой поддерживает запись всех объектов Kubernetes в системе и запускает непрерывные циклы управления для обработки состояния этих объектов. В любое время циклы управления управляющего слоя будут реагировать на изменения в кластере и работать, чтобы фактическое состояние всех объектов в системе соответствовало желаемому состоянию, которое вы указали. -Например, когда вы используете API Kubernetes для создания развертывания, вы предоставляете новое желаемое состояние для системы. Плоскость управления Kubernetes записывает создание этого объекта и выполняет ваши инструкции, запуская необходимые приложения и планируя их на узлы кластера, чтобы фактическое состояние кластера соответствовало желаемому состоянию. +Например, когда вы используете API Kubernetes для создания развертывания, вы предоставляете новое желаемое состояние для системы. Управляющий слой Kubernetes записывает создание этого объекта и выполняет ваши инструкции, запуская необходимые приложения и планируя их на узлы кластера, чтобы фактическое состояние кластера соответствовало желаемому состоянию. ### Мастер Kubernetes diff --git a/content/ru/docs/concepts/architecture/cloud-controller.md b/content/ru/docs/concepts/architecture/cloud-controller.md index 8c51bbcb0ae8d..a8a537049364c 100644 --- a/content/ru/docs/concepts/architecture/cloud-controller.md +++ b/content/ru/docs/concepts/architecture/cloud-controller.md @@ -22,11 +22,11 @@ weight: 40 ![Kubernetes components](/images/docs/components-of-kubernetes.svg) -Диспетчер облачных контроллеров работает в панели управления как реплицированный набор процессов (обычно это контейнер в Pod-ах). Каждый диспетчер облачных контроллеров реализует множество {{< glossary_tooltip text="контроллеров" term_id="controller" >}} в единственном процессе. +Диспетчер облачных контроллеров работает в управляющем слое (control plane) как реплицированный набор процессов (обычно это контейнер в Pod-ах). Каждый диспетчер облачных контроллеров реализует множество {{< glossary_tooltip text="контроллеров" term_id="controller" >}} в единственном процессе. {{< note >}} -Вы также можете запустить диспетчер облачных контроллеров как {{< glossary_tooltip text="дополнение" term_id="addons" >}} Kubernetes, а не как часть панели управления. +Вы также можете запустить диспетчер облачных контроллеров как {{< glossary_tooltip text="дополнение" term_id="addons" >}} Kubernetes, а не как часть управляющего слоя. {{< /note >}} ## Функции диспетчера облачных контроллеров {#functions-of-the-ccm} diff --git a/content/ru/docs/concepts/architecture/control-plane-node-communication.md b/content/ru/docs/concepts/architecture/control-plane-node-communication.md index 7b2f43991f854..93f9f6c0d670f 100644 --- a/content/ru/docs/concepts/architecture/control-plane-node-communication.md +++ b/content/ru/docs/concepts/architecture/control-plane-node-communication.md @@ -2,7 +2,7 @@ reviewers: - dchen1107 - liggitt -title: Связь между плоскостью управления и узлом +title: Связь между управляющим слоем и узлом content_type: concept weight: 20 aliases: @@ -11,13 +11,13 @@ aliases: -Этот документ описывает связь между плоскостью управления (apiserver) и кластером Kubernetes. Цель состоит в том, чтобы позволить пользователям настраивать свою установку для усиления сетевой конфигурации, чтобы кластер мог работать в ненадежной сети (или на полностью общедоступных IP-адресах облачного провайдера). +Этот документ описывает связь между API-сервером и кластером Kubernetes. Цель состоит в том, чтобы позволить пользователям настраивать свою установку для усиления сетевой конфигурации, чтобы кластер мог работать в ненадежной сети (или на полностью общедоступных IP-адресах облачного провайдера). -## Связь между плоскостью управления и узлом +## От узла к управляющему слою -В Kubernetes имеется API шаблон «ступица и спица» (hub-and-spoke). Все используемые API из узлов (или которые запускают pod-ы) завершает apiserver. Ни один из других компонентов плоскости управления не предназначен для предоставления удаленных сервисов. Apiserver настроен на прослушивание удаленных подключений через безопасный порт HTTPS (обычно 443) с одной или несколькими включенными формами [аутентификации](/docs/reference/access-authn-authz/authentication/) клиента. +В Kubernetes имеется API шаблон «ступица и спица» (hub-and-spoke). Все используемые API из узлов (или которые запускают pod-ы) завершает apiserver. Ни один из других компонентов управляющего слоя не предназначен для предоставления удаленных сервисов. Apiserver настроен на прослушивание удаленных подключений через безопасный порт HTTPS (обычно 443) с одной или несколькими включенными формами [аутентификации](/docs/reference/access-authn-authz/authentication/) клиента. Должна быть включена одна или несколько форм [авторизации](/docs/reference/access-authn-authz/authorization/), особенно, если разрешены [анонимные запросы](/docs/reference/access-authn-authz/authentication/#anonymous-requests) или [ServiceAccount токены](/docs/reference/access-authn-authz/authentication/#service-account-tokens). @@ -28,11 +28,11 @@ Pod-ы, которые хотят подключиться к apiserver, мог Компоненты уровня управления также взаимодействуют с кластером apiserver-а через защищенный порт. -В результате режим работы по умолчанию для соединений от узлов и модулей, работающих на узлах, к плоскости управления по умолчанию защищен и может работать в ненадежных и/или общедоступных сетях. +В результате режим работы по умолчанию для соединений от узлов и модулей, работающих на узлах, к управляющему слою по умолчанию защищен и может работать в ненадежных и/или общедоступных сетях. -## Узел к плоскости управления +## От управляющего слоя к узлу -Существуют два пути связи плоскости управления (apiserver) с узлами. Первый - от apiserver-а до kubelet процесса, который выполняется на каждом узле кластера. Второй - от apiserver к любому узлу, pod-у или службе через промежуточную функциональность apiserver-а. +Существуют два пути связи управляющего слоя (API-сервера) с узлами. Первый - от apiserver-а до kubelet процесса, который выполняется на каждом узле кластера. Второй - от apiserver к любому узлу, pod-у или службе через промежуточную функциональность apiserver-а. ### apiserver в kubelet @@ -56,7 +56,7 @@ Pod-ы, которые хотят подключиться к apiserver, мог ### SSH-туннели -Kubernetes поддерживает SSH-туннели для защиты плоскости управления узлов от путей связи. В этой конфигурации apiserver инициирует SSH-туннель для каждого узла в кластере (подключается к ssh-серверу, прослушивая порт 22) и передает весь трафик предназначенный для kubelet, узлу, pod-у или службе через туннель. Этот туннель гарантирует, что трафик не выводится за пределы сети, в которой работает узел. +Kubernetes поддерживает SSH-туннели для защиты путей связи от управляющего слоя к узлам. В этой конфигурации apiserver инициирует SSH-туннель для каждого узла в кластере (подключается к ssh-серверу, прослушивая порт 22) и передает весь трафик предназначенный для kubelet, узлу, pod-у или службе через туннель. Этот туннель гарантирует, что трафик не выводится за пределы сети, в которой работает узел. SSH-туннели в настоящее время устарели, поэтому вы не должны использовать их, если не знаете, что делаете. Служба подключения является заменой этого канала связи. @@ -64,6 +64,6 @@ SSH-туннели в настоящее время устарели, поэто {{< feature-state for_k8s_version="v1.18" state="beta" >}} -В качестве замены SSH-туннелям, служба подключения обеспечивает уровень полномочия TCP для плоскости управления кластерной связи. Служба подключения состоит из двух частей: сервер подключения к сети плоскости управления и агентов подключения в сети узлов. Агенты службы подключения инициируют подключения к серверу подключения и поддерживают сетевое подключение. После включения службы подключения, весь трафик с плоскости управления на узлы проходит через эти соединения. +В качестве замены SSH-туннелям, служба подключения обеспечивает прокси TCP-уровня для взаимодействия управляющего слоя с кластером. Служба подключения состоит из двух частей: сервер подключения к сети управляющего слоя и агентов подключения в сети узлов. Агенты службы подключения инициируют подключения к серверу подключения и поддерживают сетевое подключение. После включения службы подключения, весь трафик с управляющего слоя на узлы проходит через эти соединения. Следуйте инструкциям [Задача службы подключения,](/docs/tasks/extend-kubernetes/setup-konnectivity/) чтобы настроить службу подключения в кластере. diff --git a/content/ru/docs/concepts/architecture/controller.md b/content/ru/docs/concepts/architecture/controller.md index e46fbb022b25a..122f8abf2ee56 100644 --- a/content/ru/docs/concepts/architecture/controller.md +++ b/content/ru/docs/concepts/architecture/controller.md @@ -47,7 +47,7 @@ weight: 30 Когда контроллер задания видит новую задачу, он убеждается что где-то в вашем кластере kubelet-ы на множестве узлов запускают нужное количество Pod-ов для выполнения работы. Контроллер задания сам по себе не запускает никакие Pod-ы или контейнеры. Вместо этого контроллер задания сообщает серверу API о создании или удалении Pod-ов. Другие компоненты в -{{< glossary_tooltip text="плоскости управления" term_id="control-plane" >}} +{{< glossary_tooltip text="управляющем слое" term_id="control-plane" >}} действуют на основе информации (имеются ли новые запланированные Pod-ы для запуска), и в итоге работа завершается. После того как вы создадите новое задание, желаемое состояние для этого задания будет завершено. Контроллер задания приближает текущее состояние этой задачи к желаемому состоянию: создает Pod-ы, выполняющие работу, которую вы хотели для этой задачи, чтобы задание было ближе к завершению. @@ -70,7 +70,7 @@ weight: 30 Важным моментом здесь является то, что контроллер вносит некоторые изменения, чтобы вызвать желаемое состояние, а затем сообщает текущее состояние обратно на сервер API вашего кластера. Другие контуры управления могут наблюдать за этими отчетными данными и предпринимать собственные действия. -В примере с термостатом, если в помещении очень холодно, тогда другой контроллер может также включить обогреватель для защиты от замерзания. В кластерах Kubernetes, плоскость управления косвенно работает с инструментами управления IP-адресами, службами хранения данных, API облачных провайдеров и другими службами для реализации +В примере с термостатом, если в помещении очень холодно, тогда другой контроллер может также включить обогреватель для защиты от замерзания. В кластерах Kubernetes управляющий слой косвенно работает с инструментами управления IP-адресами, службами хранения данных, API облачных провайдеров и другими службами для реализации [расширения Kubernetes](/docs/concepts/extend-kubernetes/). ## Желаемое против текущего состояния {#desired-vs-current} @@ -99,9 +99,9 @@ Kubernetes использует систему вида cloud-native и спос Kubernetes поставляется с набором встроенных контроллеров, которые работают внутри {{< glossary_tooltip term_id="kube-controller-manager" >}}. Эти встроенные контроллеры обеспечивают важные основные функции. Контроллер развертывания и контроллер заданий - это примеры контроллеров, которые входят в состав самого Kubernetes («встроенные» контроллеры). -Kubernetes позволяет вам запускать устойчивую плоскость управления, так что в случае отказа одного из встроенных контроллеров работу берет на себя другая часть плоскости управления. +Kubernetes позволяет вам запускать устойчивый управляющий слой (control plane), так что в случае отказа одного из встроенных контроллеров работу берет на себя другая часть управляющего слоя. -Вы можете найти контроллеры, которые работают вне плоскости управления, чтобы расширить Kubernetes. +Вы можете найти контроллеры, которые работают вне управляющего слоя, чтобы расширить Kubernetes. Или, если вы хотите, можете написать новый контроллер самостоятельно. Вы можете запустить свой собственный контроллер в виде наборов Pod-ов, или внешнее в Kubernetes. Что подойдет лучше всего, будет зависеть от того, что делает этот конкретный контроллер. @@ -109,7 +109,7 @@ Kubernetes позволяет вам запускать устойчивую п ## {{% heading "whatsnext" %}} -* Прочтите о [плоскости управления Kubernetes ](/docs/concepts/overview/components/#control-plane-components) -* Откройте для себя некоторые из основных [объектов Kubernetes ](/docs/concepts/overview/working-with-objects/kubernetes-objects/) -* Узнайте больше о [Kubernetes API](/docs/concepts/overview/kubernetes-api/) +* Прочтите об [управляющем слое Kubernetes ](/ru/docs/concepts/overview/components/#компоненты-управляющего-слоя) +* Откройте для себя некоторые из основных [объектов Kubernetes](/ru/docs/concepts/overview/working-with-objects/kubernetes-objects/) +* Узнайте больше о [Kubernetes API](/ru/docs/concepts/overview/kubernetes-api/) * Если вы хотите написать собственный контроллер, см [Шаблоны расширения](/docs/concepts/extend-kubernetes/extend-cluster/#extension-patterns) в расширении Kubernetes. diff --git a/content/ru/docs/concepts/architecture/nodes.md b/content/ru/docs/concepts/architecture/nodes.md index 613155f0124ad..da2969d7892ef 100644 --- a/content/ru/docs/concepts/architecture/nodes.md +++ b/content/ru/docs/concepts/architecture/nodes.md @@ -13,7 +13,7 @@ Kubernetes запускает ваши приложения, помещая ко В зависимости от кластера, узел может быть виртуальной или физической машиной. Каждый узел содержит сервисы, необходимые для запуска {{< glossary_tooltip text="Подов" term_id="pod" >}}, управляемых -{{< glossary_tooltip text="плоскостью управления" term_id="control-plane" >}}. +{{< glossary_tooltip text="control plane (управляющим слоем)" term_id="control-plane" >}}. Обычно у вас есть несколько узлов в кластере; однако в среде обучения или среде с ограниченными ресурсами у вас может быть только один. @@ -29,11 +29,11 @@ Kubernetes запускает ваши приложения, помещая ко Существует два основных способа добавления Узлов в {{< glossary_tooltip text="API сервер" term_id="kube-apiserver" >}}: -1. Kubelet на узле саморегистрируется в плоскости управления +1. Kubelet на узле саморегистрируется в управляющем слое 2. Вы или другой пользователь вручную добавляете объект Узла После того как вы создадите объект Узла или kubelet на узле самозарегистируется, -плоскость управления проверяет, является ли новый объект Узла валидным (правильным). Например, если вы +управляющий слой проверяет, является ли новый объект Узла валидным (правильным). Например, если вы попробуете создать Узел при помощи следующего JSON манифеста: ```json @@ -217,7 +217,7 @@ kubectl describe node ### Контроллер узла {{< glossary_tooltip text="Контроллер " term_id="controller" >}} узла является компонентом -плоскости управления Kubernetes, который управляет различными аспектами узлов. +управляющего слоя Kubernetes, который управляет различными аспектами узлов. Контроллер узла играет различные роли в жизни узла. Первая - назначение CIDR-блока узлу при его регистрации (если включено назначение CIDR). diff --git a/content/ru/docs/concepts/cluster-administration/_index.md b/content/ru/docs/concepts/cluster-administration/_index.md index 77f610bf180b9..c8e750d2c898d 100644 --- a/content/ru/docs/concepts/cluster-administration/_index.md +++ b/content/ru/docs/concepts/cluster-administration/_index.md @@ -59,7 +59,7 @@ no_list: true * [Аудит](/docs/tasks/debug-application-cluster/audit/) описывает, как взаимодействовать с журналами аудита Kubernetes. ### Обеспечение безопасности kubelet - * [Связь между плоскостью управления и узлом](/docs/concepts/architecture/control-plane-node-communication/) + * [Связь между управляющим слоем и узлом](/ru/docs/concepts/architecture/control-plane-node-communication/) * [Загрузка TLS](/docs/reference/command-line-tools-reference/kubelet-tls-bootstrapping/) * [Аутентификация/авторизация Kubelet](/docs/reference/command-line-tools-reference/kubelet-authentication-authorization/) diff --git a/content/ru/docs/concepts/cluster-administration/addons.md b/content/ru/docs/concepts/cluster-administration/addons.md index 53be662b177dc..cccba3562a665 100644 --- a/content/ru/docs/concepts/cluster-administration/addons.md +++ b/content/ru/docs/concepts/cluster-administration/addons.md @@ -30,7 +30,7 @@ content_type: concept * [NSX-T](https://docs.vmware.com/en/VMware-NSX-T-Data-Center/index.html) плагин для контейнера (NCP) обеспечивающий интеграцию между VMware NSX-T и контейнерами оркестраторов, таких как Kubernetes, а так же интеграцию между NSX-T и контейнеров на основе платформы CaaS/PaaS, таких как Pivotal Container Service (PKS) и OpenShift. * [Nuage](https://github.com/nuagenetworks/nuage-kubernetes/blob/v5.1.1-1/docs/kubernetes-1-installation.rst) - эта платформа SDN, которая обеспечивает сетевое взаимодействие на основе политик между Kubernetes подами и не Kubernetes окружением, с отображением и мониторингом безопасности. * [Romana](https://github.com/romana/romana) - это сетевое решение уровня 3 для сетей подов, которое также поддерживает [NetworkPolicy API](/docs/concepts/services-networking/network-policies/). Подробности установки Kubeadm доступны [здесь](https://github.com/romana/romana/tree/master/containerize). -* [Weave Net](https://www.weave.works/docs/net/latest/kubernetes/kube-addon/) предоставляет сеть и обеспечивает сетевую политику, будет работать на обеих сторонах сетевого раздела и не требует внешней базы данных. +* [Weave Net](https://github.com/rajch/weave#using-weave-on-kubernetes) предоставляет сеть и обеспечивает сетевую политику, будет работать на обеих сторонах сетевого раздела и не требует внешней базы данных. ## Обнаружение служб diff --git a/content/ru/docs/concepts/overview/components.md b/content/ru/docs/concepts/overview/components.md index fdff4ef9aa363..86a6df5a73126 100644 --- a/content/ru/docs/concepts/overview/components.md +++ b/content/ru/docs/concepts/overview/components.md @@ -23,11 +23,11 @@ card: -## Плоскость управления компонентами +## Компоненты управляющего слоя -Компоненты панели управления отвечают за основные операции кластера (например, планирование), а также обрабатывают события кластера (например, запускают новый {{< glossary_tooltip text="под" term_id="pod">}}, когда поле `replicas` развертывания не соответствует требуемому количеству реплик). +Компоненты управляющего слоя (control plane) отвечают за основные операции кластера (например, планирование), а также обрабатывают события кластера (например, запускают новый {{< glossary_tooltip text="под" term_id="pod">}}, когда поле `replicas` развертывания не соответствует требуемому количеству реплик). -Компоненты панели управления могут быть запущены на любой машине в кластере. Однако для простоты сценарии настройки обычно запускают все компоненты панели управления на одном компьютере и в то же время не позволяют запускать пользовательские контейнеры на этом компьютере. Смотрите страницу [Создание высоконадёжных кластеров](/docs/admin/high-availability/) для примера настройки нескольких ведущих виртуальных машин. +Компоненты управляющего слоя могут быть запущены на любой машине в кластере. Однако для простоты сценарии настройки обычно запускают все компоненты управляющего слоя на одном компьютере и в то же время не позволяют запускать пользовательские контейнеры на этом компьютере. Смотрите страницу [Создание высоконадёжных кластеров](/docs/admin/high-availability/) для примера настройки нескольких ведущих виртуальных машин. ### kube-apiserver diff --git a/content/ru/docs/concepts/overview/working-with-objects/kubernetes-objects.md b/content/ru/docs/concepts/overview/working-with-objects/kubernetes-objects.md index cc4ba312f1877..5acc024a186d1 100644 --- a/content/ru/docs/concepts/overview/working-with-objects/kubernetes-objects.md +++ b/content/ru/docs/concepts/overview/working-with-objects/kubernetes-objects.md @@ -32,7 +32,7 @@ card: Почти в каждом объекте Kubernetes есть два вложенных поля-объекта, которые управляют конфигурацией объекта: *`spec`* и *`status`*. При создании объекта в поле `spec` указывается _требуемое состояние_ (описание характеристик, которые должны быть у объекта). -Поле `status` описывает _текущее состояние_ объекта, которое создаётся и обновляется самим Kubernetes и его компонентами. {{< glossary_tooltip text="Плоскость управления" term_id="control-plane" >}} Kubernetes непрерывно управляет фактическим состоянием каждого объекта, чтобы оно соответствовало требуемому состоянию, которое было задано пользователем. +Поле `status` описывает _текущее состояние_ объекта, которое создаётся и обновляется самим Kubernetes и его компонентами. {{< glossary_tooltip text="Управляющий слой" term_id="control-plane" >}} Kubernetes непрерывно управляет фактическим состоянием каждого объекта, чтобы оно соответствовало требуемому состоянию, которое было задано пользователем. Например: Deployment — это объект Kubernetes, представляющий работающее приложение в кластере. При создании объекта Deployment вы можете указать в его поле `spec`, что хотите иметь три реплики приложения. Система Kubernetes получит спецификацию объекта Deployment и запустит три экземпляра приложения, таким образом обновит статус (состояние) объекта, чтобы он соответствовал заданной спецификации. В случае сбоя одного из экземпляров (это влечет за собой изменение состояние), Kubernetes обнаружит несоответствие между спецификацией и статусом и исправит его, т.е. активирует новый экземпляр вместо того, который вышел из строя. diff --git a/content/ru/docs/concepts/scheduling-eviction/assign-pod-node.md b/content/ru/docs/concepts/scheduling-eviction/assign-pod-node.md new file mode 100644 index 0000000000000..a26c5c66869a4 --- /dev/null +++ b/content/ru/docs/concepts/scheduling-eviction/assign-pod-node.md @@ -0,0 +1,503 @@ +--- +title: Распределение подов по узлам +content_type: concept +weight: 20 +--- + + + + +Можно настроить {{< glossary_tooltip text="под" term_id="pod" >}} так, чтобы тот мог запускаться _только_ на определенном(-ых) {{< glossary_tooltip text="узле(-ах)" term_id="node" >}} или _предпочитал_ определенную группу узлов. +Сделать это можно несколькими способами, при этом все рекомендуемые подходы используют [селекторы лейблов](/ru/docs/concepts/overview/working-with-objects/labels/) для выбора. +Зачастую нужды в подобных ограничениях нет; {{< glossary_tooltip text="планировщик" term_id="kube-scheduler" >}} автоматически размещает поды оптимальным образом (например, распределяет их по узлам, чтобы они не оказались все на одном узле с дефицитом ресурсов). +Однако в некоторых обстоятельствах возможность контролировать, куда именно попадет под, может пригодиться. Например, она поможет запланировать под на узел с быстрым SSD-хранилищем или разместить два активно взаимодействующих друг с другом пода в одной зоне доступности. + + + +Для планирования подов на определенные узлы можно использовать любой из методов: + + * Поле [nodeSelector](#nodeselector) и [лейблы узлов](#built-in-node-labels); + * Правила [совместного/раздельного существования (affinity и anti-affinity)](#affinity-and-anti-affinity); + * Поле [nodeName](#nodename); + * [Ограничения на топологию распределения подов](#pod-topology-spread-constraints). + +## Лейблы узлов {#built-in-node-labels} + +Как и у многих других объектов Kubernetes, у узлов есть [лейблы](/ru/docs/concepts/overview/working-with-objects/labels/). Их можно [навешивать вручную](/docs/tasks/configure-pod-container/assign-pods-nodes/#add-a-label-to-a-node). +Kubernetes также навешивает [стандартный набор лейблов](/docs/reference/node/node-labels/) на все узлы кластера. + +{{}} +Значения этих лейблов зависят от облачного провайдера, поэтому на них нельзя полагаться. +Например, в одних окружениях значение `kubernetes.io/hostname` может совпадать с именем узла, в других — отличаться. +{{}} + +### Изоляция узла/ограничение его использования + +Лейблы узлов позволяют размещать поды на определенные узлы или группы узлов. С их помощью можно планировать поды на узлы с определенными требованиями к изоляции, безопасности или соответствию нормативным положениям. + +При использовании лейблов для изоляции узлов следует выбирать ключи лейблов, которые {{}} не может изменить. В этом случае взломанный узел не сможет навесить на себя эти лейблы в надежде, что планировщик разместит на него рабочие нагрузки. + +[Admission-плагин NodeRestriction](/docs/reference/access-authn-authz/admission-controllers/#noderestriction) не позволяет kubelet'у устанавливать или изменять лейблы с префиксом `node-restriction.kubernetes.io/`. + +Чтобы использовать этот префикс для изоляции узла: + +1. Убедитесь, что используется [авторизатор узлов](/docs/reference/access-authn-authz/node/) и _включен_ admission-плагин `NodeRestriction`. +2. Добавьте лейблы с префиксом `node-restriction.kubernetes.io/` к узлам и используйте их в [селекторах узлов](#nodeselector). Например, `example.com.node-restriction.kubernetes.io/fips=true` или `example.com.node-restriction.kubernetes.io/pci-dss=true`. + +## nodeSelector + +`nodeSelector` — простейшая рекомендуемая форма настроек выбора узлов. +Можно добавить поле `nodeSelector` в спецификацию пода и перечислить в нем [лейблы узлов](#built-in-node-labels), которые подходят для развертывания пода. В этом случае Kubernetes будет планировать под только на узлы со всеми указанными лейблами. + +Дополнительную информацию см. в разделе [Размещение подов на узлах](/docs/tasks/configure-pod-container/assign-pods-nodes). + +## Правила совместного/раздельного существования (affinity и anti-affinity) {#affinity-and-anti-affinity} + +`nodeSelector` — самый простой способ развернуть поды на узлах с определенными лейблами. Правила совместного/раздельного существования расширяют типы ограничений, которые можно накладывать. Вот некоторые из их преимуществ: + +* Язык правил affinity/anti-affinity более выразителен. `nodeSelector` выбирает узлы только со всеми указанными лейблами. Правила affinity/anti-affinity расширяют логику выбора и делают ее более гибкой. +* Правило может быть *мягким* (soft) или *предпочтительным* (preferred). В этом случае планировщик все равно запланирует под, даже если подходящего узла для него не найдется. +* При планировании пода планировщик может учитывать лейблы других подов, запущенных на узле (или в иной топологической области), а не только лейблы самого узла. Это позволяет формулировать правила, определяющие сосуществование подов на узле. + +Правила совместного существования (affinity) бывают двух типов: + +* *Правила для узлов* (node affinity) работают подобно полю `nodeSelector`, но более выразительны. Кроме того, можно задавать мягкие правила. +* *Правила для подов* (inter-pod affinity и anti-affinity) позволяют при планировании учитывать лейблы других подов. + +### Правила совместного существования для узлов (node affinity) {#node-affinity} + +Правила совместного существования для узлов концептуально похожи на `nodeSelector`. С помощью лейблов они позволяют ограничивать список узлов, на которые может быть запланирован под. Существует два типа таких правил: + + * `requiredDuringSchedulingIgnoredDuringExecution`: Планировщик не может запланировать под, если правило не выполнено. Работает как `nodeSelector`, но с более выразительным синтаксисом. + * `preferredDuringSchedulingIgnoredDuringExecution`: Планировщик пытается найти узел, который соответствует правилу. Если подходящий узел не удается найти, планировщик все равно планирует под. + +{{}} +В типах выше `IgnoredDuringExecution` означает, что под продолжит свою работу, если лейблы узлов изменятся после того, как Kubernetes запланировал его. +{{}} + +Задавать правила совместного существования для узлов можно с помощью поля `.spec.affinity.nodeAffinity` в спецификации пода. + +В качестве примера рассмотрим следующую спецификацию пода: + +{{< codenew file="pods/pod-with-node-affinity.yaml" >}} + +В этом примере применяются следующие правила: + + * У узла *должен* быть лейбл с ключом `topology.kubernetes.io/zone`, и значение этого лейбла *должно* быть либо `antarctica-east1`, либо `antarctica-west1`. + * *Предпочтительно*, чтобы у узла был лейбл с ключом `another-node-label-key` и значением `another-node-label-value`. + +Можно использовать поле `operator` для указания логического оператора, который Kubernetes будет применять при интерпретации правил. Доступны `In`, `NotIn`, `Exists`, `DoesNotExist`, `Gt` и `Lt`. + +Узнать больше о том, как они работают, можно в подразделе [Операторы](/#operators). + +`NotIn` и `DoesNotExist` позволяют задавать правила раздельного существования (anti-affinity) для узла. +Кроме того, можно использовать [taint'ы узлов](/docs/concepts/scheduling-eviction/taint-and-toleration/), чтобы "отвадить" поды от определенных узлов. + +{{}} +Когда указаны и `nodeSelector`, и `nodeAffinity`, под будет запланирован на узел только в том случае, если *оба* этих условия удовлетворены. + +Если указать несколько условий `nodeSelectorTerms`, привязанных к типам `nodeAffinity`, то под может быть запланирован на узел, если удовлетворяется одно из указанных условий `nodeSelectorTerms`. К условиям применяется логическое ИЛИ. + +Если задать несколько выражений в поле `matchExpressions` для одного условия `nodeSelectorTerms`, под будет запланирован на узел только если удовлетворены все выражения `matchExpressions`. К условиям применяется логическое И. +{{}} + +Дополнительную информацию см. в разделе [Размещаем поды на узлы с помощью Node Affinity](/docs/tasks/configure-pod-container/assign-pods-nodes-using-node-affinity/). + +#### Вес правил совместного существования + +Для каждого правила типа `preferredDuringSchedulingIgnoredDuringExecution` можно указать вес `weight` в диапазоне от 1 до 100. Найдя несколько узлов, удовлетворяющих всем остальным требованиям для планирования пода, планировщик перебирает предпочтительные правила, которым удовлетворяет узел, и суммирует их веса. + +Итоговая сумма добавляется к оценке, полученной при анализе других параметров, влияющих на приоритет узла. Принимая решение о размещении пода, планировщик отдает предпочтение узлам с наибольшей суммарной оценкой. + +В качестве примера рассмотрим следующую спецификацию пода: + +{{< codenew file="pods/pod-with-affinity-anti-affinity.yaml" >}} + +Если правилу `preferredDuringSchedulingIgnoredDuringExecution` соответствуют два узла (один — с лейблом `label-1:key-1`, другой — с `label-2:key-2`), планировщик считает вес `weight` каждого узла и добавляет его к другим оценкам для этого узла. Под планируется на узел с наивысшей итоговой оценкой. + +{{}} +Чтобы Kubernetes смог запланировать поды в этом примере, необходимо, чтобы существовали узлы с лейблом `kubernetes.io/os=linux`. +{{}} + +#### Правила совместного существования и профили планирования + +{{< feature-state for_k8s_version="v1.20" state="beta" >}} + +При настройке нескольких [профилей планирования](/docs/reference/scheduling/config/#multiple-profiles) можно связать профиль с правилами совместного существования для узлов (это удобно, когда профиль применяется к определенному набору узлов). Для этого необходимо добавить `addedAffinity` в поле `args` [плагина `NodeAffinity`](/docs/reference/scheduling/config/#scheduling-plugins) в [конфигурации планировщика](/docs/reference/scheduling/config/). Например: + +```yaml +apiVersion: kubescheduler.config.k8s.io/v1beta3 +kind: KubeSchedulerConfiguration + +profiles: + - schedulerName: default-scheduler + - schedulerName: foo-scheduler + pluginConfig: + - name: NodeAffinity + args: + addedAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: scheduler-profile + operator: In + values: + - foo +``` + +Правило `addedAffinity` применяется ко всем подам с полем `.spec.schedulerName`, имеющим значение `foo-scheduler`, в дополнение к NodeAffinity, заданному в PodSpec. Таким образом, подходящие для пода узлы должны удовлетворять параметрам `addedAffinity` и правилам `.spec.NodeAffinity` пода. + +Поскольку конечные пользователи не видят `addedAffinity`, результат применения этих правил может быть для них неожиданным. Используйте лейблы узлов, которые однозначно соотносятся с именем профиля планировщика. + +{{< note >}} +Контроллер DaemonSet, [создающий поды для DaemonSet'ов](/docs/concepts/workloads/controllers/daemonset/#scheduled-by-default-scheduler), не поддерживает профили планирования. Контроллер DaemonSet создает поды, а штатный планировщик Kubernetes, размещая их, следит за соблюдением правил `nodeAffinity`. +{{< /note >}} + +### Правила совместного/раздельного существования подов + +Правила совместного/раздельного существования подов позволяют выбирать узлы для планирования в зависимости от лейблов **подов**, которые уже на этих узлах работают (вместо лейблов самих узлов). + +Алгоритм работы правил совместного/раздельного существования подов можно описать так: "данный под _должен_ (или _не должен_ в случае раздельного (anti-affinity) существования) размещаться на X, если на нем уже работает один или несколько подов, удовлетворяющих правилу Y", где X — топологический домен, например, узел, стойка, зона/регион облачного провайдера и т. п., а Y — правило, которое Kubernetes пытается удовлетворить. + +Для задания правил Y используются [селекторы лейблов](/ru/docs/concepts/overview/working-with-objects/labels/#селекторы-меток) с необязательным связанным списком пространств имен. Для подов в Kubernetes указываются пространства имен, соответственно, их лейблы также оказываются неявно связаны с этими же пространствами имен. Любые селекторы лейблов для лейблов подов должны содержать пространства имен, в которых Kubernetes должен искать эти лейблы. + +Топологический домен X задается с помощью `topologyKey` — ключа для лейбла узла, который система использует для обозначения домена. Примеры см. в разделе [Типичные лейблы, аннотации и taint'ы](/docs/reference/labels-annotations-taints/). + +{{< note >}} +Обработка правил совместного/раздельного существования подов требует значительных ресурсов и может значительно замедлить планирование в больших кластерах. Их не рекомендуется использовать в кластерах, число узлов в которых превышает несколько сотен. +{{< /note >}} + +{{< note >}} +Правила раздельного существования для подов требуют согласованности лейблов узлов. Другими словами, у каждого узла в кластере должен быть лейбл, относящий его к определенному ключу `topologyKey`. Отсутствие лейблов `topologyKey` у некоторых или всех узлов в кластере может привести к непредсказуемому поведению. +{{< /note >}} + +#### Типы правил совместного/раздельного существования подов + +По аналогии [c правилами для узлов](#node-affinity) существует два типа правил для подов: + + * `requiredDuringSchedulingIgnoredDuringExecution` + * `preferredDuringSchedulingIgnoredDuringExecution` + +Например, с помощью правила совместного существования `requiredDuringSchedulingIgnoredDuringExecution` можно заставить планировщик размещать поды, относящиеся к разным сервисам, в одной зоне облачного провайдера, поскольку они активно обмениваются данными друг с другом. + +Аналогичным образом можно использовать правило раздельного существования `preferredDuringSchedulingIgnoredDuringExecution` для распределения подов по нескольким зонам облачного провайдера. + +Для задания правил совместного существования предназначено поле `affinity.podAffinity` в спецификации пода. + +Для задания правил раздельного существования предназначено поле `affinity.podAntiAffinity` в спецификации пода. + +#### Планирование группы подов, связанных правилами совместного существования + +Если планируемый под — первый в серии подов, связанных правилами совместного существования, +он может быть запланирован, если удовлетворит всем остальным правилам совместного существования. Чтобы подтвердить, что этот под — действительно первый, +проводится проверка, которая должна показать, что пространство имен и селектор этого пода уникальны в кластере (то есть нет других таких подов). Кроме того, +под должен соответствовать своим собственным правилам, а выбранный узел — всем запрошенным топологиям. +Это предотвращает тупиковую ситуацию, когда поды не могут запланироваться из-за того, что все они связаны правилами совместного существования. + +#### Пример правил совместного/раздельного существования для пода {#an-example-of-a-pod-that-uses-pod-affinity} + +Рассмотрим следующую спецификацию пода: + +{{< codenew file="pods/pod-with-pod-affinity.yaml" >}} + +В примере задается одно правило совместного существования подов, и одно — раздельного. Для совместного правила используется жесткий тип `requiredDuringSchedulingIgnoredDuringExecution`, для раздельного — мягкий `preferredDuringSchedulingIgnoredDuringExecution`. + +Правило совместного существования гласит, что планировщик может разместить под на узел, только если тот находится в зоне с одним или более подами с лейблом `security=S1`. +Например, если есть кластер с выделенной зоной, назовем ее "V", +состоящей из узлов с лейблом `topology.kubernetes.io/zone=V`, планировщик может +назначить под на любой узел зоны V только если в этой зоне уже есть хотя бы один под +с лейблом `security=S1`. И наоборот, если в зоне V нет подов с лейблом `security=S1`, +планировщик не сможет назначить под на какой-либо из узлов в этой зоне. + +Правило раздельного существования гласит, что планировщик при возможности не должен размещать под на узел, если тот находится в зоне с одним или более подами с лейблом `security=S2`. +Например, если есть кластер с выделенной зоной, назовем ее "R", +состоящей из узлов с лейблами `topology.kubernetes.io/zone=R`. Планировщик должен избегать +назначать поды на узлы из зоны R, если в ней уже есть по крайней мере один под +с лейблом `security=S2`. Соответственно, если в зоне R нет подов с лейблами `security=S2`, +правило раздельного существования не будет влиять на планирование подов в эту зону. + +Больше примеров правил совместного/раздельного существования для подов можно найти в [рабочей документации](https://git.k8s.io/design-proposals-archive/scheduling/podaffinity.md). + +Поле `operator` пода поддерживает значения `In`, `NotIn`, `Exists` и `DoesNotExist` при задании правил совместного/раздельного существования. + +Узнать больше о том, как они работают, можно в подразделе [Операторы](/#operators). + +В принципе, `topologyKey` может быть любым разрешенным лейблом-ключом со следующими исключениями по соображениям производительности и безопасности: + +* При задании правил совместного/раздельного существования для подов пустое поле `topologyKey` не допускается как для `requiredDuringSchedulingIgnoredDuringExecution`, так и для `preferredDuringSchedulingIgnoredDuringExecution`. +* Для правил раздельного существования типа `requiredDuringSchedulingIgnoredDuringExecution` admission-контроллер разрешает использовать только `kubernetes.io/hostname` в качестве `topologyKey`. Для работы с кастомными топологиями admission-контроллер можно дополнить или совсем отключить его. + +В дополнение к `labelSelector` и `topologyKey` можно опционально указать список пространств имен, которые должен выбирать `labelSelector`, с помощью поля `namespaces` на том же уровне, что `labelSelector` и `topologyKey`. Если поле `namespaces` опущено или пусто, по умолчанию выбирается пространство имен пода, в котором задаются правила совместного/раздельного существования. + +#### Селектор пространств имен +{{< feature-state for_k8s_version="v1.24" state="stable" >}} + +Подходящие пространства имен также можно выбрать с помощью `namespaceSelector`, который попытается найти лейбл в наборе пространств имен. +Условия совместного существования применяются к пространствам имен, выбранным как селектором `namespaceSelector`, так и полем `namespaces`. +Обратите внимание, что пустой селектор `namespaceSelector` ({}) выбирает все пространства имен, в то время как пустой или null-список `namespaces` и null-селектор `namespaceSelector` выбирает пространство имен пода, в котором правило задано. + +#### matchLabelKeys + +{{< feature-state feature_gate_name="MatchLabelKeysInPodAffinity" >}} + +{{< note >}} + +Поле `matchLabelKeys` является полем альфа-уровня и по умолчанию отключено в +Kubernetes {{< skew currentVersion >}}. +Включить его можно с помощью [переключателя функциональности](/docs/reference/command-line-tools-reference/feature-gates/) +(feature gate) `MatchLabelKeysInPodAffinity`. +{{< /note >}} + +Kubernetes включает необязательное поле `matchLabelKeys` для правил совместного (раздельного) существования подов. +В нем указываются ключи для лейблов, которые должны совпадать с лейблами входящего пода, +чтобы правила совместного (раздельного) существования выполнялись. + +Ключи используются для поиска значений в лейблах подов; эти ключи-лейблы объединяются (с помощью `AND`) +с ограничениями, задаваемыми с помощью поля `labelSelector`. Такая комбинированная фильтрация позволяет отобрать +набор существующих подов, которые приниматься в расчет при обработке правил совместного (раздельного) существования. + +Обычно `matchLabelKeys` используется вместе с `pod-template-hash` (задается для подов, +которые управляются как часть деплоймента, где значение уникально для каждой ревизии). +Использование `pod-template-hash` в `matchLabelKeys` позволяет нацеливаться на поды, принадлежащие +к той же ревизии, что и входящий под. Таким образом, что скользящее обновление не нарушит правила совместного существования. + +```yaml +apiVersion: apps/v1 +kind: Deployment +metadata: + name: application-server +... +spec: + template: + spec: + affinity: + podAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + - labelSelector: + matchExpressions: + - key: app + operator: In + values: + - database + topologyKey: topology.kubernetes.io/zone + # При расчете affinity подов учитываются только поды из определенного выката. + # При обновлении Deployment'а новые поды будут следовать своим собственным правилам совместного существования + # (если они заданы в новом шаблоне подов) + matchLabelKeys: + - pod-template-hash +``` + +#### mismatchLabelKeys + +{{< feature-state feature_gate_name="MatchLabelKeysInPodAffinity" >}} + +{{< note >}} + +Поле `mismatchLabelKeys` является полем альфа-уровня и по умолчанию отключено в +Kubernetes {{< skew currentVersion >}}. +Включить его можно с помощью [переключателя функциональности](/docs/reference/command-line-tools-reference/feature-gates/) +(feature gate) `MatchLabelKeysInPodAffinity`. +{{< /note >}} + +Kubernetes включает необязательное поле `mismatchLabelKeys` для определения правил совместного (раздельного) существования подов. +В поле указываются ключи для лейблов, которые **не** должны совпадать с лейблами входящего пода, +чтобы правила совместного (раздельного) существования подов удовлетворялись. + +Один из примеров использования — размещение подов определенной группы пользователей (tenant'ов) или команды в конкретном топологическом домене (узле, зоне и т. д.). +То есть идея в том, чтобы избежать одновременного запуска подов от разных групп пользователей в одном топологическом домене. + +```yaml +apiVersion: v1 +kind: Pod +metadata: + labels: + # Assume that all relevant Pods have a "tenant" label set + tenant: tenant-a +... +spec: + affinity: + podAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + # следим за тем, чтобы поды, связанные с этим тенантом, попадали на нужный пул узлов + - matchLabelKeys: + - tenant + topologyKey: node-pool + podAntiAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + # следим за тем, чтобы поды, связанные с этим тенантом, не смогли планироваться на узлы для другого тенанта + - mismatchLabelKeys: + - tenant # значение лейбла "tenant" этого пода будет предотвращать + # планирование на узлы в пулах, на которых работают поды + # другого тенанта + labelSelector: + # Должен быть labelSelector, который выбирает поды с лейблом tenant, + # иначе этот под также будет "ненавидеть" поды из daemonset'ов, например, + # те, у которых нет лейбла tenant. + matchExpressions: + - key: tenant + operator: Exists + topologyKey: node-pool +``` + +#### Другие примеры использования + +Правила совместного/раздельного существования для подов особенно удобны, когда используются совместно с абстракциями более высокого уровня, такими как ReplicaSet, StatefulSet, Deployment и т. д. Эти правила позволяют настроить размещение рабочих нагрузок с учетом имеющейся топологии; например, пара связанных подов будет планироваться на один и тот же узел. + +Представьте кластер, состоящий из трех узлов. Он используется для запуска веб-приложения и как in-memory-кэш (например, Redis). Предположим, что задержка между веб-приложением и кэшем должна быть минимальной. Правила совместного/раздельного существования для подов позволяют настроить планировщик так, чтобы тот размещал веб-серверы как можно ближе к кэшу. + +В приведенном ниже примере конфигурации деплоймента с Redis его реплики получают лейбл `app=store`. Правило `podAntiAffinity` запрещает планировщику размещать несколько реплик с лейблом `app=store` на одном узле. В результате каждый узел получает по отдельной кэш-реплике. + +```yaml +apiVersion: apps/v1 +kind: Deployment +metadata: + name: redis-cache +spec: + selector: + matchLabels: + app: store + replicas: 3 + template: + metadata: + labels: + app: store + spec: + affinity: + podAntiAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + - labelSelector: + matchExpressions: + - key: app + operator: In + values: + - store + topologyKey: "kubernetes.io/hostname" + containers: + - name: redis-server + image: redis:3.2-alpine +``` + +Конфигурация деплоймента, приведенная ниже, создает три реплики веб-сервера с лейблом `app=web-store`. +Правило совместного существования предписывает планировщику размещать каждую реплику на узле, на котором уже имеется под с лейблом `app=store`. В то же время правило раздельного существования запрещает планировщику размещать несколько серверов с лейблом `app=web-store` на одном узле. + +```yaml +apiVersion: apps/v1 +kind: Deployment +metadata: + name: web-server +spec: + selector: + matchLabels: + app: web-store + replicas: 3 + template: + metadata: + labels: + app: web-store + spec: + affinity: + podAntiAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + - labelSelector: + matchExpressions: + - key: app + operator: In + values: + - web-store + topologyKey: "kubernetes.io/hostname" + podAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + - labelSelector: + matchExpressions: + - key: app + operator: In + values: + - store + topologyKey: "kubernetes.io/hostname" + containers: + - name: web-app + image: nginx:1.16-alpine +``` + +Развертывание ресурсов в соответствии с приведенными выше конфигурациями приведет к созданию кластера, в котором на каждом узле будет по одному веб-серверу и одной реплике Redis (всего три отдельных узла): + +| узел 1 | узел 2 | узел 3 | +|:--------------------:|:-------------------:|:------------------:| +| *webserver-1* | *webserver-2* | *webserver-3* | +| *cache-1* | *cache-2* | *cache-3* | + +В итоге к каждому инстансу Redis'а, скорее всего, будет обращаться клиент, который работает с ним на том же узле. Подобный подход позволит минимизировать как перекос (дисбаланс нагрузки), так и задержки. + +Правила совместного/раздельного существования для подов можно использовать и в других случаях. + +См., например, [руководство по ZooKeeper](/docs/tutorials/stateful-application/zookeeper/#tolerating-node-failure). В нем с помощью правил раздельного существования StatefulSet настраивается так, чтобы обеспечить высокую доступность (используется подход, аналогичный тому, что применен выше). + +## nodeName + +Поле `nodeName` в спецификации пода — более непосредственный способ выбора узлов по сравнению с правилами совместного существования или селектором `nodeSelector`. Если поле `nodeName` не пустое, планировщик игнорирует под, а kubelet на узле с соответствующим именем пытается разместить под на этом узле. Приоритет поля `nodeName` выше, чем селектора `nodeSelector` или правил совместного/раздельного существования. + +Однако у `nodeName` имеются и некоторые недостатки: + +- Если узел с заданным именем не существует, под не будет запущен. Кроме того, в некоторых случаях он может быть автоматически удален. +- Если на узле с заданным именем недостаточно ресурсов для работы пода, последний будет остановлен; соответствующая причина (например, OutOfmemory или OutOfcpu) будет указана. +- В облачных окружениях имена узлов не всегда предсказуемы или стабильны. + +{{< note >}} +Поле `nodeName` предназначено для использования в кастомных планировщиках или в продвинутых случаях, +когда необходимо обойти настроенные планировщики. Обход планировщиков может привести к тому, что поды не будут запущены, +если целевые узлы окажутся перегруженными. С помощью правила [совместного существования (affinity) узла](#node-affinity) или поля [`nodeselector`](#nodeselector) под можно назначить на определенный узел, не обходя планировщики с помощью `nodeName`. +{{}} + +Ниже приведен пример спецификации пода с полем `nodeName`: + +```yaml +apiVersion: v1 +kind: Pod +metadata: + name: nginx +spec: + containers: + - name: nginx + image: nginx + nodeName: kube-01 +``` + +Такой под будет работать только на узле с именем `kube-01`. + +## Ограничения на топологию распределения подов + +С помощью _ограничений на топологию распределения_ (_topology spread constraints_) можно настроить размещение {{< glossary_tooltip text="подов" term_id="Pod" >}} в кластере по failure-доменам, таким как регионы, зоны, узлы, или любым другим заданным топологическим конфигурациям. Это позволяет повысить производительность, ожидаемую доступность или эффективность использования ресурсов. + +Дополнительные сведения о принципах их работы читайте в разделе [Ограничения на топологию распределения подов](/docs/concepts/scheduling-eviction/topology-spread-constraints/). + +## Операторы {#operators} + +Ниже приведены все логические операторы, которые можно использовать в поле `operator` для `nodeAffinity` и `podAffinity`. + +| Оператор | Действие | +| :------------: | :-------------: | +| `In` | Значение лейбла присутствует в предоставленном наборе строк | +| `NotIn` | Значение лейбла отсутствует в предоставленном наборе строк | +| `Exists` | Лейбл с таким ключом существует для объекта | +| `DoesNotExist` | У объекта не существует лейбла с таким ключом | + +Следующие операторы могут использоваться только с `nodeAffinity`. + +| Оператор | Действие | +| :------------: | :-------------: | +| `Gt` | Введенное значение будет обработано как целое число, и это целое число меньше, чем целое число, полученное в результате обработки значения лейбла, указанного этим селектором | +| `Lt` | Введенное значение будет обработано как целое число, и это целое число больше, чем целое число, полученное в результате обработки значения лейбла, указанного этим селектором | + +{{}} +Операторы `Gt` и `Lt` не работают с нецелыми значениями. Если заданное значение +не является целым числом, под не будет запланирован. Кроме того, `Gt` и `Lt` +недоступны для `podAffinity`. +{{}} + +## {{% heading "whatsnext" %}} + +* Дополнительная информация о [taint'ах и toleration'ах](/docs/concepts/scheduling-eviction/taint-and-toleration/). +* Рабочая документация по правилам [совместного существования для узлов](https://git.k8s.io/design-proposals-archive/scheduling/nodeaffinity.md) и по правилам [совместного/раздельного существования для подов](https://git.k8s.io/design-proposals-archive/scheduling/podaffinity.md). +* [Информация о том](/docs/tasks/administer-cluster/topology-manager/), как менеджер топологии участвует в принятии решений о распределении ресурсов на уровне узлов. +* Подробнее об использовании [селектора nodeSelector](/docs/tasks/configure-pod-container/assign-pods-nodes/). +* Подробнее об использовании правил [совместного/раздельного существования](/docs/tasks/configure-pod-container/assign-pods-nodes-using-node-affinity/). diff --git a/content/ru/docs/concepts/workloads/controllers/cron-jobs.md b/content/ru/docs/concepts/workloads/controllers/cron-jobs.md new file mode 100644 index 0000000000000..346cf6c7ceeb6 --- /dev/null +++ b/content/ru/docs/concepts/workloads/controllers/cron-jobs.md @@ -0,0 +1,233 @@ +--- +title: CronJob +content_type: concept +description: >- + CronJob запускает одноразовые задания по повторяющемуся расписанию +weight: 80 +hide_summary: true # Listed separately in section index +--- + + + +{{< feature-state for_k8s_version="v1.21" state="stable" >}} + +_CronJob_ создает {{< glossary_tooltip term_id="job" text="задания (Jobs)" >}}, которые повторяются по расписанию. + +CronJob предназначен для выполнения регулярных заданий по расписанию, таких как резервное копирование, создание отчетов, +и так далее. Один CronJob объект — это как одна строка файла _crontab_ (cron table) в Unix-системе. +Он периодически запускает задание по заданному расписанию, составленному в формате формате +[Cron](https://ru.wikipedia.org/wiki/Cron). + +У CronJob'a есть свои ограничения и особенности. +Например, при определенных обстоятельствах один CronJob может создавать несколько параллельных заданий. См. раздел [Ограничения](#cron-job-limitations) ниже. + +Когда управляющий слой _(control plane)_ создает новые задания и (косвенно) поды для CronJob'а, поле `.metadata.name` в CronJob +является частью основы для наименования этих подов. Имя CronJob должно быть действительным +значением [поддомена DNS](/ru/docs/concepts/overview/working-with-objects/names#имена-поддоменов-dns), но это может привести к неожиданным результатам для имен хостов подов. Для наилучшей совместимости имя должно соответствовать более строгим правилам +[имен меток DNS](/ru/docs/concepts/overview/working-with-objects/names#имена-меток-dns). +Даже если имя является поддоменом DNS, оно не должно превышать 52 символов. Это связано с тем, что контроллер CronJob автоматически добавляет +11 символов к указанному вами имени и существует ограничение на то, что +длина имени задания (Job) не должна превышать 63 символа. + + +## Пример + +Этот пример манифеста CronJob печатает текущее время и сообщение hello каждую минуту: + +{{% code_sample file="application/job/cronjob.yaml" %}} + +([Выполнение автоматических заданий с помощью CronJob](/docs/tasks/job/automated-tasks-with-cron-jobs/) +более подробно рассматривает этот пример.) + +## Написание спецификации CronJob'a +### Синтаксис расписания +Поле `.spec.schedule` является обязательным. Значение этого поля соответствует синтаксису [Cron](https://ru.wikipedia.org/wiki/Cron): + +``` +# ┌───────────── минута (0 - 59) +# │ ┌───────────── час (0 - 23) +# │ │ ┌───────────── день месяца (1 - 31) +# │ │ │ ┌───────────── месяц (1 - 12) +# │ │ │ │ ┌───────────── день недели (0 - 6) (воскресенье - суббота) +# │ │ │ │ │ ИЛИ sun, mon, tue, wed, thu, fri, sat +# │ │ │ │ │ +# * * * * * +``` + +Например, `0 0 13 * 5` указывает, что задание должно запускаться каждую пятницу в полночь, а также 13 числа каждого месяца в полночь. + +Формат также включает расширенные значения шагов "Vixie cron". Как объясняется в +[инструкции для FreeBSD](https://www.freebsd.org/cgi/man.cgi?crontab%285%29): + +> Значения шагов можно использовать в сочетании с диапазонами. Если после диапазона указать `/<число>`, то это означает +> пропуск значения числа в диапазоне. Например, `0-23/2` можно использовать, чтобы указать выполнение команды +> каждый второй час (альтернативой в стандарте V7 является +> `0,2,4,6,8,10,12,14,16,18,20,22`). Шаги также разрешены после звездочки, так что если +> нужно указать "каждые два часа", можно использовать `*/2`. + +{{< note >}} +Вопросительный знак (`?`) в расписании обозначает то же, что и звездочка `*`, то есть любое из доступных значений для данного поля. +{{< /note >}} + +Помимо стандартного синтаксиса можно также использовать макросы вроде `@monthly`: + +| Запись | Описание | Эквивалент | +| ------------- | ------------- |------------- | +| @yearly (или @annually) | Запускается один раз в год в полночь 1 января | 0 0 1 1 * | +| @monthly | Запускается раз в месяц в полночь первого дня месяца | 0 0 1 * * | +| @weekly | Запускается раз в неделю в полночь в воскресенье утром | 0 0 * * 0 | +| @daily (или @midnight) | Запускается один раз в день в полночь | 0 0 * * * | +| @hourly | Запускается раз в час в начале часа | 0 * * * * | + +Для создания CronJob-расписания можно также использовать такие веб-инструменты, как [crontab.guru](https://crontab.guru/). + +### Шаблон задания + +Поле `.spec.jobTemplate` определяет шаблон для заданий, которые создает CronJob, и является обязательным. +Он имеет точно такой же вид, как и [Job](/docs/concepts/workloads/controllers/job/), за исключением того, +что является вложенным и не имеет полей `apiVersion` и `kind`. +Можно указать типичные метаданные для шаблонных заданий (Jobs), такие как +{{< glossary_tooltip text="метки" term_id="label" >}} или +{{< glossary_tooltip text="аннотации" term_id="annotation" >}}. +О том, как написать `.spec` для Job, см. [Написание спецификации Job](/docs/concepts/workloads/controllers/job/#writing-a-job-spec). + +### Дедлайн задержки начала задания {#starting-deadline} + +Поле `.spec.startingDeadlineSeconds` является необязательным. +В этом поле задается крайний срок (в целых секундах) для запуска задания (Job), если оно по какой-либо причине +не успевает к назначенному времени. + +Если дедлайн пропущен, CronJob пропускает этот вызов задания (последующие выполнения по-прежнему запланированы). +Например, если задание резервного копирования выполняется дважды в день, можно разрешить ему +запускаться с опозданием до 8 часов, но не позже, поскольку резервная копия, +сделанная позже, не будет полезной: лучше дождаться следующего запуска по расписанию. + +Задания, которые не успели выполниться в установленный срок, Kubernetes рассматривает как неудачные. +Если не указать `startingDeadlineSeconds` для CronJob, то задания не будут иметь дедлайн. + +Если поле `.spec.startingDeadlineSeconds` установлено (не является нулевым), контроллер CronJob +измеряет время между моментом, когда задание должно быть создано, и реальным временем. +Если разница превышает указанный предел, он пропустит этот вызов задания. + +Например, если установлено значение `200`, задание может быть создано в период до 200 секунд позже фактического расписания. + +### Политика параллелизма (concurrency policy) + +Поле `.spec.concurrencyPolicy` также является необязательным. +Оно определяет, как обращаться с одновременным выполнением заданий, созданных этим CronJob. +В этой спецификации может быть указана только одна из следующих политик параллелизма: + +* `Allow` (по умолчанию): CronJob разрешает одновременное выполнение заданий. +* `Forbid`: CronJob не разрешает одновременное выполнение заданий; если пришло время для выполнения нового задания, + а предыдущее еще не завершилось, CronJob пропускает новое задание. +* `Replace`: Если пришло время для выполнения нового задания, а предыдущее еще не завершилось, + CronJob заменит текущее задание на новое. + +Заметьте, что принцип параллелизма применяется только к заданиям, созданным одним и тем же Cronjob'ом. +Если есть несколько CronJob'ов, их соответствующие задания всегда могут выполняться одновременно. + +### Остановка выполнения заданий по расписанию + +Можно приостановить выполнение CronJob-заданий, присвоив необязательному полю `.spec.suspend` значение true. +По умолчанию это поле имеет значение false. + +Эта настройка _не_ влияет на задания, которые уже были запущены CronJob'ом. + +Если установить это поле как true, все последующие выполнения будут приостановлены +(они остаются запланированными, но CronJob-контроллер не запускает задания для выполнения), +пока вы не отмените приостановку CronJob'a. + +{{< caution >}} +Работы, приостановленные во время запланированного выполнения, считаются пропущенными. +Когда `.spec.suspend` изменяется с `true` на `false` для существующего CronJob'a без +[дедлайна задержки начала задания](#starting-deadline), пропущенные задания планируются немедленно. +{{< /caution >}} + +### Лимиты на историю заданий + +Поля `.spec.successfulJobsHistoryLimit` и `.spec.failedJobsHistoryLimit` являются необязательными. +В этих полях указывается, сколько завершенных и неудачных заданий должно быть сохранено в истории. +По умолчанию они установлены на 3 и 1 соответственно. Установка предела в `0` будет означать, +что никакие задания соответствующего типа не сохранятся после их завершения. + +Другой способ автоматической очистки заданий см. в разделе [Автоматическая очистка завершенных заданий](/docs/concepts/workloads/controllers/job/#clean-up-finished-jobs-automatically). + +### Часовые пояса + +{{< feature-state for_k8s_version="v1.27" state="stable" >}} + +Для CronJob'a, в которых не указан часовой пояс, {{< glossary_tooltip term_id="kube-controller-manager" text="kube-controller-manager" >}} +интерпретирует расписания относительно своего локального часового пояса. + +Можно указать часовой пояс для CronJob'a, присвоив `.spec.timeZone` имя действительного +[часового пояса](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones). +Например, установка `.spec.timeZone: "Etc/UTC"` инструктирует Kubernetes интерпретировать расписание +относительно всемирного координированного времени. + +База данных часовых поясов из стандартной библиотеки Go включена в бинарные файлы и используется в качестве запасного варианта на случай, если внешняя база данных недоступна в системе. + +## Ограничения CronJob {#cron-job-limitations} + +### Неподдерживаемая спецификация TimeZone + +Установка часового пояса с помощью переменных `CRON_TZ` или `TZ` в `.spec.schedule` +**не поддерживается официально** (и никогда не поддерживалась). + +Начиная с Kubernetes 1.29, если попытаться задать расписание, +включающее спецификацию часового пояса `TZ` или `CRON_TZ`, +Kubernetes не сможет создать ресурс, выдав ошибку валидации. +Обновления для CronJobs, уже использующих `TZ` или `CRON_TZ`, будут продолжать выдавать +[предупреждение](/blog/2020/09/03/warnings/) клиенту. + +### Модификация задания CronJob + +По своей структуре CronJob содержит шаблон для _новых_ заданий. +Если изменить существующее задание CronJob, внесенные изменения будут +применены к новым заданиям, которые начнут выполняться после завершения +модификации. Задания (и их поды), которые уже были запущены, продолжат выполняться без изменений. +То есть CronJob _не_ обновляет существующие задания, даже если они остаются запущенными. + +### Создание заданий + +CronJob создает объект задания (Job) примерно один раз за время выполнения своего расписания. +Расписание является приблизительным, поскольку есть определенные обстоятельства, +при которых могут быть созданы два задания или не создано ни одного. +Kubernetes старается избегать таких ситуаций, но не может полностью предотвратить их. Поэтому +задания, которые вы определяете, должны быть _идемпотентными_. + +Если в поле `startingDeadlineSeconds` задано большое значение или оно не определено (по умолчанию), +а также при условии, что `concurrencyPolicy` имеет значение `Allow`, задания всегда будут выполняться по крайней мере один раз. + +{{< caution >}} +Если `startingDeadlineSeconds` имеет значение меньше 10 секунд, задание CronJob, возможно, не будет запланировано. Это происходит потому, что CronJob выполняет проверку каждые 10 секунд. +{{< /caution >}} + + +Для каждого задания CronJob {{< glossary_tooltip term_id="controller" text="контроллер" >}} проверяет, сколько расписаний он пропустил за время, прошедшее с последнего расписания до настоящего момента. Если пропущено более 100 расписаний, то задание не запускается и фиксируется ошибка. + +``` +Cannot determine if job needs to be started. Too many missed start time (> 100). Set or decrease .spec.startingDeadlineSeconds or check clock skew. +``` + +Важно отметить, что если поле `startingDeadlineSeconds` установлено (не равно `nil`), контроллер считает, сколько пропущенных заданий произошло с момента значения `startingDeadlineSeconds` до настоящего момента, а не с момента последнего запланированного задания до настоящего момента. Например, если `startingDeadlineSeconds` равно `200`, контроллер подсчитывает, сколько пропущенных заданий произошло за последние 200 секунд. + +Задание CronJob считается пропущенным, если оно не было создано в запланированное время. Например, если для `concurrencyPolicy` установлено значение `Forbid`, и CronJob пытался быть запланирован, когда предыдущее расписание еще выполнялось, то он будет считаться пропущенным. + +Например, предположим, что задание CronJob настроено на планирование нового задания каждую минуту, начиная с `08:30:00`, а его поле поле `startingDeadlineSeconds` не установлено. +Если контроллер CronJob не функционирует с `08:29:00` до `10:21:00`, задание не будет запущено, так как количество пропущенных заданий, которые не успели выполнить свое расписание, больше 100. + +Чтобы подробнее проиллюстрировать эту концепцию, предположим, что задание CronJob настроено на планирование нового задания каждую одну минуту, начиная с `08:30:00`, и его параметр `startingDeadlineSeconds` установлен на 200 секунд. Если контроллер CronJob вдруг не функционирует в течение того же периода, что и в предыдущем примере (с `08:29:00` по `10:21:00`), задание все равно начнется в 10:22:00. Это происходит потому, что контроллер в данном случае проверяет, сколько пропущенных запланированных заданий было за последние 200 секунд (т. е. 3 пропущенных расписания), а не с момента последнего запланированного времени до настоящего момента. + +CronJob отвечает только за создание заданий (Jobs), соответствующих его расписанию, а задание, в свою очередь, отвечает за управление подами, которые оно представляет. + +## {{% heading "whatsnext" %}} + +* Ознакомьтесь с [Подами](/docs/concepts/workloads/pods/) и + [Заданиями](/docs/concepts/workloads/controllers/job/) — двумя концепциями, на которые опираются CronJobs. +* Ознакомьтесь с подробным [форматом](https://pkg.go.dev/github.com/robfig/cron/v3#hdr-CRON_Expression_Format) + полей CronJob `.spec.schedule`. +* Для инструкции по созданию и работе с CronJob, а также для примера + CronJob-манифеста см. раздел [Выполнение автоматизированных задач с помощью CronJob](/docs/tasks/job/automated-tasks-with-cron-jobs/). +* `CronJob` является частью Kubernetes REST API. + Для получения более подробной информации прочтите справочник по {{< api-reference page="workload-resources/cron-job-v1" >}} API. + diff --git a/content/ru/docs/contribute/style/style-guide.md b/content/ru/docs/contribute/style/style-guide.md index c2d464f7903f4..bac94470d199c 100644 --- a/content/ru/docs/contribute/style/style-guide.md +++ b/content/ru/docs/contribute/style/style-guide.md @@ -74,7 +74,7 @@ PodList — это список Pod. | Pod List — это список подо Можно | Нельзя :--| :----- _Кластер_ — это набор узлов ... | "Кластер" — это набор узлов ... -Эти компоненты формируют _плоскость управления_. | Эти компоненты формируют **плоскость управления**. +Эти компоненты формируют _управляющий слой_. | Эти компоненты формируют **управляющий слой**. {{< /table >}} ### Оформляйте как код имена файлов, директории и пути diff --git a/content/ru/docs/reference/glossary/cloud-controller-manager.md b/content/ru/docs/reference/glossary/cloud-controller-manager.md index d8f0615778a14..c12c8db9923dd 100644 --- a/content/ru/docs/reference/glossary/cloud-controller-manager.md +++ b/content/ru/docs/reference/glossary/cloud-controller-manager.md @@ -11,7 +11,7 @@ tags: - architecture - operation --- -Компонент {{< glossary_tooltip text="панель управления" term_id="control-plane" >}} Kubernetes - это встраиваемый в логику управления облочная спецификация. Диспетчер облачных контроллеров позволяет связать кластер с API поставщика облачных услуг и отделить компоненты, взаимодействующие с этой облачной платформой, от компонентов, взаимодействующих только с вашим кластером. +Компонент {{< glossary_tooltip text="управляющего слоя" term_id="control-plane" >}} Kubernetes, встраивающий специфику облака в логику управления. Диспетчер облачных контроллеров позволяет связать кластер с API поставщика облачных услуг и отделить компоненты, взаимодействующие с этой облачной платформой, от компонентов, взаимодействующих только с вашим кластером. diff --git a/content/ru/docs/reference/glossary/cloud-provider.md b/content/ru/docs/reference/glossary/cloud-provider.md index 55414a63ee1ac..696c9116b73ac 100644 --- a/content/ru/docs/reference/glossary/cloud-provider.md +++ b/content/ru/docs/reference/glossary/cloud-provider.md @@ -27,6 +27,6 @@ tags: Вы также можете найти Kubernetes в качестве управляемого сервиса; иногда его называют Платформа как Услуга (Platform as a Service) или PaaS. С упарвляемым Kubernetes ваш облачный провайдер отвечает за -{{< glossary_tooltip term_id="control-plane" text="плоскость управления" >}} Kubernetes, а также за +{{< glossary_tooltip term_id="control-plane" text="управляющий слой" >}} Kubernetes, а также за {{< glossary_tooltip term_id="node" text="узлы" >}} и инфраструктуру, на которую они полагаются: сеть, хранилище и, возможно, другие элементы, такие как балансировщики нагрузки. diff --git a/content/ru/docs/reference/glossary/cluster.md b/content/ru/docs/reference/glossary/cluster.md index 00c5609b487f3..365ceb277bd88 100644 --- a/content/ru/docs/reference/glossary/cluster.md +++ b/content/ru/docs/reference/glossary/cluster.md @@ -14,4 +14,4 @@ tags: Набор машин, так называемые узлы, которые запускают контейнеризированные приложения. Кластер имеет как минимум один рабочий узел. -В рабочих узлах размещены поды, являющиеся компонентами приложения. Плоскость управления управляет рабочими узлами и подами в кластере. В промышленных средах плоскость управления обычно запускается на нескольких компьютерах, а кластер, как правило, развёртывается на нескольких узлах, гарантируя отказоустойчивость и высокую надёжность. +В рабочих узлах размещены поды, являющиеся компонентами приложения. Управляющий слой (control plane) управляет рабочими узлами и подами в кластере. В промышленных средах управляющий слой обычно запускается на нескольких компьютерах, а кластер, как правило, развёртывается на нескольких узлах, гарантируя отказоустойчивость и высокую надёжность. diff --git a/content/ru/docs/reference/glossary/container-runtime.md b/content/ru/docs/reference/glossary/container-runtime.md index 0ff3f1c47d574..8c6b54cbd517f 100644 --- a/content/ru/docs/reference/glossary/container-runtime.md +++ b/content/ru/docs/reference/glossary/container-runtime.md @@ -1,17 +1,17 @@ --- -title: Иполняемая среда контейнеров +title: Иcполняемая среда контейнеров id: container-runtime date: 2019-06-05 full_link: /docs/setup/production-environment/container-runtimes short_description: > - Иполняемая среда контейнеров — это программа, предназначенная для запуска контейнеров. + Иcполняемая среда контейнеров — это программа, предназначенная для запуска контейнеров. aka: tags: - fundamental - workload --- - Иполняемая среда контейнера — это программа, предназначенная для запуска контейнера в Kubernetes. + Иcполняемая среда контейнера — это программа, предназначенная для запуска контейнера в Kubernetes. diff --git a/content/ru/docs/reference/glossary/control-plane.md b/content/ru/docs/reference/glossary/control-plane.md index a4565af381fc1..98653864c3bd3 100644 --- a/content/ru/docs/reference/glossary/control-plane.md +++ b/content/ru/docs/reference/glossary/control-plane.md @@ -1,5 +1,5 @@ --- -title: Плоскость управления (Control Plane) +title: Управляющий слой (Control Plane) id: control-plane date: 2019-05-12 full_link: diff --git a/content/ru/docs/reference/glossary/node.md b/content/ru/docs/reference/glossary/node.md index 34f68b99b0794..f359bc422759b 100644 --- a/content/ru/docs/reference/glossary/node.md +++ b/content/ru/docs/reference/glossary/node.md @@ -14,4 +14,4 @@ tags: -Рабочий узел может быть как виртуальной, так и физической машиной, в зависимости от кластера. У него есть локальные демоны или сервисы, необходимые для запуска {{< glossary_tooltip text="подов" term_id="pod" >}}, а сам он управляется плоскостью управления. Демоны на узле включают в себя {{< glossary_tooltip text="kubelet" term_id="kubelet" >}}, {{< glossary_tooltip text="kube-proxy" term_id="kube-proxy" >}} и среду выполнения контейнера, основанную на {{< glossary_tooltip text="CRI" term_id="cri" >}}, например {{< glossary_tooltip term_id="docker" >}}. +Рабочий узел может быть как виртуальной, так и физической машиной, в зависимости от кластера. У него есть локальные демоны или сервисы, необходимые для запуска {{< glossary_tooltip text="подов" term_id="pod" >}}, а сам он управляется управляющим слоем (control plane). Демоны на узле включают в себя {{< glossary_tooltip text="kubelet" term_id="kubelet" >}}, {{< glossary_tooltip text="kube-proxy" term_id="kube-proxy" >}} и среду выполнения контейнера, основанную на {{< glossary_tooltip text="CRI" term_id="cri" >}}, например {{< glossary_tooltip term_id="docker" >}}. diff --git a/content/ru/docs/reference/issues-security/_index.md b/content/ru/docs/reference/issues-security/_index.md new file mode 100644 index 0000000000000..669b610f969a9 --- /dev/null +++ b/content/ru/docs/reference/issues-security/_index.md @@ -0,0 +1,4 @@ +--- +title: Проблемы и безопасность Kubernetes +weight: 70 +--- diff --git a/content/ru/docs/reference/issues-security/issues.md b/content/ru/docs/reference/issues-security/issues.md new file mode 100644 index 0000000000000..2724d349f8e8e --- /dev/null +++ b/content/ru/docs/reference/issues-security/issues.md @@ -0,0 +1,15 @@ +--- +title: Трекер задач (Issues) Kubernetes +weight: 10 +aliases: [/cve/,/cves/] +--- + +Чтобы сообщить о проблеме в области безопасности, воспользуйтесь процедурой [раскрытия информации о безопасности Kubernetes](/ru/docs/reference/issues-security/security/#report-a-vulnerability). + +Механизм [GitHub Issues](https://github.com/kubernetes/kubernetes/issues/) позволяет работать с кодом Kubernetes и отслеживать активные задачи. + +* Официальный [список известных CVE](/ru/docs/reference/issues-security/official-cve-feed/) +(уязвимостей в области безопасности), которые были обнародованы [Комитетом по реагированию на угрозы в области безопасности Kubernetes](https://github.com/kubernetes/committee-security-response). +* [Issues на GitHub, связанные с CVE](https://github.com/kubernetes/kubernetes/issues?utf8=%E2%9C%93&q=is%3Aissue+label%3Aarea%2Fsecurity+in%3Atitle+CVE) + +Связанные с безопасностью анонсы публикуются в рассылке [kubernetes-security-announce@googlegroups.com](https://groups.google.com/forum/#!forum/kubernetes-security-announce). diff --git a/content/ru/docs/reference/issues-security/official-cve-feed.md b/content/ru/docs/reference/issues-security/official-cve-feed.md new file mode 100644 index 0000000000000..5f1d63dc7932d --- /dev/null +++ b/content/ru/docs/reference/issues-security/official-cve-feed.md @@ -0,0 +1,47 @@ +--- +title: Официальный CVE-фид +linkTitle: CVE-фид +weight: 25 +outputs: + - json + - html + - rss +layout: cve-feed +--- + +{{< feature-state for_k8s_version="v1.27" state="beta" >}} + +Поддерживаемый сообществом список официальных CVE, анонсированных +Комитетом по реагированию на проблемы безопасности Kubernetes. Подробности см. на странице +[Общие сведения о безопасности Kubernetes и раскрытии информации](/ru/docs/reference/issues-security/security/). + +Проект Kubernetes публикует фиды с анонсами проблем в области безопасности в формате [JSON](/docs/reference/issues-security/official-cve-feed/index.json) и [RSS](/docs/reference/issues-security/official-cve-feed/feed.xml), доступные для автоматического считывания. Доступ к ним можно получить, выполнив следующие команды: + +{{< tabs name="CVE-фиды" >}} +{{% tab name="JSON-фид" %}} +[Ссылка на JSON-формат](/docs/reference/issues-security/official-cve-feed/index.json) +```shell +curl -Lv https://k8s.io/docs/reference/issues-security/official-cve-feed/index.json +``` +{{% /tab %}} +{{% tab name="RSS-фид" %}} +[Ссылка на RSS-формат](/docs/reference/issues-security/official-cve-feed/feed.xml) +```shell +curl -Lv https://k8s.io/docs/reference/issues-security/official-cve-feed/feed.xml +``` +{{% /tab %}} +{{< /tabs >}} + +{{< cve-feed >}} + + + +Список автоматически обновляется с заметной, но небольшой задержкой (от нескольких минут до нескольких часов) +с момента анонса CVE до момента его появления в этом фиде. + +В качестве источника используется набор GitHub Issues, отфильтрованный по контролируемому и +ограниченному лейблу `official-cve-feed`. Исходные данные хранятся в бакете Google Cloud, +право на запись в который есть только у небольшого числа доверенных представителей сообщества. diff --git a/content/ru/docs/reference/issues-security/security.md b/content/ru/docs/reference/issues-security/security.md new file mode 100644 index 0000000000000..b114f049187d5 --- /dev/null +++ b/content/ru/docs/reference/issues-security/security.md @@ -0,0 +1,55 @@ +--- +title: Общие сведения о безопасности Kubernetes и раскрытии информации +aliases: [/security/] +reviewers: +- eparis +- erictune +- philips +- jessfraz +content_type: concept +weight: 20 +--- + + +На этой странице приводятся общие сведения о безопасности Kubernetes и раскрытии информации, имеющей к ней отношение. + + + +## Анонсы в области безопасности + +Информация о проблемах в области безопасности и ключевых изменениях API доступна в рассылке [kubernetes-security-announce](https://groups.google.com/forum/#!forum/kubernetes-security-announce). + +## Сообщить об уязвимости + +Мы искренне признательны исследователям в области безопасности и пользователям, которые передают информацию об уязвимостях в Open Source-сообщество Kubernetes. Все отчеты тщательно изучаются группой добровольцев сообщества. + +Чтобы создать отчет, отправьте свою уязвимость в [Bug Bounty-программу Kubernetes](https://hackerone.com/kubernetes). Это позволит отследить и обработать уязвимость в стандартные сроки. + +Также можно оправить [стандартное письмо об ошибках Kubernetes](https://github.com/kubernetes/kubernetes/blob/master/.github/ISSUE_TEMPLATE/bug-report.yaml) с описанием проблемы с безопасностью и ее подробностями в закрытый список [security@kubernetes.io](mailto:security@kubernetes.io). + +Письмо можно зашифровать, используя GPG-ключи [членов Комитета по безопасности](https://git.k8s.io/security/README.md#product-security-committee-psc). Шифрование с использованием GPG НЕ является обязательным. + +### Когда следует сообщать об уязвимости + +- Вы думаете, что обнаружили уязвимость в безопасности Kubernetes. +- Вы не уверены, как именно уязвимость повлияет на Kubernetes. +- Вы думаете, что обнаружили уязвимость в другом проекте, от которого зависит работа Kubernetes. + - Если у проекта имеется собственный регламент регистрации и раскрытия информации об уязвимостях, пожалуйста, следуйте ему и пишите сразу в проект. + +### Когда НЕ следует сообщать об уязвимости + +- Вам нужна помощь в настройке компонентов Kubernetes для обеспечения безопасности. +- Вам нужна помощь в применении обновлений, связанных с безопасностью. +- Проблема не связана с безопасностью. + +## Реагирование на уязвимости в области безопасности + +Каждый отчет об уязвимости подтверждается и анализируется членами Комитета по реагированию на угрозы безопасности в течение 3 рабочих дней. После этого [запускается соответствующая процедура](https://git.k8s.io/security/security-release-process.md#disclosures). + +Любая информация об уязвимостях, переданная Комитету по реагированию на угрозы безопасности, остается внутри проекта Kubernetes и не передается в другие проекты, если только этого не требуется для устранения проблемы. + +Автору отчета будет сообщено о результатах триажа и дальнейших шагах по подготовке исправления и планированию релиза. + +## Сроки раскрытия информации + +Дата публичного раскрытия согласовывается Комитетом по реагированию на угрозы безопасности Kubernetes и автором отчета об уязвимости. Мы предпочитаем полностью раскрывать информацию об обнаруженной проблеме сразу после того, как станет понятно, какие шаги необходимо предпринять для устранения ее последствий. Разумно отложить раскрытие информации, если проблема или порядок дальнейших шагов не до конца понятны, решение плохо протестировано или необходима координация действий вендоров. Срок раскрытия информации варьируется от незамедлительного (особенно если она уже широко известна) до нескольких недель. Для "простых" уязвимостей с момента подачи отчета до даты раскрытия обычно проходит около 7 дней. Комитет по реагированию на угрозы безопасности сохраняет последнее слово при определении даты раскрытия информации. diff --git a/content/ru/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes.md b/content/ru/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes.md index 97de8ecffb766..c2beffcb4bac5 100644 --- a/content/ru/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes.md +++ b/content/ru/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes.md @@ -124,7 +124,7 @@ liveness-exec 1/1 Running 1 1m ## Определение liveness HTTP запроса -Другой вид liveness пробы использует запрос HTTP GET. Ниже представлен файл конфигурации для Pod, который запускает контейнер, основанный на образе `registry.k8s.io/liveness`. +Другой вид liveness пробы использует запрос HTTP GET. Ниже представлен файл конфигурации для Pod, который запускает контейнер, основанный на образе `registry.k8s.io/e2e-test-images/agnhost`. {{% codenew file="pods/probe/http-liveness.yaml" %}} @@ -213,7 +213,6 @@ kubectl describe pod goproxy ports: - name: liveness-port containerPort: 8080 - hostPort: 8080 livenessProbe: httpGet: @@ -234,8 +233,7 @@ livenessProbe: ports: - name: liveness-port containerPort: 8080 - hostPort: 8080 - + livenessProbe: httpGet: path: /healthz diff --git a/content/ru/docs/tutorials/kubernetes-basics/deploy-app/deploy-intro.html b/content/ru/docs/tutorials/kubernetes-basics/deploy-app/deploy-intro.html index da4929ed627fe..8c2e8e12e9a23 100644 --- a/content/ru/docs/tutorials/kubernetes-basics/deploy-app/deploy-intro.html +++ b/content/ru/docs/tutorials/kubernetes-basics/deploy-app/deploy-intro.html @@ -137,7 +137,7 @@

            Просмотр приложения

            export POD_NAME=$(kubectl get pods -o go-template --template '{{range .items}}{{.metadata.name}}{{"\n"}}{{end}}')
            echo Name of the Pod: $POD_NAME

            Теперь получим доступ к поду через проксированный API, выполнив команду:

            -

            curl http://localhost:8001/api/v1/namespaces/default/pods/$POD_NAME/

            +

            curl http://localhost:8001/api/v1/namespaces/default/pods/$POD_NAME:8080/proxy/

            Чтобы новый деплоймент был доступен без использования прокси, потребуется сервис (объект Service), о котором будет рассказано в следующих разделах.

            diff --git a/content/ru/docs/tutorials/kubernetes-basics/scale/scale-intro.html b/content/ru/docs/tutorials/kubernetes-basics/scale/scale-intro.html index 4399e729c234c..c1c2c2c540bdc 100644 --- a/content/ru/docs/tutorials/kubernetes-basics/scale/scale-intro.html +++ b/content/ru/docs/tutorials/kubernetes-basics/scale/scale-intro.html @@ -41,7 +41,7 @@

            Краткое содержание:

          -

          Количество экземпляров можно указать прямо при создании деплоймента, используя параметр --replicas команды kubectl create deployment

          +

          Количество экземпляров можно указать прямо при создании деплоймента, используя параметр --replicas команды kubectl create deployment

          diff --git a/content/ru/docs/tutorials/kubernetes-basics/update/update-intro.html b/content/ru/docs/tutorials/kubernetes-basics/update/update-intro.html index d74d480991fa4..daf7b0ca17f48 100644 --- a/content/ru/docs/tutorials/kubernetes-basics/update/update-intro.html +++ b/content/ru/docs/tutorials/kubernetes-basics/update/update-intro.html @@ -131,7 +131,7 @@

          Обновление версии приложения

          Чтобы увидеть версию текущего образа в приложении, воспользуйтесь подкомандой describe pods и посмотрите на поле Image:

          kubectl describe pods

          Чтобы обновить версию образа приложения до v2, воспользуемся подкомандой set image, для которой укажем имя деплоймента и новую версию нужного образа:

          -

          kubectl set image deployments/kubernetes-bootcamp kubernetes-bootcamp=jocatalin/kubernetes-bootcamp:v2

          +

          kubectl set image deployments/kubernetes-bootcamp kubernetes-bootcamp=docker.io/jocatalin/kubernetes-bootcamp:v2

          Эта команда перевела деплоймент на использование другого образа для приложения и инициировала плавающее обновление. Статус новых и старых подов (т. е. тех, которые будут остановлены) можно проверить с помощью подкоманды get pods:

          kubectl get pods

          diff --git a/content/ru/examples/application/guestbook/frontend-deployment.yaml b/content/ru/examples/application/guestbook/frontend-deployment.yaml index f97f20dab6763..9ff17ba4029b5 100644 --- a/content/ru/examples/application/guestbook/frontend-deployment.yaml +++ b/content/ru/examples/application/guestbook/frontend-deployment.yaml @@ -17,7 +17,7 @@ spec: spec: containers: - name: php-redis - image: gcr.io/google_samples/gb-frontend:v5 + image: us-docker.pkg.dev/google-samples/containers/gke/gb-frontend:v5 env: - name: GET_HOSTS_FROM value: "dns" diff --git a/content/ru/examples/application/guestbook/redis-follower-deployment.yaml b/content/ru/examples/application/guestbook/redis-follower-deployment.yaml index c418cf7364f92..c32a16e46c879 100644 --- a/content/ru/examples/application/guestbook/redis-follower-deployment.yaml +++ b/content/ru/examples/application/guestbook/redis-follower-deployment.yaml @@ -21,7 +21,7 @@ spec: spec: containers: - name: follower - image: gcr.io/google_samples/gb-redis-follower:v2 + image: us-docker.pkg.dev/google-samples/containers/gke/gb-redis-follower:v2 resources: requests: cpu: 100m diff --git a/content/ru/examples/pods/commands.yaml b/content/ru/examples/pods/commands.yaml new file mode 100644 index 0000000000000..2327d2582745f --- /dev/null +++ b/content/ru/examples/pods/commands.yaml @@ -0,0 +1,13 @@ +apiVersion: v1 +kind: Pod +metadata: + name: command-demo + labels: + purpose: demonstrate-command +spec: + containers: + - name: command-demo-container + image: debian + command: ["printenv"] + args: ["HOSTNAME", "KUBERNETES_PORT"] + restartPolicy: OnFailure diff --git a/content/ru/examples/pods/init-containers.yaml b/content/ru/examples/pods/init-containers.yaml new file mode 100644 index 0000000000000..034a18d7a9838 --- /dev/null +++ b/content/ru/examples/pods/init-containers.yaml @@ -0,0 +1,30 @@ +apiVersion: v1 +kind: Pod +metadata: + name: init-demo +spec: + containers: + - name: nginx + image: nginx + ports: + - containerPort: 80 + volumeMounts: + - name: workdir + mountPath: /usr/share/nginx/html + # Эти контейнеры запускаются во время инициализации пода + initContainers: + - name: install + image: busybox:1.28 + command: + - wget + - "-O" + - "/work-dir/index.html" + - http://info.cern.ch + volumeMounts: + - name: workdir + mountPath: "/work-dir" + dnsPolicy: Default + volumes: + - name: workdir + emptyDir: {} + diff --git a/content/ru/examples/pods/lifecycle-events.yaml b/content/ru/examples/pods/lifecycle-events.yaml new file mode 100644 index 0000000000000..4b79d7289c568 --- /dev/null +++ b/content/ru/examples/pods/lifecycle-events.yaml @@ -0,0 +1,16 @@ +apiVersion: v1 +kind: Pod +metadata: + name: lifecycle-demo +spec: + containers: + - name: lifecycle-demo-container + image: nginx + lifecycle: + postStart: + exec: + command: ["/bin/sh", "-c", "echo Hello from the postStart handler > /usr/share/message"] + preStop: + exec: + command: ["/bin/sh","-c","nginx -s quit; while killall -0 nginx; do sleep 1; done"] + diff --git a/content/ru/examples/pods/pod-configmap-env-var-valueFrom.yaml b/content/ru/examples/pods/pod-configmap-env-var-valueFrom.yaml new file mode 100644 index 0000000000000..fa172abd37135 --- /dev/null +++ b/content/ru/examples/pods/pod-configmap-env-var-valueFrom.yaml @@ -0,0 +1,21 @@ +apiVersion: v1 +kind: Pod +metadata: + name: dapi-test-pod +spec: + containers: + - name: test-container + image: registry.k8s.io/busybox + command: [ "/bin/echo", "$(SPECIAL_LEVEL_KEY) $(SPECIAL_TYPE_KEY)" ] + env: + - name: SPECIAL_LEVEL_KEY + valueFrom: + configMapKeyRef: + name: special-config + key: SPECIAL_LEVEL + - name: SPECIAL_TYPE_KEY + valueFrom: + configMapKeyRef: + name: special-config + key: SPECIAL_TYPE + restartPolicy: Never diff --git a/content/ru/examples/pods/pod-configmap-envFrom.yaml b/content/ru/examples/pods/pod-configmap-envFrom.yaml new file mode 100644 index 0000000000000..e7b5b60841edc --- /dev/null +++ b/content/ru/examples/pods/pod-configmap-envFrom.yaml @@ -0,0 +1,13 @@ +apiVersion: v1 +kind: Pod +metadata: + name: dapi-test-pod +spec: + containers: + - name: test-container + image: registry.k8s.io/busybox + command: [ "/bin/sh", "-c", "env" ] + envFrom: + - configMapRef: + name: special-config + restartPolicy: Never diff --git a/content/ru/examples/pods/pod-configmap-volume-specific-key.yaml b/content/ru/examples/pods/pod-configmap-volume-specific-key.yaml new file mode 100644 index 0000000000000..ec7a8fb541cf0 --- /dev/null +++ b/content/ru/examples/pods/pod-configmap-volume-specific-key.yaml @@ -0,0 +1,20 @@ +apiVersion: v1 +kind: Pod +metadata: + name: dapi-test-pod +spec: + containers: + - name: test-container + image: registry.k8s.io/busybox + command: [ "/bin/sh","-c","cat /etc/config/keys" ] + volumeMounts: + - name: config-volume + mountPath: /etc/config + volumes: + - name: config-volume + configMap: + name: special-config + items: + - key: SPECIAL_LEVEL + path: keys + restartPolicy: Never diff --git a/content/ru/examples/pods/pod-configmap-volume.yaml b/content/ru/examples/pods/pod-configmap-volume.yaml new file mode 100644 index 0000000000000..06f6e4a76a084 --- /dev/null +++ b/content/ru/examples/pods/pod-configmap-volume.yaml @@ -0,0 +1,19 @@ +apiVersion: v1 +kind: Pod +metadata: + name: dapi-test-pod +spec: + containers: + - name: test-container + image: registry.k8s.io/busybox + command: [ "/bin/sh", "-c", "ls /etc/config/" ] + volumeMounts: + - name: config-volume + mountPath: /etc/config + volumes: + - name: config-volume + configMap: + # Укажите имя ConfigMap с файлами, которые вы хотите + # добавить в контейнер + name: special-config + restartPolicy: Never diff --git a/content/ru/examples/pods/pod-multiple-configmap-env-variable.yaml b/content/ru/examples/pods/pod-multiple-configmap-env-variable.yaml new file mode 100644 index 0000000000000..c7b2b7abb8217 --- /dev/null +++ b/content/ru/examples/pods/pod-multiple-configmap-env-variable.yaml @@ -0,0 +1,21 @@ +apiVersion: v1 +kind: Pod +metadata: + name: dapi-test-pod +spec: + containers: + - name: test-container + image: registry.k8s.io/busybox + command: [ "/bin/sh", "-c", "env" ] + env: + - name: SPECIAL_LEVEL_KEY + valueFrom: + configMapKeyRef: + name: special-config + key: special.how + - name: LOG_LEVEL + valueFrom: + configMapKeyRef: + name: env-config + key: log_level + restartPolicy: Never diff --git a/content/ru/examples/pods/pod-nginx-preferred-affinity.yaml b/content/ru/examples/pods/pod-nginx-preferred-affinity.yaml new file mode 100644 index 0000000000000..183ba9f014225 --- /dev/null +++ b/content/ru/examples/pods/pod-nginx-preferred-affinity.yaml @@ -0,0 +1,19 @@ +apiVersion: v1 +kind: Pod +metadata: + name: nginx +spec: + affinity: + nodeAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 1 + preference: + matchExpressions: + - key: disktype + operator: In + values: + - ssd + containers: + - name: nginx + image: nginx + imagePullPolicy: IfNotPresent diff --git a/content/ru/examples/pods/pod-nginx-required-affinity.yaml b/content/ru/examples/pods/pod-nginx-required-affinity.yaml new file mode 100644 index 0000000000000..a3805eaa8d9c9 --- /dev/null +++ b/content/ru/examples/pods/pod-nginx-required-affinity.yaml @@ -0,0 +1,18 @@ +apiVersion: v1 +kind: Pod +metadata: + name: nginx +spec: + affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: disktype + operator: In + values: + - ssd + containers: + - name: nginx + image: nginx + imagePullPolicy: IfNotPresent diff --git a/content/ru/examples/pods/pod-nginx-specific-node.yaml b/content/ru/examples/pods/pod-nginx-specific-node.yaml new file mode 100644 index 0000000000000..82c1a854d3f1b --- /dev/null +++ b/content/ru/examples/pods/pod-nginx-specific-node.yaml @@ -0,0 +1,10 @@ +apiVersion: v1 +kind: Pod +metadata: + name: nginx +spec: + nodeName: foo-node # запланировать под на конкретный узел + containers: + - name: nginx + image: nginx + imagePullPolicy: IfNotPresent diff --git a/content/ru/examples/pods/pod-nginx.yaml b/content/ru/examples/pods/pod-nginx.yaml new file mode 100644 index 0000000000000..134ddae2aa1c8 --- /dev/null +++ b/content/ru/examples/pods/pod-nginx.yaml @@ -0,0 +1,13 @@ +apiVersion: v1 +kind: Pod +metadata: + name: nginx + labels: + env: test +spec: + containers: + - name: nginx + image: nginx + imagePullPolicy: IfNotPresent + nodeSelector: + disktype: ssd diff --git a/content/ru/examples/pods/pod-projected-svc-token.yaml b/content/ru/examples/pods/pod-projected-svc-token.yaml new file mode 100644 index 0000000000000..985073c8d39dc --- /dev/null +++ b/content/ru/examples/pods/pod-projected-svc-token.yaml @@ -0,0 +1,20 @@ +apiVersion: v1 +kind: Pod +metadata: + name: nginx +spec: + containers: + - image: nginx + name: nginx + volumeMounts: + - mountPath: /var/run/secrets/tokens + name: vault-token + serviceAccountName: build-robot + volumes: + - name: vault-token + projected: + sources: + - serviceAccountToken: + path: vault-token + expirationSeconds: 7200 + audience: vault diff --git a/content/ru/examples/pods/pod-rs.yaml b/content/ru/examples/pods/pod-rs.yaml new file mode 100644 index 0000000000000..df7b390597c49 --- /dev/null +++ b/content/ru/examples/pods/pod-rs.yaml @@ -0,0 +1,23 @@ +apiVersion: v1 +kind: Pod +metadata: + name: pod1 + labels: + tier: frontend +spec: + containers: + - name: hello1 + image: gcr.io/google-samples/hello-app:2.0 + +--- + +apiVersion: v1 +kind: Pod +metadata: + name: pod2 + labels: + tier: frontend +spec: + containers: + - name: hello2 + image: gcr.io/google-samples/hello-app:1.0 diff --git a/content/ru/examples/pods/pod-single-configmap-env-variable.yaml b/content/ru/examples/pods/pod-single-configmap-env-variable.yaml new file mode 100644 index 0000000000000..bf893fe9f5b01 --- /dev/null +++ b/content/ru/examples/pods/pod-single-configmap-env-variable.yaml @@ -0,0 +1,19 @@ +apiVersion: v1 +kind: Pod +metadata: + name: dapi-test-pod +spec: + containers: + - name: test-container + image: registry.k8s.io/busybox + command: [ "/bin/sh", "-c", "env" ] + env: + # Задать переменную окружения + - name: SPECIAL_LEVEL_KEY + valueFrom: + configMapKeyRef: + # ConfigMap со значением, которое вы хотите присвоить SPECIAL_LEVEL_KEY + name: special-config + # Укажите ключ, привязанный к значению + key: special.how + restartPolicy: Never diff --git a/content/ru/examples/pods/pod-with-affinity-anti-affinity.yaml b/content/ru/examples/pods/pod-with-affinity-anti-affinity.yaml new file mode 100644 index 0000000000000..cb8c5650b0841 --- /dev/null +++ b/content/ru/examples/pods/pod-with-affinity-anti-affinity.yaml @@ -0,0 +1,32 @@ +apiVersion: v1 +kind: Pod +metadata: + name: with-affinity-anti-affinity +spec: + affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: kubernetes.io/os + operator: In + values: + - linux + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 1 + preference: + matchExpressions: + - key: label-1 + operator: In + values: + - key-1 + - weight: 50 + preference: + matchExpressions: + - key: label-2 + operator: In + values: + - key-2 + containers: + - name: with-node-affinity + image: registry.k8s.io/pause:2.0 diff --git a/content/ru/examples/pods/pod-with-node-affinity.yaml b/content/ru/examples/pods/pod-with-node-affinity.yaml new file mode 100644 index 0000000000000..5fedc554bfdd4 --- /dev/null +++ b/content/ru/examples/pods/pod-with-node-affinity.yaml @@ -0,0 +1,26 @@ +apiVersion: v1 +kind: Pod +metadata: + name: with-node-affinity +spec: + affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: topology.kubernetes.io/zone + operator: In + values: + - antarctica-east1 + - antarctica-west1 + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 1 + preference: + matchExpressions: + - key: another-node-label-key + operator: In + values: + - another-node-label-value + containers: + - name: with-node-affinity + image: registry.k8s.io/pause:2.0 \ No newline at end of file diff --git a/content/ru/examples/pods/pod-with-pod-affinity.yaml b/content/ru/examples/pods/pod-with-pod-affinity.yaml new file mode 100644 index 0000000000000..1a4fd74fd7aa9 --- /dev/null +++ b/content/ru/examples/pods/pod-with-pod-affinity.yaml @@ -0,0 +1,29 @@ +apiVersion: v1 +kind: Pod +metadata: + name: with-pod-affinity +spec: + affinity: + podAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + - labelSelector: + matchExpressions: + - key: security + operator: In + values: + - S1 + topologyKey: topology.kubernetes.io/zone + podAntiAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 100 + podAffinityTerm: + labelSelector: + matchExpressions: + - key: security + operator: In + values: + - S2 + topologyKey: topology.kubernetes.io/zone + containers: + - name: with-pod-affinity + image: registry.k8s.io/pause:2.0 diff --git a/content/ru/examples/pods/pod-with-scheduling-gates.yaml b/content/ru/examples/pods/pod-with-scheduling-gates.yaml new file mode 100644 index 0000000000000..de761d969460d --- /dev/null +++ b/content/ru/examples/pods/pod-with-scheduling-gates.yaml @@ -0,0 +1,11 @@ +apiVersion: v1 +kind: Pod +metadata: + name: test-pod +spec: + schedulingGates: + - name: example.com/foo + - name: example.com/bar + containers: + - name: pause + image: registry.k8s.io/pause:3.6 diff --git a/content/ru/examples/pods/pod-with-toleration.yaml b/content/ru/examples/pods/pod-with-toleration.yaml new file mode 100644 index 0000000000000..79f2756a8ce5f --- /dev/null +++ b/content/ru/examples/pods/pod-with-toleration.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Pod +metadata: + name: nginx + labels: + env: test +spec: + containers: + - name: nginx + image: nginx + imagePullPolicy: IfNotPresent + tolerations: + - key: "example-key" + operator: "Exists" + effect: "NoSchedule" diff --git a/content/ru/examples/pods/pod-without-scheduling-gates.yaml b/content/ru/examples/pods/pod-without-scheduling-gates.yaml new file mode 100644 index 0000000000000..5638b6e97af5f --- /dev/null +++ b/content/ru/examples/pods/pod-without-scheduling-gates.yaml @@ -0,0 +1,8 @@ +apiVersion: v1 +kind: Pod +metadata: + name: test-pod +spec: + containers: + - name: pause + image: registry.k8s.io/pause:3.6 diff --git a/content/ru/examples/pods/private-reg-pod.yaml b/content/ru/examples/pods/private-reg-pod.yaml new file mode 100644 index 0000000000000..4029588dd0758 --- /dev/null +++ b/content/ru/examples/pods/private-reg-pod.yaml @@ -0,0 +1,11 @@ +apiVersion: v1 +kind: Pod +metadata: + name: private-reg +spec: + containers: + - name: private-reg-container + image: + imagePullSecrets: + - name: regcred + diff --git a/content/ru/examples/pods/probe/http-liveness.yaml b/content/ru/examples/pods/probe/http-liveness.yaml index 48ca861c14271..ecc1a6ff2e12e 100644 --- a/content/ru/examples/pods/probe/http-liveness.yaml +++ b/content/ru/examples/pods/probe/http-liveness.yaml @@ -7,9 +7,9 @@ metadata: spec: containers: - name: liveness - image: registry.k8s.io/liveness + image: registry.k8s.io/e2e-test-images/agnhost:2.40 args: - - /server + - liveness livenessProbe: httpGet: path: /healthz diff --git a/content/ru/examples/pods/share-process-namespace.yaml b/content/ru/examples/pods/share-process-namespace.yaml new file mode 100644 index 0000000000000..bd48bf0ff6e18 --- /dev/null +++ b/content/ru/examples/pods/share-process-namespace.yaml @@ -0,0 +1,17 @@ +apiVersion: v1 +kind: Pod +metadata: + name: nginx +spec: + shareProcessNamespace: true + containers: + - name: nginx + image: nginx + - name: shell + image: busybox:1.28 + securityContext: + capabilities: + add: + - SYS_PTRACE + stdin: true + tty: true diff --git a/content/ru/examples/pods/simple-pod.yaml b/content/ru/examples/pods/simple-pod.yaml new file mode 100644 index 0000000000000..0e79d8a3c6128 --- /dev/null +++ b/content/ru/examples/pods/simple-pod.yaml @@ -0,0 +1,10 @@ +apiVersion: v1 +kind: Pod +metadata: + name: nginx +spec: + containers: + - name: nginx + image: nginx:1.14.2 + ports: + - containerPort: 80 diff --git a/content/ru/examples/pods/two-container-pod.yaml b/content/ru/examples/pods/two-container-pod.yaml new file mode 100644 index 0000000000000..031ada7112b4c --- /dev/null +++ b/content/ru/examples/pods/two-container-pod.yaml @@ -0,0 +1,27 @@ +apiVersion: v1 +kind: Pod +metadata: + name: two-containers +spec: + + restartPolicy: Never + + volumes: + - name: shared-data + emptyDir: {} + + containers: + + - name: nginx-container + image: nginx + volumeMounts: + - name: shared-data + mountPath: /usr/share/nginx/html + + - name: debian-container + image: debian + volumeMounts: + - name: shared-data + mountPath: /pod-data + command: ["/bin/sh"] + args: ["-c", "echo Hello from the debian container > /pod-data/index.html"] diff --git a/content/ru/examples/pods/user-namespaces-stateless.yaml b/content/ru/examples/pods/user-namespaces-stateless.yaml new file mode 100644 index 0000000000000..d254259f66cb9 --- /dev/null +++ b/content/ru/examples/pods/user-namespaces-stateless.yaml @@ -0,0 +1,10 @@ +apiVersion: v1 +kind: Pod +metadata: + name: userns +spec: + hostUsers: false + containers: + - name: shell + command: ["sleep", "infinity"] + image: debian diff --git a/content/uk/OWNERS b/content/uk/OWNERS index 09fbf1170cb09..f7e367adb8859 100644 --- a/content/uk/OWNERS +++ b/content/uk/OWNERS @@ -8,6 +8,14 @@ reviewers: approvers: - sig-docs-uk-owners +- sig-docs-website-owners # important due to no_parent_owners option labels: +- area/localization - language/uk + +# Disable inheritance so that the localization team don't end up as approvers for all +# languages. +# https://github.com/kubernetes/community/blob/master/communication/website-guidelines.md +options: + no_parent_owners: true diff --git a/content/uk/blog/_index.md b/content/uk/blog/_index.md new file mode 100644 index 0000000000000..8f37814c3cf97 --- /dev/null +++ b/content/uk/blog/_index.md @@ -0,0 +1,15 @@ +--- +title: Блог Kubernetes +linkTitle: Блог +menu: + main: + title: "Блог" + weight: 40 + post: > +

          Читайте останні новини щодо Kubernetes та контейнеризацію загалом, а також отримуйте технічні інструкції, які щойно виходять з друку.

          +--- +{{< comment >}} + +Щодо інформації про участь у створенні матеріалів для блогу, див. [https://kubernetes.io/docs/contribute/new-content/blogs-case-studies/#write-a-blog-post](https://kubernetes.io/docs/contribute/new-content/blogs-case-studies/#write-a-blog-post) + +{{< /comment >}} \ No newline at end of file diff --git a/content/uk/blog/_posts/2024-03-12-mid-cycle-1.30.md b/content/uk/blog/_posts/2024-03-12-mid-cycle-1.30.md new file mode 100644 index 0000000000000..55298d89525d5 --- /dev/null +++ b/content/uk/blog/_posts/2024-03-12-mid-cycle-1.30.md @@ -0,0 +1,54 @@ +--- +layout: blog +title: 'Огляд Kubernetes v1.30' +date: 2024-03-12 +slug: kubernetes-1-30-upcoming-changes +--- + +**Автори:** Amit Dsouza, Frederick Kautz, Kristin Martin, Abigail McCarthy, Natali Vlatko + +## Швидкий огляд: зміни у Kubernetes v1.30 {#a-quick-look-exciting-changes-in-kubernetes-v1.30} + +Новий рік, новий реліз Kubernetes. Ми на половині релізного циклу і маємо чимало цікавих та чудових поліпшень у версії v1.30. Від абсолютно нових можливостей у режимі альфа до вже сталих функцій, які переходять у стабільний режим, а також довгоочікуваних поліпшень — цей випуск має щось для усіх, на що варто звернути увагу! + +Щоб підготувати вас до офіційного випуску, ось короткий огляд удосконалень, про які ми найбільше хочемо розповісти! + +## Основні зміни для Kubernetes v1.30 {#major-changes-for-kubernetes-v1.30} + +### Структуровані параметри для динамічного розподілу ресурсів ([KEP-4381](https://kep.k8s.io/4381)) {#structured-parameters-for-dynamic-resource-allocation-kep-4381-https-kep-k8s-io-4381} + +[Динамічний розподіл ресурсів](/docs/concepts/scheduling-eviction/dynamic-resource-allocation/) було додано до Kubernetes у версії v1.26 у режимі альфа. Він визначає альтернативу традиційному API пристроїв для запиту доступу до ресурсів сторонніх постачальників. За концепцією, динамічний розподіл ресурсів використовує параметри для ресурсів, що є абсолютно непрозорими для ядра Kubernetes. Цей підхід створює проблему для Cluster Autoscaler (CA) чи будь-якого контролера вищого рівня, який повинен приймати рішення для групи Podʼів (наприклад, планувальник завдань). Він не може симулювати ефект виділення чи звільнення заявок з плином часу. Інформацію для цього можуть надавати лише драйвери DRA сторонніх постачальників. + +Структуровані параметри для динамічного розподілу ресурсів — це розширення оригінальної реалізації, яке розвʼязує цю проблему, створюючи фреймворк для підтримки параметрів заявок, що є більш прозорими. Замість обробки семантики всіх параметрів заявок самостійно, драйвери можуть керувати ресурсами та описувати їх, використовуючи конкретну "структуровану модель", заздалегідь визначену Kubernetes. Це дозволить компонентам, які обізнані з цією "структурованою моделлю", приймати рішення щодо цих ресурсів без залучення зовнішнього контролера. Наприклад, планувальник може швидко обробляти заявки без зайвої комунікації з драйверами динамічного розподілу ресурсів. Робота, виконана для цього релізу, зосереджена на визначенні необхідного фреймворку для активації різних "структурованих моделей" та реалізації моделі "пойменованих ресурсів". Ця модель дозволяє перераховувати окремі екземпляри ресурсів та, на відміну від традиційного API пристроїв, додає можливість вибору цих екземплярів індивідуально за атрибутами. + +### Підтримка своп-памʼяті на вузлах ([KEP-2400](https://kep.k8s.io/2400)) {#node-memory-swap-support-kep-2400-https-kep-k8s-io-2400} + +У Kubernetes v1.30 підтримка своп-памʼяті на вузлах Linux отримує значущі зміни в способі її функціонування, з основним акцентом на покращенні стабільності системи. В попередніх версіях Kubernetes функція `NodeSwap` була типово вимкненою, а при увімкненні використовувала поведінку `UnlimitedSwap`. З метою досягнення кращої стабільності, поведінка `UnlimitedSwap` (яка може компрометувати стабільність вузла) буде видалена у версії v1.30. + +Оновлена, все ще бета-версія підтримки своп на вузлах Linux буде стандартно доступною. Однак типовою поведінкою буде запуск вузла в режимі `NoSwap` (а не `UnlimitedSwap`). У режимі `NoSwap` kubelet підтримує роботу на вузлі, де активний простір своп, але Podʼи не використовують жодного page-файлу. Для того, щоб kubelet працював на цьому вузлі, вам все ще потрібно встановити `--fail-swap-on=false`. Однак велика зміна стосується іншого режиму: `LimitedSwap`. У цьому режимі kubelet фактично використовує page-файл на вузлі та дозволяє Podʼам виділяти деяку частину їхньої віртуальної памʼяті. Контейнери (і їхні батьківські Podʼи) не мають доступу до своп поза їхнім обмеженням памʼяті, але система все ще може використовувати простір своп, якщо він доступний. + +Група Kubernetes Node (SIG Node) також оновить документацію, щоб допомогти вам зрозуміти, як використовувати оновлену реалізацію, на основі відгуків від кінцевих користувачів, учасників та широкої спільноти Kubernetes. + +Для отримання додаткових відомостей про підтримку своп на вузлах Linux в Kubernetes, прочитайте попередній [пост блогу](/blog/2023/08/24/swap-linux-beta/) чи [документацію про своп на вузлах](/docs/concepts/architecture/nodes/#swap-memory). + +### Підтримка просторів імен користувачів в Pod ([KEP-127](https://kep.k8s.io/127)) {#support-user-namespaces-in-pods-kep-127-https-kep-k8s-io-127} + +[Простори імен користувачів](/docs/concepts/workloads/pods/user-namespaces) — це функція лише для Linux, яка краще ізолює Podʼи для запобігання або помʼякшення кількох важливих CVEs із високим/критичним рейтингом, включаючи [CVE-2024-21626](https://github.com/opencontainers/runc/security/advisories/GHSA-xr7r-f8xq-vfvv), опубліковану у січні 2024 року. У Kubernetes 1.30 підтримка просторів імен користувачів переходить у бета-версію і тепер підтримує Podʼи з томами та без них, власні діапазони UID/GID та багато іншого! + +### Конфігурація структурованої авторизації ([KEP-3221](https://kep.k8s.io/3221)) {#structured-authorization-configuration-kep-3221-https-kep-k8s-io-3221} + +Підтримка [конфігурації структурованої авторизації](/docs/reference/access-authn-authz/authorization/#configuring-the-api-server-using-an-authorization-config-file) переходить у бета-версію та буде типово увімкненою. Ця функція дозволяє створювати ланцюги авторизації з кількома вебхуками із чітко визначеними параметрами, які перевіряють запити в певному порядку та надають деталізований контроль — такий, як явна відмова у випадку невдач. Використання конфігураційного файлу навіть дозволяє вказати правила [CEL](/docs/reference/using-api/cel/) для попередньої фільтрації запитів, перш ніж вони будуть відправлені до вебхуків, допомагаючи вам запобігти непотрібним викликам. Сервер API також автоматично перезавантажує ланцюг авторизатора при зміні конфігураційного файлу. + +Вам необхідно вказати шлях до конфігурації авторизації, використовуючи аргумент командного рядка `--authorization-config`. Якщо ви хочете продовжувати використовувати аргументи командного рядка замість конфігураційного файлу, вони продовжать працювати як є. Щоб отримати доступ до нових можливостей вебхуків авторизації, таких як кілька вебхуків, політика невдачі та правила попередньої фільтрації, перейдіть до використання параметрів у файлі `--authorization-config`. З версії Kubernetes 1.30 формат конфігураційного файлу є бета-рівнем, і потрібно вказувати лише `--authorization-config`, оскільки feature gate вже увімкнено. Приклад конфігурації із всіма можливими значеннями наведено в [документації з авторизації](/docs/reference/access-authn-authz/authorization/#configuring-the-api-server-using-an-authorization-config-file). Докладніше читайте в [документації з авторизації](/docs/reference/access-authn-authz/authorization/#configuring-the-api-server-using-an-authorization-config-file). + +### Автомасштабування Podʼів на основі ресурсів контейнера ([KEP-1610](https://kep.k8s.io/1610)) {#container-resource-based-pod-autoscaling-kep-1610-https-kep-k8s-io-1610} + +Горизонтальне автомасштабування Podʼів на основі метрик `ContainerResource` перейде у стабільний стан у версії v1.30. Це нова функціональність для HorizontalPodAutoscaler дозволяє налаштовувати автоматичне масштабування на основі використання ресурсів для окремих контейнерів, а не загального використання ресурсів для всіх контейнерів у Podʼіві. Докладні відомості можна знайти у нашій [попередній статті](2023/05/02/hpa-container-resource-metric/) або в [метриках ресурсів контейнера](/docs/tasks/run-application/horizontal-pod-autoscale/#container-resource-metrics). + +### CEL для керування допуском ([KEP-3488](https://kep.k8s.io/3488)) {#cel-for-admission-control-kep-3488-https-kep-k8s-io-3488} + +Інтеграція Common Expression Language (CEL) для керування допуском у Kubernetes вводить більш динамічний та виразний спосіб оцінки запитів на допуск. Ця функція дозволяє визначати та застосовувати складні, деталізовані політики безпосередньо через API Kubernetes, підвищуючи безпеку та здатність до управління без втрати продуктивності чи гнучкості. + +Додавання CEL до керування допуском у Kubernetes дає адміністраторам кластерів можливість створювати складні правила, які можуть оцінювати вміст API-запитів на основі бажаного стану та політик кластера, не вдаючись до вебхуків, які використовують контролери доступу. Цей рівень контролю є важливим для забезпечення цілісності, безпеки та ефективності операцій у кластері, роблячи середовища Kubernetes більш надійними та адаптованими до різних сценаріїв використання та вимог. Для отримання докладної інформації щодо використання CEL для керування допуском дивіться [документацію API](/docs/reference/access-authn-authz/validating-admission-policy/) для ValidatingAdmissionPolicy. + +Ми сподіваємося, що ви так само нетерпляче чекаєте на цей випуск, як і ми. Стежте за блогом, щоб дізнатись про офіційний випуск через кілька тижнів, де буде представлено ще більше відомостей! diff --git a/content/vi/OWNERS b/content/vi/OWNERS index 23c3d916c74cf..80919fb7b1a32 100644 --- a/content/vi/OWNERS +++ b/content/vi/OWNERS @@ -8,6 +8,14 @@ reviewers: approvers: - sig-docs-vi-owners +- sig-docs-website-owners # important due to no_parent_owners option labels: +- area/localization - language/vi + +# Disable inheritance so that the localization team don't end up as approvers for all +# languages. +# https://github.com/kubernetes/community/blob/master/communication/website-guidelines.md +options: + no_parent_owners: true diff --git a/content/zh-cn/OWNERS b/content/zh-cn/OWNERS index 6e147c98ad3ec..a771268b92104 100644 --- a/content/zh-cn/OWNERS +++ b/content/zh-cn/OWNERS @@ -1,6 +1,6 @@ # See the OWNERS docs at https://go.k8s.io/owners -# This is the localization project for Chinese. +# This is the localization project for Chinese (simplified / People's Republic of China) # Teams and members are visible at https://github.com/orgs/kubernetes/teams. reviewers: @@ -8,6 +8,14 @@ reviewers: approvers: - sig-docs-zh-owners +- sig-docs-website-owners # important due to no_parent_owners option labels: +- area/localization - language/zh + +# Disable inheritance so that the localization team don't end up as approvers for all +# languages. +# https://github.com/kubernetes/community/blob/master/communication/website-guidelines.md +options: + no_parent_owners: true diff --git a/content/zh-cn/blog/_posts/2023-12-20-contextual-logging-in-kubernetes-1-29.md b/content/zh-cn/blog/_posts/2023-12-20-contextual-logging-in-kubernetes-1-29.md new file mode 100644 index 0000000000000..e66773e5d5d99 --- /dev/null +++ b/content/zh-cn/blog/_posts/2023-12-20-contextual-logging-in-kubernetes-1-29.md @@ -0,0 +1,270 @@ +--- +layout: blog +title: "Kubernetes 1.29 中的上下文日志生成:更好的故障排除和增强的日志记录" +slug: contextual-logging-in-kubernetes-1-29 +date: 2023-12-20T09:30:00-08:00 +--- + + + +**作者**:[Mengjiao Liu](https://github.com/mengjiao-liu/) (DaoCloud), [Patrick Ohly](https://github.com/pohly) (Intel) + +**译者**:[Mengjiao Liu](https://github.com/mengjiao-liu/) (DaoCloud) + + +代表[结构化日志工作组](https://github.com/kubernetes/community/blob/master/wg-structed-logging/README.md)和 +[SIG Instrumentation](https://github.com/kubernetes/community/tree/master/sig-instrumentation#readme), +我们很高兴地宣布在 Kubernetes v1.24 中引入的上下文日志记录功能现已成功迁移了两个组件(kube-scheduler 和 kube-controller-manager) +以及一些目录。该功能旨在为 Kubernetes 提供更多有用的日志以更好地进行故障排除,并帮助开发人员增强 Kubernetes。 + + +## 上下文日志记录是什么? {#what-is-contextual-logging} + +[上下文日志记录](https://github.com/kubernetes/enhancements/tree/master/keps/sig-instrumentation/3077-contextual-logging)基于 +[go-logr](https://github.com/go-logr/logr#a-minimal-logging-api-for-go) API。 +关键思想是调用者将一个日志生成器实例传递给库,并使用它进行日志记录而不是访问全局日志生成器。 +二进制文件而不是库负责选择日志记录的实现。go-logr API 围绕结构化日志记录而设计,并支持向日志生成器提供额外信息。 + + +这一设计可以支持某些额外的使用场景: + +- 调用者可以为日志生成器提供额外的信息: + - [WithName]() 添加一个 “logger” 键, + 并用句点(.)将名称的各个部分串接起来作为取值 + - [WithValues]() 添加键/值对 + + 当将此经过扩展的日志生成器传递到函数中,并且该函数使用它而不是全局日志生成器时, + 所有日志条目中都会包含所给的额外信息,而无需修改生成日志条目的代码。 + 这一特点在高度并行的应用中非常有用。在这类应用中,很难辨识某操作的所有日志条目,因为不同操作的输出是交错的。 + +- 运行单元测试时,日志输出可以与当前测试相关联。且当测试失败时,go test 仅显示失败测试的日志输出。 + 默认情况下,该输出也可能更详细,因为它不会在成功的测试中显示。测试可以并行运行,而无需交错输出。 + + +上下文日志记录的设计决策之一是允许将日志生成器作为值附加到 `context.Context` 之上。 +由于日志生成器封装了调用所预期的、与日志记录相关的所有元素, +因此它是 context 的**一部分**,而不仅仅是**使用**它。这一设计的一个比较实际的优点是, +许多 API 已经有一个 `ctx` 参数,或者可以添加一个 `ctx` 参数。 +进而产生的额外好处还包括比如可以去掉函数内的 `context.TODO()` 调用。 + + +## 如何使用它 {#how-to-use-it} + +从 Kubernetes v1.24 开始,上下文日志记录功能处于 Alpha 状态,因此它需要启用 +`ContextualLogging` [特性门控](/docs/reference/command-line-tools-reference/feature-gates/)。 +如果你想在该功能处于 Alpha 状态时对其进行测试,则需要在 `kube-controller-manager` 和 `kube-scheduler` 上启用此特性门控。 + + +对于 `kube-scheduler`,有一点需要注意,除了启用 `ContextualLogging` 特性门控之外, +插桩行为还取决于日志的详细程度设置。 +为了避免因 1.29 添加的上下文日志记录工具而降低调度程序的速度,请务必仔细选择何时添加额外的信息: +- 在 `-v3` 或更低日志级别中,每个调度周期仅使用一次 `WithValues("pod")`。 + 这样做可以达到预期效果,即该周期的所有日志消息都包含 Pod 信息。 + 一旦上下文日志记录特性到达 GA 阶段,就可以从所有日志调用中删除 “pod” 键值对。 +- 在 `-v4` 或更高日志级别中,会生成更丰富的日志条目,其中 `WithValues` 也用于节点(如果适用),`WithName` 用于当前操作和插件。 + + +下面的示例展示了这一效果: +> I1113 08:43:37.029524 87144 default_binder.go:53] "Attempting to bind pod to node" **logger="Bind.DefaultBinder"** **pod**="kube-system/coredns-69cbfb9798-ms4pq" **node**="127.0.0.1" + + +这一设计的直接好处是在 `logger` 中可以看到操作和插件名称。`pod` 和 `node` 已作为参数记录在 +`kube-scheduler` 代码中的各个日志调用中。一旦 `kube-scheduler` 之外的其他包也支持上下文日志记录, +在这些包(例如,client-go)中也可以看到操作和插件名称。 +一旦上下文日志记录特性到达 GA 阶段,就可以简化日志调用以避免重复这些值。 + + +在 `kube-controller-manager` 中,`WithName` 被用来在日志中输出用户可见的控制器名称,例如: + +> I1113 08:43:29.284360 87141 graph_builder.go:285] "garbage controller monitor not synced: no monitors" **logger="garbage-collector-controller"** + + +`logger=”garbage-collector-controller”` 是由 `kube-controller-manager` +核心代码在实例化该控制器时添加的,会出现在其所有日志条目中——只要它所调用的代码支持上下文日志记录。 +转换像 client-go 这样的共享包还需要额外的工作。 + + +## 性能影响 {#performance-impact} + +在包中支持上下文日志记录,即接受来自调用者的记录器,成本很低。 +没有观察到 `kube-scheduler` 的性能影响。如上所述,添加 `WithName` 和 `WithValues` 需要更加小心。 + + +在 Kubernetes 1.29 中,以生产环境日志详细程度(`-v3` 或更低)启用上下文日志不会导致 `kube-scheduler` 速度出现明显的减慢, +并且 `kube-controller-manager` 速度也不会出现明显的减慢。在 debug 级别,考虑到生成的日志使调试更容易,某些测试用例减速 28% 仍然是合理的。 +详细信息请参阅[有关将该特性升级为 Beta 版的讨论](https://github.com/kubernetes/enhancements/pull/4219#issuecomment-1807811995)。 + + +## 对下游用户的影响 {#impact-on-downstream-users} + +日志输出不是 Kubernetes API 的一部分,并且经常在每个版本中都会出现更改, +无论是因为开发人员修改代码还是因为不断转换为结构化和上下文日志记录。 + +如果下游用户对特定日志有依赖性,他们需要了解此更改如何影响他们。 + + +## 进一步阅读 {#further-reading} + +- 参阅 [Kubernetes 1.24 中的上下文日志记录](https://www.kubernetes.dev/blog/2022/05/25/contextual-logging/) 。 +- 参阅 [KEP-3077:上下文日志记录](https://github.com/kubernetes/enhancements/tree/master/keps/sig-instrumentation/3077-contextual-logging)。 + + +## 如何参与 {#get-involved} + +如果你有兴趣参与,我们始终欢迎新的贡献者加入我们。上下文日志记录为你参与 +Kubernetes 开发做出贡献并产生有意义的影响提供了绝佳的机会。 +通过加入 [Structured Logging WG](https://github.com/kubernetes/community/tree/master/wg-structured-logging), +你可以积极参与 Kubernetes 的开发并做出你的第一个贡献。这是学习和参与社区并获得宝贵经验的好方法。 + + +我们鼓励你探索存储库并熟悉正在进行的讨论和项目。这是一个协作环境,你可以在这里交流想法、提出问题并与其他贡献者一起工作。 + + +如果你有任何疑问或需要指导,请随时与我们联系,你可以通过我们的[公共 Slack 频道](https://kubernetes.slack.com/messages/wg-structured-logging)联系我们。 +如果你尚未加入 Slack 工作区,可以访问 [https://slack.k8s.io/](https://slack.k8s.io/) 获取邀请。 + + +我们要向所有提供精彩评论、分享宝贵见解并协助实施此功能的贡献者表示感谢(按字母顺序排列): + +- Aldo Culquicondor ([alculquicondor](https://github.com/alculquicondor)) +- Andy Goldstein ([ncdc](https://github.com/ncdc)) +- Feruzjon Muyassarov ([fmuyassarov](https://github.com/fmuyassarov)) +- Freddie ([freddie400](https://github.com/freddie400)) +- JUN YANG ([yangjunmyfm192085](https://github.com/yangjunmyfm192085)) +- Kante Yin ([kerthcet](https://github.com/kerthcet)) +- Kiki ([carlory](https://github.com/carlory)) +- Lucas Severo Alve ([knelasevero](https://github.com/knelasevero)) +- Maciej Szulik ([soltysh](https://github.com/soltysh)) +- Mengjiao Liu ([mengjiao-liu](https://github.com/mengjiao-liu)) +- Naman Lakhwani ([Namanl2001](https://github.com/Namanl2001)) +- Oksana Baranova ([oxxenix](https://github.com/oxxenix)) +- Patrick Ohly ([pohly](https://github.com/pohly)) +- songxiao-wang87 ([songxiao-wang87](https://github.com/songxiao-wang87)) +- Tim Allclai ([tallclair](https://github.com/tallclair)) +- ZhangYu ([Octopusjust](https://github.com/Octopusjust)) +- Ziqi Zhao ([fatsheep9146](https://github.com/fatsheep9146)) +- Zac ([249043822](https://github.com/249043822)) diff --git a/content/zh-cn/blog/_posts/2024-01-23-image-filesystem.md b/content/zh-cn/blog/_posts/2024-01-23-image-filesystem.md new file mode 100644 index 0000000000000..579be8798e86c --- /dev/null +++ b/content/zh-cn/blog/_posts/2024-01-23-image-filesystem.md @@ -0,0 +1,417 @@ +--- +layout: blog +title: '镜像文件系统:配置 Kubernetes 将容器存储在独立的文件系统上' +date: 2024-01-23 +slug: kubernetes-separate-image-filesystem +--- + + + +**作者:** Kevin Hannon (Red Hat) + +**译者:** [Michael Yao](https://github.com/windsonsea) + + +磁盘空间不足是运行或操作 Kubernetes 集群时的一个常见问题。 +在制备节点时,你应该为容器镜像和正在运行的容器留足够的存储空间。 +[容器运行时](/zh-cn/docs/setup/production-environment/container-runtimes/)通常会向 `/var` 目录写入数据。 +此目录可以位于单独的分区或根文件系统上。CRI-O 默认将其容器和镜像写入 `/var/lib/containers`, +而 containerd 将其容器和镜像写入 `/var/lib/containerd`。 + + +在这篇博文中,我们想要关注的是几种不同方式,用来配置容器运行时将其内容存储到别的位置而非默认分区。 +这些配置允许我们更灵活地配置 Kubernetes,支持在保持默认文件系统不受影响的情况下为容器存储添加更大的磁盘。 + +需要额外讲述的是 Kubernetes 向磁盘在写入数据的具体位置及内容。 + + +## 了解 Kubernetes 磁盘使用情况 {#understanding-kubernetes-disk-usage} + +Kubernetes 有持久数据和临时数据。kubelet 和特定于 Kubernetes 的本地存储的基础路径是可配置的, +但通常假定为 `/var/lib/kubelet`。在 Kubernetes 文档中, +这一位置有时被称为根文件系统或节点文件系统。写入的数据可以大致分类为: + + +- 临时存储 +- 日志 +- 容器运行时 + +与大多数 POSIX 系统不同,这里的根/节点文件系统不是 `/`,而是 `/var/lib/kubelet` 所在的磁盘。 + + +### 临时存储 {#ephemeral-storage} + +Pod 和容器的某些操作可能需要临时或瞬态的本地存储。 +临时存储的生命周期短于 Pod 的生命周期,且临时存储不能被多个 Pod 共享。 + + +### 日志 {#logs} + +默认情况下,Kubernetes 将每个运行容器的日志存储为 `/var/log` 中的文件。 +这些日志是临时性质的,并由 kubelet 负责监控以确保不会在 Pod 运行时变得过大。 + +你可以为每个节点自定义[日志轮换](/zh-cn/docs/concepts/cluster-administration/logging/#log-rotation)设置, +以管控这些日志的大小,并(使用第三方解决方案)配置日志转储以避免对节点本地存储形成依赖。 + + +### 容器运行时 {#container-runtime} + +容器运行时针对容器和镜像使用两个不同的存储区域。 + +- 只读层:镜像通常被表示为只读层,因为镜像在容器处于运行状态期间不会被修改。 + 只读层可以由多个层组成,这些层组合到一起形成最终的只读层。 + 如果容器要向文件系统中写入数据,则在容器层之上会存在一个薄层为容器提供临时存储。 + + +- 可写层:取决于容器运行时的不同实现,本地写入可能会用分层写入机制来实现 + (例如 Linux 上的 `overlayfs` 或 Windows 上的 CimFS)。这一机制被称为可写层。 + 本地写入也可以使用一个可写文件系统来实现,该文件系统使用容器镜像的完整克隆来初始化; + 这种方式适用于某些基于 Hypervisor 虚拟化的运行时。 + +容器运行时文件系统包含只读层和可写层。在 Kubernetes 文档中,这一文件系统被称为 `imagefs`。 + + +## 容器运行时配置 {#container-runtime-configurations} + +### CRI-O + +CRI-O 使用 TOML 格式的存储配置文件,让你控制容器运行时如何存储持久数据和临时数据。 +CRI-O 使用了 [containers-storage 库](https://github.com/containers/storage)。 +某些 Linux 发行版为 containers-storage 提供了帮助手册条目(`man 5 containers-storage.conf`)。 +存储的主要配置位于 `/etc/containers/storage.conf` 中,你可以控制临时数据和根目录的位置。 +根目录是 CRI-O 存储持久数据的位置。 + + +```toml +[storage] +# 默认存储驱动 +driver = "overlay" +# 临时存储位置 +runroot = "/var/run/containers/storage" +# 容器存储的主要读/写位置 +graphroot = "/var/lib/containers/storage" +``` + + +- `graphroot` + - 存储来自容器运行时的持久数据 + - 如果 SELinux 被启用,则此项必须是 `/var/lib/containers/storage` +- `runroot` + - 容器的临时读/写访问 + - 建议将其放在某个临时文件系统上 + + +以下是为你的 graphroot 目录快速重新打标签以匹配 `/var/lib/containers/storage` 的方法: + +```bash +semanage fcontext -a -e /var/lib/containers/storage <你的存储路径> +restorecon -R -v <你的存储路径> +``` + + +### containerd + +containerd 运行时使用 TOML 配置文件来控制存储持久数据和临时数据的位置。 +配置文件的默认路径位于 `/etc/containerd/config.toml`。 + +与 containerd 存储的相关字段是 `root` 和 `state`。 + + +- `root` + - containerd 元数据的根目录 + - 默认为 `/var/lib/containerd` + - 如果你的操作系统要求,需要为根目录设置 SELinux 标签 +- `state` + - containerd 的临时数据 + - 默认为 `/run/containerd` + + +## Kubernetes 节点压力驱逐 {#kubernetes-node-pressure-eviction} + +Kubernetes 将自动检测容器文件系统是否与节点文件系统分离。 +当你分离文件系统时,Kubernetes 负责同时监视节点文件系统和容器运行时文件系统。 +Kubernetes 文档将节点文件系统称为 nodefs,将容器运行时文件系统称为 imagefs。 +如果 nodefs 或 imagefs 中有一个磁盘空间不足,则整个节点被视为有磁盘压力。 +这种情况下,Kubernetes 先通过删除未使用的容器和镜像来回收空间,之后会尝试驱逐 Pod。 +在同时具有 nodefs 和 imagefs 的节点上,kubelet 将在 imagefs +上对未使用的容器镜像执行[垃圾回收](/zh-cn/docs/concepts/architecture/garbage-collection/#containers-images), +并从 nodefs 中移除死掉的 Pod 及其容器。 +如果只有 nodefs,则 Kubernetes 垃圾回收将包括死掉的容器、死掉的 Pod 和未使用的镜像。 + + +Kubernetes 提供额外的配置方法来确定磁盘是否已满。kubelet 中的驱逐管理器有一些让你可以控制相关阈值的配置项。 +对于文件系统,相关测量值有 `nodefs.available`、`nodefs.inodesfree`、`imagefs.available` 和 +`imagefs.inodesfree`。如果容器运行时没有专用磁盘,则 imagefs 被忽略。 + +用户可以使用现有的默认值: + + +- `memory.available` < 100MiB +- `nodefs.available` < 10% +- `imagefs.available` < 15% +- `nodefs.inodesFree` < 5%(Linux 节点) + +Kubernetes 允许你在 kubelet 配置文件中将 `EvictionHard` 和 `EvictionSoft` 设置为用户定义的值。 + + +`EvictionHard` +: 定义限制;一旦超出这些限制,Pod 将被立即驱逐,没有任何宽限期。 + +`EvictionSoft` +: 定义限制;一旦超出这些限制,Pod 将在按各信号所设置的宽限期后被驱逐。 + + +如果你为 `EvictionHard` 指定了值,所设置的值将取代默认值。 +这意味着在你的配置中设置所有信号非常重要。 + +例如,以下 kubelet +配置可用于配置[驱逐信号](/zh-cn/docs/concepts/scheduling-eviction/node-pressure-eviction/#eviction-signals-and-thresholds)和宽限期选项。 + +```yaml +apiVersion: kubelet.config.k8s.io/v1beta1 +kind: KubeletConfiguration +address: "192.168.0.8" +port: 20250 +serializeImagePulls: false +evictionHard: + memory.available: "100Mi" + nodefs.available: "10%" + nodefs.inodesFree: "5%" + imagefs.available: "15%" + imagefs.inodesFree: "5%" +evictionSoft: + memory.available: "100Mi" + nodefs.available: "10%" + nodefs.inodesFree: "5%" + imagefs.available: "15%" + imagefs.inodesFree: "5%" +evictionSoftGracePeriod: + memory.available: "1m30s" + nodefs.available: "2m" + nodefs.inodesFree: "2m" + imagefs.available: "2m" + imagefs.inodesFree: "2m" +evictionMaxPodGracePeriod: 60s +``` + + +### 问题 {#problems} + +Kubernetes 项目建议你针对 Pod 驱逐要么使用其默认设置,要么设置与之相关的所有字段。 +你可以使用默认设置或指定你自己的 `evictionHard` 设置。 如果你漏掉一个信号,那么 Kubernetes 将不会监视该资源。 +管理员或用户可能会遇到的一个常见误配是将新的文件系统挂载到 `/var/lib/containers/storage` 或 `/var/lib/containerd`。 +Kubernetes 将检测到一个单独的文件系统,因此你要确保 `imagefs.inodesfree` 和 `imagefs.available` 符合你的需要。 + + +另一个令人困惑的地方是,如果你为节点定义了镜像文件系统,则临时存储报告不会发生变化。 +镜像文件系统(`imagefs`)用于存储容器镜像层;如果容器向自己的根文件系统写入, +那么这种本地写入不会计入容器镜像的大小。容器运行时存储这些本地修改的位置是由运行时定义的,但通常是镜像文件系统。 +如果 Pod 中的容器正在向基于文件系统的 `emptyDir` 卷写入,所写入的数据将使用 `nodefs` 文件系统的空间。 +kubelet 始终根据 `nodefs` 所表示的文件系统来报告临时存储容量和分配情况; +当临时写入操作实际上是写到镜像文件系统时,这种差别可能会让人困惑。 + + +### 后续工作 {#future-work} + +为了解决临时存储报告相关的限制并为容器运行时提供更多配置选项,SIG Node +正在处理 [KEP-4191](http://kep.k8s.io/4191)。在 KEP-4191 中, +Kubernetes 将检测可写层是否与只读层(镜像)分离。 +这种检测使我们可以将包括可写层在内的所有临时存储放在同一磁盘上,同时也可以为镜像使用单独的磁盘。 + + +### 参与其中 {#getting-involved} + +如果你想参与其中,可以加入 +[Kubernetes Node 特别兴趣小组](https://github.com/kubernetes/community/tree/master/sig-node)(SIG)。 + +如果你想分享反馈,可以分享到我们的 +[#sig-node](https://kubernetes.slack.com/archives/C0BP8PW9G) Slack 频道。 +如果你还没有加入该 Slack 工作区,可以访问 https://slack.k8s.io/ 获取邀请。 + + +特别感谢所有提供出色评审、分享宝贵见解或建议主题想法的贡献者。 + +- Peter Hunt +- Mrunal Patel +- Ryan Phillips +- Gaurav Singh diff --git a/content/zh-cn/blog/_posts/2024-03-12-mid-cycle-1.30.md b/content/zh-cn/blog/_posts/2024-03-12-mid-cycle-1.30.md new file mode 100644 index 0000000000000..e64b8023bfb63 --- /dev/null +++ b/content/zh-cn/blog/_posts/2024-03-12-mid-cycle-1.30.md @@ -0,0 +1,246 @@ +--- +layout: blog +title: 'Kubernetes v1.30 初探' +date: 2024-03-12 +slug: kubernetes-1-30-upcoming-changes +--- + + + +**作者:** Amit Dsouza, Frederick Kautz, Kristin Martin, Abigail McCarthy, Natali Vlatko + +**译者:** Paco Xu (DaoCloud) + + + +## 快速预览:Kubernetes v1.30 中令人兴奋的变化 + +新年新版本,v1.30 发布周期已过半,我们将迎来一系列有趣且令人兴奋的增强功能。 +从全新的 alpha 特性,到已有的特性升级为稳定版,再到期待已久的改进,这个版本对每个人都有值得关注的内容! + +为了让你在正式发布之前对其有所了解,下面给出我们在这个周期中最为期待的增强功能的预览! + + +## Kubernetes v1.30 的主要变化 + + +### 动态资源分配(DRA)的结构化参数 ([KEP-4381](https://kep.k8s.io/4381)) + + +[动态资源分配(DRA)](/zh-cn/docs/concepts/scheduling-eviction/dynamic-resource-allocation/) 在 Kubernetes v1.26 中作为 alpha 特性添加。 +它定义了一种替代传统设备插件 device plugin API 的方式,用于请求访问第三方资源。 +在设计上,动态资源分配(DRA)使用的资源参数对于核心 Kubernetes 完全不透明。 +这种方法对于集群自动缩放器(CA)或任何需要为一组 Pod 做决策的高级控制器(例如作业调度器)都会带来问题。 +这一设计无法模拟在不同时间分配或释放请求的效果。 +只有第三方 DRA 驱动程序才拥有信息来做到这一点。 + + +动态资源分配(DRA)的结构化参数是对原始实现的扩展,它通过构建一个框架来支持增加请求参数的透明度来解决这个问题。 +驱动程序不再需要自己处理所有请求参数的语义,而是可以使用 Kubernetes 预定义的特定“结构化模型”来管理和描述资源。 +这一设计允许了解这个“结构化规范”的组件做出关于这些资源的决策,而不再将它们外包给某些第三方控制器。 +例如,调度器可以在不与动态资源分配(DRA)驱动程序反复通信的前提下快速完成分配请求。 +这个版本的工作重点是定义一个框架来支持不同的“结构化模型”,并实现“命名资源”模型。 +此模型允许列出各个资源实例,同时,与传统的设备插件 API 相比,模型增加了通过属性逐一选择实例的能力。 + + +### 节点交换内存 SWAP 支持 ([KEP-2400](https://kep.k8s.io/2400)) + + +在 Kubernetes v1.30 中,Linux 节点上的交换内存支持机制有了重大改进,其重点是提高系统的稳定性。 +以前的 Kubernetes 版本默认情况下禁用了 `NodeSwap` 特性门控。当门控被启用时,`UnlimitedSwap` 行为被作为默认行为。 +为了提高稳定性,`UnlimitedSwap` 行为(可能会影响节点的稳定性)将在 v1.30 中被移除。 + + +更新后的 Linux 节点上的交换内存支持仍然是 beta 级别,并且默认情况下开启。 +然而,节点默认行为是使用 `NoSwap`(而不是 `UnlimitedSwap`)模式。 +在 `NoSwap` 模式下,kubelet 支持在启用了磁盘交换空间的节点上运行,但 Pod 不会使用页面文件(pagefile)。 +你仍然需要为 kubelet 设置 `--fail-swap-on=false` 才能让 kubelet 在该节点上运行。 +特性的另一个重大变化是针对另一种模式:`LimitedSwap`。 +在 `LimitedSwap` 模式下,kubelet 会实际使用节点上的页面文件,并允许 Pod 的一些虚拟内存被换页出去。 +容器(及其父 Pod)访问交换内存空间不可超出其内存限制,但系统的确可以使用可用的交换空间。 + + +Kubernetes 的 SIG Node 小组还将根据最终用户、贡献者和更广泛的 Kubernetes 社区的反馈更新文档, +以帮助你了解如何使用经过修订的实现。 + + +阅读之前的[博客文章](/zh-cn/blog/2023/08/24/swap-linux-beta/)或[交换内存管理文档](/zh-cn/docs/concepts/architecture/nodes/#swap-memory)以获取有关 +Kubernetes 中 Linux 节点交换支持的更多详细信息。 + + +### 支持 Pod 运行在用户命名空间 ([KEP-127](https://kep.k8s.io/127)) + + +[用户命名空间](/zh-cn/docs/concepts/workloads/pods/user-namespaces) 是一个仅在 Linux 上可用的特性,它更好地隔离 Pod, +以防止或减轻几个高/严重级别的 CVE,包括 2024 年 1 月发布的 [CVE-2024-21626](https://github.com/opencontainers/runc/security/advisories/GHSA-xr7r-f8xq-vfvv)。 +在 Kubernetes 1.30 中,对用户命名空间的支持正在迁移到 beta,并且现在支持带有和不带有卷的 Pod,自定义 UID/GID 范围等等! + + +### 结构化鉴权配置([KEP-3221](https://kep.k8s.io/3221)) + + +对[结构化鉴权配置](/zh-cn/docs/reference/access-authn-authz/authorization/#configuring-the-api-server-using-an-authorization-config-file)的支持正在晋级到 Beta 版本,并将默认启用。 +这个特性支持创建具有明确参数定义的多个 Webhook 所构成的鉴权链;这些 Webhook 按特定顺序验证请求, +并允许进行细粒度的控制,例如在失败时明确拒绝。 +配置文件方法甚至允许你指定 [CEL](/zh-cn/docs/reference/using-api/cel/) 规则,以在将请求分派到 Webhook 之前对其进行预过滤,帮助你防止不必要的调用。 +当配置文件被修改时,API 服务器还会自动重新加载鉴权链。 + + +你必须使用 `--authorization-config` 命令行参数指定鉴权配置的路径。 +如果你想继续使用命令行标志而不是配置文件,命令行方式没有变化。 +要访问新的 Webhook 功能,例如多 Webhook 支持、失败策略和预过滤规则,需要切换到将选项放在 `--authorization-config` 文件中。 +从 Kubernetes 1.30 开始,配置文件格式约定是 beta 级别的,只需要指定 `--authorization-config`,因为特性门控默认启用。 +[鉴权文档](/zh-cn/docs/reference/access-authn-authz/authorization/#configuring-the-api-server-using-an-authorization-config-file) +中提供了一个包含所有可能值的示例配置。 +有关更多详细信息,请阅读[鉴权文档](/zh-cn/docs/reference/access-authn-authz/authorization/#configuring-the-api-server-using-an-authorization-config-file)。 + + +### 基于容器资源指标的 Pod 自动扩缩容 ([KEP-1610](https://kep.k8s.io/1610)) + + +基于 `ContainerResource` 指标的 Pod 水平自动扩缩容将在 v1.30 中升级为稳定版。 +HorizontalPodAutoscaler 的这一新行为允许你根据各个容器的资源使用情况而不是 Pod 的聚合资源使用情况来配置自动伸缩。 +有关更多详细信息,请参阅我们的[先前文章](/zh-cn/blog/2023/05/02/hpa-container-resource-metric/), +或阅读[容器资源指标](/zh-cn/docs/tasks/run-application/horizontal-pod-autoscale/#container-resource-metrics)。 + + +### 在准入控制中使用 CEL ([KEP-3488](https://kep.k8s.io/3488)) + + +Kubernetes 为准入控制集成了 Common Expression Language (CEL) 。 +这一集成引入了一种更动态、表达能力更强的方式来判定准入请求。 +这个特性允许通过 Kubernetes API 直接定义和执行复杂的、细粒度的策略,同时增强了安全性和治理能力,而不会影响性能或灵活性。 + + +将 CEL 引入到 Kubernetes 的准入控制后,集群管理员就具有了制定复杂规则的能力, +这些规则可以根据集群的期望状态和策略来评估 API 请求的内容,而无需使用基于 Webhook 的访问控制器。 +这种控制水平对于维护集群操作的完整性、安全性和效率至关重要,使 Kubernetes 环境更加健壮,更适应各种用例和需求。 +有关使用 CEL 进行准入控制的更多信息,请参阅 [API 文档](/zh-cn/docs/reference/access-authn-authz/validating-admission-policy/)中的 ValidatingAdmissionPolicy。 + + +我们希望你和我们一样对这个版本的发布感到兴奋。请在未来几周内密切关注官方发布博客,以了解其他亮点! diff --git a/content/zh-cn/docs/concepts/architecture/cgroups.md b/content/zh-cn/docs/concepts/architecture/cgroups.md index 40c4dc6468621..45497ee1ee7dd 100644 --- a/content/zh-cn/docs/concepts/architecture/cgroups.md +++ b/content/zh-cn/docs/concepts/architecture/cgroups.md @@ -70,11 +70,11 @@ cgroup v2 对 cgroup v1 进行了多项改进,例如: 一些 Kubernetes 特性专门使用 cgroup v2 来增强资源管理和隔离。 -例如,[MemoryQoS](/blog/2021/11/26/qos-memory-resources/) 特性改进了内存 QoS 并依赖于 cgroup v2 原语。 +例如,[MemoryQoS](/zh-cn/docs/concepts/workloads/pods/pod-qos/#memory-qos-with-cgroup-v2) 特性改进了内存 QoS 并依赖于 cgroup v2 原语。 #### 未使用容器镜像的垃圾收集 {#image-maximum-age-gc} -{{< feature-state for_k8s_version="v1.29" state="alpha" >}} +{{< feature-state feature_gate_name="ImageMaximumGCAge" >}} -这是一个 Alpha 特性,不论磁盘使用情况如何,你都可以指定本地镜像未被使用的最长时间。 +这是一个 Beta 特性,不论磁盘使用情况如何,你都可以指定本地镜像未被使用的最长时间。 这是一个可以为每个节点配置的 kubelet 设置。 +这个特性不会跟踪 kubelet 重新启动后的镜像使用情况。 +如果 kubelet 被重新启动,所跟踪的镜像年龄会被重置, +导致 kubelet 在根据镜像年龄进行垃圾收集时需要等待完整的 +`ImageMaximumGCAge` 时长。 +{{< /note>}} + ## API 服务器身份 {#api-server-identity} -{{< feature-state for_k8s_version="v1.26" state="beta" >}} +{{< feature-state feature_gate_name="APIServerIdentity" >}} -{{< feature-state state="alpha" for_k8s_version="v1.28" >}} +{{< feature-state feature_gate_name="UnknownVersionInteroperabilityProxy" >}} @@ -206,14 +212,14 @@ are enabled, kubelets are only authorized to create/modify their own Node resour 正如[节点名称唯一性](#node-name-uniqueness)一节所述,当 Node 的配置需要被更新时, 一种好的做法是重新向 API 服务器注册该节点。例如,如果 kubelet 重启时其 `--node-labels` 是新的值集,但同一个 Node 名称已经被使用,则所作变更不会起作用, -因为节点标签是在 Node 注册时完成的。 +因为节点标签是在 Node 注册到 API 服务器时完成(或修改)的。 -- 如果不健康节点的比例超过 `--unhealthy-zone-threshold` (默认为 0.55), +- 如果不健康节点的比例超过 `--unhealthy-zone-threshold`(默认为 0.55), 驱逐速率将会降低。 - 如果集群较小(意即小于等于 `--large-cluster-size-threshold` 个节点 - 默认为 50), 驱逐操作将会停止。 @@ -534,7 +540,7 @@ If you want to explicitly reserve resources for non-Pod processes, see --> ## 节点拓扑 {#node-topology} -{{< feature-state state="stable" for_k8s_version="v1.27" >}} +{{< feature-state feature_gate_name="TopologyManager" >}} ## 节点体面关闭 {#graceful-node-shutdown} -{{< feature-state state="beta" for_k8s_version="v1.21" >}} +{{< feature-state feature_gate_name="GracefulNodeShutdown" >}} ### 基于 Pod 优先级的节点体面关闭 {#pod-priority-graceful-node-shutdown} -{{< feature-state state="beta" for_k8s_version="v1.24" >}} +{{< feature-state feature_gate_name="GracefulNodeShutdownBasedOnPodPriority" >}} ## 处理节点非体面关闭 {#non-graceful-node-shutdown} -{{< feature-state state="stable" for_k8s_version="v1.28" >}} +{{< feature-state feature_gate_name="NodeOutOfServiceVolumeDetach" >}} +### 存储超时强制解除挂接 {#storage-force-detach-on-timeout} + +当任何 Pod 未能在 6 分钟内被成功删除时,如果节点当时不健康, +Kubernetes 将强制解除挂接正在被卸载的卷。 +在启用了强制解除挂接卷的节点上仍在运行的所有工作负载都将导致违反 +[CSI 规范](https://github.com/container-storage-interface/spec/blob/master/spec.md#controllerunpublishvolume), +该规范指出 `ControllerUnpublishVolume` "**必须**在调用卷上的所有 `NodeUnstageVolume` +和 `NodeUnpublishVolume` 执行且成功后被调用"。在这种情况下,相关节点上的卷可能会遇到数据损坏。 + + +强制存储解除挂接行为是可选的;用户可以选择使用"非体面节点关闭"特性。 + + +可以通过在 `kube-controller-manager` 中设置 `disable-force-detach-on-timeout` +配置字段来禁用超时时存储强制解除挂接。 +禁用超时强制解除挂接特性意味着托管在不正常运行时间超过 6 分钟的节点上的卷将不会删除其关联的 +[VolumeAttachment](/zh-cn/docs/reference/kubernetes-api/config-and-storage-resources/volume-attachment-v1/)。 + + +应用此设置后,仍关联到某卷的不健康 Pod 必须通过上述[非体面节点关闭](#non-graceful-node-shutdown)过程进行恢复。 + +{{< note >}} + +- 使用[非体面节点关闭](#non-graceful-node-shutdown)过程时必须小心。 +- 偏离上述步骤可能会导致数据损坏。 +{{< /note >}} + -## 交换内存管理 {#swap-memory} +## 交换内存(swap)管理 {#swap-memory} -{{< feature-state state="beta" for_k8s_version="v1.28" >}} +{{< feature-state feature_gate_name="NodeSwap" >}} -要在节点上启用交换内存,必须启用 kubelet 的 `NodeSwap` 特性门控, +要在节点上启用交换内存,必须启用 kubelet 的 `NodeSwap` 特性门控(默认启用), 同时使用 `--fail-swap-on` 命令行参数或者将 `failSwapOn` [配置](/zh-cn/docs/reference/config-api/kubelet-config.v1beta1/)设置为 false。 +为了允许 Pod 使用交换内存,在 kubelet 配置中不应将 `swapBehavior` 设置为 `NoSwap`(默认行为)。 {{< warning >}} -用户还可以选择配置 `memorySwap.swapBehavior` 以指定节点使用交换内存的方式。例如: +用户还可以选择配置 `memorySwap.swapBehavior` 以指定节点使用交换内存的方式。例如: ```yaml memorySwap: - swapBehavior: UnlimitedSwap + swapBehavior: LimitedSwap ``` -- `UnlimitedSwap`(默认):Kubernetes 工作负载可以根据请求使用尽可能多的交换内存, - 一直到达到系统限制为止。 +- `NoSwap`(默认):Kubernetes 工作负载不会使用交换内存。 - `LimitedSwap`:Kubernetes 工作负载对交换内存的使用受到限制。 - 只有具有 Burstable QoS 的 Pod 可以使用交换空间。 + 只有具有 Burstable QoS 的 Pod 可以使用交换内存。 如果启用了特性门控但是未指定 `memorySwap` 的配置,默认情况下 kubelet 将使用与 -`UnlimitedSwap` 设置相同的行为。 +`NoSwap` 设置相同的行为。 -交换限制被配置为 `(containerMemoryRequest / nodeTotalMemory) * totalPodsSwapAvailable` 的值。 +交换内存限制被配置为 `(containerMemoryRequest / nodeTotalMemory) * totalPodsSwapAvailable` 的值。 -需要注意的是,位于 Burstable QoS Pod 中的容器可以通过将内存请求设置为与内存限制相同来选择不使用交换空间。 +需要注意的是,位于 Burstable QoS Pod 中的容器可以通过将内存请求设置为与内存限制相同来选择不使用交换内存。 以这种方式配置的容器将无法访问交换内存。 -只有 **cgroup v2** 支持交换空间,cgroup v1 不支持。 +只有 **Cgroup v2** 支持交换内存,Cgroup v1 不支持。 如需了解更多信息、协助测试和提交反馈,请参阅关于 [Kubernetes 1.28:NodeSwap 进阶至 Beta1](/zh-cn/blog/2023/08/24/swap-linux-beta/) 的博客文章、 @@ -1065,6 +1126,8 @@ Learn more about the following: * [Components](/docs/concepts/overview/components/#node-components) that make up a node. * [API definition for Node](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#node-v1-core). * [Node](https://git.k8s.io/design-proposals-archive/architecture/architecture.md#the-kubernetes-node) section of the architecture design document. +* [Cluster autoscaling](/docs/concepts/cluster-administration/cluster-autoscaling/) to + manage the number and size of nodes in your cluster. * [Taints and Tolerations](/docs/concepts/scheduling-eviction/taint-and-toleration/). * [Node Resource Managers](/docs/concepts/policy/node-resource-managers/). * [Resource Management for Windows nodes](/docs/concepts/configuration/windows-resource-management/). @@ -1076,6 +1139,8 @@ Learn more about the following: * 架构设计文档中有关 [Node](https://git.k8s.io/design-proposals-archive/architecture/architecture.md#the-kubernetes-node) 的章节。 +* [集群自动扩缩](https://git.k8s.io/design-proposals-archive/architecture/architecture.md#the-kubernetes-node) + 以管理集群中节点的数量和规模。 * [污点和容忍度](/zh-cn/docs/concepts/scheduling-eviction/taint-and-toleration/)。 * [节点资源管理器](/zh-cn/docs/concepts/policy/node-resource-managers/)。 * [Windows 节点的资源管理](/zh-cn/docs/concepts/configuration/windows-resource-management/)。 diff --git a/content/zh-cn/docs/concepts/cluster-administration/_index.md b/content/zh-cn/docs/concepts/cluster-administration/_index.md index cec70f46da945..89e39aba98bce 100644 --- a/content/zh-cn/docs/concepts/cluster-administration/_index.md +++ b/content/zh-cn/docs/concepts/cluster-administration/_index.md @@ -98,12 +98,14 @@ Before choosing a guide, here are some considerations: ## Managing a cluster * Learn how to [manage nodes](/docs/concepts/architecture/nodes/). + * Read about [cluster autoscaling](/docs/concepts/cluster-administration/cluster-autoscaling/). * Learn how to set up and manage the [resource quota](/docs/concepts/policy/resource-quotas/) for shared clusters. --> ## 管理集群 {#managing-a-cluster} * 学习如何[管理节点](/zh-cn/docs/concepts/architecture/nodes/)。 + * 阅读[集群自动扩缩](/zh-cn/docs/concepts/cluster-administration/cluster-autoscaling/)。 * 学习如何设定和管理集群共享的[资源配额](/zh-cn/docs/concepts/policy/resource-quotas/)。 diff --git a/content/zh-cn/docs/concepts/cluster-administration/addons.md b/content/zh-cn/docs/concepts/cluster-administration/addons.md index 4e8f9f96f4513..98ddf26000a65 100644 --- a/content/zh-cn/docs/concepts/cluster-administration/addons.md +++ b/content/zh-cn/docs/concepts/cluster-administration/addons.md @@ -148,7 +148,7 @@ Add-on 扩展了 Kubernetes 的功能。 * [Spiderpool](https://github.com/spidernet-io/spiderpool) is an underlay and RDMA networking solution for Kubernetes. Spiderpool is supported on bare metal, virtual machines, and public cloud environments. -* [Weave Net](https://www.weave.works/docs/net/latest/kubernetes/kube-addon/) +* [Weave Net](https://github.com/rajch/weave#using-weave-on-kubernetes) provides networking and network policy, will carry on working on both sides of a network partition, and does not require an external database. --> @@ -161,7 +161,7 @@ Add-on 扩展了 Kubernetes 的功能。 [NetworkPolicy](/zh-cn/docs/concepts/services-networking/network-policies/) API。 * [Spiderpool](https://github.com/spidernet-io/spiderpool) 为 Kubernetes 提供了下层网络和 RDMA 高速网络解决方案,兼容裸金属、虚拟机和公有云等运行环境。 -* [Weave Net](https://www.weave.works/docs/net/latest/kubernetes/kube-addon/) +* [Weave Net](https://github.com/rajch/weave#using-weave-on-kubernetes) 提供在网络分组两端参与工作的联网和网络策略,并且不需要额外的数据库。 +## 插桩 {#instrumentation} + +* [kube-state-metrics](/zh-cn/docs/concepts/cluster-administration/kube-state-metrics) + + + +Kubernetes API 中 Kubernetes 对象的状态可以被公开为指标。 +一个名为 [kube-state-metrics](https://github.com/kubernetes/kube-state-metrics) +的插件代理可以连接到 Kubernetes API 服务器并公开一个 HTTP 端点,提供集群中各个对象的状态所生成的指标。 +此代理公开了关于对象状态的各种信息,如标签和注解、启动和终止时间、对象当前所处的状态或阶段。 +例如,针对运行在 Pod 中的容器会创建一个 `kube_pod_container_info` 指标。 +其中包括容器的名称、所属的 Pod 的名称、Pod 所在的{{< glossary_tooltip text="命名空间" term_id="namespace" >}}、 +容器镜像的名称、镜像的 ID、容器规约中的镜像名称、运行中容器的 ID 和用作标签的 Pod ID。 + +{{% thirdparty-content single="true" %}} + + +有能力(例如通过 Prometheus)抓取 kube-state-metrics 端点的外部组件现在可用于实现以下使用场景。 + + +## 示例:使用来自 kube-state-metrics 的指标查询集群状态 {#example-kube-state-metrics-query-1} + +通过 kube-state-metrics 生成的系列指标有助于进一步洞察集群,因为这些指标可用于查询。 + +如果你使用 Prometheus 或其他采用相同查询语言的工具,则以下 PromQL 查询将返回未就绪的 Pod 数: + +``` +count(kube_pod_status_ready{condition="false"}) by (namespace, pod) +``` + + +## 示例:基于 kube-state-metrics 发出警报 {#example-kube-state-metrics-alert-1} + +kube-state-metrics 生成的指标还允许在集群中出现问题时发出警报。 + +如果你使用 Prometheus 或类似采用相同警报规则语言的工具,若有某些 Pod 处于 `Terminating` 状态超过 5 分钟,将触发以下警报: + +```yaml +groups: +- name: Pod state + rules: + - alert: PodsBlockedInTerminatingState + expr: count(kube_pod_deletion_timestamp) by (namespace, pod) * count(kube_pod_status_reason{reason="NodeLost"} == 0) by (namespace, pod) > 0 + for: 5m + labels: + severity: page + annotations: + summary: Pod {{$labels.namespace}}/{{$labels.pod}} blocked in Terminating state. +``` diff --git a/content/zh-cn/docs/concepts/cluster-administration/logging.md b/content/zh-cn/docs/concepts/cluster-administration/logging.md index f0258410d9d74..9e92191aec65a 100644 --- a/content/zh-cn/docs/concepts/cluster-administration/logging.md +++ b/content/zh-cn/docs/concepts/cluster-administration/logging.md @@ -166,34 +166,46 @@ kubelet 通过 Kubernetes API 的特殊功能将日志提供给客户端访问 {{< feature-state for_k8s_version="v1.21" state="stable" >}} -你可以配置 kubelet 令其自动轮转日志。 - -如果配置轮转,kubelet 负责轮转容器日志并管理日志目录结构。 +kubelet 负责轮换容器日志并管理日志目录结构。 kubelet(使用 CRI)将此信息发送到容器运行时,而运行时则将容器日志写到给定位置。 你可以使用 [kubelet 配置文件](/zh-cn/docs/reference/config-api/kubelet-config.v1beta1/)配置两个 kubelet [配置选项](/zh-cn/docs/reference/config-api/kubelet-config.v1beta1/#kubelet-config-k8s-io-v1beta1-KubeletConfiguration)、 -`containerLogMaxSize` 和 `containerLogMaxFiles`。 +`containerLogMaxSize` (默认 10Mi)和 `containerLogMaxFiles`(默认 5)。 这些设置分别允许你分别配置每个日志文件大小的最大值和每个容器允许的最大文件数。 + +为了在工作负载生成的日志量较大的集群中执行高效的日志轮换,kubelet +还提供了一种机制,基于可以执行多少并发日志轮换以及监控和轮换日志所需要的间隔来调整日志的轮换方式。 +你可以使用 [kubelet 配置文件](/zh-cn/docs/reference/config-api/kubelet-config.v1beta1/) +配置两个 kubelet [配置选项](/zh-cn/docs/tasks/administer-cluster/kubelet-config-file/): +`containerLogMaxWorkers` 和 `containerLogMonitorInterval`。 + + 当类似于基本日志示例一样运行 [`kubectl logs`](/docs/reference/generated/kubectl/kubectl-commands#logs) 时, 节点上的 kubelet 会处理请求并直接从日志文件读取。kubelet 将返回该日志文件的内容。 @@ -266,12 +278,12 @@ kubelet logs to a directory that you choose. 并使用该工具将 kubelet 日志重定向到你所选择的目录。 -kubelet 始终指示你的容器运行时将日志写入 `/var/log/pods` 中的目录。 +默认情况下,kubelet 指示你的容器运行时将日志写入 `/var/log/pods` 中的目录。 有关 `kube-log-runner` 的更多信息,请阅读[系统日志](/zh-cn/docs/concepts/cluster-administration/system-logs/#klog)。 @@ -295,7 +307,7 @@ If you want to have logs written elsewhere, you can indirectly run the kubelet via a helper tool, `kube-log-runner`, and use that tool to redirect kubelet logs to a directory that you choose. -However, the kubelet always directs your container runtime to write logs within the +However, by default, kubelet directs your container runtime to write logs within the directory `C:\var\log\pods`. For more information on `kube-log-runner`, read [System Logs](/docs/concepts/cluster-administration/system-logs/#klog). @@ -303,7 +315,7 @@ For more information on `kube-log-runner`, read [System Logs](/docs/concepts/clu 如果你想将日志写入其他地方,你可以通过辅助工具 `kube-log-runner` 间接运行 kubelet, 并使用该工具将 kubelet 日志重定向到你所选择的目录。 -但是,kubelet 总是指示你的容器运行时在目录 `C:\var\log\pods` 中写入日志。 +但是,kubelet 默认指示你的容器运行时在目录 `C:\var\log\pods` 中写入日志。 有关 `kube-log-runner` 的更多信息,请阅读[系统日志](/zh-cn/docs/concepts/cluster-administration/system-logs/#klog)。 {{% /tab %}} @@ -316,15 +328,44 @@ For Kubernetes cluster components that run in pods, these write to files inside the `/var/log` directory, bypassing the default logging mechanism (the components do not write to the systemd journal). You can use Kubernetes' storage mechanisms to map persistent storage into the container that runs the component. - -For details about etcd and its logs, view the [etcd documentation](https://etcd.io/docs/). -Again, you can use Kubernetes' storage mechanisms to map persistent storage into -the container that runs the component. --> 对于在 Pod 中运行的 Kubernetes 集群组件,其日志会写入 `/var/log` 目录中的文件, 相当于绕过默认的日志机制(组件不会写入 systemd 日志)。 你可以使用 Kubernetes 的存储机制将持久存储映射到运行该组件的容器中。 + +kubelet 允许将 Pod 日志目录从默认的 `/var/log/pods` 更改为自定义路径。 +可以通过在 kubelet 的配置文件中配置 `podLogsDir` 参数来进行此调整。 + +{{< caution >}} + +需要注意的是,默认位置 `/var/log/pods` 已使用很长一段时间,并且某些进程可能会隐式使用此路径。 +因此,更改此参数必须谨慎,并自行承担风险。 + + +另一个需要留意的问题是 kubelet 支持日志写入位置与 `/var` 位于同一磁盘上。 +否则,如果日志位于与 `/var` 不同的文件系统上,kubelet +将不会跟踪该文件系统的使用情况。如果文件系统已满,则可能会出现问题。 +{{< /caution >}} + + 有关 etcd 及其日志的详细信息,请查阅 [etcd 文档](https://etcd.io/docs/)。 同样,你可以使用 Kubernetes 的存储机制将持久存储映射到运行该组件的容器中。 @@ -343,7 +384,7 @@ Some deploy tools account for that log rotation and automate it; others leave th as your responsibility. --> 如果你部署 Kubernetes 集群组件(例如调度器)以将日志记录到从父节点共享的卷中, -则需要考虑并确保这些日志被轮转。 **Kubernetes 不管理这种日志轮转**。 +则需要考虑并确保这些日志被轮转。**Kubernetes 不管理这种日志轮转**。 你的操作系统可能会自动实现一些日志轮转。例如,如果你将目录 `/var/log` 共享到一个组件的静态 Pod 中, 则节点级日志轮转会将该目录中的文件视同为 Kubernetes 之外的组件所写入的文件。 diff --git a/content/zh-cn/docs/concepts/cluster-administration/system-logs.md b/content/zh-cn/docs/concepts/cluster-administration/system-logs.md index cabb6aea40b96..5690d77937592 100644 --- a/content/zh-cn/docs/concepts/cluster-administration/system-logs.md +++ b/content/zh-cn/docs/concepts/cluster-administration/system-logs.md @@ -207,7 +207,7 @@ second line.} --> ### 上下文日志 {#contextual-logging} -{{< feature-state for_k8s_version="v1.24" state="alpha" >}} +{{< feature-state for_k8s_version="v1.30" state="beta" >}} -目前这一特性是由 `StructuredLogging` 特性门控所控制的,默认关闭。 +对于 Kubernetes {{< skew currentVersion >}},这一特性是由 `StructuredLogging` +[特性门控](/zh-cn/docs/reference/command-line-tools-reference/feature-gates/)所控制的,默认启用。 这个基础设施是在 1.24 中被添加的,并不需要修改组件。 该 [`component-base/logs/example`](https://github.com/kubernetes/kubernetes/blob/v1.24.0-beta.0/staging/src/k8s.io/component-base/logs/example/cmd/logger.go) 命令演示了如何使用新的日志记录调用以及组件如何支持上下文日志记录。 @@ -248,15 +250,15 @@ $ go run . --help --feature-gates mapStringBool A set of key=value pairs that describe feature gates for alpha/experimental features. Options are: AllAlpha=true|false (ALPHA - default=false) AllBeta=true|false (BETA - default=false) - ContextualLogging=true|false (ALPHA - default=false) + ContextualLogging=true|false (BETA - default=true) $ go run . --feature-gates ContextualLogging=true ... -I0404 18:00:02.916429 451895 logger.go:94] "example/myname: runtime" foo="bar" duration="1m0s" -I0404 18:00:02.916447 451895 logger.go:95] "example: another runtime" foo="bar" duration="1m0s" +I0222 15:13:31.645988 197901 example.go:54] "runtime" logger="example.myname" foo="bar" duration="1m0s" +I0222 15:13:31.646007 197901 example.go:55] "another runtime" logger="example" foo="bar" duration="1h0m0s" duration="1m0s" ``` -`example` 前缀和 `foo="bar"` 会被函数的调用者添加上, +`logger` 键和 `foo="bar"` 会被函数的调用者添加上, 不需修改该函数,它就会记录 `runtime` 消息和 `duration="1m0s"` 值。 禁用上下文日志后,`WithValues` 和 `WithName` 什么都不会做, @@ -274,8 +276,8 @@ is not in the log output anymore: ```console $ go run . --feature-gates ContextualLogging=false ... -I0404 18:03:31.171945 452150 logger.go:94] "runtime" duration="1m0s" -I0404 18:03:31.171962 452150 logger.go:95] "another runtime" duration="1m0s" +I0222 15:14:40.497333 198174 example.go:54] "runtime" duration="1m0s" +I0222 15:14:40.497346 198174 example.go:55] "another runtime" duration="1h0m0s" duration="1m0s" ``` ## 日志查询 {#log-query} -{{< feature-state for_k8s_version="v1.27" state="alpha" >}} +{{< feature-state feature_gate_name="NodeLogQuery" >}} 为了帮助在节点上调试问题,Kubernetes v1.27 引入了一个特性来查看节点上当前运行服务的日志。 @@ -419,7 +421,7 @@ in the application log provider. On both operating systems, logs are also availa 在两种操作系统上,都可以通过读取 `/var/log/` 内的文件查看日志。 -假如你被授权与节点对象交互,你可以在所有节点或只是某个子集上试用此 Alpha 特性。 +假如你被授权与节点对象交互,你可以在所有节点或只是某个子集上试用此特性。 这里有一个从节点中检索 kubelet 服务日志的例子: ```shell @@ -504,10 +506,12 @@ kubectl get --raw "/api/v1/nodes/node-1.example/proxy/logs/?query=kubelet&patter * Read about [Contextual Logging](https://github.com/kubernetes/enhancements/tree/master/keps/sig-instrumentation/3077-contextual-logging) * Read about [deprecation of klog flags](https://github.com/kubernetes/enhancements/tree/master/keps/sig-instrumentation/2845-deprecate-klog-specific-flags-in-k8s-components) * Read about the [Conventions for logging severity](https://github.com/kubernetes/community/blob/master/contributors/devel/sig-instrumentation/logging.md) +* Read about [Log Query](https://kep.k8s.io/2258) --> * 阅读 [Kubernetes 日志架构](/zh-cn/docs/concepts/cluster-administration/logging/) * 阅读[结构化日志提案(英文)](https://github.com/kubernetes/enhancements/tree/master/keps/sig-instrumentation/1602-structured-logging) * 阅读[上下文日志提案(英文)](https://github.com/kubernetes/enhancements/tree/master/keps/sig-instrumentation/3077-contextual-logging) * 阅读 [klog 参数的废弃(英文)](https://github.com/kubernetes/enhancements/tree/master/keps/sig-instrumentation/2845-deprecate-klog-specific-flags-in-k8s-components) * 阅读[日志严重级别约定(英文)](https://github.com/kubernetes/community/blob/master/contributors/devel/sig-instrumentation/logging.md) +* 阅读[日志查询](https://kep.k8s.io/2258) diff --git a/content/zh-cn/docs/concepts/cluster-administration/system-metrics.md b/content/zh-cn/docs/concepts/cluster-administration/system-metrics.md index d19fe29fce376..daeef745802ea 100644 --- a/content/zh-cn/docs/concepts/cluster-administration/system-metrics.md +++ b/content/zh-cn/docs/concepts/cluster-administration/system-metrics.md @@ -369,7 +369,7 @@ allow-list: 此外,`cardinality_enforcement_unexpected_categorizations_total` 元指标记录基数执行期间意外分类的计数,即每当遇到允许列表约束不允许的标签值时。 diff --git a/content/zh-cn/docs/concepts/cluster-administration/system-traces.md b/content/zh-cn/docs/concepts/cluster-administration/system-traces.md index aefeb8e90a2ed..1e4f131f29a19 100644 --- a/content/zh-cn/docs/concepts/cluster-administration/system-traces.md +++ b/content/zh-cn/docs/concepts/cluster-administration/system-traces.md @@ -156,7 +156,7 @@ For more information about the `TracingConfiguration` struct, see --> ### kubelet 追踪 {#kubelet-traces} -{{< feature-state for_k8s_version="v1.27" state="beta" >}} +{{< feature-state feature_gate_name="KubeletTracing" >}} +### 使用 Configmap 作为环境变量 {#using-configmaps-as-environment-variables} + +使用 Configmap 在 Pod 中设置{{< glossary_tooltip text="环境变量" term_id="container-env-variables" >}}: + + +1. 对于 Pod 规约中的每个容器,为要使用的每个 ConfigMap 键添加一个环境变量到 + `env[].valueFrom.configMapKeyRef` 字段。 +2. 修改你的镜像和/或命令行,以便程序查找指定环境变量中的值。 + + +下面是一个将 ConfigMap 定义为 Pod 环境变量的示例: + +```yaml +apiVersion: v1 +kind: Pod +metadata: + name: env-configmap +spec: + containers: + - name: envars-test-container + image: nginx + env: + - name: CONFIGMAP_USERNAME + valueFrom: + configMapKeyRef: + name: myconfigmap + key: username + +``` + + +需要注意的是,Pod 中环境变量名称允许的字符范围是[有限的](/zh-cn/docs/tasks/inject-data-application/define-environment-variable-container/#using-environment-variables-inside-of-your-config)。 +如果某些变量名称不满足这些规则,则即使 Pod 可以被启动,你的容器也无法访问这些环境变量。 + diff --git a/content/zh-cn/docs/concepts/configuration/manage-resources-containers.md b/content/zh-cn/docs/concepts/configuration/manage-resources-containers.md index 68d3d738b2ad4..9bbbd602dd580 100644 --- a/content/zh-cn/docs/concepts/configuration/manage-resources-containers.md +++ b/content/zh-cn/docs/concepts/configuration/manage-resources-containers.md @@ -1094,11 +1094,11 @@ available amount is simultaneously allocated to Pods. API 服务器将扩展资源的数量限制为整数。 **有效** 数量的示例是 `3`、`3000m` 和 `3Ki`。 -**无效** 数量的示例是 `0.5` 和 `1500m`。 +**无效** 数量的示例是 `0.5` 和 `1500m`(因为 `1500m` 结果等同于 `1.5`)。 {{< note >}} -#### 非法环境变量 {#restriction-env-from-invalid} - -如果 Pod 规约中环境变量定义会被视为非法的环境变量名,这些主键将在你的容器中不可用。 -Pod 仍然可以启动。 - - -Kubernetes 添加一个 Event,其 reason 设置为 `InvalidVariableNames`,其消息将列举被略过的非法主键。 -下面的例子中展示了一个 Pod,引用的是名为 `mysecret` 的 Secret, -其中包含两个非法的主键:`1badkey` 和 `2alsobad`。 - -```shell -kubectl get events -``` - - -输出类似于: - -``` -LASTSEEN FIRSTSEEN COUNT NAME KIND SUBOBJECT TYPE REASON -0s 0s 1 dapi-test-pod Pod Warning InvalidEnvironmentVariableNames kubelet, 127.0.0.1 Keys [1badkey, 2alsobad] from the EnvFrom secret default/mysecret were skipped since they are considered invalid environment variable names. -``` +需要注意的是,Pod 中环境变量名称允许的字符范围是[有限的](/zh-cn/docs/tasks/inject-data-application/define-environment-variable-container/#using-environment-variables-inside-of-your-config)。 +如果某些变量名称不满足这些规则,则即使 Pod 是可以启动的,你的容器也无法访问这些变量。 一旦一个 Secret 或 ConfigMap 被标记为不可更改,撤销此操作或者更改 `data` -字段的内容都是 **不** 可能的。 +字段的内容都是**不**可能的。 只能删除并重新创建这个 Secret。现有的 Pod 将维持对已删除 Secret 的挂载点 -- 建议重新创建这些 Pod。 {{< /note >}} diff --git a/content/zh-cn/docs/concepts/containers/images.md b/content/zh-cn/docs/concepts/containers/images.md index ac3b849b5bed7..4389a39b0d71a 100644 --- a/content/zh-cn/docs/concepts/containers/images.md +++ b/content/zh-cn/docs/concepts/containers/images.md @@ -300,6 +300,31 @@ which is 300 seconds (5 minutes). Kubernetes 会增加每次尝试之间的延迟,直到达到编译限制,即 300 秒(5 分钟)。 + +### 基于运行时类的镜像拉取 {#image-pull-per-runtime-class} + +{{< feature-state feature_gate_name="RuntimeClassInImageCriApi" >}} + + +Kubernetes 包含了根据 Pod 的 RuntimeClass 来执行镜像拉取的 Alpha 支持。 + + +如果你启用了 `RuntimeClassInImageCriApi` [特性门控](/zh-cn/docs/reference/command-line-tools-reference/feature-gates/), +kubelet 会通过一个元组(镜像名称,运行时处理程序)而不仅仅是镜像名称或镜像摘要来引用容器镜像。 +你的{{< glossary_tooltip text="容器运行时" term_id="container-runtime" >}} +可能会根据选定的运行时处理程序调整其行为。 +基于运行时类来拉取镜像对于基于 VM 的容器(如 Windows Hyper-V 容器)会有帮助。 + diff --git a/content/zh-cn/docs/concepts/extend-kubernetes/api-extension/custom-resources.md b/content/zh-cn/docs/concepts/extend-kubernetes/api-extension/custom-resources.md index 7be515b5a03c2..1cfb815c48e89 100644 --- a/content/zh-cn/docs/concepts/extend-kubernetes/api-extension/custom-resources.md +++ b/content/zh-cn/docs/concepts/extend-kubernetes/api-extension/custom-resources.md @@ -1,5 +1,8 @@ --- title: 定制资源 +api_metadata: +- apiVersion: "apiextensions.k8s.io/v1" + kind: "CustomResourceDefinition" content_type: concept weight: 10 --- @@ -8,6 +11,9 @@ title: Custom Resources reviewers: - enisoc - deads2k +api_metadata: +- apiVersion: "apiextensions.k8s.io/v1" + kind: "CustomResourceDefinition" content_type: concept weight: 10 --> diff --git a/content/zh-cn/docs/concepts/extend-kubernetes/compute-storage-net/device-plugins.md b/content/zh-cn/docs/concepts/extend-kubernetes/compute-storage-net/device-plugins.md index d926ce6bae8db..e97e682896383 100644 --- a/content/zh-cn/docs/concepts/extend-kubernetes/compute-storage-net/device-plugins.md +++ b/content/zh-cn/docs/concepts/extend-kubernetes/compute-storage-net/device-plugins.md @@ -280,13 +280,13 @@ The general workflow of a device plugin includes the following steps: 设备管理器处理完全限定的 CDI 设备名称时, 需要为 kubelet 和 kube-apiserver 启用 `DevicePluginCDIDevices` [特性门控](/zh-cn/docs/reference/command-line-tools-reference/feature-gates/)。 - 这在 Kubernetes v1.28 版本中作为 Alpha 特性被加入。 + 在 Kubernetes v1.28 版本中作为 Alpha 特性被加入,并在 v1.29 版本中升级为 Beta 特性。 {{< /note >}} 下面是一些设备插件实现的示例: -* [AMD GPU 设备插件](https://github.com/RadeonOpenCompute/k8s-device-plugin) +* [AMD GPU 设备插件](https://github.com/ROCm/k8s-device-plugin) * 适用于通用 Linux 设备和 USB 设备的[通用设备插件](https://github.com/squat/generic-device-plugin) * [Intel 设备插件](https://github.com/intel/intel-device-plugins-for-kubernetes)支持 Intel GPU、FPGA、QAT、VPU、SGX、DSA、DLB 和 IAA 设备 diff --git a/content/zh-cn/docs/concepts/overview/_index.md b/content/zh-cn/docs/concepts/overview/_index.md index 356defdfeaf44..1064fba93c4ed 100644 --- a/content/zh-cn/docs/concepts/overview/_index.md +++ b/content/zh-cn/docs/concepts/overview/_index.md @@ -53,7 +53,7 @@ Kubernetes project in 2014. Kubernetes combines [over 15 years of Google's experience](/blog/2015/04/borg-predecessor-to-kubernetes/) running production workloads at scale with best-of-breed ideas and practices from the community. --> -**Kubernetes** 这个名字源于希腊语,意为“舵手”或“飞行员”。k8s 这个缩写是因为 k 和 s 之间有八个字符的关系。 +**Kubernetes** 这个名字源于希腊语,意为“舵手”或“飞行员”。K8s 这个缩写是因为 K 和 s 之间有 8 个字符的关系。 Google 在 2014 年开源了 Kubernetes 项目。 Kubernetes 建立在 [Google 大规模运行生产工作负载十几年经验](https://research.google/pubs/pub43438)的基础上, 结合了社区中最优秀的想法和实践。 diff --git a/content/zh-cn/docs/concepts/overview/components.md b/content/zh-cn/docs/concepts/overview/components.md index 059947e521170..da682a83c2113 100644 --- a/content/zh-cn/docs/concepts/overview/components.md +++ b/content/zh-cn/docs/concepts/overview/components.md @@ -25,6 +25,7 @@ card: --> + ## 控制平面组件(Control Plane Components) {#control-plane-components} 控制平面组件会为集群做出全局决策,比如资源的调度。 -以及检测和响应集群事件,例如当不满足部署的 `replicas` 字段时, -要启动新的 {{< glossary_tooltip text="pod" term_id="pod">}})。 +以及检测和响应集群事件,例如当不满足部署的 `{{< glossary_tooltip text="replicas" term_id="replica" >}}` +字段时,要启动新的 {{< glossary_tooltip text="Pod" term_id="pod">}})。 @@ -206,7 +212,9 @@ Kubernetes 启动的容器自动将此 DNS 服务器包含在其 DNS 搜索列 ### Web 界面(仪表盘) {#web-ui-dashboard} @@ -218,7 +226,8 @@ Kubernetes 启动的容器自动将此 DNS 服务器包含在其 DNS 搜索列 ### 容器资源监控 {#container-resource-monitoring} @@ -254,7 +263,8 @@ allocating IP addresses to pods and enabling them to communicate with each other 大部分操作都可以通过 [kubectl](/zh-cn/docs/reference/kubectl/) 命令行接口或类似 [kubeadm](/zh-cn/docs/reference/setup-tools/kubeadm/) 这类命令行工具来执行, 这些工具在背后也是调用 API。不过,你也可以使用 REST 调用来访问这些 API。 +Kubernetes 为那些希望使用 Kubernetes API +编写应用的开发者提供一组[客户端库](/zh-cn/docs/reference/using-api/client-libraries/)。 + + +每个 Kubernetes 集群都会发布集群所使用的 API 规范。 +Kubernetes 使用两种机制来发布这些 API 规范;这两种机制都有助于实现自动互操作。 +例如,`kubectl` 工具获取并缓存 API 规范,以实现命令行补全和其他特性。所支持的两种机制如下: + + +- [发现 API](#discovery-api) 提供有关 Kubernetes API 的信息:API 名称、资源、版本和支持的操作。 + 此 API 是特定于 Kubernetes 的一个术语,因为它是一个独立于 Kubernetes OpenAPI 的 API。 + 其目的是为可用的资源提供简要总结,不详细说明资源的具体模式。有关资源模式的参考,请参阅 OpenAPI 文档。 + + +- [Kubernetes OpenAPI 文档](#openapi-interface-definition)为所有 Kubernetes API 端点提供(完整的) + [OpenAPI v2.0 和 v3.0 模式](https://www.openapis.org/)。OpenAPI v3 是访问 OpenAPI 的首选方法, + 因为它提供了更全面和准确的 API 视图。其中包括所有可用的 API 路径,以及每个端点上每个操作所接收和生成的所有资源。 + 它还包括集群支持的所有可扩展组件。这些数据是完整的规范,比 Discovery API 提供的规范要大得多。 + + +## Discovery API + +Kubernetes 通过 Discovery API 发布集群所支持的所有组版本和资源列表。对于每个资源,包括以下内容: + + +- 名称 +- 集群作用域还是名字空间作用域 +- 端点 URL 和所支持的动词 +- 别名 +- 组、版本、类别 + + +API 以聚合和非聚合形式提供。聚合的发现提供两个端点,而非聚合的发现为每个组版本提供单独的端点。 + + +### 聚合的发现 {#aggregated-discovery} + +{{< feature-state state="beta" for_k8s_version="v1.27" >}} + + +Kubernetes 为聚合的发现提供了 Beta 支持,通过两个端点(`/api` 和 `/apis`)发布集群所支持的所有资源。 +请求这个端点会大大减少从集群获取发现数据时发送的请求数量。你可以通过带有 +`Accept` 头(`Accept: application/json;v=v2beta1;g=apidiscovery.k8s.io;as=APIGroupDiscoveryList`) +的请求发送到不同端点,来指明聚合发现的资源。 + + +如果没有使用 `Accept` 头指示资源类型,对于 `/api` 和 `/apis` 端点的默认响应将是一个非聚合的发现文档。 + + +内置资源的[发现文档](https://github.com/kubernetes/kubernetes/blob/release-{{< skew currentVersion >}}/api/discovery/aggregated_v2beta1.json)可以在 +Kubernetes GitHub 代码仓库中找到。如果手头没有 Kubernetes 集群可供查询, +此 Github 文档可用作可用资源的基础集合的参考。端点还支持 ETag 和 protobuf 编码。 + + +### 非聚合的发现 {#unaggregated-discovery} + +在不使用聚合发现的情况下,发现 API 以不同级别发布,同时根端点为下游文档发布发现信息。 + +集群支持的所有组版本列表发布在 `/api` 和 `/apis` 端点。例如: + +``` +{ + "kind": "APIGroupList", + "apiVersion": "v1", + "groups": [ + { + "name": "apiregistration.k8s.io", + "versions": [ + { + "groupVersion": "apiregistration.k8s.io/v1", + "version": "v1" + } + ], + "preferredVersion": { + "groupVersion": "apiregistration.k8s.io/v1", + "version": "v1" + } + }, + { + "name": "apps", + "versions": [ + { + "groupVersion": "apps/v1", + "version": "v1" + } + ], + "preferredVersion": { + "groupVersion": "apps/v1", + "version": "v1" + } + }, + ... +} +``` -如果你正在编写程序来访问 Kubernetes API, -可以考虑使用[客户端库](/zh-cn/docs/reference/using-api/client-libraries/)之一。 + +用户需要发出额外的请求才能在 `/apis//`(例如 `/apis/rbac.authorization.k8s.io/v1alpha1`) +获取每个组版本的发现文档。这些发现文档会公布在特定组版本下所提供的资源列表。 +kubectl 使用这些端点来获取某集群所支持的资源列表。 + + +## OpenAPI 接口定义 {#openapi-interface-definition} + +有关 OpenAPI 规范的细节,参阅 [OpenAPI 文档](https://www.openapis.org/)。 + +Kubernetes 同时提供 OpenAPI v2.0 和 OpenAPI v3.0。OpenAPI v3 是访问 OpenAPI 的首选方法, +因为它提供了对 Kubernetes 资源更全面(无损)的表示。由于 OpenAPI v2 的限制, +所公布的 OpenAPI 中会丢弃掉一些字段,包括但不限于 `default`、`nullable`、`oneOf`。 + + -## OpenAPI 规范 {#api-specification} - -完整的 API 细节是用 [OpenAPI](https://www.openapis.org/) 来表述的。 - ### OpenAPI v2 Kubernetes API 服务器通过 `/openapi/v2` 端点提供聚合的 OpenAPI v2 规范。 @@ -144,21 +327,9 @@ Kubernetes API 服务器通过 `/openapi/v2` 端点提供聚合的 OpenAPI v2 - -Kubernetes 为 API 实现了一种基于 Protobuf 的序列化格式,主要用于集群内部通信。 -关于此格式的详细信息,可参考 -[Kubernetes Protobuf 序列化](https://git.k8s.io/design-proposals-archive/api-machinery/protobuf.md)设计提案。 -每种模式对应的接口描述语言(IDL)位于定义 API 对象的 Go 包中。 - ### OpenAPI v3 -{{< feature-state state="stable" for_k8s_version="v1.27" >}} +{{< feature-state feature_gate_name="OpenAPIV3" >}} +[`k8s.io/client-go/openapi3`](https://pkg.go.dev/k8s.io/client-go/openapi3) +包中提供了获取 OpenAPI v3 的 Golang 实现。 + +Kubernetes {{< skew currentVersion >}} 发布了 OpenAPI v2.0 和 v3.0; +近期没有支持 v3.1 的计划。 + + -`k8s.io/client-go/openapi3` 包中提供了获取 OpenAPI v3 的 Golang 实现。 +### Protobuf 序列化 {#protobuf-serialization} + +Kubernetes 为 API 实现了一种基于 Protobuf 的序列化格式,主要用于集群内部通信。 +关于此格式的详细信息,可参考 +[Kubernetes Protobuf 序列化](https://git.k8s.io/design-proposals-archive/api-machinery/protobuf.md)设计提案。 +每种模式对应的接口描述语言(IDL)位于定义 API 对象的 Go 包中。 +RFC 1035 和 RFC 1123 标签标准之间的唯一区别是 RFC 1123 +标签允许以数字开头,而 RFC 1035 标签只能以小写字母字符开头。 +{{< /note >}} + * 进一步了解 Kubernetes [标签](/zh-cn/docs/concepts/overview/working-with-objects/labels/)和[注解](/zh-cn/docs/concepts/overview/working-with-objects/annotations/)。 -* 参阅 [Kubernetes 标识符和名称](https://git.k8s.io/design-proposals-archive/architecture/identifiers.md)的设计文档 +* 参阅 [Kubernetes 标识符和名称](https://git.k8s.io/design-proposals-archive/architecture/identifiers.md)的设计文档。 diff --git a/content/zh-cn/docs/concepts/overview/working-with-objects/namespaces.md b/content/zh-cn/docs/concepts/overview/working-with-objects/namespaces.md index 2b288fc5e36b1..fd41642eab192 100644 --- a/content/zh-cn/docs/concepts/overview/working-with-objects/namespaces.md +++ b/content/zh-cn/docs/concepts/overview/working-with-objects/namespaces.md @@ -1,5 +1,8 @@ --- title: 名字空间 +api_metadata: +- apiVersion: "v1" + kind: "Namespace" content_type: concept weight: 45 --- @@ -9,6 +12,9 @@ reviewers: - mikedanese - thockin title: Namespaces +api_metadata: +- apiVersion: "v1" + kind: "Namespace" content_type: concept weight: 45 --> @@ -16,7 +22,7 @@ weight: 45 在 Kubernetes 中,**名字空间(Namespace)** 提供一种机制,将同一集群中的资源划分为相互隔离的组。 同一名字空间内的资源名称要唯一,但跨名字空间时没有这个要求。 diff --git a/content/zh-cn/docs/concepts/policy/limit-range.md b/content/zh-cn/docs/concepts/policy/limit-range.md index a03811ecb7cde..f2e19bde68435 100644 --- a/content/zh-cn/docs/concepts/policy/limit-range.md +++ b/content/zh-cn/docs/concepts/policy/limit-range.md @@ -78,7 +78,7 @@ LimitRange 的名称必须是合法的 - 管理员在一个命名空间内创建一个 `LimitRange` 对象。 - 用户在此命名空间内创建(或尝试创建) Pod 和 PersistentVolumeClaim 等对象。 -- 首先,`LimitRanger` 准入控制器对所有没有设置计算资源需求的所有 Pod(及其容器)设置默认请求值与限制值。 +- 首先,`LimitRange` 准入控制器对所有没有设置计算资源需求的所有 Pod(及其容器)设置默认请求值与限制值。 - 其次,`LimitRange` 跟踪其使用量以保证没有超出命名空间中存在的任意 `LimitRange` 所定义的最小、最大资源使用量以及使用量比值。 - 若尝试创建或更新的对象(Pod 和 PersistentVolumeClaim)违反了 `LimitRange` 的约束, 向 API 服务器的请求会失败,并返回 HTTP 状态码 `403 Forbidden` 以及描述哪一项约束被违反的消息。 diff --git a/content/zh-cn/docs/concepts/policy/resource-quotas.md b/content/zh-cn/docs/concepts/policy/resource-quotas.md index 2e12306c11bfc..561f72c596abe 100644 --- a/content/zh-cn/docs/concepts/policy/resource-quotas.md +++ b/content/zh-cn/docs/concepts/policy/resource-quotas.md @@ -1,5 +1,8 @@ --- title: 资源配额 +api_metadata: +- apiVersion: "v1" + kind: "ResourceQuota" content_type: concept weight: 20 --- @@ -8,6 +11,9 @@ weight: 20 reviewers: - derekwaynecarr title: Resource Quotas +api_metadata: +- apiVersion: "v1" + kind: "ResourceQuota" content_type: concept weight: 20 --> diff --git a/content/zh-cn/docs/concepts/scheduling-eviction/assign-pod-node.md b/content/zh-cn/docs/concepts/scheduling-eviction/assign-pod-node.md index aaae90cd6c604..ecce2ff2ee223 100644 --- a/content/zh-cn/docs/concepts/scheduling-eviction/assign-pod-node.md +++ b/content/zh-cn/docs/concepts/scheduling-eviction/assign-pod-node.md @@ -29,7 +29,7 @@ the Pod deploys to, for example, to ensure that a Pod ends up on a node with an or to co-locate Pods from two different services that communicate a lot into the same availability zone. --> 你可以约束一个 {{< glossary_tooltip text="Pod" term_id="pod" >}} -以便 **限制** 其只能在特定的{{< glossary_tooltip text="节点" term_id="node" >}}上运行, +以便**限制**其只能在特定的{{< glossary_tooltip text="节点" term_id="node" >}}上运行, 或优先在特定的节点上运行。有几种方法可以实现这点,推荐的方法都是用 [标签选择算符](/zh-cn/docs/concepts/overview/working-with-objects/labels/)来进行选择。 通常这样的约束不是必须的,因为调度器将自动进行合理的放置(比如,将 Pod 分散到节点上, @@ -278,7 +278,7 @@ to repel Pods from specific nodes. If you specify both `nodeSelector` and `nodeAffinity`, *both* must be satisfied for the Pod to be scheduled onto a node. --> -如果你同时指定了 `nodeSelector` 和 `nodeAffinity`,**两者** 必须都要满足, +如果你同时指定了 `nodeSelector` 和 `nodeAffinity`,**两者**必须都要满足, 才能将 Pod 调度到候选节点上。 @@ -483,7 +483,7 @@ Pod 间亲和性和反亲和性都需要相当的计算量,因此会在大规 {{< note >}} -亲和性规则规定,只有节点属于特定的 -[区域](/zh-cn/docs/concepts/scheduling-eviction/topology-spread-constraints/topology-spread-constraints/) +亲和性规则规定,只有节点属于特定的[区域](/zh-cn/docs/concepts/scheduling-eviction/topology-spread-constraints/) 且该区域中的其他 Pod 已打上 `security=S1` 标签时,调度器才可以将示例 Pod 调度到此节点上。 例如,如果我们有一个具有指定区域(称之为 "Zone V")的集群,此区域由带有 `topology.kubernetes.io/zone=V` 标签的节点组成,那么只要 Zone V 内已经至少有一个 Pod 打了 `security=S1` 标签, @@ -585,17 +584,16 @@ labels in Zone V, the scheduler will not assign the example Pod to any node in t 则调度器不会将示例 Pod 调度给该区域中的任何节点。 -反亲和性规则规定,如果节点属于特定的 -[区域](/zh-cn/docs/concepts/scheduling-eviction/topology-spread-constraints/topology-spread-constraints/) +反亲和性规则规定,如果节点属于特定的[区域](/zh-cn/docs/concepts/scheduling-eviction/topology-spread-constraints/) 且该区域中的其他 Pod 已打上 `security=S2` 标签,则调度器应尝试避免将 Pod 调度到此节点上。 例如,如果我们有一个具有指定区域(我们称之为 "Zone R")的集群,此区域由带有 `topology.kubernetes.io/zone=R` 标签的节点组成,只要 Zone R 内已经至少有一个 Pod 打了 `security=S2` 标签, @@ -676,6 +674,178 @@ null `namespaceSelector` matches the namespace of the Pod where the rule is defi 注意,空的 `namespaceSelector`(`{}`)会匹配所有名字空间,而 null 或者空的 `namespaces` 列表以及 null 值 `namespaceSelector` 意味着“当前 Pod 的名字空间”。 +#### matchLabelKeys + +{{< feature-state feature_gate_name="MatchLabelKeysInPodAffinity" >}} + +{{< note >}} + + +`matchLabelKeys` 字段是一个 Alpha 级别的字段,在 Kubernetes {{< skew currentVersion >}} 中默认被禁用。 +当你想要使用此字段时,你必须通过 `MatchLabelKeysInPodAffinity` +[特性门控](/zh-cn/docs/reference/command-line-tools-reference/feature-gates/)启用它。 +{{< /note >}} + + +Kubernetes 在 Pod 亲和性或反亲和性中包含一个可选的 `matchLabelKeys` 字段。 +此字段指定了应与传入 Pod 的标签匹配的标签键,以满足 Pod 的(反)亲和性。 + +这些键用于从 Pod 的标签中查找值;这些键值标签与使用 `labelSelector` 字段定义的匹配限制组合(使用 `AND` 操作)。 +这种组合的过滤机制选择将用于 Pod(反)亲和性计算的现有 Pod 集合。 + + +一个常见的用例是在 `matchLabelKeys` 中使用 `pod-template-hash` +(设置在作为 Deployment 的一部分进行管理的 Pod 上,其中每个版本的值是唯一的)。 +在 `matchLabelKeys` 中使用 `pod-template-hash` 允许你定位与传入 Pod 相同版本的 Pod, +确保滚动升级不会破坏亲和性。 + + +```yaml +apiVersion: apps/v1 +kind: Deployment +metadata: + name: application-server +... +spec: + template: + spec: + affinity: + podAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + - labelSelector: + matchExpressions: + - key: app + operator: In + values: + - database + topologyKey: topology.kubernetes.io/zone + # 只有在计算 Pod 亲和性时,才考虑指定上线的 Pod。 + # 如果你更新 Deployment,替代的 Pod 将遵循它们自己的亲和性规则 + # (如果在新的 Pod 模板中定义了任何规则)。 + matchLabelKeys: + - pod-template-hash +``` + +#### mismatchLabelKeys + +{{< feature-state feature_gate_name="MatchLabelKeysInPodAffinity" >}} + +{{< note >}} + + +`mismatchLabelKeys` 字段是一个 Alpha 级别的字段,在 Kubernetes {{< skew currentVersion >}} 中默认被禁用。 +当你想要使用此字段时,你必须通过 `MatchLabelKeysInPodAffinity` +[特性门控](/zh-cn/docs/reference/command-line-tools-reference/feature-gates/)启用它。 +{{< /note >}} + + +Kubernetes 为 Pod 亲和性或反亲和性提供了一个可选的 `mismatchLabelKeys` 字段。 +此字段指定了在满足 Pod(反)亲和性时,**不**应与传入 Pod 的标签匹配的键。 + +一个示例用例是确保 Pod 进入指定的拓扑域(节点、区域等),在此拓扑域中只调度来自同一租户或团队的 Pod。 +换句话说,你想要避免在同一拓扑域中同时运行来自两个不同租户的 Pod。 + + +```yaml +apiVersion: v1 +kind: Pod +metadata: + labels: + # 假设所有相关的 Pod 都设置了 “tenant” 标签 + tenant: tenant-a +... +spec: + affinity: + podAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + # 确保与此租户关联的 Pod 落在正确的节点池上 + - matchLabelKeys: + - tenant + topologyKey: node-pool + podAntiAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + # 确保与此租户关联的 Pod 不能调度到用于其他租户的节点上 + - mismatchLabelKeys: + - tenant # 无论此 Pod 的 “tenant” 标签的值是什么, + # 如果节点池中有来自别的租户的任何 Pod 在运行, + # 都会阻碍此 Pod 被调度到这些节点池中的节点上 + labelSelector: + # 我们必须有一个 labelSelector,只选择具有 “tenant” 标签的 Pod, + # 否则此 Pod 也会与来自 DaemonSet 的 Pod 发生冲突, + # 而这些 Pod 不应该具有 “tenant” 标签 + matchExpressions: + - key: tenant + operator: Exists + topologyKey: node-pool +``` + -总体效果是每个缓存实例都非常可能被在同一个节点上运行的某个客户端访问。 +总体效果是每个缓存实例都非常可能被在同一个节点上运行的某个客户端访问, 这种方法旨在最大限度地减少偏差(负载不平衡)和延迟。 `nodeName` 旨在供自定义调度器或需要绕过任何已配置调度器的高级场景使用。 如果已分配的 Node 负载过重,绕过调度器可能会导致 Pod 失败。 你可以使用[节点亲和性](#node-affinity)或 [`nodeselector` 字段](#nodeselector)将 Pod 分配给特定 Node,而无需绕过调度器。 -{{}} +{{}} | 操作符 | 行为 | @@ -952,8 +1123,8 @@ The following operators can only be used with `nodeAffinity`. {{}} `Gt` 和 `Lt` 操作符不能与非整数值一起使用。 @@ -973,9 +1144,8 @@ are not available for `podAffinity`. - Learn how to use [affinity and anti-affinity](/docs/tasks/configure-pod-container/assign-pods-nodes-using-node-affinity/). --> - 进一步阅读[污点与容忍度](/zh-cn/docs/concepts/scheduling-eviction/taint-and-toleration/)文档。 -- 阅读[节点亲和性](https://git.k8s.io/design-proposals-archive/scheduling/nodeaffinity.md) - 和 [Pod 间亲和性与反亲和性](https://git.k8s.io/design-proposals-archive/scheduling/podaffinity.md) - 的设计文档。 +- 阅读[节点亲和性](https://git.k8s.io/design-proposals-archive/scheduling/nodeaffinity.md)和 + [Pod 间亲和性与反亲和性](https://git.k8s.io/design-proposals-archive/scheduling/podaffinity.md)的设计文档。 - 了解[拓扑管理器](/zh-cn/docs/tasks/administer-cluster/topology-manager/)如何参与节点层面资源分配决定。 - 了解如何使用 [nodeSelector](/zh-cn/docs/tasks/configure-pod-container/assign-pods-nodes/)。 -* 了解如何使用[亲和性和反亲和性](/zh-cn/docs/tasks/configure-pod-container/assign-pods-nodes-using-node-affinity/)。 +- 了解如何使用[亲和性和反亲和性](/zh-cn/docs/tasks/configure-pod-container/assign-pods-nodes-using-node-affinity/)。 diff --git a/content/zh-cn/docs/concepts/scheduling-eviction/dynamic-resource-allocation.md b/content/zh-cn/docs/concepts/scheduling-eviction/dynamic-resource-allocation.md index 705f7c789c1e5..1dced79b9c913 100644 --- a/content/zh-cn/docs/concepts/scheduling-eviction/dynamic-resource-allocation.md +++ b/content/zh-cn/docs/concepts/scheduling-eviction/dynamic-resource-allocation.md @@ -63,14 +63,14 @@ ResourceClass driver. ResourceClaim -: Defines a particular resource instances that is required by a +: Defines a particular resource instance that is required by a workload. Created by a user (lifecycle managed manually, can be shared between different Pods) or for individual Pods by the control plane based on a ResourceClaimTemplate (automatic lifecycle, typically used by just one Pod). ResourceClaimTemplate -: Defines the spec and some meta data for creating +: Defines the spec and some metadata for creating ResourceClaims. Created by a user when deploying a workload. PodSchedulingContext @@ -350,7 +350,7 @@ kube-scheduler, kube-controller-manager and kubelet also need the feature gate. --> 动态资源分配是一个 **Alpha 特性**,只有在启用 `DynamicResourceAllocation` [特性门控](/zh-cn/docs/reference/command-line-tools-reference/feature-gates/) -和 `resource.k8s.io/v1alpha1` +和 `resource.k8s.io/v1alpha2` {{< glossary_tooltip text="API 组" term_id="api-group" >}} 时才启用。 有关详细信息,参阅 `--feature-gates` 和 `--runtime-config` [kube-apiserver 参数](/zh-cn/docs/reference/command-line-tools-reference/kube-apiserver/)。 diff --git a/content/zh-cn/docs/concepts/scheduling-eviction/kube-scheduler.md b/content/zh-cn/docs/concepts/scheduling-eviction/kube-scheduler.md index b419e20f5d030..54f3307ecf2c5 100644 --- a/content/zh-cn/docs/concepts/scheduling-eviction/kube-scheduler.md +++ b/content/zh-cn/docs/concepts/scheduling-eviction/kube-scheduler.md @@ -122,7 +122,7 @@ kube-scheduler 给一个 Pod 做调度选择时包含两个步骤: kubelet 具有以下默认硬驱逐条件: @@ -331,10 +332,11 @@ kubelet 具有以下默认硬驱逐条件: - `nodefs.available<10%` - `imagefs.available<15%` - `nodefs.inodesFree<5%`(Linux 节点) +- `imagefs.inodesFree<5%` (Linux 节点) -## 使用示例 +## 使用示例 {#usage-example} 要使用 Pod 开销,你需要一个定义了 `overhead` 字段的 RuntimeClass。 -作为例子,下面的 RuntimeClass 定义中包含一个虚拟化所用的容器运行时, -RuntimeClass 如下,其中每个 Pod 大约使用 120MiB 用来运行虚拟机和寄宿操作系统: +例如,你可以使用以下 RuntimeClass 定义,其中使用了一个虚拟化容器运行时(在这个例子中,Kata Containers 与 Firecracker 虚拟机监视器结合使用), +每个 Pod 使用大约 120MiB 的虚拟机和寄宿操作系统: + + ```yaml +# 你需要修改这个示例以匹配实际的运行时名称, +# 以及在你的集群中运行时在 Pod 层面增加的资源开销。 apiVersion: node.k8s.io/v1 kind: RuntimeClass metadata: @@ -234,7 +253,7 @@ The output shows requests for 2250m CPU, and for 320MiB of memory. The requests -## 验证 Pod cgroup 限制 +## 验证 Pod cgroup 限制 {#verify-pod-cgroup-limits} -### 可观察性 +### 可观察性 {#observability} ### Pod 优先级对调度顺序的影响 {#effect-of-pod-priority-on-scheduling-order} @@ -329,7 +329,7 @@ Pod 被创建后会进入队列等待调度。 ### User exposed information When Pod P preempts one or more Pods on Node N, `nominatedNodeName` field of Pod -P's status is set to the name of Node N. This field helps scheduler track +P's status is set to the name of Node N. This field helps the scheduler track resources reserved for Pod P and also gives users information about preemptions in their clusters. @@ -339,8 +339,8 @@ After victim Pods are preempted, they get their graceful termination period. If another node becomes available while scheduler is waiting for the victim Pods to terminate, scheduler may use the other node to schedule Pod P. As a result `nominatedNodeName` and `nodeName` of Pod spec are not always the same. Also, if -scheduler preempts Pods on Node N, but then a higher priority Pod than Pod P -arrives, scheduler may give Node N to the new higher priority Pod. In such a +the scheduler preempts Pods on Node N, but then a higher priority Pod than Pod P +arrives, the scheduler may give Node N to the new higher priority Pod. In such a case, scheduler clears `nominatedNodeName` of Pod P. By doing this, scheduler makes Pod P eligible to preempt Pods on another Node. --> @@ -502,7 +502,7 @@ enough demand and if we find an algorithm with reasonable performance. ## 故障排除 {#troubleshooting} diff --git a/content/zh-cn/docs/concepts/scheduling-eviction/pod-scheduling-readiness.md b/content/zh-cn/docs/concepts/scheduling-eviction/pod-scheduling-readiness.md index 1df056b6c7827..b79fb7c425643 100644 --- a/content/zh-cn/docs/concepts/scheduling-eviction/pod-scheduling-readiness.md +++ b/content/zh-cn/docs/concepts/scheduling-eviction/pod-scheduling-readiness.md @@ -11,11 +11,11 @@ weight: 40 -{{< feature-state for_k8s_version="v1.27" state="beta" >}} +{{< feature-state for_k8s_version="v1.30" state="stable" >}} 要通知调度程序此 Pod 已准备好进行调度,你可以通过重新应用修改后的清单来完全删除其 `schedulingGates`: @@ -130,7 +130,7 @@ transited from previous `SchedulingGated` to `Running`: `SchedulingGated` 转变为 `Running`: ```none -NAME READY STATUS RESTARTS AGE IP NODE +NAME READY STATUS RESTARTS AGE IP NODE test-pod 1/1 Running 0 15s 10.0.0.4 node-2 ``` @@ -148,16 +148,14 @@ scheduling. You can use `scheduler_pending_pods{queue="gated"}` to check the met 你可以使用 `scheduler_pending_pods{queue="gated"}` 来检查指标结果。 ## 可变 Pod 调度指令 {#mutable-pod-scheduling-directives} -{{< feature-state for_k8s_version="v1.27" state="beta" >}} - 当 Pod 具有调度门控时,你可以在某些约束条件下改变 Pod 的调度指令。 @@ -180,7 +178,7 @@ Pod 只能被调度到它之前匹配的节点子集上。 or `fieldExpressions` are allowed, and no changes to existing `matchExpressions` and `fieldExpressions` will be allowed. This is because the terms in `.requiredDuringSchedulingIgnoredDuringExecution.NodeSelectorTerms`, are ORed - while the expressions in `nodeSelectorTerms[].matchExpressions` and + while the expressions in `nodeSelectorTerms[].matchExpressions` and `nodeSelectorTerms[].fieldExpressions` are ANDed. --> 3. 如果 `NodeSelectorTerms` 之前为空,则允许设置该字段。 diff --git a/content/zh-cn/docs/concepts/scheduling-eviction/resource-bin-packing.md b/content/zh-cn/docs/concepts/scheduling-eviction/resource-bin-packing.md index bf47d6b5569e8..44ac338c38493 100644 --- a/content/zh-cn/docs/concepts/scheduling-eviction/resource-bin-packing.md +++ b/content/zh-cn/docs/concepts/scheduling-eviction/resource-bin-packing.md @@ -84,8 +84,8 @@ Within the `scoringStrategy` field, you can configure two parameters: `requested `resources`. The `shape` in the `requestedToCapacityRatio` parameter allows the user to tune the function as least requested or most requested based on `utilization` and `score` values. The `resources` parameter -consists of `name` of the resource to be considered during scoring and `weight` -specify the weight of each resource. +comprises both the `name` of the resource to be considered during scoring and +its corresponding `weight`, which specifies the weight of each resource. --> ## 使用 RequestedToCapacityRatio 策略来启用资源装箱 {#enabling-bin-packing-using-requestedtocapacityratio} @@ -97,7 +97,8 @@ specify the weight of each resource. 字段来控制。在 `scoringStrategy` 字段中,你可以配置两个参数: `requestedToCapacityRatio` 和 `resources`。`requestedToCapacityRatio` 参数中的 `shape` 设置使得用户能够调整函数的算法,基于 `utilization` 和 `score` 值计算最少请求或最多请求。 -`resources` 参数中包含计分过程中需要考虑的资源的 `name`,以及用来设置每种资源权重的 `weight`。 +`resources` 参数中包含计分过程中需要考虑的资源的 `name`,以及对应的 `weight`, +后者指定了每个资源的权重。 diff --git a/content/zh-cn/docs/concepts/scheduling-eviction/scheduling-framework.md b/content/zh-cn/docs/concepts/scheduling-eviction/scheduling-framework.md index d32a8fc167288..57d1fa67d64d0 100644 --- a/content/zh-cn/docs/concepts/scheduling-eviction/scheduling-framework.md +++ b/content/zh-cn/docs/concepts/scheduling-eviction/scheduling-framework.md @@ -222,7 +222,7 @@ called for that node. Nodes may be evaluated concurrently. ### PostFilter {#post-filter} -这里是一个使用了容忍度的 Pod: +默认的 Kubernetes 调度器在选择一个节点来运行特定的 Pod 时会考虑污点和容忍度。 +然而,如果你手动为一个 Pod 指定了 `.spec.nodeName`,那么选节点操作会绕过调度器; +这个 Pod 将会绑定到你指定的节点上,即使你选择的节点上有 `NoSchedule` 的污点。 +如果这种情况发生,且节点上还设置了 `NoExecute` 的污点,kubelet 会将 Pod 驱逐出去,除非有适当的容忍度设置。 + + +下面是一个定义了一些容忍度的 Pod 的例子: {{% code_sample file="pods/pod-with-toleration.yaml" %}} @@ -141,7 +155,7 @@ An empty `effect` matches all effects with key `key1`. {{< /note >}} 上述例子中 `effect` 使用的值为 `NoSchedule`,你也可以使用另外一个值 `PreferNoSchedule`。 @@ -389,7 +403,7 @@ are true. The following taints are built in: * `node.kubernetes.io/network-unavailable`: Node's network is unavailable. * `node.kubernetes.io/unschedulable`: Node is unschedulable. * `node.cloudprovider.kubernetes.io/uninitialized`: When the kubelet is started - with "external" cloud provider, this taint is set on a node to mark it + with an "external" cloud provider, this taint is set on a node to mark it as unusable. After a controller from the cloud-controller-manager initializes this node, the kubelet removes this taint. --> diff --git a/content/zh-cn/docs/concepts/scheduling-eviction/topology-spread-constraints.md b/content/zh-cn/docs/concepts/scheduling-eviction/topology-spread-constraints.md index ef6cf4e31b4d4..3a3db98d464a5 100644 --- a/content/zh-cn/docs/concepts/scheduling-eviction/topology-spread-constraints.md +++ b/content/zh-cn/docs/concepts/scheduling-eviction/topology-spread-constraints.md @@ -496,7 +496,7 @@ can use a manifest similar to: @@ -981,7 +981,7 @@ section of the enhancement proposal about Pod topology spread constraints. because, in this case, those topology domains won't be considered until there is at least one node in them. - You can work around this by using an cluster autoscaling tool that is aware of + You can work around this by using a cluster autoscaling tool that is aware of Pod topology spread constraints and is also aware of the overall set of topology domains. --> diff --git a/content/zh-cn/docs/concepts/security/_index.md b/content/zh-cn/docs/concepts/security/_index.md index 6043801a77077..9c475a157ad75 100644 --- a/content/zh-cn/docs/concepts/security/_index.md +++ b/content/zh-cn/docs/concepts/security/_index.md @@ -2,4 +2,253 @@ title: "安全" weight: 85 description: 确保云原生工作负载安全的一组概念。 +simple_list: true --- + + + + +Kubernetes 文档的这一部分内容的旨在引导你学习如何更安全地运行工作负载, +以及维护 Kubernetes 集群的基本安全性。 + +Kubernetes 基于云原生架构,并借鉴了 +{{< glossary_tooltip text="CNCF" term_id="cncf" >}} 有关云原生信息安全良好实践的建议。 + + +请阅读[云原生安全和 Kubernetes](/zh-cn/docs/concepts/security/cloud-native-security/), +了解有关如何保护集群及其上运行的应用程序的更广泛背景信息。 + + +## Kubernetes 安全机制 {#security-mechanisms} + +Kubernetes 包含多个 API 和安全组件, +以及定义[策略](#policies)的方法,这些策略可以作为你的信息安全管理的一部分。 + + +### 控制平面保护 + +任何 Kubernetes 集群的一个关键安全机制是[控制对 Kubernetes API 的访问](/zh-cn/docs/concepts/security/controlling-access)。 + + +Kubernetes 希望你配置并使用 TLS, +以便在控制平面内以及控制平面与其客户端之间提供[传输中的数据加密](/zh-cn/docs/tasks/tls/managing-tls-in-a-cluster/)。 +你还可以为 Kubernetes 控制平面中存储的数据启用静态加密; +这与对你自己的工作负载数据使用静态加密不同,后者可能也是一个好主意。 + + +### Secret + +[Secret](/zh-cn/docs/concepts/configuration/secret/) API +为需要保密的配置值提供基本保护。 + + +### 工具负载保护 + +实施 [Pod 安全标准](/zh-cn/docs/concepts/security/pod-security-standards/)以确保 +Pod 及其容器得到适当隔离。如果需要,你还可以使用 +[RuntimeClass](/zh-cn/docs/concepts/containers/runtime-class) 来配置自定义隔离。 + + +[网络策略(NetworkPolicy)](/zh-cn/docs/concepts/services-networking/network-policies/) +可让控制 Pod 之间或 Pod 与集群外部网络之间的网络流量。 + + +### 审计 + +Kubernetes [审计日志记录](/zh-cn/docs/tasks/debug/debug-cluster/audit/)提供了一组与安全相关、 +按时间顺序排列的记录,记录了集群中的操作序列。 +集群审计用户、使用 Kubernetes API 的应用程序以及控制平面本身生成的活动。 + + +## 云提供商安全 + +{{% thirdparty-content vendor="true" %}} + +如果你在自己的硬件或不同的云平台上运行 Kubernetes 集群,请参阅对应云平台的文档以了解安全最佳实践。 +以下是一些流行云提供商的安全文档的链接: + + +{{< table caption="Cloud provider security" >}} + +IaaS 提供商 | 链接 | +-------------------- | ------------ | +阿里云 | https://www.alibabacloud.com/trust-center | +亚马逊网络服务 | https://aws.amazon.com/security | +谷歌云平台 | https://cloud.google.com/security | +华为云 | https://www.huaweicloud.com/intl/en-us/securecenter/overallsafety | +IBM 云 | https://www.ibm.com/cloud/security | +微软 Azure | https://docs.microsoft.com/en-us/azure/security/azure-security | +Oracle 云基础设施| https://www.oracle.com/security | +VMware vSphere | https://www.vmware.com/security/hardening-guides | + +{{< /table >}} + + +## 策略 + +你可以使用 Kubernetes 原生机制定义安全策略,例如 +[NetworkPolicy](/zh-cn/docs/concepts/services-networking/network-policies/)(对网络数据包过滤的声明式控制) +或 [ValidatingAdmisisonPolicy](/zh-cn/docs/reference/access -authn-authz/validating-admission-policy/) +(对某人可以使用 Kubernetes API 进行哪些更改的声明性限制)。 + + +你还可以依赖 Kubernetes 周边更广泛的生态系统的策略实现。 +Kubernetes 提供了扩展机制,让这些生态系统项目在源代码审查、 +容器镜像审批、API 访问控制、网络等方面实施自己的策略控制。 + + +有关策略机制和 Kubernetes 的更多信息,请阅读[策略](/zh-cn/docs/concepts/policy/)。 + +## {{% heading "whatsnext" %}} + + +了解相关的 Kubernetes 安全主题: + +* [保护集群](/zh-cn/docs/tasks/administer-cluster/secure-a-cluster/) +* Kubernetes 中的[已知漏洞](/zh-cn/docs/reference/issues-security/official-cve-feed/)(以及更多信息的链接) +* [传输中的数据加密](/zh-cn/docs/tasks/tls/managing-tls-in-a-cluster/)(针对控制平面) +* [静态数据加密](/zh-cn/docs/tasks/administer-cluster/encrypt-data/) +* [控制对 Kubernetes API 的访问](/zh-cn/docs/concepts/security/controlling-access) +* Pod 的 [网络策略](/zh-cn/docs/concepts/services-networking/network-policies/) +* [Kubernetes 中的 Secret](/zh-cn/docs/concepts/configuration/secret/) +* [Pod 安全标准](/zh-cn/docs/concepts/security/pod-security-standards/) +* [运行时类](/zh-cn/docs/concepts/containers/runtime-class) + + +了解上下文: + + + +* [云原生安全和 Kubernetes](/zh-cn/docs/concepts/security/cloud-native-security/) + + +获取认证: + +* [Kubernetes 安全专家认证](https://training.linuxfoundation.org/certification/certified-kubernetes-security-specialist/)和官方培训课程。 + +阅读本节的更多内容: + diff --git a/content/zh-cn/docs/concepts/security/api-server-bypass-risks.md b/content/zh-cn/docs/concepts/security/api-server-bypass-risks.md index 8fe8e339dc424..ae78f328770a4 100644 --- a/content/zh-cn/docs/concepts/security/api-server-bypass-risks.md +++ b/content/zh-cn/docs/concepts/security/api-server-bypass-risks.md @@ -148,7 +148,7 @@ The default anonymous access doesn't make this assertion with the control plane. --> kubelet API 可以配置为以多种方式验证请求。 默认情况下,kubelet 的配置允许匿名访问。大多数 Kubernetes 提供商将默认值更改为使用 Webhook 和证书身份认证。 -这使得控制平面能够确保调用者访问 `Node` API 资源或子资源是经过授权的。但控制平面不能确保默认的匿名访问也是如此。 +这使得控制平面能够确保调用者访问 `nodes` API 资源或子资源是经过授权的。但控制平面不能确保默认的匿名访问也是如此。 -- 使用 [RBAC](/zh-cn/docs/reference/access-authn-authz/rbac/) 等机制限制对 `Node` API 对象的子资源的访问。 +- 使用 [RBAC](/zh-cn/docs/reference/access-authn-authz/rbac/) 等机制限制对 `nodes` API 对象的子资源的访问。 只在有需要时才授予此访问权限,例如监控服务。 - 限制对 kubelet 端口的访问。只允许指定和受信任的 IP 地址段访问该端口。 - 确保将 diff --git a/content/zh-cn/docs/concepts/security/multi-tenancy.md b/content/zh-cn/docs/concepts/security/multi-tenancy.md index 97bfe4675abf3..b1146c521b070 100644 --- a/content/zh-cn/docs/concepts/security/multi-tenancy.md +++ b/content/zh-cn/docs/concepts/security/multi-tenancy.md @@ -608,7 +608,7 @@ sandboxing implementations are available: * [gVisor](https://gvisor.dev/) intercepts syscalls from containers and runs them through a userspace kernel, written in Go, with limited access to the underlying host. -* [Kata Containers](https://katacontainers.io/) is an OCI compliant runtime that allows you to run +* [Kata Containers](https://katacontainers.io/) provide a secure container runtime that allows you to run containers in a VM. The hardware virtualization available in Kata offers an added layer of security for containers running untrusted code. --> @@ -617,8 +617,8 @@ sandboxing implementations are available: * [gVisor](https://gvisor.dev/) 拦截来自容器的系统调用,并通过用户空间内核运行它们, 用户空间内核采用 Go 编写,对底层主机的访问是受限的 -* [Kata Containers](https://katacontainers.io/) 是符合 OCI 的运行时,允许你在 VM 中运行容器。 - Kata 中提供的硬件虚拟化为运行不受信任代码的容器提供了额外的安全层。 +* [Kata Containers](https://katacontainers.io/) 提供了一个安全的容器运行时, + 允许你在 VM 中运行容器。Kata 中提供的硬件虚拟化为运行不受信任代码的容器提供了额外的安全层。 - - - -本概述定义了一个模型,用于在 Cloud Native 安全性上下文中考虑 Kubernetes 安全性。 - - -{{< warning >}} -此容器安全模型只提供建议,而不是经过验证的信息安全策略。 -{{< /warning >}} - - - - -## 云原生安全的 4 个 C {#the-4c-s-of-cloud-native-security} - -你可以分层去考虑安全性,云原生安全的 4 个 C 分别是云(Cloud)、集群(Cluster)、容器(Container)和代码(Code)。 - - -{{< note >}} -这种分层方法增强了[深度防护方法](https://en.wikipedia.org/wiki/Defense_in_depth_(computing))在安全性方面的 -防御能力,该方法被广泛认为是保护软件系统的最佳实践。 - -{{< /note >}} - -{{< figure src="/images/docs/4c.png" title="云原生安全的 4C" >}} - - -云原生安全模型的每一层都是基于下一个最外层,代码层受益于强大的基础安全层(云、集群、容器)。 -你无法通过在代码层解决安全问题来为基础层中糟糕的安全标准提供保护。 - - -## 云 {#cloud} - - -在许多方面,云(或者位于同一位置的服务器,或者是公司数据中心)是 Kubernetes 集群中的 -[可信计算基](https://en.wikipedia.org/wiki/Trusted_computing_base)。 -如果云层容易受到攻击(或者被配置成了易受攻击的方式),就不能保证在此基础之上构建的组件是安全的。 -每个云提供商都会提出安全建议,以在其环境中安全地运行工作负载。 - - -### 云提供商安全性 {#cloud-provider-security} - -如果你是在你自己的硬件或者其他不同的云提供商上运行 Kubernetes 集群, -请查阅相关文档来获取最好的安全实践。 - -下面是一些比较流行的云提供商的安全性文档链接: - -{{< table caption="云提供商安全" >}} - -IaaS 提供商 | 链接 | --------------------- | ------------ | -Alibaba Cloud | https://www.alibabacloud.com/trust-center | -Amazon Web Services | https://aws.amazon.com/security | -Google Cloud Platform | https://cloud.google.com/security | -Huawei Cloud | https://www.huaweicloud.com/intl/zh-cn/securecenter/overallsafety | -IBM Cloud | https://www.ibm.com/cloud/security | -Microsoft Azure | https://docs.microsoft.com/en-us/azure/security/azure-security | -Oracle Cloud Infrastructure | https://www.oracle.com/security | -VMWare VSphere | https://www.vmware.com/security/hardening-guides | - -{{< /table >}} - - -### 基础设施安全 {#infrastructure-security} - -关于在 Kubernetes 集群中保护你的基础设施的建议: - -{{< table caption="基础设施安全" >}} - -Kubernetes 基础架构关注领域 | 建议 | ---------------------------------------------- | -------------- | -通过网络访问 API 服务(控制平面)|所有对 Kubernetes 控制平面的访问不允许在 Internet 上公开,同时应由网络访问控制列表控制,该列表包含管理集群所需的 IP 地址集。| -通过网络访问 Node(节点)| 节点应配置为 _仅能_ 从控制平面上通过指定端口来接受(通过网络访问控制列表)连接,以及接受 NodePort 和 LoadBalancer 类型的 Kubernetes 服务连接。如果可能的话,这些节点不应完全暴露在公共互联网上。| -Kubernetes 访问云提供商的 API | 每个云提供商都需要向 Kubernetes 控制平面和节点授予不同的权限集。为集群提供云提供商访问权限时,最好遵循对需要管理的资源的[最小特权原则](https://en.wikipedia.org/wiki/Principle_of_least_privilege)。[Kops 文档](https://github.com/kubernetes/kops/blob/master/docs/iam_roles.md#iam-roles)提供有关 IAM 策略和角色的信息。| -访问 etcd | 对 etcd(Kubernetes 的数据存储)的访问应仅限于控制平面。根据配置情况,你应该尝试通过 TLS 来使用 etcd。更多信息可以在 [etcd 文档](https://github.com/etcd-io/etcd/tree/master/Documentation)中找到。| -etcd 加密 | 在所有可能的情况下,最好对所有存储进行静态数据加密,并且由于 etcd 拥有整个集群的状态(包括机密信息),因此其磁盘更应该进行静态数据加密。| - -{{< /table >}} - - -## 集群 {#cluster} - -保护 Kubernetes 有两个方面需要注意: - -* 保护可配置的集群组件 -* 保护在集群中运行的应用程序 - - -### 集群组件 {#cluster-components} - -如果想要保护集群免受意外或恶意的访问,采取良好的信息管理实践,请阅读并遵循有关[保护集群](/zh-cn/docs/tasks/administer-cluster/securing-a-cluster/)的建议。 - - -### 集群中的组件(你的应用) {#cluster-applications} - -根据你的应用程序的受攻击面,你可能需要关注安全性的特定面,比如: -如果你正在运行中的一个服务(A 服务)在其他资源链中很重要,并且所运行的另一工作负载(服务 B) -容易受到资源枯竭的攻击,则如果你不限制服务 B 的资源的话,损害服务 A 的风险就会很高。 -下表列出了安全性关注的领域和建议,用以保护 Kubernetes 中运行的工作负载: - -工作负载安全性关注领域 | 建议 | ------------------------------- | --------------------- | -RBAC 授权(访问 Kubernetes API) | https://kubernetes.io/zh-cn/docs/reference/access-authn-authz/rbac/ -认证方式 | https://kubernetes.io/zh-cn/docs/concepts/security/controlling-access/ -应用程序 Secret 管理 (并在 etcd 中对其进行静态数据加密) | https://kubernetes.io/zh-cn/docs/concepts/configuration/secret/
          https://kubernetes.io/zh-cn/docs/tasks/administer-cluster/encrypt-data/ -确保 Pod 符合定义的 Pod 安全标准 | https://kubernetes.io/zh-cn/docs/concepts/security/pod-security-standards/#policy-instantiation -服务质量(和集群资源管理)| https://kubernetes.io/zh-cn/docs/tasks/configure-pod-container/quality-service-pod/ -网络策略 | https://kubernetes.io/zh-cn/docs/concepts/services-networking/network-policies/ -Kubernetes Ingress 的 TLS 支持 | https://kubernetes.io/zh-cn/docs/concepts/services-networking/ingress/#tls - - -## 容器 {#container} - -容器安全性不在本指南的探讨范围内。下面是一些探索此主题的建议和连接: - -容器关注领域 | 建议 | ------------------------------- | -------------- | -容器漏洞扫描和操作系统依赖安全性 | 作为镜像构建的一部分,你应该扫描你的容器里的已知漏洞。 -镜像签名和执行 | 对容器镜像进行签名,以维护对容器内容的信任。 -禁止特权用户 | 构建容器时,请查阅文档以了解如何在具有最低操作系统特权级别的容器内部创建用户,以实现容器的目标。 -使用带有较强隔离能力的容器运行时 | 选择提供较强隔离能力的[容器运行时类](/zh-cn/docs/concepts/containers/runtime-class/)。 - -## 代码 {#code} - -应用程序代码是你最能够控制的主要攻击面之一,虽然保护应用程序代码不在 Kubernetes 安全主题范围内,但以下是保护应用程序代码的建议: - - -### 代码安全性 {#code-security} - -{{< table caption="代码安全" >}} - -代码关注领域 | 建议 | --------------------------| -------------- | -仅通过 TLS 访问 | 如果你的代码需要通过 TCP 通信,请提前与客户端执行 TLS 握手。除少数情况外,请加密传输中的所有内容。更进一步,加密服务之间的网络流量是一个好主意。这可以通过被称为双向 TLS 或 [mTLS](https://en.wikipedia.org/wiki/Mutual_authentication) 的过程来完成,该过程对两个证书持有服务之间的通信执行双向验证。 | -限制通信端口范围 | 此建议可能有点不言自明,但是在任何可能的情况下,你都只应公开服务上对于通信或度量收集绝对必要的端口。| -第三方依赖性安全 | 最好定期扫描应用程序的第三方库以了解已知的安全漏洞。每种编程语言都有一个自动执行此检查的工具。 | -静态代码分析 | 大多数语言都提供给了一种方法,来分析代码段中是否存在潜在的不安全的编码实践。只要有可能,你都应该使用自动工具执行检查,该工具可以扫描代码库以查找常见的安全错误,一些工具可以在以下连接中找到: https://owasp.org/www-community/Source_Code_Analysis_Tools | -动态探测攻击 | 你可以对服务运行一些自动化工具,来尝试一些众所周知的服务攻击。这些攻击包括 SQL 注入、CSRF 和 XSS。[OWASP Zed Attack](https://www.zaproxy.org/) 代理工具是最受欢迎的动态分析工具之一。 | - -{{< /table >}} - -## {{% heading "whatsnext" %}} - - -学习了解相关的 Kubernetes 安全主题: - -* [Pod 安全标准](/zh-cn/docs/concepts/security/pod-security-standards/) -* [Pod 的网络策略](/zh-cn/docs/concepts/services-networking/network-policies/) -* [控制对 Kubernetes API 的访问](/zh-cn/docs/concepts/security/controlling-access/) -* [保护你的集群](/zh-cn/docs/tasks/administer-cluster/securing-a-cluster/) -* 为控制面[加密通信中的数据](/zh-cn/docs/tasks/tls/managing-tls-in-a-cluster/) -* [加密静止状态的数据](/zh-cn/docs/tasks/administer-cluster/encrypt-data/) -* [Kubernetes 中的 Secret](/zh-cn/docs/concepts/configuration/secret/) -* [运行时类](/zh-cn/docs/concepts/containers/runtime-class) - diff --git a/content/zh-cn/docs/concepts/security/pod-security-admission.md b/content/zh-cn/docs/concepts/security/pod-security-admission.md index 861b6399bf6b1..38d3156ff22e7 100644 --- a/content/zh-cn/docs/concepts/security/pod-security-admission.md +++ b/content/zh-cn/docs/concepts/security/pod-security-admission.md @@ -235,14 +235,14 @@ current policy level: - Any metadata updates **except** changes to the seccomp or AppArmor annotations: - `seccomp.security.alpha.kubernetes.io/pod` (deprecated) - `container.seccomp.security.alpha.kubernetes.io/*` (deprecated) - - `container.apparmor.security.beta.kubernetes.io/*` + - `container.apparmor.security.beta.kubernetes.io/*` (deprecated) - Valid updates to `.spec.activeDeadlineSeconds` - Valid updates to `.spec.tolerations` --> - 除了对 seccomp 或 AppArmor 注解之外的所有元数据(Metadata)更新操作: - `seccomp.security.alpha.kubernetes.io/pod` (已弃用) - `container.seccomp.security.alpha.kubernetes.io/*` (已弃用) - - `container.apparmor.security.beta.kubernetes.io/*` + - `container.apparmor.security.beta.kubernetes.io/*`(已弃用) - 对 `.spec.activeDeadlineSeconds` 的合法更新 - 对 `.spec.tolerations` 的合法更新 diff --git a/content/zh-cn/docs/concepts/security/rbac-good-practices.md b/content/zh-cn/docs/concepts/security/rbac-good-practices.md index 17b3602ad436f..6eace4665752f 100644 --- a/content/zh-cn/docs/concepts/security/rbac-good-practices.md +++ b/content/zh-cn/docs/concepts/security/rbac-good-practices.md @@ -151,7 +151,7 @@ Kubernetes 默认提供访问权限并非是每个集群都需要的。 It is vital to periodically review the Kubernetes RBAC settings for redundant entries and possible privilege escalations. If an attacker is able to create a user account with the same name as a deleted user, -they can automatically inherit all the rights of the deleted user, especially the +they can automatically inherit all the rights of the deleted user, specially the rights assigned to that user. --> ### 定期检查 {#periodic-review} @@ -260,8 +260,8 @@ You should only allow access to create PersistentVolume objects for: 你应该只允许以下实体具有创建 PersistentVolume 对象的访问权限: @@ -369,6 +369,20 @@ mutating webhooks, also mutate admitted objects. 的用户可以控制能读取任何允许进入集群的对象的 webhook, 并且在有变更 webhook 的情况下,还可以变更准入的对象。 + +### 命名空间修改 {#namespace-modification} +可以对命名空间对象执行 **patch** 操作的用户(通过命名空间内的 RoleBinding 关联到具有该权限的 Role), +可以修改该命名空间的标签。在使用 Pod 安全准入的集群中,这可能允许用户将命名空间配置为比管理员预期更宽松的策略。 +对于使用 NetworkPolicy 的集群,用户所设置的标签可能间接导致对某些本不应被允许访问的服务的访问权限被开放。 + 在 Linux 中,内核的主机名字段(`struct utsname` 的 `nodename` 字段)限定最多 64 个字符。 @@ -381,7 +381,7 @@ Pod 会一直出于 `Pending` 状态(通过 `kubectl` 所看到的 `ContainerC `long-FQDN` is too long (64 characters is the max, 70 characters requested)." (无法基于 Pod 主机名和集群域名构造 FQDN,FQDN `long-FQDN` 过长,至多 64 个字符,请求字符数为 70)。 对于这种场景而言,改善用户体验的一种方式是创建一个 -[准入 Webhook 控制器](/zh-cn/docs/reference/access-authn-authz/extensible-admission-controllers/#admission-webhooks), +[准入 Webhook 控制器](/zh-cn/docs/reference/access-authn-authz/extensible-admission-controllers/#what-are-admission-webhooks), 在用户创建顶层对象(如 Deployment)的时候控制 FQDN 的长度。 {{< /note >}} diff --git a/content/zh-cn/docs/concepts/services-networking/endpoint-slices.md b/content/zh-cn/docs/concepts/services-networking/endpoint-slices.md index 615728a216616..1f1cf1be6be45 100644 --- a/content/zh-cn/docs/concepts/services-networking/endpoint-slices.md +++ b/content/zh-cn/docs/concepts/services-networking/endpoint-slices.md @@ -380,7 +380,7 @@ perfectly full distribution of EndpointSlices. As an example, if there are 10 new endpoints to add and 2 EndpointSlices with room for 5 more endpoints each, this approach will create a new EndpointSlice instead of filling up the 2 existing EndpointSlices. In other words, a single EndpointSlice creation is -preferrable to multiple EndpointSlice updates. +preferable to multiple EndpointSlice updates. --> 这里比较重要的是,与在 EndpointSlice 之间完成最佳的分布相比,第三步中更看重限制 EndpointSlice 更新的操作次数。例如,如果有 10 个端点待添加,有两个 EndpointSlice diff --git a/content/zh-cn/docs/concepts/services-networking/gateway.md b/content/zh-cn/docs/concepts/services-networking/gateway.md new file mode 100644 index 0000000000000..915f740d63d90 --- /dev/null +++ b/content/zh-cn/docs/concepts/services-networking/gateway.md @@ -0,0 +1,362 @@ +--- +title: Gateway API +content_type: concept +description: >- + 网关(Gateway)API 是一组 API 类别,可提供动态基础设施配置和高级流量路由。 +weight: 55 +--- + + + + + + +[Gateway API](https://gateway-api.sigs.k8s.io/) 通过使用可扩展的、角色导向的、 +协议感知的配置机制来提供网络服务。它是一个{{}}, +包含可提供动态基础设施配置和高级流量路由的 +API [类别](https://gateway-api.sigs.k8s.io/references/spec/)。 + + + + +## 设计原则 {#design-principles} + +Gateway API 的设计和架构遵从以下原则: + + +* **角色导向:** Gateway API 类别是基于负责管理 Kubernetes 服务网络的组织角色建模的: + * **基础设施提供者:** 管理使用多个独立集群为多个租户提供服务的基础设施,例如,云提供商。 + * **集群操作员:** 管理集群,通常关注策略、网络访问、应用程序权限等。 + * **应用程序开发人员:** 管理在集群中运行的应用程序,通常关注应用程序级配置和 [Service](/zh-cn/docs/concepts/services-networking/service/) 组合。 + + +* **可移植:** Gateway API 规范用[自定义资源](/zh-cn/docs/concepts/extend-kubernetes/api-extension/custom-resources)来定义, + 并受到许多[实现](https://gateway-api.sigs.k8s.io/implementations/)的支持。 +* **表达能力强:** Gateway API 类别支持常见流量路由场景的功能,例如基于标头的匹配、流量加权以及其他只能在 + [Ingress](/zh-cn/docs/concepts/services-networking/ingress/) 中使用自定义注解才能实现的功能。 +* **可扩展的:** Gateway 允许在 API 的各个层链接自定义资源。这使得在 API 结构内的适当位置进行精细定制成为可能。 + + +## 资源模型 {#resource-model} + +Gateway API 具有三种稳定的 API 类别: + + +* **GatewayClass:** 定义一组具有配置相同的网关,由实现该类的控制器管理。 + +* **Gateway:** 定义流量处理基础设施(例如云负载均衡器)的一个实例。 + +* **HTTPRoute:** 定义特定于 HTTP 的规则,用于将流量从网关监听器映射到后端网络端点的表示。 + 这些端点通常表示为 {{}}。 + + +Gateway API 被组织成不同的 API 类别,这些 API 类别具有相互依赖的关系,以支持组织中角色导向的特点。 +一个 Gateway 对象只能与一个 GatewayClass 相关联;GatewayClass 描述负责管理此类 Gateway 的网关控制器。 +各个(可以是多个)路由类别(例如 HTTPRoute)可以关联到此 Gateway 对象。 +Gateway 可以对能够挂接到其 `listeners` 的路由进行过滤,从而与路由形成双向信任模型。 + + + +下图说明这三个稳定的 Gateway API 类别之间的关系: + +{{< figure src="/docs/images/gateway-kind-relationships.svg" alt="此图呈现的是三个稳定的 Gateway API 类别之间的关系" class="diagram-medium" >}} + + +### GatewayClass {#api-kind-gateway-class} + +Gateway 可以由不同的控制器实现,通常具有不同的配置。 +Gateway 必须引用某 GatewayClass,而后者中包含实现该类的控制器的名称。 + +下面是一个最精简的 GatewayClass 示例: + +```yaml +apiVersion: gateway.networking.k8s.io/v1 +kind: GatewayClass +metadata: + name: example-class +spec: + controllerName: example.com/gateway-controller +``` + + +在此示例中,一个实现了 Gateway API 的控制器被配置为管理某些 GatewayClass 对象, +这些对象的控制器名为 `example.com/gateway-controller`。 +归属于此类的 Gateway 对象将由此实现的控制器来管理。 + +有关此 API 类别的完整定义,请参阅 +[GatewayClass](https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io/v1.GatewayClass)。 + + +### Gateway {#api-kind-gateway} + +Gateway 用来描述流量处理基础设施的一个实例。Gateway 定义了一个网络端点,该端点可用于处理流量, +即对 Service 等后端进行过滤、平衡、拆分等。 +例如,Gateway 可以代表某个云负载均衡器,或配置为接受 HTTP 流量的集群内代理服务器。 + +下面是一个精简的 Gateway 资源示例: + +```yaml +apiVersion: gateway.networking.k8s.io/v1 +kind: Gateway +metadata: + name: example-gateway +spec: + gatewayClassName: example-class + listeners: + - name: http + protocol: HTTP + port: 80 +``` + + +在此示例中,流量处理基础设施的实例被编程为监听 80 端口上的 HTTP 流量。 +由于未指定 `addresses` 字段,因此对应实现的控制器负责将地址或主机名设置到 Gateway 之上。 +该地址用作网络端点,用于处理路由中定义的后端网络端点的流量。 + +有关此类 API 的完整定义,请参阅 [Gateway](https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io/v1.Gateway)。 + + +### HTTPRoute {#api-kind-httproute} + +HTTPRoute 类别指定从 Gateway 监听器到后端网络端点的 HTTP 请求的路由行为。 +对于服务后端,实现可以将后端网络端点表示为服务 IP 或服务的支持端点。 +HTTPRoute 表示将被应用到下层 Gateway 实现的配置。 +例如,定义新的 HTTPRoute 可能会导致在云负载均衡器或集群内代理服务器中配置额外的流量路由。 + +下面是一个最精简的 HTTPRoute 示例: + +```yaml +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: example-httproute +spec: + parentRefs: + - name: example-gateway + hostnames: + - "www.example.com" + rules: + - matches: + - path: + type: PathPrefix + value: /login + backendRefs: + - name: example-svc + port: 8080 +``` + + +在此示例中,来自 Gateway `example-gateway` 的 HTTP 流量, +如果 Host 的标头设置为 `www.example.com` 且请求路径指定为 `/login`, +将被路由到 Service `example-svc` 的 `8080` 端口。 + +有关此类 API 的完整定义,请参阅 [HTTPRoute](https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io/v1.HTTPRoute)。 + + +## 请求数据流 {#request-flow} + +以下是使用 Gateway 和 HTTPRoute 将 HTTP 流量路由到服务的简单示例: + +{{< figure src="/docs/images/gateway-request-flow.svg" alt="此图为使用 Gateway 和 HTTPRoute 将 HTTP 流量路由到服务的示例" class="diagram-medium" >}} + +在此示例中,实现为反向代理的 Gateway 的请求数据流如下: + + +1. 客户端开始准备 URL 为 `http://www.example.com` 的 HTTP 请求 +2. 客户端的 DNS 解析器查询目标名称并了解与 Gateway 关联的一个或多个 IP 地址的映射。 +3. 客户端向 Gateway IP 地址发送请求;反向代理接收 HTTP 请求并使用 Host: + 标头来匹配基于 Gateway 和附加的 HTTPRoute 所获得的配置。 +4. 可选的,反向代理可以根据 HTTPRoute 的匹配规则进行请求头和(或)路径匹配。 +5. 可选地,反向代理可以修改请求;例如,根据 HTTPRoute 的过滤规则添加或删除标头。 +6. 最后,反向代理将请求转发到一个或多个后端。 + + +## 标准合规性 {#conformance} + +Gateway API 涵盖广泛的功能并得到广泛实现。 +这种组合需要明确的标准合规性定义和测试,以确保 API 在任何地方使用时都能提供一致的体验。 + +请参阅[合规性](https://gateway-api.sigs.k8s.io/concepts/conformance/)相关的文档, +以了解发布渠道、支持级别和运行合规性测试等详细信息。 + + +## 从 Ingress 迁移 {#migrating-from-ingress} + +Gateway API 是 [Ingress](/zh-cn/docs/concepts/services-networking/ingress/) API 的后继者。 +但是其中不包括 Ingress 类型。因此,需要将现有 Ingress 资源一次性转换为 Gateway API 资源。 + +有关将 Ingress 资源迁移到 Gateway API 资源的详细信息,请参阅 +[Ingress 迁移](https://gateway-api.sigs.k8s.io/guides/migration-from-ingress/#migration-from-ingress)指南。 + +## {{% heading "whatsnext" %}} + + +Gateway API 资源不是由 Kubernetes 原生实现的, +而是被定义为受广泛[实现](https://gateway-api.sigs.k8s.io/implementations/)支持的[自定义资源](/zh-cn/docs/concepts/extend-kubernetes/api-extension/custom-resources/)。 +用户需要[安装](https://gateway-api.sigs.k8s.io/guides/#installing-gateway-api) Gateway API CRD +或按照所选实现的安装说明进行操作。 +安装完成后,使用[入门](https://gateway-api.sigs.k8s.io/guides/)指南来帮助你快速开始使用 Gateway API。 + +{{< note >}} + +请务必查看所选实现的文档以了解可能存在的注意事项。 +{{< /note >}} + + +有关所有 Gateway API 类型的其他详细信息,请参阅 [API 规范](https://gateway-api.sigs.k8s.io/reference/spec/)。 diff --git a/content/zh-cn/docs/concepts/services-networking/network-policies.md b/content/zh-cn/docs/concepts/services-networking/network-policies.md index a92413332fc42..eb441af8a88ea 100644 --- a/content/zh-cn/docs/concepts/services-networking/network-policies.md +++ b/content/zh-cn/docs/concepts/services-networking/network-policies.md @@ -1,6 +1,9 @@ --- title: 网络策略 content_type: concept +api_metadata: + - apiVersion: "networking.k8s.io/v1" + kind: "NetworkPolicy" weight: 70 description: >- 如果你希望在 IP 地址或端口层面(OSI 第 3 层或第 4 层)控制网络流量, @@ -15,6 +18,9 @@ reviewers: - danwinship title: Network Policies content_type: concept +api_metadata: +- apiVersion: "networking.k8s.io/v1" + kind: "NetworkPolicy" weight: 70 description: >- If you want to control traffic flow at the IP address or port level (OSI layer 3 or 4), @@ -28,8 +34,8 @@ description: >- Pod 可以与之通信的实体是通过如下三个标识符的组合来辩识的: -1. 其他被允许的 Pods(例外:Pod 无法阻塞对自身的访问) +1. 其他被允许的 Pod(例外:Pod 无法阻塞对自身的访问) 2. 被允许的名字空间 3. IP 组块(例外:与 Pod 运行所在的节点的通信总是被允许的, 无论 Pod 或节点的 IP 地址) 在定义基于 Pod 或名字空间的 NetworkPolicy 时, 你会使用{{< glossary_tooltip text="选择算符" term_id="selector">}}来设定哪些流量可以进入或离开与该算符匹配的 Pod。 + 另外,当创建基于 IP 的 NetworkPolicy 时,我们基于 IP 组块(CIDR 范围)来定义策略。 @@ -86,17 +93,17 @@ Creating a NetworkPolicy resource without a controller that implements it will h 创建一个 NetworkPolicy 资源对象而没有控制器来使它生效的话,是没有任何作用的。 ## Pod 隔离的两种类型 {#the-two-sorts-of-pod-isolation} -Pod 有两种隔离: 出口的隔离和入口的隔离。它们涉及到可以建立哪些连接。 +Pod 有两种隔离:出口的隔离和入口的隔离。它们涉及到可以建立哪些连接。 这里的“隔离”不是绝对的,而是意味着“有一些限制”。 另外的,“非隔离方向”意味着在所述方向上没有限制。这两种隔离(或不隔离)是独立声明的, 并且都与从一个 Pod 到另一个 Pod 的连接有关。 @@ -106,13 +113,15 @@ By default, a pod is non-isolated for egress; all outbound connections are allow A pod is isolated for egress if there is any NetworkPolicy that both selects the pod and has "Egress" in its `policyTypes`; we say that such a policy applies to the pod for egress. When a pod is isolated for egress, the only allowed connections from the pod are those allowed by -the `egress` list of some NetworkPolicy that applies to the pod for egress. +the `egress` list of some NetworkPolicy that applies to the pod for egress. Reply traffic for those +allowed connections will also be implicitly allowed. The effects of those `egress` lists combine additively. --> 默认情况下,一个 Pod 的出口是非隔离的,即所有外向连接都是被允许的。如果有任何的 NetworkPolicy -选择该 Pod 并在其 `policyTypes` 中包含 “Egress”,则该 Pod 是出口隔离的, +选择该 Pod 并在其 `policyTypes` 中包含 "Egress",则该 Pod 是出口隔离的, 我们称这样的策略适用于该 Pod 的出口。当一个 Pod 的出口被隔离时, 唯一允许的来自 Pod 的连接是适用于出口的 Pod 的某个 NetworkPolicy 的 `egress` 列表所允许的连接。 +针对那些允许连接的应答流量也将被隐式允许。 这些 `egress` 列表的效果是相加的。 默认情况下,一个 Pod 对入口是非隔离的,即所有入站连接都是被允许的。如果有任何的 NetworkPolicy 选择该 Pod 并在其 `policyTypes` 中包含 “Ingress”,则该 Pod 被隔离入口, 我们称这种策略适用于该 Pod 的入口。当一个 Pod 的入口被隔离时,唯一允许进入该 Pod 的连接是来自该 Pod 节点的连接和适用于入口的 Pod 的某个 NetworkPolicy 的 `ingress` -列表所允许的连接。这些 `ingress` 列表的效果是相加的。 +列表所允许的连接。针对那些允许连接的应答流量也将被隐式允许。这些 `ingress` 列表的效果是相加的。 -除非选择支持网络策略的网络解决方案,否则将上述示例发送到API服务器没有任何效果。 +除非选择支持网络策略的网络解决方案,否则将上述示例发送到 API 服务器没有任何效果。 {{< /note >}} -所以,该网络策略示例: +所以,该网络策略示例: 1. 隔离 `default` 名字空间下 `role=db` 的 Pod (如果它们不是已经被隔离的话)。 2. (Ingress 规则)允许以下 Pod 连接到 `default` 名字空间下的带有 `role=db` @@ -253,13 +264,13 @@ walkthrough for further examples. * `default` 名字空间下带有 `role=frontend` 标签的所有 Pod * 带有 `project=myproject` 标签的所有名字空间中的 Pod - * IP 地址范围为 172.17.0.0–172.17.0.255 和 172.17.2.0–172.17.255.255 - (即,除了 172.17.1.0/24 之外的所有 172.17.0.0/16) + * IP 地址范围为 `172.17.0.0–172.17.0.255` 和 `172.17.2.0–172.17.255.255` + (即,除了 `172.17.1.0/24` 之外的所有 `172.17.0.0/16`) 3. (Egress 规则)允许 `default` 名字空间中任何带有标签 `role=db` 的 Pod 到 CIDR - 10.0.0.0/24 下 5978 TCP 端口的连接。 + `10.0.0.0/24` 下 5978 TCP 端口的连接。 -参阅[声明网络策略](/zh-cn/docs/tasks/administer-cluster/declare-network-policy/)演练了解更多示例。 +有关更多示例,请参阅[声明网络策略](/zh-cn/docs/tasks/administer-cluster/declare-network-policy/)演练。 你可以通过创建选择所有 Pod 但不允许任何进入这些 Pod 的入站流量的 NetworkPolicy -来为名字空间创建 “default” 隔离策略。 +来为名字空间创建 "default" 隔离策略。 {{< code_sample file="service/networking/network-policy-default-deny-ingress.yaml" >}} @@ -415,7 +426,7 @@ that explicitly allows that. 有了这个策略,任何额外的策略都不会导致到这些 Pod 的任何入站连接被拒绝。 此策略对任何 Pod 的出口隔离没有影响。 @@ -429,7 +440,7 @@ that selects all pods but does not allow any egress traffic from those pods. ### 默认拒绝所有出站流量 {#default-deny-all-egress-traffic} 你可以通过创建选择所有容器但不允许来自这些容器的任何出站流量的 NetworkPolicy -来为名字空间创建 “default” 隔离策略。 +来为名字空间创建 "default" 隔离策略。 {{< code_sample file="service/networking/network-policy-default-deny-egress.yaml" >}} @@ -456,7 +467,7 @@ explicitly allows all outgoing connections from pods in that namespace. 有了这个策略,任何额外的策略都不会导致来自这些 Pod 的任何出站连接被拒绝。 此策略对进入任何 Pod 的隔离没有影响。 @@ -469,7 +480,7 @@ creating the following NetworkPolicy in that namespace. --> ### 默认拒绝所有入站和所有出站流量 {#default-deny-all-ingress-and-all-egress-traffic} -你可以为名字空间创建“默认”策略,以通过在该名字空间中创建以下 NetworkPolicy +你可以为名字空间创建 "default" 策略,以通过在该名字空间中创建以下 NetworkPolicy 来阻止所有入站和出站流量。 {{< code_sample file="service/networking/network-policy-default-deny-all.yaml" >}} @@ -483,8 +494,8 @@ ingress or egress traffic. ## 网络流量过滤 {#network-traffic-filtering} @@ -504,7 +515,7 @@ protocol NetworkPolicies. When a `deny all` network policy is defined, it is only guaranteed to deny TCP, UDP and SCTP connections. For other protocols, such as ARP or ICMP, the behaviour is undefined. The same applies to allow rules: when a specific pod is allowed as ingress source or egress destination, -it is undefined what happens with (for example) ICMP packets. Protocols such as ICMP may be allowed by some +it is undefined what happens with (for example) ICMP packets. Protocols such as ICMP may be allowed by some network plugins and denied by others. --> 当 `deny all` 网络策略被定义时,此策略只能保证拒绝 TCP、UDP 和 SCTP 连接。 @@ -532,8 +543,8 @@ This is achievable with the usage of the `endPort` field, as the following examp {{< code_sample file="service/networking/networkpolicy-multiport-egress.yaml" >}} 上面的规则允许名字空间 `default` 中所有带有标签 `role=db` 的 Pod 使用 TCP 协议与 @@ -556,7 +567,7 @@ The following restrictions apply when using this field: @@ -573,20 +584,20 @@ NetworkPolicy 规约中使用 `endPort` 字段。 In this scenario, your `Egress` NetworkPolicy targets more than one namespace using their label names. For this to work, you need to label the target namespaces. For example: --> -## 按标签选择多个命名空间 {#targeting-multiple-namespaces-by-label} +## 按标签选择多个名字空间 {#targeting-multiple-namespaces-by-label} 在这种情况下,你的 `Egress` NetworkPolicy 使用名字空间的标签名称来将多个名字空间作为其目标。 为此,你需要为目标名字空间设置标签。例如: ```shell - kubectl label namespace frontend namespace=frontend - kubectl label namespace backend namespace=backend +kubectl label namespace frontend namespace=frontend +kubectl label namespace backend namespace=backend ``` -在 NetworkPolicy 文档中的 namespaceSelector 下添加标签。例如: +在 NetworkPolicy 文档中的 `namespaceSelector` 下添加标签。例如: ```yaml apiVersion: networking.k8s.io/v1 @@ -614,9 +625,9 @@ It is not possible to directly specify the name of the namespaces in a NetworkPo You must use a `namespaceSelector` with `matchLabels` or `matchExpressions` to select the namespaces based on their labels. --> -你不可以在 NetworkPolicy 中直接指定命名空间的名称。 +你不可以在 NetworkPolicy 中直接指定名字空间的名称。 你必须使用带有 `matchLabels` 或 `matchExpressions` 的 `namespaceSelector` -来根据标签选择命名空间。 +来根据标签选择名字空间。 {{< /note >}} 当新的 NetworkPolicy 对象被创建时,网络插件可能需要一些时间来处理这个新对象。 @@ -665,11 +676,11 @@ the NetworkPolicy handling is completed. Once the NetworkPolicy is handled by a network plugin, 1. All newly created pods affected by a given NetworkPolicy will be isolated before -they are started. -Implementations of NetworkPolicy must ensure that filtering is effective throughout -the Pod lifecycle, even from the very first instant that any container in that Pod is started. -Because they are applied at Pod level, NetworkPolicies apply equally to init containers, -sidecar containers, and regular containers. + they are started. + Implementations of NetworkPolicy must ensure that filtering is effective throughout + the Pod lifecycle, even from the very first instant that any container in that Pod is started. + Because they are applied at Pod level, NetworkPolicies apply equally to init containers, + sidecar containers, and regular containers. --> 一旦 NetworkPolicy 被网络插件处理, @@ -680,8 +691,8 @@ sidecar containers, and regular containers. @@ -705,7 +717,7 @@ kubelet 启动应用容器之前等待这些目的地变得可达。 - 网络插件无法正确辨别 `hostNetwork` Pod 流量,因此在匹配 `podSelector` 和 `namespaceSelector` @@ -767,9 +779,10 @@ This applies when ``` -2. `hostNetwork` Pod 在 `ingress` 或 `egress` 规则中被 `podSelector` 或 `namespaceSelector` 选中。 +2. `hostNetwork` Pod 在 `ingress` 或 `egress` 规则中被 `podSelector` 或 + `namespaceSelector` 选中。 ```yaml ... @@ -795,7 +808,7 @@ from a `hostNetwork` Pod using an `ipBlock` rule. As of Kubernetes {{< skew currentVersion >}}, the following functionality does not exist in the NetworkPolicy API, but you might be able to implement workarounds using Operating System components (such as SELinux, OpenVSwitch, IPTables, and so on) or Layer 7 technologies (Ingress -controllers, Service Mesh implementations) or admission controllers. In case you are new to +controllers, Service Mesh implementations) or admission controllers. In case you are new to network security in Kubernetes, its worth noting that the following User Stories cannot (yet) be implemented using the NetworkPolicy API. --> @@ -834,7 +847,7 @@ implemented using the NetworkPolicy API. - The ability to prevent loopback or incoming host traffic (Pods cannot currently block localhost access, nor do they have the ability to block access from their resident node). --> -- 实现适用于所有名字空间或 Pods 的默认策略(某些第三方 Kubernetes 发行版本或项目可以做到这点); +- 实现适用于所有名字空间或 Pod 的默认策略(某些第三方 Kubernetes 发行版本或项目可以做到这点); - 高级的策略查询或者可达性相关工具; - 生成网络安全事件日志的能力(例如,被阻塞或接收的连接请求); - 显式地拒绝策略的能力(目前,NetworkPolicy 的模型默认采用拒绝操作, @@ -842,6 +855,25 @@ implemented using the NetworkPolicy API. - 禁止本地回路或指向宿主的网络流量(Pod 目前无法阻塞 localhost 访问, 它们也无法禁止来自所在节点的访问请求)。 + +## NetworkPolicy 对现有连接的影响 {#networkpolicys-impact-on-existing-connections} + +当应用到现有连接的 NetworkPolicy 集合发生变化时,这可能是由于 NetworkPolicy +发生变化或者在现有连接过程中(主体和对等方)策略所选择的名字空间或 Pod 的相关标签发生变化, +此时是否对该现有连接生效是由实现定义的。例如:某个策略的创建导致之前允许的连接被拒绝, +底层网络插件的实现负责定义这个新策略是否会关闭现有的连接。 +建议不要以可能影响现有连接的方式修改策略、Pod 或名字空间。 + ## {{% heading "whatsnext" %}} -- 参阅[声明网络策略](/zh-cn/docs/tasks/administer-cluster/declare-network-policy/)演练了解更多示例; +- 有关更多示例,请参阅[声明网络策略](/zh-cn/docs/tasks/administer-cluster/declare-network-policy/)演练。 - 有关 NetworkPolicy 资源所支持的常见场景的更多信息, 请参见[此指南](https://github.com/ahmetb/kubernetes-network-policy-recipes)。 diff --git a/content/zh-cn/docs/concepts/services-networking/service.md b/content/zh-cn/docs/concepts/services-networking/service.md index 7cc0fd8eb2df2..1f21ca3536c11 100644 --- a/content/zh-cn/docs/concepts/services-networking/service.md +++ b/content/zh-cn/docs/concepts/services-networking/service.md @@ -1100,7 +1100,7 @@ can define your own (provider specific) annotations on the Service that specify --> #### 混合协议类型的负载均衡器 -{{< feature-state for_k8s_version="v1.26" state="stable" >}} +{{< feature-state feature_gate_name="MixedProtocolLBService" >}} #### 指定负载均衡器状态的 IPMode {#load-balancer-ip-mode} -{{< feature-state for_k8s_version="v1.29" state="alpha" >}} +{{< feature-state feature_gate_name="LoadBalancerIPMode" >}} -请注意,集群上最多只能有一个 **默认** 存储类,否则无法创建没有明确指定 -`storageClassName` 的 `PersistentVolumeClaim`。 +Note that if you set the `storageclass.kubernetes.io/is-default-class` +annotation to true on more than one StorageClass in your cluster, and you then +create a `PersistentVolumeClaim` with no `storageClassName` set, Kubernetes +uses the most recently created default StorageClass. +--> +请注意,如果你在集群的多个 StorageClass 设置 `storageclass.kubernetes.io/is-default-class` 注解为 true, +并之后创建了未指定 `storageClassName` 的 `PersistentVolumeClaim`, +Kubernetes 会使用最新创建的默认 StorageClass。 -如果你想要使用 `claimPolicy` 属性设置为 `Retain` 的 PersistentVolume 卷时, +如果你想要使用 `persistentVolumeReclaimPolicy` 属性设置为 `Retain` 的 PersistentVolume 卷时, 包括你希望复用现有的 PV 卷时,这点是很有用的 ## 介绍 {#introduction} @@ -46,6 +46,7 @@ Currently, the following types of volume sources can be projected: * [`downwardAPI`](/zh-cn/docs/concepts/storage/volumes/#downwardapi) * [`configMap`](/zh-cn/docs/concepts/storage/volumes/#configmap) * [`serviceAccountToken`](#serviceaccounttoken) +* [`clusterTrustBundle`](#clustertrustbundle) +## clusterTrustBundle 投射卷 {#clustertrustbundle} + +{{}} + +{{< note >}} + +要在 Kubernetes {{< skew currentVersion >}} 中使用此特性,你必须通过 `ClusterTrustBundle` +[特性门控](/zh-cn/docs/reference/command-line-tools-reference/feature-gates/)和 +`--runtime-config=certificates.k8s.io/v1alpha1/clustertrustbundles=true` kube-apiserver +标志启用对 ClusterTrustBundle 对象的支持,然后才能启用 `ClusterTrustBundleProjection` 特性门控。 +{{< /note >}} + + +`clusterTrustBundle` 投射卷源将一个或多个 +[ClusterTrustBundle](/zh-cn/docs/reference/access-authn-authz/certificate-signing-requests#cluster-trust-bundles) +对象的内容作为一个自动更新的文件注入到容器文件系统中。 + + +ClusterTrustBundle 可以通过[名称](/zh-cn/docs/reference/access-authn-authz/certificate-signing-requests#ctb-signer-unlinked) +或[签名者名称](/zh-cn/docs/reference/access-authn-authz/certificate-signing-requests#ctb-signer-linked)被选中。 + + +要按名称选择,可以使用 `name` 字段指定单个 ClusterTrustBundle 对象。 + +要按签名者名称选择,可以使用 `signerName` 字段(也可选用 `labelSelector` 字段) +指定一组使用给定签名者名称的 ClusterTrustBundle 对象。 +如果 `labelSelector` 不存在,则针对该签名者的所有 ClusterTrustBundles 将被选中。 + + +kubelet 会对所选 ClusterTrustBundle 对象中的证书进行去重,规范化 PEM 表示(丢弃注释和头部), +重新排序证书,并将这些证书写入由 `path` 指定的文件中。 +随着所选 ClusterTrustBundles 的集合或其内容发生变化,kubelet 会保持更新此文件。 + + +默认情况下,如果找不到指定的 ClusterTrustBundle,或者 `signerName` / `labelSelector` +与所有 ClusterTrustBundle 都不匹配,kubelet 将阻止 Pod 启动。如果这不是你想要的行为, +可以将 `optional` 字段设置为 `true`,Pod 将使用 `path` 处的空白文件启动。 + +{{% code_sample file="pods/storage/projected-clustertrustbundle.yaml" %}} + @@ -257,4 +318,3 @@ the Linux only `RunAsUser` option with Windows Pods. Pod 会一直阻塞在 `ContainerCreating` 状态。因此,建议不要在 Windows 节点上使用仅针对 Linux 的 `RunAsUser` 选项。 {{< /note >}} - diff --git a/content/zh-cn/docs/concepts/storage/storage-classes.md b/content/zh-cn/docs/concepts/storage/storage-classes.md index 6d6d39d7aaef4..12a542a670b19 100644 --- a/content/zh-cn/docs/concepts/storage/storage-classes.md +++ b/content/zh-cn/docs/concepts/storage/storage-classes.md @@ -27,8 +27,6 @@ with [volumes](/docs/concepts/storage/volumes/) and -## 介绍 {#introduction} - StorageClass 为管理员提供了描述存储"类"的方法。 不同的类型可能会映射到不同的服务质量等级或备份策略,或是由集群管理员制定的任意策略。 Kubernetes 本身并不清楚各种类代表的什么。这个类的概念在其他存储系统中有时被称为"配置文件"。 -## StorageClass 资源 {#the-storageclass-resource} +## StorageClass API {#the-storageclass-api} 每个 StorageClass 都包含 `provisioner`、`parameters` 和 `reclaimPolicy` 字段, 这些字段会在 StorageClass 需要动态制备 PersistentVolume 时会使用到。 diff --git a/content/zh-cn/docs/concepts/windows/intro.md b/content/zh-cn/docs/concepts/windows/intro.md index 77480fbbb6a98..013d37286dde6 100644 --- a/content/zh-cn/docs/concepts/windows/intro.md +++ b/content/zh-cn/docs/concepts/windows/intro.md @@ -28,7 +28,7 @@ of operating system. --> 在许多组织中,所运行的很大一部分服务和应用是 Windows 应用。 [Windows 容器](https://aka.ms/windowscontainers)提供了一种封装进程和包依赖项的方式, -从而简化了 DevOps 实践,令 Windows 应用程序同样遵从云原生模式。 +从而简化了 DevOps 实践,令 Windows 应用同样遵从云原生模式。 对于同时投入基于 Windows 应用和 Linux 应用的组织而言,他们不必寻找不同的编排系统来管理其工作负载, 使其跨部署的运营效率得以大幅提升,而不必关心所用的操作系统。 @@ -48,7 +48,7 @@ multiple operating systems. While you can only run the {{< glossary_tooltip text="control plane" term_id="control-plane" >}} on Linux, you can deploy worker nodes running either Windows or Linux. --> -## Kubernetes 中的 Windows 节点 {#windows-nodes-in-k8s} +## Kubernetes 中的 Windows 节点 {#windows-nodes-in-k8s} 若要在 Kubernetes 中启用对 Windows 容器的编排,可以在现有的 Linux 集群中包含 Windows 节点。 在 Kubernetes 上调度 {{< glossary_tooltip text="Pod" term_id="pod" >}} 中的 Windows 容器与调度基于 Linux 的容器类似。 @@ -60,13 +60,14 @@ you can deploy worker nodes running either Windows or Linux. -支持 Windows {{< glossary_tooltip text="节点" term_id="node" >}}的前提是操作系统为 Windows Server 2019。 +支持 Windows {{< glossary_tooltip text="节点" term_id="node" >}}的前提是操作系统为 +Windows Server 2019 或 Windows Server 2022。 本文使用术语 **Windows 容器**表示具有进程隔离能力的 Windows 容器。 Kubernetes 不支持使用 @@ -85,7 +86,7 @@ including: [HostProcess Containers](/docs/tasks/configure-pod-container/create-hostprocess-pod/) offer similar functionality. * TerminationGracePeriod: requires containerD --> -## 兼容性与局限性 {#limitations} +## 兼容性与局限性 {#limitations} 某些节点层面的功能特性仅在使用特定[容器运行时](#container-runtime)时才可用; 另外一些特性则在 Windows 节点上不可用,包括: @@ -109,7 +110,8 @@ functionality which are outlined in this section. Windows 节点并不支持共享命名空间的所有功能特性。 有关更多详细信息,请参考 [API 兼容性](#api)。 -有关 Kubernetes 测试时所使用的 Windows 版本的详细信息,请参考 [Windows 操作系统版本兼容性](#windows-os-version-support)。 +有关 Kubernetes 测试时所使用的 Windows 版本的详细信息,请参考 +[Windows 操作系统版本兼容性](#windows-os-version-support)。 从 API 和 kubectl 的角度来看,Windows 容器的行为与基于 Linux 的容器非常相似。 然而,在本节所概述的一些关键功能上,二者存在一些显著差异。 @@ -120,7 +122,7 @@ Windows 节点并不支持共享命名空间的所有功能特性。 Key Kubernetes elements work the same way in Windows as they do in Linux. This section refers to several key workload abstractions and how they map to Windows. --> -### 与 Linux 比较 {#comparison-with-Linux-similarities} +### 与 Linux 比较 {#comparison-with-Linux-similarities} Kubernetes 关键组件在 Windows 上的工作方式与在 Linux 上相同。 本节介绍几个关键的工作负载抽象及其如何映射到 Windows。 @@ -140,6 +142,7 @@ Kubernetes 关键组件在 Windows 上的工作方式与在 Linux 上相同。 你不可以在同一个 Pod 中部署 Windows 和 Linux 容器。 Pod 中的所有容器都调度到同一 Node 上,每个 Node 代表一个特定的平台和体系结构。 Windows 容器支持以下 Pod 能力、属性和事件: + -### kubelet 的命令行选项 {#kubelet-compatibility} +### kubelet 的命令行选项 {#kubelet-compatibility} 某些 kubelet 命令行选项在 Windows 上的行为不同,如下所述: @@ -296,7 +299,7 @@ and container runtime. Some workload properties were designed for Linux, and fai At a high level, these OS concepts are different: --> -### API 兼容性 {#api} +### API 兼容性 {#api} 由于操作系统和容器运行时的缘故,Kubernetes API 在 Windows 上的工作方式存在细微差异。 某些工作负载属性是为 Linux 设计的,无法在 Windows 上运行。 @@ -367,7 +370,7 @@ work between Windows and Linux: node. They should be applied to all containers as a best practice if the operator wants to avoid overprovisioning entirely. --> -#### 容器规约的字段兼容性 {#compatibility-v1-pod-spec-containers} +#### 容器规约的字段兼容性 {#compatibility-v1-pod-spec-containers} 以下列表记录了 Pod 容器规约在 Windows 和 Linux 之间的工作方式差异: @@ -437,7 +440,7 @@ The following list documents differences between how Pod specifications work bet which are not implemented on Windows. Windows cannot share process namespaces or the container's root filesystem. Only the network can be shared. --> -#### Pod 规约的字段兼容性 {#compatibility-v1-pod} +#### Pod 规约的字段兼容性 {#compatibility-v1-pod} 以下列表记录了 Pod 规约在 Windows 和 Linux 之间的工作方式差异: @@ -446,7 +449,7 @@ The following list documents differences between how Pod specifications work bet * `dnsPolicy` - Windows 不支持将 Pod `dnsPolicy` 设为 `ClusterFirstWithHostNet`, 因为未提供主机网络。Pod 始终用容器网络运行。 * `podSecurityContext` [参见下文](#compatibility-v1-pod-spec-containers-securitycontext) -* `shareProcessNamespace` - 这是一个 beta 版功能特性,依赖于 Windows 上未实现的 Linux 命名空间。 +* `shareProcessNamespace` - 这是一个 Beta 版功能特性,依赖于 Windows 上未实现的 Linux 命名空间。 Windows 无法共享进程命名空间或容器的根文件系统(root filesystem)。 只能共享网络。 -#### hostNetwork 的字段兼容性 {#compatibility-v1-pod-spec-containers-hostnetwork} +#### hostNetwork 的字段兼容性 {#compatibility-v1-pod-spec-containers-hostnetwork} {{< feature-state for_k8s_version="v1.26" state="alpha" >}} @@ -505,9 +508,9 @@ This functionality requires a container runtime that supports this functionality Only the `securityContext.runAsNonRoot` and `securityContext.windowsOptions` from the Pod [`securityContext`](/docs/reference/kubernetes-api/workload-resources/pod-v1/#security-context) fields work on Windows. --> -#### Pod 安全上下文的字段兼容性 {#compatibility-v1-pod-spec-containers-securitycontext} +#### Pod 安全上下文的字段兼容性 {#compatibility-v1-pod-spec-containers-securitycontext} -Pod 的 [`securityContext`](/docs/reference/kubernetes-api/workload-resources/pod-v1/#security-context) +Pod 的 [`securityContext`](/zh-cn/docs/reference/kubernetes-api/workload-resources/pod-v1/#security-context) 中只有 `securityContext.runAsNonRoot` 和 `securityContext.windowsOptions` 字段在 Windows 上生效。 -## 节点问题检测器 {#node-problem-detector} +## 节点问题检测器 {#node-problem-detector} 节点问题检测器(参考[节点健康监测](/zh-cn/docs/tasks/debug/debug-cluster/monitor-node-health/))初步支持 Windows。 有关更多信息,请访问该项目的 [GitHub 页面](https://github.com/kubernetes/node-problem-detector#windows)。 @@ -534,7 +537,7 @@ containers, share a common network endpoint (same IPv4 and / or IPv6 address, sa network port spaces). Kubernetes uses pause containers to allow for worker containers crashing or restarting without losing any of the networking configuration. --> -## Pause 容器 {#pause-container} +## Pause 容器 {#pause-container} 在 Kubernetes Pod 中,首先创建一个基础容器或 “pause” 容器来承载容器。 在 Linux 中,构成 Pod 的 cgroup 和命名空间维持持续存在需要一个进程; @@ -577,7 +580,7 @@ into each node in the cluster so that Pods can run there. The following container runtimes work with Windows: --> -## 容器运行时 {#container-runtime} +## 容器运行时 {#container-runtime} 你需要将{{< glossary_tooltip text="容器运行时" term_id="container-runtime" >}}安装到集群中的每个节点, 这样 Pod 才能在这些节点上运行。 @@ -596,7 +599,7 @@ as the container runtime for Kubernetes nodes that run Windows. Learn how to [install ContainerD on a Windows node](/docs/setup/production-environment/container-runtimes/#containerd). --> -### ContainerD {#containerd} +### ContainerD {{< feature-state for_k8s_version="v1.20" state="stable" >}} @@ -624,7 +627,7 @@ is available as a container runtime for all Windows Server 2019 and later versio See [Install MCR on Windows Servers](https://docs.mirantis.com/mcr/20.10/install/mcr-windows.html) for more information. --> -### Mirantis 容器运行时 {#mcr} +### Mirantis 容器运行时 {#mcr} [Mirantis 容器运行时](https://docs.mirantis.com/mcr/20.10/overview.html)(MCR) 可作为所有 Windows Server 2019 和更高版本的容器运行时。 @@ -641,7 +644,7 @@ operating system of Windows Server 2019 are fully supported. For Kubernetes v{{< skew currentVersion >}}, operating system compatibility for Windows nodes (and Pods) is as follows: --> -## Windows 操作系统版本兼容性 {#windows-os-version-support} +## Windows 操作系统版本兼容性 {#windows-os-version-support} 在 Windows 节点上,如果主机操作系统版本必须与容器基础镜像操作系统版本匹配, 则会应用严格的兼容性规则。 @@ -654,13 +657,79 @@ Windows Server LTSC release : Windows Server 2022 Windows Server SAC release -: Windows Server version 20H2 +: Windows Server version 20H2 也适用 Kubernetes [版本偏差策略](/zh-cn/releases/version-skew-policy/)。 + +## 硬件建议和注意事项 {#windows-hardware-recommendations} + +{{% thirdparty-content %}} + +{{< note >}} + +这里列出的硬件规格应被视为合理的默认值。 +它们并不代表生产环境的最低要求或具体推荐。 +根据你的工作负载要求,这些值可能需要进行调整。 +{{< /note >}} + + +- 64 位处理器,4 核或更多的 CPU,能够支持虚拟化 +- 8GB 或更多的 RAM +- 50GB 或更多的可用磁盘空间 + + +有关最新的最低硬件要求信息, +请参考[微软文档:Windows Server 的硬件要求](https://learn.microsoft.com/zh-cn/windows-server/get-started/hardware-requirements)。 +有关决定生产工作节点资源的指导信息, +请参考 [Kubernetes 文档:生产用工作节点](https://kubernetes.io/zh-cn/docs/setup/production-environment/#production-worker-nodes)。 + + +为了优化系统资源,如果图形用户界面不是必需的,最好选择一个不包含 +[Windows 桌面体验](https://learn.microsoft.com/zh-cn/windows-server/get-started/install-options-server-core-desktop-experience)安装选项的 +Windows Server 操作系统安装包,因为这种配置通常会释放更多的系统资源。 + + +在估算 Windows 工作节点的磁盘空间时,需要注意 Windows 容器镜像通常比 Linux 容器镜像更大, +单个镜像的容器大小范围从 [300MB 到超过 10GB](https://techcommunity.microsoft.com/t5/containers/nano-server-x-server-core-x-server-which-base-image-is-the-right/ba-p/2835785)。 +此外,需要注意 Windows 容器中的 `C:` 驱动器默认呈现的虚拟剩余空间为 20GB, +这不是实际的占用空间,而是使用主机上的本地存储时单个容器可以最多占用的磁盘大小。 +有关更多详细信息, +请参见[在 Windows 上运行容器 - 容器存储文档](https://learn.microsoft.com/zh-cn/virtualization/windowscontainers/manage-containers/container-storage#storage-limits)。 + -## 获取帮助和故障排查 {#troubleshooting} +## 获取帮助和故障排查 {#troubleshooting} 对 Kubernetes 集群进行故障排查的主要帮助来源应始于[故障排查](/zh-cn/docs/tasks/debug/)页面。 @@ -695,17 +764,36 @@ reported previously and comment with your experience on the issue and add additi logs. SIG Windows channel on the Kubernetes Slack is also a great avenue to get some initial support and troubleshooting ideas prior to creating a ticket. --> -### 报告问题和功能请求 {#report-issue-and-feature-request} +### 报告问题和功能请求 {#report-issue-and-feature-request} 如果你发现疑似 bug,或者你想提出功能请求,请按照 [SIG Windows 贡献指南](https://github.com/kubernetes/community/blob/master/sig-windows/CONTRIBUTING.md#reporting-issues-and-feature-requests) -新建一个 Issue。 -你应该先搜索 issue 列表,以防之前报告过这个问题,凭你对该问题的经验添加评论, -并随附日志信息。 -Kubernetes Slack 上的 SIG Windows 频道也是一个很好的途径, +新建一个 Issue。你应该先搜索 Issue 列表,以防之前报告过这个问题,凭你对该问题的经验添加评论, +并随附日志信息。Kubernetes Slack 上的 SIG Windows 频道也是一个很好的途径, 可以在创建工单之前获得一些初始支持和故障排查思路。 -## {{% heading "whatsnext" %}} + + +### 验证 Windows 集群的操作性 {#validating-windows-cluster-operability} + +Kubernetes 项目提供了 **Windows 操作准备** 规范,配备了结构化的测试套件。 +这个套件分为两组测试:核心和扩展。每组测试都包含了针对特定场景的分类测试。 +它可以用来验证 Windows 和混合系统(混合了 Linux 节点)的所有功能,实现全面覆盖。 + +要在新创建的集群上搭建此项目, +请参考[项目指南](https://github.com/kubernetes-sigs/windows-operational-readiness/blob/main/README.md)中的说明。 + -## 部署工具 {#deployment-tools} +## 部署工具 {#deployment-tools} kubeadm 工具帮助你部署 Kubernetes 集群,提供管理集群的控制平面以及运行工作负载的节点。 @@ -732,7 +820,7 @@ Information on the different Windows Server servicing channels including their support models can be found at [Windows Server servicing channels](https://docs.microsoft.com/en-us/windows-server/get-started/servicing-channels-comparison). --> -## Windows 分发渠道 {#windows-distribution-channels} +## Windows 分发渠道 {#windows-distribution-channels} 有关 Windows 分发渠道的详细阐述,请参考 [Microsoft 文档](https://docs.microsoft.com/zh-cn/windows-server/get-started-19/servicing-channels-19)。 diff --git a/content/zh-cn/docs/concepts/workloads/autoscaling.md b/content/zh-cn/docs/concepts/workloads/autoscaling.md new file mode 100644 index 0000000000000..7cee0b79f3b31 --- /dev/null +++ b/content/zh-cn/docs/concepts/workloads/autoscaling.md @@ -0,0 +1,293 @@ +--- +title: 自动扩缩工作负载 +description: >- + 通过自动扩缩,你可以用某种方式自动更新你的工作负载。在面对资源需求变化的时候可以使你的集群更灵活、更高效。 +content_type: concept +weight: 40 +--- + + + + + +在 Kubernetes 中,你可以根据当前的资源需求**扩缩**工作负载。 +这让你的集群可以更灵活、更高效地面对资源需求的变化。 + +当你扩缩工作负载时,你可以增加或减少工作负载所管理的副本数量,或者就地调整副本的可用资源。 + +第一种手段称为**水平扩缩**,第二种称为**垂直扩缩**。 + +扩缩工作负载有手动和自动两种方式,这取决于你的使用情况。 + + + + +## 手动扩缩工作负载 {#scaling-workloads-manually} + + +Kubernetes 支持工作负载的手动扩缩。水平扩缩可以使用 `kubectl` 命令行工具完成。 +对于垂直扩缩,你需要**更新**工作负载的资源定义。 + +这两种策略的示例见下文。 + + +- **水平扩缩**:[运行应用程序的多个实例](/docs/tutorials/kubernetes-basics/scale/scale-intro/) +- **垂直扩缩**:[调整分配给容器的 CPU 和内存资源](/docs/tasks/configure-pod-container/resize-container-resources) + + +## 自动扩缩工作负载 {#scaling-workloads-automatically} + + +Kubernetes 也支持工作负载的**自动扩缩**,这也是本页的重点。 + + +在 Kubernetes 中**自动扩缩**的概念是指自动更新管理一组 Pod 的能力(例如 +{{< glossary_tooltip text="Deployment" term_id="deployment" >}})。 + + +### 水平扩缩工作负载 {#scaling-workloads-horizontally} + + +在 Kubernetes 中,你可以使用 HorizontalPodAutoscaler (HPA) 实现工作负载的自动水平扩缩。 + + +它以 Kubernetes API 资源和{{< glossary_tooltip text="控制器" term_id="controller" >}}的方式实现, +并定期调整工作负载中{{< glossary_tooltip text="副本" term_id="replica" >}}的数量 +以满足设置的资源利用率,如 CPU 或内存利用率。 + + +这是一个为 Deployment 部署配置 HorizontalPodAutoscaler 的[示例教程](/docs/tasks/run-application/horizontal-pod-autoscale-walkthrough)。 + + +### 垂直扩缩工作负载 {#scaling-workloads-vertically} + +{{< feature-state for_k8s_version="v1.25" state="stable" >}} + + +你可以使用 VerticalPodAutoscaler (VPA) 实现工作负载的垂直扩缩。 +不同于 HPA,VPA 并非默认来源于 Kubernetes,而是一个独立的项目, +参见 [on GitHub](https://github.com/kubernetes/autoscaler/tree/9f87b78df0f1d6e142234bb32e8acbd71295585a/vertical-pod-autoscaler)。 + + +安装后,你可以为工作负载创建 {{< glossary_tooltip text="CustomResourceDefinitions" term_id="customresourcedefinition" >}}(CRDs), +定义**如何**以及**何时**扩缩被管理副本的资源。 + +{{< note >}} + +你需要在集群中安装 [Metrics Server](https://github.com/kubernetes-sigs/metrics-server),这样,你的 HPA 才能正常工作。 +{{< /note >}} + + +目前,VPA 可以有四种不同的运行模式: + + +{{< table caption="VPA 的不同模式" >}} +模式 | 描述 +:----|:----------- +`Auto` | 目前是 `Recreate`,将来可能改为就地更新 +`Recreate` | VPA 会在创建 Pod 时分配资源请求,并且当请求的资源与新的建议值区别很大时通过驱逐 Pod 的方式来更新现存的 Pod +`Initial` | VPA 只有在创建时分配资源请求,之后不做更改 +`Off` | VPA 不会自动更改 Pod 的资源需求,建议值仍会计算并可在 VPA 对象中查看 +{{< /table >}} + + +#### 就地调整的要求 + +{{< feature-state for_k8s_version="v1.27" state="alpha" >}} + + +在**不**重启 {{< glossary_tooltip text="Pod" term_id="pod" >}} 或其中{{< glossary_tooltip text="容器" term_id="container" >}}就地调整工作负载的情况下要求 Kubernetes 版本大于 1.27。 +此外,特性门控 `InPlaceVerticalScaling` 需要开启。 + +{{< feature-gate-description name="InPlacePodVerticalScaling" >}} + + +### 根据集群规模自动扩缩 {#autoscaling-based-on-cluster-size} + + +对于需要根据集群规模实现扩缩的工作负载(例如:`cluster-dns` 或者其他系统组件), +你可以使用 [Cluster Proportional Autoscaler](https://github.com/kubernetes-sigs/cluster-proportional-autoscaler)。 +与 VPA 一样,这个项目不是 Kubernetes 核心项目的一部分,它在 GitHub 上有自己的项目。 + + +集群弹性伸缩器 (Cluster Proportional Autoscaler) 会观测可调度 {{< glossary_tooltip text="节点" term_id="node" >}} 和 内核数量, +并调整目标工作负载的副本数量。 + + +如果副本的数量需要保持一致,你可以使用 [Cluster Proportional Vertical Autoscaler](https://github.com/kubernetes-sigs/cluster-proportional-vertical-autoscaler) 来根据集群规模进行垂直扩缩。 +这个项目目前处于 **beta** 阶段,你可以在 GitHub 上找到它。 + + +集群弹性伸缩器会扩缩工作负载的副本数量,垂直集群弹性伸缩器 (Cluster Proportional Vertical Autoscaler) 会根据节点和/或核心的数量 +调整工作负载的资源请求(例如 Deployment 和 DaemonSet)。 + + +### 事件驱动型自动扩缩 {#event-driven-autoscaling} + + +通过事件驱动实现工作负载的扩缩也是可行的, +例如使用 [Kubernetes Event Driven Autoscaler (**KEDA**)](https://keda.sh/)。 + + +KEDA 是 CNCF 的毕业项目,能让你根据要处理事件的数量对工作负载进行扩缩,例如队列中消息的数量。 +有多种针对不同事件源的适配可供选择。 + + +### 根据计划自动扩缩 {#autoscaling-based-on-schedules} + + +扩缩工作负载的另一种策略是**计划**进行扩缩,例如在非高峰时段减少资源消耗。 + + +与事件驱动型自动扩缩相似,这种行为可以使用 KEDA 和 [`Cron` scaler](https://keda.sh/docs/2.13/scalers/cron/) 实现。 +你可以在计划扩缩器 (Cron scaler) 中定义计划来实现工作负载的横向扩缩。 + + +## 扩缩集群基础设施 {#scaling-cluster-infrastructure} + + +如果扩缩工作负载无法满足你的需求,你也可以扩缩集群基础设施本身。 + + +扩缩集群基础设施通常是指增加或移除{{< glossary_tooltip text="节点" term_id="node" >}}。 + + +阅读[集群自动扩缩](/zh-cn/docs/concepts/cluster-administration/cluster-autoscaling/)了解更多信息。 + +## {{% heading "whatsnext" %}} + + +- 了解有关横向扩缩的更多信息 + - [扩缩 StatefulSet](/zh-cn/docs/tasks/run-application/scale-stateful-set/) + - [HorizontalPodAutoscaler 演练](/zh-cn/docs/tasks/run-application/horizontal-pod-autoscale-walkthrough/) +- [调整分配给容器的 CPU 和内存资源](/zh-cn/docs/tasks/configure-pod-container/resize-container-resources/) +- [自动扩缩集群 DNS 服务](/zh-cn/docs/tasks/administer-cluster/dns-horizontal-autoscaling/) +- 了解[集群自动扩缩]((/zh-cn/docs/concepts/cluster-administration/cluster-autoscaling/)) diff --git a/content/zh-cn/docs/concepts/workloads/controllers/cron-jobs.md b/content/zh-cn/docs/concepts/workloads/controllers/cron-jobs.md index c6f4f89a8e265..778f3566687ee 100644 --- a/content/zh-cn/docs/concepts/workloads/controllers/cron-jobs.md +++ b/content/zh-cn/docs/concepts/workloads/controllers/cron-jobs.md @@ -367,26 +367,22 @@ Go 标准库中的时区数据库包含在二进制文件中,并用作备用 ### 不支持的时区规范 {#unsupported-timezone-spec} -Kubernetes {{< skew currentVersion >}} 中的 CronJob API 实现允许你设置 -`.spec.schedule` 字段,在其中包括时区信息; -例如 `CRON_TZ=UTC * * * * *` 或 `TZ=UTC * * * * *`。 +在 `.spec.schedule` 中通过 `CRON_TZ` 或 `TZ` 变量来指定时区**并未得到官方支持**(而且从未支持过)。 -以这种方式指定时区是 **未正式支持的**(而且也从未正式支持过)。 - -如果你尝试设置包含 `TZ` 或 `CRON_TZ` 时区规范的排期表, -Kubernetes 会向客户端报告一条[警告](/blog/2020/09/03/warnings/)。 -后续的 Kubernetes 版本将完全阻止设置非正式的时区机制。 +从 Kubernetes 1.29 版本开始,如果你尝试设定包含 `TZ` 或 `CRON_TZ` 时区规范的排期表, +Kubernetes 将无法创建该资源,并会报告验证错误。 +对已经设置 `TZ` 或 `CRON_TZ` 的 CronJob 进行更新时, +系统会继续向客户端发送[警告](/zh-cn/blog/2020/09/03/warnings/)。 除了应用容器,Pod 还可以包含在 Pod 启动期间运行的 -[Init 容器](/zh-cn/docs/concepts/workloads/pods/init-containers/)。 -你也可以在集群支持[临时性容器](/zh-cn/docs/concepts/workloads/pods/ephemeral-containers/)的情况下, -为调试的目的注入临时性容器。 +{{< glossary_tooltip text="Init 容器" term_id="init-container" >}}。 +你也可以注入{{< glossary_tooltip text="临时性容器" term_id="ephemeral-container" >}}来调试正在运行的 Pod。 @@ -78,6 +77,42 @@ Pod 的共享上下文包括一组 Linux 名字空间、控制组(cgroup)和 Pod 类似于共享名字空间并共享文件系统卷的一组容器。 + +Kubernetes 集群中的 Pod 主要有两种用法: + +* **运行单个容器的 Pod**。"每个 Pod 一个容器"模型是最常见的 Kubernetes 用例; + 在这种情况下,可以将 Pod 看作单个容器的包装器,并且 Kubernetes 直接管理 Pod,而不是容器。 +* **运行多个协同工作的容器的 Pod**。 + Pod 可以封装由紧密耦合且需要共享资源的[多个并置容器](#how-pods-manage-multiple-containers)组成的应用。 + 这些位于同一位置的容器构成一个内聚单元。 + + + 将多个并置、同管的容器组织到一个 Pod 中是一种相对高级的使用场景。 + 只有在一些场景中,容器之间紧密关联时你才应该使用这种模式。 + + 你不需要运行多个容器来扩展副本(为了弹性或容量); + 如果你需要多个副本,请参阅[工作负载管理](/zh-cn/docs/concepts/workloads/controllers/)。 + 通常你不需要直接创建 Pod,甚至单实例 Pod。相反,你会使用诸如 {{< glossary_tooltip text="Deployment" term_id="deployment" >}} 或 @@ -125,40 +158,6 @@ Pods in a Kubernetes cluster are used in two main ways: 如果 Pod 需要跟踪状态,可以考虑 {{< glossary_tooltip text="StatefulSet" term_id="statefulset" >}} 资源。 -Kubernetes 集群中的 Pod 主要有两种用法: - - -* **运行单个容器的 Pod**。"每个 Pod 一个容器" 模型是最常见的 Kubernetes 用例; - 在这种情况下,可以将 Pod 看作单个容器的包装器,并且 Kubernetes 直接管理 Pod,而不是容器。 -* **运行多个协同工作的容器的 Pod**。 - Pod 可能封装由多个紧密耦合且需要共享资源的共处容器组成的应用程序。 - 这些位于同一位置的容器可能形成单个内聚的服务单元 —— 一个容器将文件从共享卷提供给公众, - 而另一个单独的 “边车”(sidecar)容器则刷新或更新这些文件。 - Pod 将这些容器和存储资源打包为一个可管理的实体。 - - {{< note >}} - - 将多个并置、同管的容器组织到一个 Pod 中是一种相对高级的使用场景。 - 只有在一些场景中,容器之间紧密关联时你才应该使用这种模式。 - {{< /note >}} - -### Pod 怎样管理多个容器 {#how-pods-manage-multiple-containers} - -Pod 被设计成支持形成内聚服务单元的多个协作过程(形式为容器)。 -Pod 中的容器被自动安排到集群中的同一物理机或虚拟机上,并可以一起进行调度。 -容器之间可以共享资源和依赖、彼此通信、协调何时以及何种方式终止自身。 - - -例如,你可能有一个容器,为共享卷中的文件提供 Web 服务器支持,以及一个单独的 -"边车 (sidercar)" 容器负责从远端更新这些文件,如下图所示: - -{{< figure src="/zh-cn/docs/images/pod.svg" alt="Pod 创建示意图" class="diagram-medium" >}} - - -有些 Pod 具有 {{< glossary_tooltip text="Init 容器" term_id="init-container" >}}和 -{{< glossary_tooltip text="应用容器" term_id="app-container" >}}。 -Init 容器会在启动应用容器之前运行并完成。 - -{{< feature-state for_k8s_version="v1.29" state="beta" >}} - - -启用 `SidecarContainers` [特性门控](/zh-cn/docs/reference/command-line-tools-reference/feature-gates/)(默认启用)允许你为 -Init 容器指定 `restartPolicy: Always`。设置重启策略为 `Always` 会确保 Init 容器在 Pod 的整个生命周期内保持运行。 -更多细节参阅[边车容器和重启策略](/zh-cn/docs/concepts/workloads/pods/init-containers/#sidecar-containers-and-restartpolicy) - +### Pod 管理多个容器 {#how-pods-manage-multiple-containers} + +Pod 被设计成支持构造内聚的服务单元的多个协作进程(形式为容器)。 +Pod 中的容器被自动并置到集群中的同一物理机或虚拟机上,并可以一起进行调度。 +容器之间可以共享资源和依赖、彼此通信、协调何时以及何种方式终止自身。 + + + + +Kubernetes 集群中的 Pod 主要有两种用法: + +* **运行单个容器的 Pod**。"每个 Pod 一个容器" 模型是最常见的 Kubernetes 用例; + 在这种情况下,可以将 Pod 看作单个容器的包装器。Kubernetes 直接管理 Pod,而不是容器。 +* **运行多个需要协同工作的容器的 Pod**。 + Pod 可以封装由多个紧密耦合且需要共享资源的并置容器组成的应用。 + 这些位于同一位置的容器可能形成单个内聚的服务单元 —— 一个容器将文件从共享卷提供给公众, + 而另一个单独的{{< glossary_tooltip text="边车容器" term_id="sidecar-container" >}}则刷新或更新这些文件。 + Pod 将这些容器和存储资源打包为一个可管理的实体。 + + +例如,你可能有一个容器,为共享卷中的文件提供 Web 服务器支持,以及一个单独的 +[边车(Sidercar)](/zh-cn/docs/concepts/workloads/pods/sidecar-containers/) +容器负责从远端更新这些文件,如下图所示: + +{{< figure src="/zh-cn/docs/images/pod.svg" alt="Pod 创建示意图" class="diagram-medium" >}} + + +有些 Pod 具有 {{< glossary_tooltip text="Init 容器" term_id="init-container" >}}和 +{{< glossary_tooltip text="应用容器" term_id="app-container" >}}。 +Init 容器默认会在启动应用容器之前运行并完成。 + + +你还可以拥有为主应用 Pod 提供辅助服务的 +[边车容器](/zh-cn/docs/concepts/workloads/pods/sidecar-containers/)(例如:服务网格)。 + + +{{< feature-state for_k8s_version="v1.29" state="beta" >}} + + +启用 `SidecarContainers` [特性门控](/zh-cn/docs/reference/command-line-tools-reference/feature-gates/)(默认启用)允许你为 +Init 容器指定 `restartPolicy: Always`。设置重启策略为 `Always` 会确保设置的 Init 容器被视为**边车**, +并在 Pod 的整个生命周期内保持运行。 +更多细节参阅[边车容器和重启策略](/zh-cn/docs/concepts/workloads/pods/init-containers/#sidecar-containers-and-restartpolicy) + +在 Kubernetes 中,[边车容器](/zh-cn/docs/concepts/workloads/pods/sidecar-containers/) +是在主应用容器之前启动并**持续运行**的容器。本文介绍 Init 容器:在 Pod 初始化期间完成运行的容器。 + ### 与普通容器的不同之处 {#differences-from-regular-containers} @@ -104,13 +104,60 @@ Init 容器支持应用容器的全部字段和特性,包括资源限制、 然而,Init 容器对资源请求和限制的处理稍有不同, 在下面[容器内的资源共享](#resource-sharing-within-containers)节有说明。 -同时 Init 容器不支持 `lifecycle`、`livenessProbe`、`readinessProbe` 和 `startupProbe`, -因为它们必须在 Pod 就绪之前运行完成。 + +常规的 Init 容器(即不包括边车容器)不支持 `lifecycle`、`livenessProbe`、`readinessProbe` 或 +`startupProbe` 字段。Init 容器必须在 Pod 准备就绪之前完成运行;而边车容器在 Pod 的生命周期内继续运行, +它支持一些探针。有关边车容器的细节请参阅[边车容器](/zh-cn/docs/concepts/workloads/pods/sidecar-containers/)。 + 如果为一个 Pod 指定了多个 Init 容器,这些容器会按顺序逐个运行。 每个 Init 容器必须运行成功,下一个才能够运行。当所有的 Init 容器运行完成时, Kubernetes 才会为 Pod 初始化应用容器并像平常一样运行。 + +### 与边车容器的不同之处 {#differences-from-sidecar-containers} + +Init 容器在主应用容器启动之前运行并完成其任务。 +与[边车容器](/zh-cn/docs/concepts/workloads/pods/sidecar-containers)不同, +Init 容器不会持续与主容器一起运行。 + + +Init 容器按顺序完成运行,等到所有 Init 容器成功完成之后,主容器才会启动。 + +Init 容器不支持 `lifecycle`、`livenessProbe`、`readinessProbe` 或 `startupProbe`, +而边车容器支持所有这些[探针](/zh-cn/docs/concepts/workloads/pods/pod-lifecycle/#types-of-probe)以控制其生命周期。 + + +Init 容器与主应用容器共享资源(CPU、内存、网络),但不直接与主应用容器进行交互。 +不过这些容器可以使用共享卷进行数据交换。 + -#### 边车容器 API {#api-for-sidecar-containers} - -{{< feature-state for_k8s_version="v1.28" state="alpha" >}} - - -Kubernetes 自 1.28 版本起引入了一个名为 `SidecarContainers` 的 Alpha 特性门控, -允许你为 Init 容器指定独立于 Pod 和其他 Init 容器的 `restartPolicy`。 -你还可以添加容器[探针](/zh-cn/docs/concepts/workloads/pods/pod-lifecycle/#types-of-probe)来控制 -Init 容器的生命周期。 - - -如果 Init 容器被创建时 `restartPolicy` 设置为 `Always`,则 Init 容器将启动并在整个 Pod -的生命期内保持运行,这对于运行与主应用容器分离的支持服务非常有用。 - -如果为该 Init 容器指定了 `readinessProbe`,则其结果将用于确定 Pod 的 `ready` 状态。 - - -由于这些容器以 Init 容器的形式定义,所以它们具有与其他 Init 容器相同的按序执行和顺序保证优势, -从而允许使用这些容器与其他 Init 容器混合在一起构造复杂的 Pod 初始化流程。 - -与常规的 Init 容器相比,只要 kubelet 将边车风格的 Init 容器的 `started` 容器状态设置为 true, -边车风格的 Init 容器会继续运行,下一个 Init 容器可以开始启动。 -到达该状态的前提是,要么需要容器中有进程正在运行且未定义启动探针,要么其 `startupProbe` 的结果是成功的。 - - -此特性可用于以更稳健的方式实现边车容器模式,这是因为如果某个边车容器失败,kubelet 总会重新启动它。 - -以下是一个具有两个容器的 Deployment 示例,其中一个是边车: - -{{% code_sample language="yaml" file="application/deployment-sidecar.yaml" %}} - - -此特性也可用于运行带有边车的 Job,因为在主容器完成后,边车容器不会阻止 Job 完成。 - -以下是一个具有两个容器的 Job 示例,其中一个是边车: - -{{% code_sample language="yaml" file="application/job/job-sidecar.yaml" %}} - #### 容器内的资源共享 {#resource-sharing-within-containers} -在给定的 Init 容器执行顺序下,资源使用适用于如下规则: +在给定的 Init、边车和应用容器执行顺序下,资源使用适用于如下规则: 配额和限制适用于有效 Pod 的请求和限制值。 -Pod 级别的 cgroups 是基于有效 Pod 的请求和限制值,和调度器相同。 + +Pod 级别的控制组(Cgroup)是基于 Pod 的有效 request 和 limit,与调度器相同。 +这部分内容也出现在[边车容器](/zh-cn/docs/concepts/workloads/pods/sidecar-containers/)页面上。 +如果你正在编辑这部分内容,请同时修改两处。 +{{< /comment >}} + -* 阅读[创建包含 Init 容器的 Pod](/zh-cn/docs/tasks/configure-pod-container/configure-pod-initialization/#create-a-pod-that-has-an-init-container) -* 学习如何[调试 Init 容器](/zh-cn/docs/tasks/debug/debug-application/debug-init-containers/) -* 阅读 [kubelet](/zh-cn/docs/reference/command-line-tools-reference/kubelet/) 和 +进一步了解以下内容: + +* [创建包含 Init 容器的 Pod](/zh-cn/docs/tasks/configure-pod-container/configure-pod-initialization/#create-a-pod-that-has-an-init-container) +* [调试 Init 容器](/zh-cn/docs/tasks/debug/debug-application/debug-init-containers/) +* [kubelet](/zh-cn/docs/reference/command-line-tools-reference/kubelet/) 和 [kubectl](/zh-cn/docs/reference/kubectl/) 的概述。 -* 了解探针的[类型](/zh-cn/docs/concepts/workloads/pods/pod-lifecycle/#types-of-probe): +* [探针类型](/zh-cn/docs/concepts/workloads/pods/pod-lifecycle/#types-of-probe): 存活态探针、就绪态探针、启动探针。 +* [边车容器](/zh-cn/docs/concepts/workloads/pods/sidecar-containers)。 diff --git a/content/zh-cn/docs/concepts/workloads/pods/pod-lifecycle.md b/content/zh-cn/docs/concepts/workloads/pods/pod-lifecycle.md index ba1c6d8f14490..e533fbe698a91 100644 --- a/content/zh-cn/docs/concepts/workloads/pods/pod-lifecycle.md +++ b/content/zh-cn/docs/concepts/workloads/pods/pod-lifecycle.md @@ -320,7 +320,7 @@ Pod 级别的 `restartPolicy` 字段:在 Kubernetes 中,Sidecar 被定义为 When the kubelet is handling container restarts according to the configured restart policy, that only applies to restarts that make replacement containers inside the same Pod and running on the same node. After containers in a Pod exit, the kubelet -restarts them with an exponential back-off delay (10s, 20s,40s, …), that is capped at +restarts them with an exponential back-off delay (10s, 20s, 40s, …), that is capped at five minutes. Once a container has executed for 10 minutes without any problems, the kubelet resets the restart backoff timer for that container. [Sidecar containers and Pod lifecycle](/docs/concepts/workloads/pods/sidecar-containers/#sidecar-containers-and-pod-lifecycle) diff --git a/content/zh-cn/docs/concepts/workloads/pods/pod-qos.md b/content/zh-cn/docs/concepts/workloads/pods/pod-qos.md index cac5fc0488e55..f74a6f07e1431 100644 --- a/content/zh-cn/docs/concepts/workloads/pods/pod-qos.md +++ b/content/zh-cn/docs/concepts/workloads/pods/pod-qos.md @@ -164,7 +164,7 @@ CPU request 时,Pod 才是 `BestEffort`。Pod 中的容器可以请求(除 C --> ## 使用 cgroup v2 的内存 QoS {#memory-qos-with-cgroup-v2} -{{< feature-state for_k8s_version="v1.22" state="alpha" >}} +{{< feature-state feature-gate-name="MemoryQoS" >}} + + +{{< feature-state for_k8s_version="v1.29" state="beta" >}} + + +边车容器是与主应用容器在同一个 {{< glossary_tooltip text="Pod" term_id="pod" >}} 中运行的辅助容器。 +这些容器通过提供额外的服务或功能(如日志记录、监控、安全性或数据同步)来增强或扩展主应用容器的功能, +而无需直接修改主应用代码。 + + + + +## 启用边车容器 {#enabling-sidecar-containers} + +Kubernetes 1.29 默认启用,一个名为 `SidecarContainers` +的[特性门控](/zh-cn/docs/reference/command-line-tools-reference/feature-gates/)允许你为 +Pod 的 `initContainers` 字段中列出的容器指定 `restartPolicy`。这些可重启的**边车**容器与同一 +Pod 内的其他 [Init 容器](/zh-cn/docs/concepts/workloads/pods/init-containers/)及主应用容器相互独立。 +边车容器可以在不影响主应用容器和其他 Init 容器的情况下启动、停止或重启。 + + +## 边车容器和 Pod 生命周期 {#sidecar-containers-and-pod-lifecyle} + +如果创建 Init 容器时将 `restartPolicy` 设置为 `Always`, +则它将在整个 Pod 的生命周期内启动并持续运行。这对于运行与主应用容器分离的支持服务非常有帮助。 + + +如果为此 Init 容器指定了 `readinessProbe`,其结果将用于确定 Pod 的 `ready` 状态。 + +由于这些容器被定义为 Init 容器,所以它们享有与其他 Init 容器相同的顺序和按序执行保证, +可以将它们与其他 Init 容器混合在一起,形成复杂的 Pod 初始化流程。 + + +与常规 Init 容器相比,在 `initContainers` 中定义的边车容器在启动后继续运行。 +当 Pod 的 `.spec.initContainers` 中有多个条目时,这一点非常重要。 +在边车风格的 Init 容器运行后(kubelet 将该 Init 容器的 `started` 状态设置为 true), +kubelet 启动 `.spec.initContainers` 这一有序列表中的下一个 Init 容器。 +该状态要么因为容器中有一个正在运行的进程且没有定义启动探针而变为 true, +要么是其 `startupProbe` 成功而返回的结果。 + + +以下是一个具有两个容器的 Deployment 示例,其中一个是边车: + +{{% code_sample language="yaml" file="application/deployment-sidecar.yaml" %}} + + +此特性也适用于带有边车的 Job,因为边车容器在主容器完成后不会阻止 Job 的完成。 + +以下是一个具有两个容器的 Job 示例,其中一个是边车: + +{{% code_sample language="yaml" file="application/job/job-sidecar.yaml" %}} + + +## 与常规容器的区别 {#differences-from-regular-containers} + +边车容器与同一 Pod 中的常规容器并行运行。不过边车容器不执行主应用逻辑,而是为主应用提供支持功能。 + + +边车容器具有独立的生命周期。它们可以独立于常规容器启动、停止和重启。 +这意味着你可以更新、扩展或维护边车容器,而不影响主应用。 + +边车容器与主容器共享相同的网络和存储命名空间。这种共存使它们能够紧密交互并共享资源。 + + +## 与 Init 容器的区别 {#differences-from-init-containers} + +边车容器与主容器并行工作,扩展其功能并提供附加服务。 + + +边车容器与主应用容器同时运行。它们在整个 Pod 的生命周期中都处于活动状态,并且可以独立于主容器启动和停止。 +与 [Init 容器](/zh-cn/docs/concepts/workloads/pods/init-containers/)不同, +边车容器支持[探针](/zh-cn/docs/concepts/workloads/pods/pod-lifecycle/#types-of-probe)来控制其生命周期。 + + +这些边车容器可以直接与主应用容器进行交互,共享相同的网络命名空间、文件系统和环境变量。 +所有这些容器紧密合作,提供额外的功能。 + +## 容器内的资源共享 {#resource-sharing-within-containers} + +{{< comment >}} + +这部分内容也出现在 [Init 容器](/zh-cn/docs/concepts/workloads/pods/init-containers/)页面上。 +如果你正在编辑这部分内容,请同时修改两处。 +{{< /comment >}} + + +假如执行顺序为 Init 容器、边车容器和应用容器,则关于资源用量适用以下规则: + + +* 所有 Init 容器上定义的任何特定资源的 limit 或 request 的最大值,作为 + Pod **有效初始 request/limit**。 + 如果任何资源没有指定资源限制,则被视为最高限制。 +* Pod 对资源的 **有效 limit/request** 是如下两者中的较大者: + * 所有应用容器对某个资源的 limit/request 之和 + * Init 容器中对某个资源的有效 limit/request +* 系统基于有效的 limit/request 完成调度,这意味着 Init 容器能够为初始化过程预留资源, + 而这些资源在 Pod 的生命周期中不再被使用。 +* Pod 的 **有效 QoS 级别**,对于 Init 容器和应用容器而言是相同的。 + + +配额和限制适用于 Pod 的有效请求和限制值。 + +Pod 级别的 cgroup 是基于 Pod 的有效请求和限制值,与调度器相同。 + +## {{% heading "whatsnext" %}} + + +* 阅读关于[原生边车容器](/zh-cn/blog/2023/08/25/native-sidecar-containers/)的博文。 +* 阅读[如何创建具有 Init 容器的 Pod](/zh-cn/docs/tasks/configure-pod-container/configure-pod-initialization/#create-a-pod-that-has-an-init-container)。 +* 了解[探针类型](/zh-cn/docs/concepts/workloads/pods/pod-lifecycle/#types-of-probe): + 存活态探针、就绪态探针、启动探针。 +* 了解 [Pod 开销](/zh-cn/docs/concepts/scheduling-eviction/pod-overhead/)。 diff --git a/content/zh-cn/docs/contribute/analytics.md b/content/zh-cn/docs/contribute/analytics.md index 9050cf0cf5be9..1a8d5f3c41798 100644 --- a/content/zh-cn/docs/contribute/analytics.md +++ b/content/zh-cn/docs/contribute/analytics.md @@ -26,13 +26,13 @@ This page contains information about the kubernetes.io analytics dashboard. -[查看仪表板](https://datastudio.google.com/reporting/fede2672-b2fd-402a-91d2-7473bdb10f04)。 +[查看仪表板](https://lookerstudio.google.com/u/0/reporting/fe615dc5-59b0-4db5-8504-ef9eacb663a9/page/4VDGB/)。 -此仪表板使用 Google Data Studio 构建,显示使用 Google Analytics 在 kubernetes.io 上收集的信息。 +此仪表板使用 [Google Looker Studio](https://lookerstudio.google.com/overview) 构建,并显示自 2022 年 8 月以来使用 Google Analytics 4 在 kubernetes.io 上收集的信息。 -### 使用仪表板 +### 使用仪表板 {#using-the-dashboard} 默认情况下,仪表板显示过去 30 天收集的所有分析。 使用日期选择器查看来自不同日期范围的数据。 diff --git a/content/zh-cn/docs/contribute/localization.md b/content/zh-cn/docs/contribute/localization.md index 3f80f71ae7c08..e630d6cfcb7df 100644 --- a/content/zh-cn/docs/contribute/localization.md +++ b/content/zh-cn/docs/contribute/localization.md @@ -341,13 +341,21 @@ script and use it in the theme. Assign "language name in latin script" to 例如,`languageNameLatinScript ="Korean"` 或 `languageNameLatinScript = "Deutsch"`。 +`weight` 参数决定语言选择栏中的语言顺序, +优先显示权重较低的语言。 +分配 `weight` 参数时,检查现有语言块并调整其权重以确保它们相对于所有语言 +(包括任何新添加的语言)按排序顺序非常重要。 + -为你的语言块分配一个 `weight` 参数时,找到权重最高的语言块并将其加 1。 有关 Hugo 多语言支持的更多信息,请参阅"[多语言模式](https://gohugo.io/content-management/multilingual/)"。 @@ -781,7 +789,7 @@ German (`de`): [`data/i18n/en/en.toml`](https://github.com/kubernetes/website/blob/main/data/i18n/en/en.toml) 的内容。以德语为例:`data/i18n/de/de.toml`。 -将新的本地化文件和目录添加到 `data/i18n/`。例如德语 (`de`): +将新的本地化文件和目录添加到 `data/i18n/`。例如德语(`de`): ```bash mkdir -p data/i18n/de diff --git a/content/zh-cn/docs/contribute/new-content/blogs-case-studies.md b/content/zh-cn/docs/contribute/new-content/blogs-case-studies.md index a19821a252a28..1ce75a0083fd0 100644 --- a/content/zh-cn/docs/contribute/new-content/blogs-case-studies.md +++ b/content/zh-cn/docs/contribute/new-content/blogs-case-studies.md @@ -153,7 +153,7 @@ To submit a blog post, follow these steps: to ask in real time. --> - 博客内容并非在某特定日期发表。 - - 文章会交由社区自愿者评阅。我们会尽力满足特定的时限要求,只是无法就此作出承诺。 + - 文章会交由社区自愿者评阅。我们会尽力满足特定的时限要求,只是无法就此作出承诺。 - Kubernetes 项目的很多核心组件会在发布窗口期内提交博客文章,导致发表时间被推迟。 因此,请考虑在发布周期内较为平静的时间段提交博客文章。 - 如果你希望就博文发表日期上进行较大范围的协调,请联系 @@ -189,6 +189,7 @@ To submit a blog post, follow these steps: 有些时候,某个 CNCF 项目的主要功能特性或者里程碑的变化可能是用户有兴趣在 Kubernetes 博客上阅读的内容。 - 关于为 Kubernetes 项目做贡献的博客内容应该放在 [Kubernetes 贡献者站点](https://kubernetes.dev)上。 + -- 博客文章应该是原创内容。 +- 博客文章须是原创内容。 - 官方博客的目的不是将某第三方已发表的内容重新作为新内容发表。 - 博客的[授权协议](https://github.com/kubernetes/website/blob/main/LICENSE) 的确允许出于商业目的来使用博客内容;但并不是所有可以商用的内容都适合在这里发表。 @@ -219,6 +220,10 @@ Submissions need to be in Markdown format to be used by the [Hugo](https://gohug for the blog. There are [many resources available](https://gohugo.io/documentation/) on how to use this technology stack. +For illustrations, diagrams or charts, the [figure shortcode](https://gohugo.io/content-management/shortcodes/#figure) +can be used. For other images, we strongly encourage use of alt attributes; if an image doesn't +need any alt attrribute, maybe it's not needed in the article at all. + We recognize that this requirement makes the process more difficult for less-familiar folks to submit, and we're constantly looking at solutions to lower this bar. If you have ideas on how to lower the barrier, please volunteer to help out. @@ -228,6 +233,10 @@ lower the barrier, please volunteer to help out. 所提交的内容应该是 Markdown 格式的,以便能够被 [Hugo](https://gohugo.io/) 生成器来处理。 关于如何使用相关技术,有[很多可用的资源](https://gohugo.io/documentation/)。 +对于插图、表格或图表,可以使用 [figure shortcode](https://gohugo.io/content-management/shortcodes/#figure)。 +对于其他图片,我们强烈建议使用 alt 属性;如果一张图片不需要任何 alt 属性, +那么这张图片在文章中就不是必需的。 + 我们知道这一需求可能给那些对此过程不熟悉的朋友们带来不便, 我们也一直在寻找降低难度的解决方案。 如果你有降低难度的好主意,请自荐帮忙。 @@ -313,9 +322,6 @@ SIG Docs 之后,机器人会将你的博文合并并发表。 +### 制作 Kubernetes 贡献者博客的镜像 {#mirroring-from-the-kubernetes-contributor-blog} + +要从 [Kubernetes 贡献者博客](https://www.kubernetes.dev/blog/)制作某篇博文的镜像,遵循以下指导原则: + + +- 保持博客内容不变。如有变更,应该先在原稿上进行更改,然后再更改到镜像的文章上。 +- 镜像博客应该有一个 `canonicalUrl`,即基本上是原始博客发布后的网址。 +- [Kubernetes 贡献者博客](https://kubernetes.dev/blog)在 YAML 头部中提及作者, + 而 Kubernetes 博文在博客内容中提及作者。你在镜像内容时应修改这一点。 +- 发布日期与原博客保持一致。 + +在制作镜像博客时,你也需遵守本文所述的所有其他指导原则和期望。 + +- 同时检查针对[参考文档生成器](https://github.com/kubernetes-sigs/reference-docs)的代码拉取请求, + 并对其进行审查(或寻求帮助)。 +- 支持[问题管理者](/zh-cn/docs/contribute/participate/issue-wrangler/)每日对新问题进行分类和标记。 + 参见[分类和组织问题](/zh-cn/docs/contribute/review/for-approvers/#triage-and-categorize-issues) + 了解 SIG Docs 如何使用元数据。 + +{{< note >}} + +PR 管理者的职责不适用于本地化 PR(非英语 PR)。 +本地化团队有自己的流程和团队来审查其语言 PR。 +但是,其对于确保被语言 PR 被正确标记,审查与语言无关的小型 PR(如链接更新),或为长期搁置的 +PR(已打开超过 6 个月且一个月或更长时间未更新的)添加审阅者或贡献者标签通常很有帮助。 +{{< /note >}} + +### 从描述文件中检索特征状态 + +要动态确定特性的状态,请使用 `feature_gate_name` 短代码参数,此参数将从 +`content/en/docs/reference/command-line-tools-reference/feature-gates/` +中相应的特性门控描述文件中提取特性的详细状态信息。 + +例如: + +``` +{{}} +``` + + +会转换为: + +{{< feature-state feature_gate_name="NodeSwap" >}} + ## 行间代码格式 {#inline-code-formatting} -### 为行间代码、命令与 API 对象使用代码样式 {#code-style-inline-code} +### 为行间代码、命令使用代码样式 {#code-style-inline-code} -对于 HTML 文档中的行间代码,使用 `` 标记。 -在 Markdown 文档中,使用反引号(`` ` ``)。 +对于 HTML 文档中的行间代码,使用 `` 标记。在 Markdown 文档中,使用反引号(`` ` ``)。 +然而,StatefulSet 或 ConfigMap 这些 API 类别是直接书写的(不用反引号);这样允许使用表示所有格的撇号。 +然而,在读者可能会将某些值与 API 类别混淆时,请考虑为这些值添加引号。 + ## 引用 Kubernetes API 资源 {#referring-to-kubernetes-api-resources} @@ -413,44 +425,83 @@ confusion with CPU and memory resources. ### 有关 “资源” 的阐述 -Kubernetes 使用 “resource” 一词来指代 API 资源,例如 `pod`、`deployment` 等。 -我们还使用 “resource” 来谈论 CPU 和内存请求和限制。 -所以始终将 API 资源称为 “API resources” 以避免与 CPU 和内存资源混淆。 +Kubernetes 使用单词 _resource_ 一词来指代 API 资源。 +例如,URL 路径 `/apis/apps/v1/namespaces/default/deployments/my-app` 表示 "default" +{{< glossary_tooltip text="名字空间" term_id="namespace" >}}中名为 "my-app" 的 Deployment。 +在 HTTP 的术语中,{{< glossary_tooltip text="名字空间" term_id="namespace" >}}是一个资源, +就像所有 Web URL 都标识一个资源。 + + +Kubernetes 文档在讨论 CPU 和内存请求以及限制也使用“资源(resource)”一词。 +将 API 资源称为 "API 资源" 往往是一个好的做法;这有助于避免与 CPU 和内存资源或其他类别的资源混淆。 + + +如果你使用资源名称的小写复数形式,例如 `deployments` 或 `configmaps`, +请提供额外的书面上下文来帮助读者理解你的用意。 +如果你使用术语时所处的上下文中使用驼峰编码(UpperCamelCase)的名称也可行,且术语存在歧义的风险, +应该考虑使用 UpperCamelCase 形式的 API 类别。 ### 何时使用 Kubernetes API 术语 不同 Kubernetes API 术语的说明如下: -- 资源类型:API URL 中使用的名称(如 `pods`、`namespaces`) -- 资源:资源类型的单个实例(如 `pod`、`secret`) -- 对象:作为 “意向记录” 的资源。对象是集群特定部分的期望状态, +- **API 类别** :API URL 中使用的名称(如 `pods`、`namespaces`)。 + API 类别有时也称为 **资源类型** 。 +- **API 资源** :API 类别的单个实例(如 `pod`、`secret`) +- **对象** :作为 “意向记录” 的资源。对象是集群特定部分的期望状态, 该状态由 Kubernetes 控制平面负责维护。 + Kubernetes API 中的所有对象也都是资源。 -在文档中引用 API 资源时始终使用 “资源” 或 “对象”。 -例如,使用 “一个 `Secret` 对象” 而不是 “一个 `Secret`”。 + +为了清晰起见,在 Kubernetes 文档中引用 API 资源时可以使用 "资源" 或 "对象"。 +例如:写成 "Secret 对象" 而不是 "Secret"。 +如果仅大写就能明确含义,那么无需添加额外的单词。 + +当修改有助于避免误解时,那就考虑修改表述。 +一个常见的情况是当你想要某个句子以 "Secret" 这种 API 类别开头时; +因为英语和其他几种语言会对句首的第一个字母大写,所以读者无法确定你说的是 API 类别还是一般概念。 +此时重新构词有助于让句子更清晰。 ## 代码段格式 {#code-snippet-formatting} @@ -495,7 +543,7 @@ kubectl get pods | $ kubectl get pods {{< table caption = "命令行提示符约定" >}} 可以 | 不可以 :--| :----- -kubectl get pods | $ kubectl get pods +`kubectl get pods` | `$ kubectl get pods` {{< /table >}} @@ -31,4 +25,5 @@ which versions of Kubernetes are officially supported, and for how long. 本网站包含当前版本和之前四个版本的 Kubernetes 文档。 Kubernetes 版本的文档可用性与当前是否支持该版本是分开的。 -阅读[支持期限](/zh-cn/releases/patch-releases/#support-period),了解官方支持 Kubernetes 的哪些版本,以及支持多长时间。 +阅读[支持期限](/zh-cn/releases/patch-releases/#support-period),了解官方支持 +Kubernetes 的哪些版本,以及支持多长时间。 diff --git a/content/zh-cn/docs/reference/command-line-tools-reference/feature-gates/readonly-apidata-volumes.md b/content/zh-cn/docs/reference/command-line-tools-reference/feature-gates/readonly-apidata-volumes.md new file mode 100644 index 0000000000000..98b0348d9eea0 --- /dev/null +++ b/content/zh-cn/docs/reference/command-line-tools-reference/feature-gates/readonly-apidata-volumes.md @@ -0,0 +1,36 @@ +--- +# Removed from Kubernetes +title: ReadOnlyAPIDataVolumes +content_type: feature_gate + +_build: + list: never + render: false + +stages: + - stage: beta + defaultValue: true + fromVersion: "1.8" + toVersion: "1.9" + - stage: stable + fromVersion: "1.10" + toVersion: "1.10" + +removed: true +--- + + +请参阅以只读方式挂载的 [`configMap`](/zh-cn/docs/concepts/storage/volumes/#configmap)、 +[`secret`](/zh-cn/docs/concepts/storage/volumes/#secret)、 +[`downwardAPI`](/zh-cn/docs/concepts/storage/volumes/#downwardapi) +和 [`projected`](/zh-cn/docs/concepts/storage/volumes/#projected) 卷。 + +自 Kubernetes v1.10 起,这些卷类型始终是只读的,无法选择其它模式。 diff --git a/content/zh-cn/docs/reference/command-line-tools-reference/feature-gates/stateful-set-auto-delete-pvc.md b/content/zh-cn/docs/reference/command-line-tools-reference/feature-gates/stateful-set-auto-delete-pvc.md index 0421cdb60db31..48a956694feb8 100644 --- a/content/zh-cn/docs/reference/command-line-tools-reference/feature-gates/stateful-set-auto-delete-pvc.md +++ b/content/zh-cn/docs/reference/command-line-tools-reference/feature-gates/stateful-set-auto-delete-pvc.md @@ -12,7 +12,7 @@ stages: fromVersion: "1.23" toVersion: "1.26" - stage: beta - defaultValue: false + defaultValue: true fromVersion: "1.27" --- [必需]
          -
          authentication/v1.UserInfo +authentication/v1.UserInfo +

          生成事件所对应的审计级别。

          @@ -58,7 +60,9 @@ Event 结构包含可出现在 API 审计日志中的所有信息。 k8s.io/apimachinery/pkg/types.UID - +

          为每个请求所生成的唯一审计 ID。

          @@ -70,7 +74,9 @@ Event 结构包含可出现在 API 审计日志中的所有信息。

          - + 生成此事件时请求的处理阶段。

          @@ -81,7 +87,9 @@ Event 结构包含可出现在 API 审计日志中的所有信息。

          - + requestURI 是客户端发送到服务器端的请求 URI。

          @@ -103,22 +111,26 @@ Event 结构包含可出现在 API 审计日志中的所有信息。 user [必需]
          -authentication/v1.UserInfo +authentication/v1.UserInfo

          - + 关于认证用户的信息。

          impersonatedUser
          -authentication/v1.UserInfo +authentication/v1.UserInfo

          - + 关于所伪装(impersonated)的用户的信息。

          @@ -162,14 +174,15 @@ Note: All but the last IP can be arbitrarily set by the client. - userAgent
          string

          - + userAgent 中记录客户端所报告的用户代理(User Agent)字符串。 注意 userAgent 信息是由客户端提供的,一定不要信任。

          @@ -181,21 +194,25 @@ Note: All but the last IP can be arbitrarily set by the client.

          - + 此请求所指向的对象引用。对于 List 类型的请求或者非资源请求,此字段可忽略。

          responseStatus
          -meta/v1.Status +meta/v1.Status

          - + For non-status type error responses, this will be auto-populated with the error Message. + --> 响应的状态,当 responseObject 不是 Status 类型时被赋值。 对于成功的请求,此字段仅包含 code 和 statusSuccess。 对于非 Status 类型的错误响应,此字段会被自动赋值为出错信息。 @@ -215,15 +232,13 @@ Note: All but the last IP can be arbitrarily set by the client. Omitted for non-resource requests. Only logged at Request Level and higher. --> 来自请求的 API 对象,以 JSON 格式呈现。requestObject 在请求中按原样记录 - (可能会采用 JSON 重新编码),之后会进入版本转换、默认值填充、准入控制以及 - 配置信息合并等阶段。此对象为外部版本化的对象类型,甚至其自身可能并不是一个 - 合法的对象。对于非资源请求,此字段被忽略。 + (可能会采用 JSON 重新编码),之后会进入版本转换、默认值填充、准入控制以及配置信息合并等阶段。 + 此对象为外部版本化的对象类型,甚至其自身可能并不是一个合法的对象。对于非资源请求,此字段被忽略。 只有当审计级别为 Request 或更高的时候才会记录。

          - responseObject
          k8s.io/apimachinery/pkg/runtime.Unknown @@ -234,19 +249,20 @@ Note: All but the last IP can be arbitrarily set by the client. to the external type, and serialized as JSON. Omitted for non-resource requests. Only logged at Response Level. --> - 响应中包含的 API 对象,以 JSON 格式呈现。responseObject 是在被转换为外部类型 - 并序列化为 JSON 格式之后才被记录的。 - 对于非资源请求,此字段会被忽略。 + 响应中包含的 API 对象,以 JSON 格式呈现。responseObject 是在被转换为外部类型并序列化为 + JSON 格式之后才被记录的。对于非资源请求,此字段会被忽略。 只有审计级别为 Response 时才会记录。

          requestReceivedTimestamp
          -meta/v1.MicroTime +meta/v1.MicroTime - +

          请求到达 API 服务器时的时间。

          @@ -254,11 +270,13 @@ Note: All but the last IP can be arbitrarily set by the client. stageTimestamp
          -meta/v1.MicroTime +meta/v1.MicroTime

          - + 请求到达当前审计阶段时的时间。

          @@ -278,8 +296,7 @@ Note: All but the last IP can be arbitrarily set by the client. should be short. Annotations are included in the Metadata level. --> annotations 是一个无结构的键-值映射,其中保存的是一个审计事件。 - 该事件可以由请求处理链路上的插件来设置,包括身份认证插件、鉴权插件以及 - 准入控制插件等。 + 该事件可以由请求处理链路上的插件来设置,包括身份认证插件、鉴权插件以及准入控制插件等。 注意这些注解是针对审计事件本身的,与所提交的对象中的 metadata.annotations 之间不存在对应关系。 映射中的键名应该唯一性地标识生成该事件的组件,从而避免名字上的冲突 @@ -309,7 +326,7 @@ EventList 是审计事件(Event)的列表。 kind
          stringEventList metadata
          -meta/v1.ListMeta +meta/v1.ListMeta 列表结构元数据 @@ -351,11 +368,13 @@ Policy 定义的是审计日志的配置以及不同类型请求的日志记录 kind
          stringPolicy metadata
          -meta/v1.ObjectMeta +meta/v1.ObjectMeta

          - + 包含 metadata 字段是为了便于与 API 基础设施之间实现互操作。

          @@ -368,15 +387,15 @@ Policy 定义的是审计日志的配置以及不同类型请求的日志记录

          - 字段 rules 设置请求要被记录的审计级别(level)。 每个请求可能会与多条规则相匹配;发生这种状况时遵从第一条匹配规则。 - 默认的审计级别是 None,不过可以在列表的末尾使用一条全抓(catch-all)规则 - 重载其设置。 + 默认的审计级别是 None,不过可以在列表的末尾使用一条全抓(catch-all)规则重载其设置。 列表中的规则(PolicyRule)是严格有序的。

          @@ -398,7 +417,6 @@ PolicyRules are strictly ordered. - omitManagedFields
          @@ -440,7 +458,7 @@ PolicyList 是由审计策略(Policy)组成的列表。 kind
          stringPolicyList metadata
          -meta/v1.ListMeta +meta/v1.ListMeta 列表结构元数据。 @@ -481,8 +499,10 @@ GroupResources 代表的是某 API 组中的资源类别。 string - + 字段 group 给出包含资源的 API 组的名称。 空字符串代表 core API 组。 @@ -493,34 +513,33 @@ GroupResources 代表的是某 API 组中的资源类别。 -

          例如:

          -
            -
          • pods 匹配 Pod;
          • -
          • pods/log 匹配 Pod 的 log 子资源;
          • -
          • * 匹配所有资源及其子资源;
          • -
          • pods/* 匹配 Pod 的所有子资源;
          • +

            resources 是此规则所适用的资源的列表。

            +

            例如:

            +
              +
            • pods 匹配 Pod。
            • +
            • pods/log 匹配 Pod 的 log 子资源。
            • +
            • * 匹配所有资源及其子资源。
            • +
            • pods/* 匹配 Pod 的所有子资源。
            • */scale 匹配所有的 scale 子资源。
            • -
            - - -

            - 如果存在通配符,则合法性检查逻辑会确保 resources 中的条目不会彼此重叠。 -

            -
            -

            - 空的列表意味着规则适用于该 API 组中的所有资源及其子资源。 -

            + +

            如果存在通配符,则合法性检查逻辑会确保 resources 中的条目不会彼此重叠。

            +

            空的列表意味着规则适用于该 API 组中的所有资源及其子资源。

            @@ -621,8 +640,10 @@ ObjectReference 包含的是用来检查或修改所引用对象时将需要的 string - +

            字段 apiGroup 给出包含所引用对象的 API 组的名称。 空字符串代表 core API 组。 @@ -634,7 +655,9 @@ ObjectReference 包含的是用来检查或修改所引用对象时将需要的 string - +

            字段 apiVersion 是包含所引用对象的 API 组的版本。

            @@ -685,7 +708,9 @@ PolicyRule 包含一个映射,基于元数据将请求映射到某审计级别 Level - +

            与此规则匹配的请求所对应的日志记录级别(Level)。

            @@ -697,8 +722,10 @@ PolicyRule 包含一个映射,基于元数据将请求映射到某审计级别

            - + 根据身份认证所确定的用户名的列表,给出此规则所适用的用户。 空列表意味着适用于所有用户。

            @@ -710,9 +737,11 @@ PolicyRule 包含一个映射,基于元数据将请求映射到某审计级别

            - + An empty list implies every user group. + --> 此规则所适用的用户组的列表。如果用户是所列用户组中任一用户组的成员,则视为匹配。 空列表意味着适用于所有用户组。

            @@ -738,7 +767,9 @@ PolicyRule 包含一个映射,基于元数据将请求映射到某审计级别 []GroupResources - +

            此规则所适用的资源类别列表。 空列表意味着适用于 API 组中的所有资源类别。 @@ -751,9 +782,11 @@ PolicyRule 包含一个映射,基于元数据将请求映射到某审计级别

            - + An empty list implies every namespace. + --> 此规则所适用的名字空间列表。 空字符串("")意味着适用于非名字空间作用域的资源。 空列表意味着适用于所有名字空间。 @@ -766,20 +799,21 @@ PolicyRule 包含一个映射,基于元数据将请求映射到某审计级别 -

            - 字段 nonResourceURLs 给出一组需要被审计的 URL 路径。 - 允许使用 *s,但只能作为路径中最后一个完整分段。 - 例如: -

            -
          • "/metrics" - 记录对 API 服务器度量值(metrics)的所有请求;
          • -
          • "/healthz*" - 记录所有健康检查请求。
          • + nonResourceURLs 是一组需要被审计的 URL 路径。 + 允许使用 *,但只能作为路径中最后一个完整分段。 + 例如:

            +
              +
            • "/metrics" - 记录对 API 服务器度量值(metrics)的所有请求;
            • +
            • "/healthz*" - 记录所有健康检查。
            @@ -802,34 +836,36 @@ PolicyRule 包含一个映射,基于元数据将请求映射到某审计级别 - - - omitManagedFields
            - bool - - - -

            - omitManagedFields 决定将请求和响应主体写入 API 审计日志时,是否省略其托管字段。 -

            -
              -
            • 值为 'true' 将从 API 审计日志中删除托管字段
            • -
            • - 值为 'false' 表示托管字段应包含在 API 审计日志中 - 请注意,如果指定此规则中的值将覆盖全局默认值。 - 如果未指定,则使用 policy.omitManagedFields 中指定的全局默认值。 -
            • -
            - - + +omitManagedFields
            +bool + + + +

            +omitManagedFields 决定将请求和响应主体写入 API 审计日志时,是否省略其托管字段。 +

            +
              +
            • 值为 'true' 将从 API 审计日志中删除托管字段
            • +
            • + 值为 'false' 表示托管字段应包含在 API 审计日志中 + 请注意,如果指定此规则中的值将覆盖全局默认值。 + 如果未指定,则使用 policy.omitManagedFields 中指定的全局默认值。 +
            • +
            + + diff --git a/content/zh-cn/docs/reference/config-api/apiserver-encryption.v1.md b/content/zh-cn/docs/reference/config-api/apiserver-encryption.v1.md deleted file mode 100644 index 943ba8594c4da..0000000000000 --- a/content/zh-cn/docs/reference/config-api/apiserver-encryption.v1.md +++ /dev/null @@ -1,465 +0,0 @@ ---- -title: kube-apiserver 加密配置(v1) -content_type: tool-reference -package: apiserver.config.k8s.io/v1 -auto_generated: true ---- - - - -

            - -包 v1 是 API 的 v1 版本。 -

            - - -## 资源类型 - -- [EncryptionConfiguration](#apiserver-config-k8s-io-v1-EncryptionConfiguration) - -## `EncryptionConfiguration` {#apiserver-config-k8s-io-v1-EncryptionConfiguration} - - -

            -EncryptionConfiguration 为加密驱动保存完整的配置信息。 -它还允许使用通配符指定应加密的资源。 -使用 *.<group> 加密组内的所有资源,或使用 *.* 加密所有资源。 -*. 可用于加密核心组内的所有资源。 -*.* 将加密所有资源,甚至是 API 服务器启动后添加的自定义资源。 -不允许在同一资源列表内或跨多个条目中使用重叠的通配符,因为部分配置将无效。 -按顺序处理资源列表,列在前面的被优先处理。 -

            - -

            例如:

            -
            kind: EncryptionConfiguration
            -apiVersion: apiserver.config.k8s.io/v1
            -resources:
            -- resources:
            -  - events
            -  providers:
            -  - identity: {}  # do not encrypt events even though *.* is specified below
            -- resources:
            -  - secrets
            -  - configmaps
            -  - pandas.awesome.bears.example
            -  providers:
            -  - aescbc:
            -      keys:
            -      - name: key1
            -        secret: c2VjcmV0IGlzIHNlY3VyZQ==
            -- resources:
            -  - '*.apps'
            -  providers:
            -  - aescbc:
            -      keys:
            -      - name: key2
            -        secret: c2VjcmV0IGlzIHNlY3VyZSwgb3IgaXMgaXQ/Cg==
            -- resources:
            -  - '*.*'
            -  providers:
            -  - aescbc:
            -      keys:
            -      - name: key3
            -        secret: c2VjcmV0IGlzIHNlY3VyZSwgSSB0aGluaw==
            - - - - - - - - - - - -
            字段描述
            apiVersion
            string
            apiserver.config.k8s.io/v1
            kind
            string
            EncryptionConfiguration
            resources [必需]
            -[]ResourceConfiguration -
            -

            - - resources 是一个包含资源及其对应的加密驱动的列表。 -

            -
            - -## `AESConfiguration` {#apiserver-config-k8s-io-v1-AESConfiguration} - - -**出现在:** - -- [ProviderConfiguration](#apiserver-config-k8s-io-v1-ProviderConfiguration) - -

            - -AESConfiguration 包含 AES 转换器的 API 配置信息。 -

            - - - - - - - - - -
            字段描述
            keys [必需]
            -[]Key -
            -

            - - keys 是一组用于创建 AES 转换器的密钥。 - 对于 AES-CBC,每个密钥必须是 32 字节长;对于 AES-GCM,每个密钥可以是 16、24、32 字节长。 -

            -
            - -## `IdentityConfiguration` {#apiserver-config-k8s-io-v1-IdentityConfiguration} - - -**出现在:** - -- [ProviderConfiguration](#apiserver-config-k8s-io-v1-ProviderConfiguration) - -

            - -IdentityConfiguration 是一个空的结构,用来支持在驱动配置中支持标识转换器。 -

            - -## `KMSConfiguration` {#apiserver-config-k8s-io-v1-KMSConfiguration} - - -**出现在:** - -- [ProviderConfiguration](#apiserver-config-k8s-io-v1-ProviderConfiguration) - -

            - -KMSConfiguration 包含基于 KMS 的封套转换器的名称、缓存大小以及配置文件路径信息。 -

            - - - - - - - - - - - - - - - - - - - - - -
            字段描述
            apiVersion
            -string -
            -

            - - KeyManagementService 的 apiVersion -

            -
            name [必需]
            -string -
            -

            - - name 是要使用的 KMS 插件名称。 -

            -
            cachesize
            -int32 -
            -

            - - cachesize 是可在内存中缓存的 Secret 数量上限。默认值是 1000。 - 将此字段设置为负值会禁用缓存。此字段仅允许用于 KMS v1 驱动。 -

            -
            endpoint [必需]
            -string -
            -

            - - endpoint 是 gRPC 服务器的监听地址,例如 "unix:///var/run/kms-provider.sock"。 -

            -
            timeout
            -meta/v1.Duration -
            -

            - - 对 KMS 插件执行 gRPC 调用的超时时长(例如:'5s')。默认值为 3 秒。 -

            -
            - -## `Key` {#apiserver-config-k8s-io-v1-Key} - - -**出现在:** - -- [AESConfiguration](#apiserver-config-k8s-io-v1-AESConfiguration) -- [SecretboxConfiguration](#apiserver-config-k8s-io-v1-SecretboxConfiguration) - -

            - -Key 中包含为某转换器所提供的键名和对应的私密数据。 -

            - - - - - - - - - - - - -
            字段描述
            name [必需]
            -string -
            -

            - - name 是在向磁盘中存储数据时使用的键名。 -

            -
            secret [必需]
            -string -
            -

            - - secret 是实际的密钥,用 base64 编码。 -

            -
            - -## `ProviderConfiguration` {#apiserver-config-k8s-io-v1-ProviderConfiguration} - - -**出现在:** - -- [ResourceConfiguration](#apiserver-config-k8s-io-v1-ResourceConfiguration) - -

            - -ProviderConfiguration 为加密驱动存储配置信息。 -

            - - - - - - - - - - - - - - - - - - - - - -
            字段描述
            aesgcm [必需]
            -AESConfiguration -
            -

            - - aesgcm 是用于 AES-GCM 转换器的配置。 -

            -
            aescbc [必需]
            -AESConfiguration -
            -

            - - aescbc 是用于 AES-CBC 转换器的配置。 -

            -
            secretbox [必需]
            -SecretboxConfiguration -
            -

            - - secretbox 是用于基于 Secretbox 的转换器的配置。 -

            -
            identity [必需]
            -IdentityConfiguration -
            -

            - - identity 是用于标识转换器的配置(空)。 -

            -
            kms [必需]
            -KMSConfiguration -
            -

            - - kms 中包含用于基于 KMS 的封套转换器的名称、缓存大小以及配置文件路径信息。 -

            -
            - -## `ResourceConfiguration` {#apiserver-config-k8s-io-v1-ResourceConfiguration} - - -**出现在:** - -- [EncryptionConfiguration](#apiserver-config-k8s-io-v1-EncryptionConfiguration) - -

            - -ResourceConfiguration 中保存资源配置。 -

            - - - - - - - - - - - - -
            字段描述
            resources [必需]
            -[]string -
            -

            - - resources 是必须要加密的 Kubernetes 资源的列表。 - 资源名称来自于组/版本/资源的 resourceresource.group。 - 例如:pandas.awesome.bears.example 是一个自定义资源, - 具有 'group': awesome.bears.example、'resource': pandas。 - 使用 *.* 加密所有资源,使用 *.<group> 加密特定组中的所有资源。 - 例如:*.awesome.bears.example 将加密组 awesome.bears.example 中的所有资源。 - 例如:*. 将加密核心组中的所有资源(如 Pod、ConfigMap 等)。 -

            -
            providers [必需]
            -[]ProviderConfiguration -
            -

            - - providers 是一个转换器列表,用来将资源写入到磁盘或从磁盘上读出。 - 例如:'aesgcm'、'aescbc'、'secretbox'、'identity'、'kms'。 -

            -
            - -## `SecretboxConfiguration` {#apiserver-config-k8s-io-v1-SecretboxConfiguration} - - -**出现在:** - -- [ProviderConfiguration](#apiserver-config-k8s-io-v1-ProviderConfiguration) - -

            - -SecretboxConfiguration 包含用于某 Secretbox 转换器的 API 配置。 -

            - - - - - - - - - -
            字段描述
            keys [必需]
            -[]Key -
            -

            - - keys 是一个密钥列表,用来创建 Secretbox 转换器。每个密钥长度必须是 32 字节。 -

            -
            diff --git a/content/zh-cn/docs/reference/config-api/client-authentication.v1.md b/content/zh-cn/docs/reference/config-api/client-authentication.v1.md index 41464dd9bc513..fa2cfdc294c1e 100644 --- a/content/zh-cn/docs/reference/config-api/client-authentication.v1.md +++ b/content/zh-cn/docs/reference/config-api/client-authentication.v1.md @@ -259,7 +259,7 @@ itself should at least be protected via file permissions. 字段描述 expirationTimestamp
            -meta/v1.Time +meta/v1.Time diff --git a/content/zh-cn/docs/reference/config-api/client-authentication.v1beta1.md b/content/zh-cn/docs/reference/config-api/client-authentication.v1beta1.md index 25c637ab360f8..aa8dcff48db95 100644 --- a/content/zh-cn/docs/reference/config-api/client-authentication.v1beta1.md +++ b/content/zh-cn/docs/reference/config-api/client-authentication.v1beta1.md @@ -290,7 +290,7 @@ exec 插件本身至少应通过文件访问许可来实施保护。

            expirationTimestamp
            -meta/v1.Time +meta/v1.Time diff --git a/content/zh-cn/docs/reference/config-api/imagepolicy.v1alpha1.md b/content/zh-cn/docs/reference/config-api/imagepolicy.v1alpha1.md index b0fdf1b19f7f3..8140699487a00 100644 --- a/content/zh-cn/docs/reference/config-api/imagepolicy.v1alpha1.md +++ b/content/zh-cn/docs/reference/config-api/imagepolicy.v1alpha1.md @@ -26,7 +26,7 @@ package: imagepolicy.k8s.io/v1alpha1 kind
            stringImageReview metadata
            -meta/v1.ObjectMeta +meta/v1.ObjectMeta +## 资源类型 {#resource-types} + + +- [CloudControllerManagerConfiguration](#cloudcontrollermanager-config-k8s-io-v1alpha1-CloudControllerManagerConfiguration) +- [LeaderMigrationConfiguration](#controllermanager-config-k8s-io-v1alpha1-LeaderMigrationConfiguration) +- [KubeControllerManagerConfiguration](#kubecontrollermanager-config-k8s-io-v1alpha1-KubeControllerManagerConfiguration) + + + + +## `NodeControllerConfiguration` {#NodeControllerConfiguration} + + + +**出现在:** + +- [CloudControllerManagerConfiguration](#cloudcontrollermanager-config-k8s-io-v1alpha1-CloudControllerManagerConfiguration) + +

            + +NodeControllerConfiguration 包含描述 NodeController 的元素。 +

            + + + + + + + + + + + +
            字段描述
            ConcurrentNodeSyncs [必需]
            +int32 +
            +

            + + ConcurrentNodeSyncs 是并发执行以进行节点同步的工作程序的数量。 +

            +
            + +## `ServiceControllerConfiguration` {#ServiceControllerConfiguration} + + + +**出现在:** + +- [CloudControllerManagerConfiguration](#cloudcontrollermanager-config-k8s-io-v1alpha1-CloudControllerManagerConfiguration) + +- [KubeControllerManagerConfiguration](#kubecontrollermanager-config-k8s-io-v1alpha1-KubeControllerManagerConfiguration) + +

            + +ServiceControllerConfiguration 包含描述 ServiceController 的元素。 +

            + + + + + + + + + + + +
            字段描述
            ConcurrentServiceSyncs [必需]
            +int32 +
            +

            + + concurrentServiceSyncs 是允许同时同步的服务数。 + 数量越大表示服务管理响应越快,但 CPU(和网络)负载也越高。 +

            +
            + + +## `CloudControllerManagerConfiguration` {#cloudcontrollermanager-config-k8s-io-v1alpha1-CloudControllerManagerConfiguration} + + + +

            + +CloudControllerManagerConfiguration 包含描述云控制器管理器的元素。 +

            + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
            字段描述
            apiVersion
            string
            cloudcontrollermanager.config.k8s.io/v1alpha1
            kind
            string
            CloudControllerManagerConfiguration
            Generic [必需]
            +GenericControllerManagerConfiguration +
            +

            + + Generic 包含通用控制器管理器的配置。 +

            +
            KubeCloudShared [必需]
            +KubeCloudSharedConfiguration +
            +

            + + KubeCloudSharedConfiguration 保存被云控制器管理器和 kube-controller 管理器共享的相关特性的配置。 +

            +
            NodeController [必需]
            +NodeControllerConfiguration +
            +

            + + NodeController 保存与节点控制器相关的特性的配置。 +

            +
            ServiceController [必需]
            +ServiceControllerConfiguration +
            +

            + + ServiceControllerConfiguration 保存 ServiceController 相关的特性的配置。 +

            +
            NodeStatusUpdateFrequency [必需]
            +meta/v1.Duration +
            +

            + + NodeStatusUpdateFrequency 是控制器更新节点状态的频率。 +

            +
            Webhook [必需]
            +WebhookConfiguration +
            +

            + + Webhook 是云控制器管理器托管的 webhook 的配置。 +

            +
            + +## `CloudProviderConfiguration` {#cloudcontrollermanager-config-k8s-io-v1alpha1-CloudProviderConfiguration} + + + +**出现在:** + +- [KubeCloudSharedConfiguration](#cloudcontrollermanager-config-k8s-io-v1alpha1-KubeCloudSharedConfiguration) + + +

            + +CloudProviderConfiguration 包含有关云提供商的一些基本元素。 +

            + + + + + + + + + + + + + + +
            字段描述
            Name [必需]
            +string +
            +

            + + Name 是云服务的提供商。 +

            +
            CloudConfigFile [必需]
            +string +
            +

            + + cloudConfigFile 是云提供程序配置文件的路径。 +

            +
            + +## `KubeCloudSharedConfiguration` {#cloudcontrollermanager-config-k8s-io-v1alpha1-KubeCloudSharedConfiguration} + + + +**出现在:** + +- [CloudControllerManagerConfiguration](#cloudcontrollermanager-config-k8s-io-v1alpha1-CloudControllerManagerConfiguration) + +- [KubeControllerManagerConfiguration](#kubecontrollermanager-config-k8s-io-v1alpha1-KubeControllerManagerConfiguration) + + +

            + +KubeCloudSharedConfiguration 包含 kube-controller 管理器和云控制器管理器共享的元素,但不包含通用配置。 +

            + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
            字段描述
            CloudProvider [必需]
            +CloudProviderConfiguration +
            +

            + + CloudProviderConfiguration 保存 CloudProvider 相关特性的配置。 +

            +
            ExternalCloudVolumePlugin [必需]
            +string +
            +

            + + 当 cloudProvider 为 "external" 时,externalCloudVolumePlugin 用于指定插件。 + 它目前被仓库内的云驱动用于处理 KCM 中的节点和卷控制。 +

            +
            UseServiceAccountCredentials [必需]
            +bool +
            +

            + + useServiceAccountCredentials 指出控制器是否应使用独立的服务帐户凭据运行。 +

            +
            AllowUntaggedCloud [必需]
            +bool +
            +

            + + 使用未标记的云实例运行。 +

            +
            RouteReconciliationPeriod [必需]
            +meta/v1.Duration +
            +

            + + routeReconciliationPeriod 是云驱动商为节点创建的路由的调和周期。 +

            +
            NodeMonitorPeriod [必需]
            +meta/v1.Duration +
            +

            + + nodeMonitorPeriod 是 NodeController 同步 NodeStatus 的周期。 +

            +
            ClusterName [必需]
            +string +
            +

            + + clusterName 是集群的实例前缀。 +

            +
            ClusterCIDR [必需]
            +string +
            +

            + + clusterCIDR 是集群中 Pod CIDR 的范围。 +

            +
            AllocateNodeCIDRs [必需]
            +bool +
            +

            + + AllocateNodeCIDRs 允许为 Pod 分配 CIDR, + 如果 ConfigureCloudRoutes 为 true,则允许在对云驱动商设置 CIDR。 +

            +
            CIDRAllocatorType [必需]
            +string +
            +

            + + CIDRAllocatorType 决定使用哪种类型的 Pod CIDR 分配器。 +

            +
            ConfigureCloudRoutes [必需]
            +bool +
            +

            + + configureCloudRoutes 使通过 allocateNodeCIDRs 分配的 CIDR 能够在云提供商上配置。 +

            +
            NodeSyncPeriod [必需]
            +meta/v1.Duration +
            +

            + + nodeSyncPeriod 从云平台同步节点的周期。 + 周期较长时,调用云平台的次数减少, + 但向集群添加新节点可能会延迟。 +

            +
            + +## `WebhookConfiguration` {#cloudcontrollermanager-config-k8s-io-v1alpha1-WebhookConfiguration} + + + +**出现在:** + +- [CloudControllerManagerConfiguration](#cloudcontrollermanager-config-k8s-io-v1alpha1-CloudControllerManagerConfiguration) + + +

            + +WebhookConfiguration 包含与云控制器管理器托管的 webhook 相关的配置。 +

            + + + + + + + + + + + +
            字段描述
            Webhooks [必需]
            +[]string +
            +

            + + Webhooks 是要启用或者禁用的 Webhook 的列表。 + '*' 表示"所有默认启用的 webhook ", + 'foo' 表示"启用 'foo'", + '-foo' 表示"禁用 'foo'", + 特定名称的首个项有效。 +

            +
            + + + +## `LeaderMigrationConfiguration` {#controllermanager-config-k8s-io-v1alpha1-LeaderMigrationConfiguration} + + + +**出现在:** + +- [GenericControllerManagerConfiguration](#controllermanager-config-k8s-io-v1alpha1-GenericControllerManagerConfiguration) + + +

            + +LeaderMigrationConfiguration 为所有迁移中的领导者锁提供了版本化配置。 +

            + + + + + + + + + + + + + + + + + + + + +
            字段描述
            apiVersion
            string
            controllermanager.config.k8s.io/v1alpha1
            kind
            string
            LeaderMigrationConfiguration
            leaderName [必需]
            +string +
            +

            + + LeaderName 是保护迁移的领导者选举资源的名称,例如:1-20-KCM-to-1-21-CCM。 +

            +
            resourceLock [必需]
            +string +
            +

            + + ResourceLock 表示将被用于加锁的资源对象类型, + 应该是 "leases" 或者是 "endpoints"。 +

            +
            controllerLeaders [必需]
            +[]ControllerLeaderConfiguration +
            +

            + + ControllerLeaders 包含迁移领导者锁配置列表。 +

            +
            + +## `ControllerLeaderConfiguration` {#controllermanager-config-k8s-io-v1alpha1-ControllerLeaderConfiguration} + + + +**出现在:** + +- [LeaderMigrationConfiguration](#controllermanager-config-k8s-io-v1alpha1-LeaderMigrationConfiguration) + + +

            + +ControllerLeaderConfiguration 提供迁移中领导者锁的配置。 +

            + + + + + + + + + + + + + + +
            字段描述
            name [必需]
            +string +
            +

            + + Name 是正被迁移的控制器的名称,例如:service-controller、route-controller、cloud-node-controller 等等 +

            +
            component [必需]
            +string +
            +

            + + Component 是控制器运行所处的组件的名称。 + 例如,kube-controller-manager、cloud-controller-manager 等。 + 或者 “*” 表示控制器可以在任何正在参与迁移的组件中运行。 +

            +
            + +## `GenericControllerManagerConfiguration` {#controllermanager-config-k8s-io-v1alpha1-GenericControllerManagerConfiguration} + + + +**出现在:** + +- [CloudControllerManagerConfiguration](#cloudcontrollermanager-config-k8s-io-v1alpha1-CloudControllerManagerConfiguration) + +- [KubeControllerManagerConfiguration](#kubecontrollermanager-config-k8s-io-v1alpha1-KubeControllerManagerConfiguration) + + +

            + +GenericControllerManagerConfiguration 保存通用控制器管理器的配置。 +

            + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
            字段描述
            Port [必需]
            +int32 +
            +

            + + port 是控制器管理器运行 HTTP 服务运行的端口。 +

            +
            Address [必需]
            +string +
            +

            + + address 是提供服务所用的 IP 地址(所有接口设置为 0.0.0.0)。 +

            +
            MinResyncPeriod [必需]
            +meta/v1.Duration +
            +

            + + minResyncPeriod 是反射器的重新同步周期;大小是在 minResyncPeriod 和 2*minResyncPeriod 范围内的随机数。 +

            +
            ClientConnection [必需]
            +ClientConnectionConfiguration +
            +

            + + ClientConnection 指定代理服务器在与 API 服务器通信时使用的 kubeconfig 文件和客户端连接设置。 +

            +
            ControllerStartInterval [必需]
            +meta/v1.Duration +
            +

            + + 两次启动控制器管理器之间的间隔时间。 +

            +
            LeaderElection [必需]
            +LeaderElectionConfiguration +
            +

            + + leaderElection 定义领导者选举客户端的配置。 +

            +
            Controllers [必需]
            +[]string +
            +

            + + Controllers 是要启用或者禁用的控制器列表。 + '*' 表示"所有默认启用的控制器", + 'foo' 表示"启用 'foo'", + '-foo' 表示"禁用 'foo'", + 特定名称的首个项有效。 +

            +
            Debugging [必需]
            +DebuggingConfiguration +
            +

            + + DebuggingConfiguration 保存调试相关特性的配置。 +

            +
            LeaderMigrationEnabled [必需]
            +bool +
            +

            + + LeaderMigrationEnabled 指示是否应为控制器管理器启用领导者迁移(Leader Migration)。 +

            +
            LeaderMigration [必需]
            +LeaderMigrationConfiguration +
            +

            + + LeaderMigration 保存领导者迁移的配置。 +

            +
            + + + +## `KubeControllerManagerConfiguration` {#kubecontrollermanager-config-k8s-io-v1alpha1-KubeControllerManagerConfiguration} + + + +

            + +KubeControllerManagerConfiguration 包含描述 kube-controller 管理器的元素。 +

            + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
            字段描述
            apiVersion
            string
            kubecontrollermanager.config.k8s.io/v1alpha1
            kind
            string
            KubeControllerManagerConfiguration
            Generic [必需]
            +GenericControllerManagerConfiguration +
            +

            + + Generic 保存通用控制器管理器的配置。 +

            +
            KubeCloudShared [必需]
            +KubeCloudSharedConfiguration +
            +

            + + KubeCloudSharedConfiguration 保存云控制器管理器和 kube-controller 管理器间共享的相关特性的配置。 +

            +
            AttachDetachController [必需]
            +AttachDetachControllerConfiguration +
            +

            + + AttachDetachControllerConfiguration 包含 AttachDetachController 相关特性的配置。 +

            +
            CSRSigningController [必需]
            +CSRSigningControllerConfiguration +
            +

            + + CSRSigningControllerConfiguration 包含 CSRSigningController 相关特性的配置。 +

            +
            DaemonSetController [必需]
            +DaemonSetControllerConfiguration +
            +

            + + DaemonSetControllerConfiguration 包含 DaemonSetController 相关特性的配置。 +

            +
            DeploymentController [必需]
            +DeploymentControllerConfiguration +
            +

            + + DeploymentControllerConfiguration 包含 DeploymentController 相关特性的配置。 +

            +
            StatefulSetController [必需]
            +StatefulSetControllerConfiguration +
            +

            + + StatefulSetControllerConfiguration 包含 StatefulSetController 相关特性的配置。 +

            +
            DeprecatedController [必需]
            +DeprecatedControllerConfiguration +
            +

            + + DeprecatedControllerConfiguration 包含一些已弃用的特性的配置。 +

            +
            EndpointController [必需]
            +EndpointControllerConfiguration +
            +

            + + EndpointControllerConfiguration 包含 EndpointController 相关特性的配置。 +

            +
            EndpointSliceController [必需]
            +EndpointSliceControllerConfiguration +
            +

            + + EndpointSliceControllerConfiguration 包含 EndpointSliceController 相关特性的配置。 +

            +
            EndpointSliceMirroringController [必需]
            +EndpointSliceMirroringControllerConfiguration +
            +

            + + EndpointSliceMirroringControllerConfiguration 包含 EndpointSliceMirroringController 相关特性的配置。 +

            +
            EphemeralVolumeController [必需]
            +EphemeralVolumeControllerConfiguration +
            +

            + + EphemeralVolumeControllerConfiguration 包含 EphemeralVolumeController 相关特性的配置。 +

            +
            GarbageCollectorController [必需]
            +GarbageCollectorControllerConfiguration +
            +

            + + GarbageCollectorControllerConfiguration 包含 GarbageCollectorController 相关特性的配置。 +

            +
            HPAController [必需]
            +HPAControllerConfiguration +
            +

            + + HPAControllerConfiguration 包含 HPAController 相关特性的配置。 +

            +
            JobController [必需]
            +JobControllerConfiguration +
            +

            + + HPAControllerConfiguration 包含 JobController 相关特性的配置。 +

            +
            CronJobController [必需]
            +CronJobControllerConfiguration +
            +

            + + CronJobControllerConfiguration 包含 CronJobController 相关特性的配置。 +

            +
            LegacySATokenCleaner [必需]
            +LegacySATokenCleanerConfiguration +
            +

            + + LegacySATokenCleanerConfiguration 包含 LegacySATokenCleaner 相关特性的配置。 +

            +
            NamespaceController [必需]
            +NamespaceControllerConfiguration +
            +

            + + NamespaceControllerConfiguration 包含 NamespaceController 相关特性的配置。 +

            +
            NodeIPAMController [必需]
            +NodeIPAMControllerConfiguration +
            +

            + + NodeIPAMControllerConfiguration 包含 NodeIPAMController 相关特性的配置。 +

            +
            NodeLifecycleController [必需]
            +NodeLifecycleControllerConfiguration +
            +

            + + NodeLifecycleControllerConfiguration 包含 NodeLifecycleController 相关特性的配置。 +

            +
            PersistentVolumeBinderController [必需]
            +PersistentVolumeBinderControllerConfiguration +
            +

            + + PersistentVolumeBinderControllerConfiguration 包含 PersistentVolumeBinderController 相关特性的配置。 +

            +
            PodGCController [必需]
            +PodGCControllerConfiguration +
            +

            + + PodGCControllerConfiguration 包含 PodGCController 相关特性的配置。 +

            +
            ReplicaSetController [必需]
            +ReplicaSetControllerConfiguration +
            +

            + + ReplicaSetControllerConfiguration 包含 ReplicaSetController 相关特性的配置。 +

            +
            ReplicationController [必需]
            +ReplicationControllerConfiguration +
            +

            + + ReplicationControllerConfiguration 包含 ReplicationController 相关特性的配置。 +

            +
            ResourceQuotaController [必需]
            +ResourceQuotaControllerConfiguration +
            +

            + + ResourceQuotaControllerConfiguration 包含 ResourceQuotaController 相关特性的配置。 +

            +
            SAController [必需]
            +SAControllerConfiguration +
            +

            + + SAControllerConfiguration 包含 ServiceAccountController 相关特性的配置。 +

            +
            ServiceController [必需]
            +ServiceControllerConfiguration +
            +

            + + ServiceControllerConfiguration 包含 ServiceController 相关特性的配置。 +

            +
            TTLAfterFinishedController [必需]
            +TTLAfterFinishedControllerConfiguration +
            +

            + + TTLAfterFinishedControllerConfiguration 包含 TTLAfterFinishedController 相关特性的配置。 +

            +
            ValidatingAdmissionPolicyStatusController [必需]
            +ValidatingAdmissionPolicyStatusControllerConfiguration +
            +

            + + ValidatingAdmissionPolicyStatusControllerConfiguration 包含 ValidatingAdmissionPolicyStatusController 相关特性的配置。 +

            +
            + +## `AttachDetachControllerConfiguration` {#kubecontrollermanager-config-k8s-io-v1alpha1-AttachDetachControllerConfiguration} + + + +**出现在:** + +- [KubeControllerManagerConfiguration](#kubecontrollermanager-config-k8s-io-v1alpha1-KubeControllerManagerConfiguration) + + +

            + +AttachDetachControllerConfiguration 包含描述 AttachDetachController 的元素。 +

            + + + + + + + + + + + + + + +
            字段描述
            DisableAttachDetachReconcilerSync [必需]
            +bool +
            +

            + + Reconciler 运行一个周期性循环,通过触发 attach/detach 操作来协调期望状态与实际状态。 + 此标志启用或禁用调和操作。默认为 false,即被启用的。 +

            +
            ReconcilerSyncLoopPeriod [必需]
            +meta/v1.Duration +
            +

            + + ReconcilerSyncLoopPeriod 是调和器在连续执行同步状态的循环间,所等待的时间量。 + 默认为 5 秒。 +

            +
            + +## `CSRSigningConfiguration` {#kubecontrollermanager-config-k8s-io-v1alpha1-CSRSigningConfiguration} + + + +**出现在:** + +- [CSRSigningControllerConfiguration](#kubecontrollermanager-config-k8s-io-v1alpha1-CSRSigningControllerConfiguration) + + +

            + +CSRSigningConfiguration 保存有关特定 CSR 签名者的信息。 +

            + + + + + + + + + + + + + + +
            字段描述
            CertFile [必需]
            +string +
            +

            + + certFile 是包含 PEM 编码的 X509 CA 证书的文件名,用于颁发证书。 +

            +
            KeyFile [必需]
            +string +
            +

            + + keyFile 是包含 PEM 编码的 RSA 或 ECDSA 私钥的文件名,用于颁发证书。 +

            +
            + +## `CSRSigningControllerConfiguration` {#kubecontrollermanager-config-k8s-io-v1alpha1-CSRSigningControllerConfiguration} + + + +**出现在:** + + +- [KubeControllerManagerConfiguration](#kubecontrollermanager-config-k8s-io-v1alpha1-KubeControllerManagerConfiguration) + + +

            + +CSRSigningControllerConfiguration 包含描述 CSRSigningController 的元素。 +

            + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
            字段描述
            ClusterSigningCertFile [必需]
            +string +
            +

            + + clusterSigningCertFile 是包含 PEM 编码的 X509 CA 证书的文件名,该证书用于颁发集群范围的证书。 +

            +
            ClusterSigningKeyFile [必需]
            +string +
            +

            + + clusterSigningCertFile 是包含 PEM 编码的 RSA 或 ECDSA 私钥的文件名,用于颁发集群范围的证书。 +

            +
            KubeletServingSignerConfiguration [必需]
            +CSRSigningConfiguration +
            +

            + + kubeletServingSignerConfiguration 保存用于为 kubernetes.io/kubelet-serving 签名者颁发证书的证书和密钥。 +

            +
            KubeletClientSignerConfiguration [必需]
            +CSRSigningConfiguration +
            +

            + + kubeletClientSignerConfiguration 保存用于为 kubernetes.io/kube-apiserver-client-kubelet 颁发证书的证书和密钥。 + +

            +
            KubeAPIServerClientSignerConfiguration [必需]
            +CSRSigningConfiguration +
            +

            + + kubeAPIServerClientSignerConfiguration 保存用于为 kubernetes.io/kube-apiserver-client 颁发证书的证书和密钥。 +

            +
            LegacyUnknownSignerConfiguration [必需]
            +CSRSigningConfiguration +
            +

            + + legacyUnknownSignerConfiguration 保存用于颁发 kubernetes.io/legacy-unknown 证书的证书和密钥。 +

            +
            ClusterSigningDuration [必需]
            +meta/v1.Duration +
            +

            + + clusterSigningDuration 是签名证书的最长持续时间。 + 单个 CSRs 可以通过设置 spec.expirationSeconds 来请求有效期更短的证书。 +

            +
            + +## `CronJobControllerConfiguration` {#kubecontrollermanager-config-k8s-io-v1alpha1-CronJobControllerConfiguration} + + + +**出现在:** + +- [KubeControllerManagerConfiguration](#kubecontrollermanager-config-k8s-io-v1alpha1-KubeControllerManagerConfiguration) + + +

            + +CronJobControllerConfiguration 包含描述 CrongJob2Controller 的元素。 +

            + + + + + + + + + + + +
            字段描述
            ConcurrentCronJobSyncs [必需]
            +int32 +
            +

            + + concurrentCronJobSyncs 是允许并发同步的 Job 对象的数量。 + 数量越大意味着 Job 响应越快,但 CPU(和网络)负载也越高。 +

            +
            + +## `DaemonSetControllerConfiguration` {#kubecontrollermanager-config-k8s-io-v1alpha1-DaemonSetControllerConfiguration} + + + +**出现在:** + +- [KubeControllerManagerConfiguration](#kubecontrollermanager-config-k8s-io-v1alpha1-KubeControllerManagerConfiguration) + + +

            + +DaemonSetControllerConfiguration 包含描述 DaemonSetController 的元素。 +

            + + + + + + + + + + + +
            字段描述
            ConcurrentDaemonSetSyncs [必需]
            +int32 +
            +

            + + concurrentDaemonSetSyncs 是允许并发同步的 DaemonSet 对象的数量。 + 数目越大意味着 DaemonSet 响应越快,但 CPU(和网络)负载也越高。 +

            +
            + +## `DeploymentControllerConfiguration` {#kubecontrollermanager-config-k8s-io-v1alpha1-DeploymentControllerConfiguration} + + +**Appears in:** + +- [KubeControllerManagerConfiguration](#kubecontrollermanager-config-k8s-io-v1alpha1-KubeControllerManagerConfiguration) + + +

            + +DeploymentControllerConfiguration 包含描述 DeploymentController 的元素。 +

            + + + + + + + + + + + +
            字段描述
            ConcurrentDeploymentSyncs [必需]
            +int32 +
            +

            + + concurrentDeploymentSyncs 是允许并发同步的 Deployment 对象的数量。 + 数量越大意味着 Deployment 响应更越快,但 CPU(和网络)负载也越高。 +

            +
            + +## `DeprecatedControllerConfiguration` {#kubecontrollermanager-config-k8s-io-v1alpha1-DeprecatedControllerConfiguration} + + + +**出现在:** + +- [KubeControllerManagerConfiguration](#kubecontrollermanager-config-k8s-io-v1alpha1-KubeControllerManagerConfiguration) + + +

            + +DeprecatedControllerConfiguration 包含被弃用的元素。 +

            + + + + +## `EndpointControllerConfiguration` {#kubecontrollermanager-config-k8s-io-v1alpha1-EndpointControllerConfiguration} + + + +**出现在:** + +- [KubeControllerManagerConfiguration](#kubecontrollermanager-config-k8s-io-v1alpha1-KubeControllerManagerConfiguration) + + +

            + +EndpointControllerConfiguration 包含描述 EndpointController 的元素。 +

            + + + + + + + + + + + + + + +
            字段描述
            ConcurrentEndpointSyncs [必需]
            +int32 +
            +

            + + concurrentEndpointSyncs 是将并发执行的 Endpoints 同步操作的数量。 + 数字越大意味着 Endpoints 更新越快,但 CPU(和网络)负载也越高。 +

            +
            EndpointUpdatesBatchPeriod [必需]
            +meta/v1.Duration +
            +

            + + EndpointUpdatesBatchPeriod 描述批量更新 Endpoints 的周期长度。 + Pod 更改的处理将被延迟相同的时长,以便将它们与即将到来的更新连接起来,并减少 Endpoints 更新的总数。 +

            +
            + +## `EndpointSliceControllerConfiguration` {#kubecontrollermanager-config-k8s-io-v1alpha1-EndpointSliceControllerConfiguration} + + + +**出现在:** + +- [KubeControllerManagerConfiguration](#kubecontrollermanager-config-k8s-io-v1alpha1-KubeControllerManagerConfiguration) + + +

            + +EndpointSliceControllerConfiguration 包含描述 EndpointSliceController 的元素。 +

            + + + + + + + + + + + + + + + + + +
            字段描述
            ConcurrentServiceEndpointSyncs [必需]
            +int32 +
            +

            + + concurrentServiceEndpointSyncs 是将并发完成的服务端点同步操作的数量。 + 数字越大意味着 EndpointSlice 更新越快,但 CPU(和网络)负载也越高。 +

            +
            MaxEndpointsPerSlice [必需]
            +int32 +
            +

            + + maxEndpointsPerSlice 是将添加到 EndpointSlice 的最大端点数。 + 每个切片的端点越多,端点切片就会更少、更大,但资源消耗就会更多。 +

            +
            EndpointUpdatesBatchPeriod [必需]
            +meta/v1.Duration +
            +

            + + EndpointUpdatesBatchPeriod 描述批量更新 Endpoints 的周期长度。 + Pod 更改的处理将被延迟相同的时长,以便将它们与即将到来的更新连接起来,并减少 Endpoints 更新的总数。 +

            +
            + +## `EndpointSliceMirroringControllerConfiguration` {#kubecontrollermanager-config-k8s-io-v1alpha1-EndpointSliceMirroringControllerConfiguration} + + + +**出现在:** + +- [KubeControllerManagerConfiguration](#kubecontrollermanager-config-k8s-io-v1alpha1-KubeControllerManagerConfiguration) + + +

            + +EndpointSliceMirroringControllerConfiguration 包含描述 EndpointSliceMirroringController 的元素。 +

            + + + + + + + + + + + + + + + + + +
            字段描述
            MirroringConcurrentServiceEndpointSyncs [必需]
            +int32 +
            +

            + + mirroringConcurrentServiceEndpointSyncs 是将并发完成的服务端点同步操作的数量。 + 数字越大意味着 EndpointSlice 更新越快,但 CPU(和网络)负载也越高。 +

            +
            MirroringMaxEndpointsPerSubset [必需]
            +int32 +
            +

            + + mirroringMaxEndpointsPerSubset 是把 EndpointSubset 映射到 EndpointSlice 的端点数上限。 +

            +
            MirroringEndpointUpdatesBatchPeriod [必需]
            +meta/v1.Duration +
            +

            + + mirroringEndpointUpdatesBatchPeriod 可用于批量更新 EndpointSlice。 + 所有由 EndpointSlice 更改触发的更新可能被延迟,延迟的时间长度上限为 “mirroringEndpointUpdatesBatchPeriod”。 + 如果同一 Endpoints 资源中的其他地址在此期间发生变化,它们将被合并到同一个 EndpointSlice 更新中以实现批处理。 + 默认值 0 表示 Endpoints 的每次更新都会触发一次 EndpointSlice 更新。 +

            +
            + +## `EphemeralVolumeControllerConfiguration` {#kubecontrollermanager-config-k8s-io-v1alpha1-EphemeralVolumeControllerConfiguration} + + + +**出现在:** + +- [KubeControllerManagerConfiguration](#kubecontrollermanager-config-k8s-io-v1alpha1-KubeControllerManagerConfiguration) + + +

            + +EphemeralVolumeControllerConfiguration 包含描述 EphemeralVolumeController 的元素。 +

            + + + + + + + + + + + +
            字段描述
            ConcurrentEphemeralVolumeSyncs [必需]
            +int32 +
            +

            + + ConcurrentEphemeralVolumeSyncseSyncs 是并发执行的临时卷同步操作数量。 + 数字越大意味着临时卷更新越快,但 CPU(和网络)负载也越高。 +

            +
            + +## `GarbageCollectorControllerConfiguration` {#kubecontrollermanager-config-k8s-io-v1alpha1-GarbageCollectorControllerConfiguration} + + + +**出现在:** + +- [KubeControllerManagerConfiguration](#kubecontrollermanager-config-k8s-io-v1alpha1-KubeControllerManagerConfiguration) + + +

            + +GarbageCollectorControllerConfiguration 包含描述 GarbageCollectorController 的元素。 +

            + + + + + + + + + + + + + + + + + +
            字段描述
            EnableGarbageCollector [必需]
            +bool +
            +

            + + 启用通用垃圾收集器。必须与 kube-apiserver 的相应标志同步。 + 警告:通用垃圾收集器是一个 Alpha 特性。 +

            +
            ConcurrentGCSyncs [必需]
            +int32 +
            +

            + + concurrentGCSyncs 是允许垃圾收集器并发同步的工作线程的数量。 +

            +
            GCIgnoredResources [必需]
            +[]GroupResource +
            +

            + + gcIgnoredResources 是垃圾收集应该忽略的 GroupResource 列表。 +

            +
            + +## `GroupResource` {#kubecontrollermanager-config-k8s-io-v1alpha1-GroupResource} + + + +**出现在:** + +- [GarbageCollectorControllerConfiguration](#kubecontrollermanager-config-k8s-io-v1alpha1-GarbageCollectorControllerConfiguration) + + +

            + +GroupResource 描述组资源。 +

            + + + + + + + + + + + + + + +
            字段描述
            Group [必需]
            +string +
            +

            + + group 是 GroupResource 的 group 部分。 +

            +
            Resource [必需]
            +string +
            +

            + + resource 是 GroupResource 的 resource 部分。 +

            +
            + +## `HPAControllerConfiguration` {#kubecontrollermanager-config-k8s-io-v1alpha1-HPAControllerConfiguration} + + + +**出现在:** + +- [KubeControllerManagerConfiguration](#kubecontrollermanager-config-k8s-io-v1alpha1-KubeControllerManagerConfiguration) + + +

            + +HPAControllerConfiguration 包含描述 HPAController 的元素。 +

            + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
            字段描述
            ConcurrentHorizontalPodAutoscalerSyncs [必需]
            +int32 +
            +

            + + ConcurrentHorizontalPodAutoscalerSyncs 是允许并发同步的 HPA 对象的数量。 + 数字越大意味着 HPA 处理响应越快,但 CPU(和网络)负载也越高。 +

            +
            HorizontalPodAutoscalerSyncPeriod [必需]
            +meta/v1.Duration +
            +

            + + HorizontalPodAutoscalerSyncPeriod 是对 HPA 中 Pod 数量进行同步的周期。 +

            +
            HorizontalPodAutoscalerUpscaleForbiddenWindow [必需]
            +meta/v1.Duration +
            +

            + + HorizontalPodAutoscalerUpscaleForbiddenWindow 是一个时间段,过了这一时间段才允许下一次扩容 +

            +
            HorizontalPodAutoscalerDownscaleStabilizationWindow [必需]
            +meta/v1.Duration +
            +

            + + horizontalpodautoscalerdowncalstabilizationwindow 是一个自动缩放器要回顾的时段长度, + 在所给时段内,自动缩放器不会按照建议执行任何缩容操作。 +

            +
            HorizontalPodAutoscalerDownscaleForbiddenWindow [必需]
            +meta/v1.Duration +
            +

            + + HorizontalPodAutoscalerDownscaleForbiddenWindow 是一个时间段长度,过了此时间段才允许执行下一此缩容操作。 +

            +
            HorizontalPodAutoscalerTolerance [必需]
            +float64 +
            +

            + + HorizontalPodAutoscalerTolerance 是当资源用量表明需要扩容/缩容时的容忍度。 +

            +
            HorizontalPodAutoscalerCPUInitializationPeriod [必需]
            +meta/v1.Duration +
            +

            + + HorizontalPodAutoscalerCPUInitializationPeriod 是 Pod 启动后可以跳过时间段,这段时间内部执行 CPU 采样。 +

            +
            HorizontalPodAutoscalerInitialReadinessDelay [必需]
            +meta/v1.Duration +
            +

            + + HorizontalPodAutoscalerInitialReadinessDelay 是 Pod 启动后的一段时间, + 在此期间,readiness 状态的变更被视为初次设置 readiness 状态。 + 这样做的唯一影响是,对于在此期间发生 readiness 状态变化但未准备好的 Pod,HPA 将忽略其 CPU 采样值。 +

            +
            + +## `JobControllerConfiguration` {#kubecontrollermanager-config-k8s-io-v1alpha1-JobControllerConfiguration} + + + +**出现在:** + +- [KubeControllerManagerConfiguration](#kubecontrollermanager-config-k8s-io-v1alpha1-KubeControllerManagerConfiguration) + + +

            + +JobControllerConfiguration 包含描述 JobController 的元素。 +

            + + + + + + + + + + + +
            字段描述
            ConcurrentJobSyncs [必需]
            +int32 +
            +

            + + concurrentJobSyncs 是允许并发同步的 Job 对象的数量。 + 数字越大意味着 Job 响应越快,但 CPU(和网络)负载也越高。 +

            +
            + +## `LegacySATokenCleanerConfiguration` {#kubecontrollermanager-config-k8s-io-v1alpha1-LegacySATokenCleanerConfiguration} + + + +**出现在:** + +- [KubeControllerManagerConfiguration](#kubecontrollermanager-config-k8s-io-v1alpha1-KubeControllerManagerConfiguration) + + +

            + +LegacySATokenCleanerConfiguration 包含描述 LegacySATokenCleaner 的元素。 +

            + + + + + + + + + + + +
            字段描述
            CleanUpPeriod [必需]
            +meta/v1.Duration +
            +

            + + CleanUpPeriod 是自动生成的服务帐户令牌上次被使用以来的时长,超出此时长的令牌可被清理。 +

            +
            + +## `NamespaceControllerConfiguration` {#kubecontrollermanager-config-k8s-io-v1alpha1-NamespaceControllerConfiguration} + + + +**出现在:** + +- [KubeControllerManagerConfiguration](#kubecontrollermanager-config-k8s-io-v1alpha1-KubeControllerManagerConfiguration) + + +

            + +NamespaceControllerConfiguration 包含描述 NamespaceController 的元素。 +

            + + + + + + + + + + + + + + +
            字段描述
            NamespaceSyncPeriod [必需]
            +meta/v1.Duration +
            +

            + + namespaceSyncPeriod 是对名字空间生命周期更新进行同步的周期。 +

            +
            ConcurrentNamespaceSyncs [必需]
            +int32 +
            +

            + + concurrentNamespaceSyncs 是允许并发同步的 Namespace 对象的数量。 +

            +
            + +## `NodeIPAMControllerConfiguration` {#kubecontrollermanager-config-k8s-io-v1alpha1-NodeIPAMControllerConfiguration} + + + +**出现在:** + +- [KubeControllerManagerConfiguration](#kubecontrollermanager-config-k8s-io-v1alpha1-KubeControllerManagerConfiguration) + + +

            + +NodeIPAMControllerConfiguration 包含描述 NodeIpamController 的元素。 +

            + + + + + + + + + + + + + + + + + + + + + + + +
            字段描述
            ServiceCIDR [必需]
            +string +
            +

            + + serviceCIDR 为集群中 Service 的 CIDR 范围。 +

            +
            SecondaryServiceCIDR [必需]
            +string +
            +

            + + SecondaryServiceCIDR 为集群中 Service 的 CIDR 范围。此字段用于双栈集群。 + SecondaryServiceCIDR 和 ServiceCIDR 的 IP 族不能相同。 +

            +
            NodeCIDRMaskSize [必需]
            +int32 +
            +

            + + NodeCIDRMaskSize 为集群中节点 CIDR 的掩码大小。 +

            +
            NodeCIDRMaskSizeIPv4 [必需]
            +int32 +
            +

            + + NodeCIDRMaskSizeIPv4 为双栈集群中节点 CIDR 的掩码大小。 +

            +
            NodeCIDRMaskSizeIPv6 [必需]
            +int32 +
            +

            + + NodeCIDRMaskSizeIPv6 为双栈集群中节点 CIDR 的掩码大小。 +

            +
            + +## `NodeLifecycleControllerConfiguration` {#kubecontrollermanager-config-k8s-io-v1alpha1-NodeLifecycleControllerConfiguration} + + + +**出现在:** + +- [KubeControllerManagerConfiguration](#kubecontrollermanager-config-k8s-io-v1alpha1-KubeControllerManagerConfiguration) + + +

            + +Nodelifecyclecontrolerconfiguration 包含描述 NodeLifecycleController 的元素。 +

            + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
            字段描述
            NodeEvictionRate [必需]
            +float32 +
            +

            + + nodeEvictionRate 是在区域健康时,如果节点发生故障,每秒删除 Pod 的节点数。 +

            +
            SecondaryNodeEvictionRate [必需]
            +float32 +
            +

            + + secondaryNodeEvictionRate 是在区域不健康时,如果节点故障,每秒删除 Pod 的节点数。 +

            +
            NodeStartupGracePeriod [必需]
            +meta/v1.Duration +
            +

            + + nodeStartupGracePeriod 是在将节点标记为不健康之前允许启动节点无响应的时长。 +

            +
            NodeMonitorGracePeriod [必需]
            +meta/v1.Duration +
            +

            + + nodeMontiorGracePeriod 是在将运行中的节点标记为不健康之前允许其无响应的时长。 + 必须是 kubelet 的 nodeStatusUpdateFrequency 的 N 倍,其中 N 表示允许 kubelet 发布节点状态的重试次数。 +

            +
            PodEvictionTimeout [必需]
            +meta/v1.Duration +
            +

            + + podEvictionTimeout 为删除故障节点上的 Pod 的宽限时间。 +

            +
            LargeClusterSizeThreshold [必需]
            +int32 +
            +

            + + 对于规模小于或等于 largeClusterSizeThreshold 的集群,secondaryNodeEvictionRate 会被隐式覆盖,取值为 0。 +

            +
            UnhealthyZoneThreshold [必需]
            +float32 +
            +

            + + 当区域中至少有 unhealthyZoneThreshold(不少于 3 个)的节点处于 NotReady 状态时, + nodeEvctionRate 和 secondaryNodeEvictionRate 两个属性的判定逻辑会将区域视为不健康。 +

            +
            + +## `PersistentVolumeBinderControllerConfiguration` {#kubecontrollermanager-config-k8s-io-v1alpha1-PersistentVolumeBinderControllerConfiguration} + + + +**出现在:** + +- [KubeControllerManagerConfiguration](#kubecontrollermanager-config-k8s-io-v1alpha1-KubeControllerManagerConfiguration) + + +

            + +PersistentVolumeBinderControllerConfiguration 包含描述 PersistentVolumeBinderController 的元素。 +

            + + + + + + + + + + + + + + + + + + + + +
            字段描述
            PVClaimBinderSyncPeriod [必需]
            +meta/v1.Duration +
            +

            + + pvClaimBinderSyncPeriod 用于同步 PV 和 PVC 的周期。 +

            +
            VolumeConfiguration [必需]
            +VolumeConfiguration +
            +

            + + volumeConfiguration 包含卷相关特性的配置。 +

            +
            VolumeHostCIDRDenylist [必需]
            +[]string +
            +

            + + 已弃用:VolumeHostCIDRDenylist 是一个不能被插件中控制器访问的 CIDR 列表。 +

            +
            VolumeHostAllowLocalLoopback [必需]
            +bool +
            +

            + + 已弃用:VolumeHostAllowLocalLoopback 表示是否应该允许插件使用本地回路主机地址(127.0.0.1 等)。 +

            +
            + +## `PersistentVolumeRecyclerConfiguration` {#kubecontrollermanager-config-k8s-io-v1alpha1-PersistentVolumeRecyclerConfiguration} + + + +**出现在:** + +- [VolumeConfiguration](#kubecontrollermanager-config-k8s-io-v1alpha1-VolumeConfiguration) + + +

            + +PersistentVolumeRecyclerConfiguration 包含描述持久卷插件的元素。 +

            + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
            字段描述
            MaximumRetry [必需]
            +int32 +
            +

            + + maximumRetry 是当 PV 回收失败时,PV 回收器重试的次数。 +

            +
            MinimumTimeoutNFS [必需]
            +int32 +
            +

            + + minimumTimeoutNFS 是用于 NFS 回收器的,用于设置 Pod 的最小 ActiveDeadlineSeconds。 +

            +
            PodTemplateFilePathNFS [必需]
            +string +
            +

            + + podTemplateFilePathNFS 是一个 Pod 定义文件的路径,该文件将被用作 NFS PV 卷回收模板。 +

            +
            IncrementTimeoutNFS [必需]
            +int32 +
            +

            + + incrementTimeoutNFS 提供给 NFS 清理器 Pod 的设置值,数据卷每增加 1 GiB, + 则需要向 Pod 中的 activeDeadlineSeconds 参数增加这里所给的秒数。 +

            +
            PodTemplateFilePathHostPath [必需]
            +string +
            +

            + + podTemplateFilePathHostPath 是一个 Pod 定义文件的路径,该文件将被作为 HostPath PV 卷回收模板。 + 此字段仅用于开发和测试场景,在多节点集群中无法正常工作。 +

            +
            MinimumTimeoutHostPath [必需]
            +int32 +
            +

            + + minimumTimeoutHostPath 是用于 HostPath 回收器 Pod 的 activeDeadlineSeconds 属性值下限。 + 此字段仅用于开发和测试场景,在多节点集群中无法正常工作。 +

            +
            IncrementTimeoutHostPath [必需]
            +int32 +
            +

            + + incrementTimeoutHostPath 是提供给 HostPath 清理器 Pod 的配置值, + HostPath 卷的尺寸每增加 1 GiB,则需要为 Pod 的 activeDeadlineSeconds 属性增加这里所给的秒数。 + 回收器 Pod 的 activeDeadlineSeconds 属性值下限。 +

            +
            + +## `PodGCControllerConfiguration` {#kubecontrollermanager-config-k8s-io-v1alpha1-PodGCControllerConfiguration} + + + +**出现在:** + +- [KubeControllerManagerConfiguration](#kubecontrollermanager-config-k8s-io-v1alpha1-KubeControllerManagerConfiguration) + + +

            + +PodGCControllerConfiguration 包含描述 PodGCController 的元素。 +

            + + + + + + + + + + + +
            字段描述
            TerminatedPodGCThreshold [必需]
            +int32 +
            +

            + + terminatedPodGCThreshold 是提供给回收已终止 Pod 的垃圾收集器的, + 所设置的数字是在垃圾收集器开始删除某 Pod 之前可以存在的、已终止 Pod 的个数。 + 如果 <= 0,则禁用已终止的 Pod 垃圾收集器。 +

            +
            + +## `ReplicaSetControllerConfiguration` {#kubecontrollermanager-config-k8s-io-v1alpha1-ReplicaSetControllerConfiguration} + + + +**出现在:** + +- [KubeControllerManagerConfiguration](#kubecontrollermanager-config-k8s-io-v1alpha1-KubeControllerManagerConfiguration) + + +

            + +ReplicaSetControllerConfiguration 包含描述 ReplicaSetController 的元素。 +

            + + + + + + + + + + + +
            字段描述
            ConcurrentRSSyncs [必需]
            +int32 +
            +

            + + concurrentRSSyncs 是允许并发同步的 ReplicaSet 的数量。 + 数量越大意味着副本管理响应越快,但 CPU(和网络)负载也越高。 +

            +
            + +## `ReplicationControllerConfiguration` {#kubecontrollermanager-config-k8s-io-v1alpha1-ReplicationControllerConfiguration} + + + +**出现在:** + +- [KubeControllerManagerConfiguration](#kubecontrollermanager-config-k8s-io-v1alpha1-KubeControllerManagerConfiguration) + + +

            + +ReplicationControllerConfiguration 包含描述 ReplicationController 的元素。 +

            + + + + + + + + + + + +
            字段描述
            ConcurrentRCSyncs [必需]
            +int32 +
            +

            + + concurrentRCSyncs 是允许并发同步的 ReplicationController 数量。 + 数量越大意味着副本管理响应越快,但 CPU(和网络)负载也越高。 +

            +
            + +## `ResourceQuotaControllerConfiguration` {#kubecontrollermanager-config-k8s-io-v1alpha1-ResourceQuotaControllerConfiguration} + + + +**出现在:** + +- [KubeControllerManagerConfiguration](#kubecontrollermanager-config-k8s-io-v1alpha1-KubeControllerManagerConfiguration) + + +

            + +ResourceQuotaControllerConfiguration 包含描述 ResourceQuotaController 的元素。 +

            + + + + + + + + + + + + + + +
            字段描述
            ResourceQuotaSyncPeriod [必需]
            +meta/v1.Duration +
            +

            + + resourceQuotaSyncPeriod 是系统中 Quota 使用状态的同步周期。 +

            +
            ConcurrentResourceQuotaSyncs [必需]
            +int32 +
            +

            + + concurrentResourceQuotaSyncs 是允许并发同步的 ResourcQuota 数目。 + 数量越大意味着配额管理响应越快,但 CPU(和网络)负载也越高。 +

            +
            + +## `SAControllerConfiguration` {#kubecontrollermanager-config-k8s-io-v1alpha1-SAControllerConfiguration} + + + +**出现在:** + +- [KubeControllerManagerConfiguration](#kubecontrollermanager-config-k8s-io-v1alpha1-KubeControllerManagerConfiguration) + + +

            + +SAControllerConfiguration 包含描述 ServiceAccountController 的元素。 +

            + + + + + + + + + + + + + + + + + +
            字段描述
            ServiceAccountKeyFile [必需]
            +string +
            +

            + + serviceAccountKeyFile 是包含 PEM 编码的用于签署服务帐户令牌的 RSA 私钥的文件名。 +

            +
            ConcurrentSATokenSyncs [必需]
            +int32 +
            +

            + + concurrentSATokenSyncs 是将并发完成的服务帐户令牌同步操作的数量。 +

            +
            RootCAFile [必需]
            +string +
            +

            + + rootCAFile 是根证书颁发机构将被包含在 ServiceAccount 的令牌 Secret 中。 + 所提供的数据必须是一个有效的 PEM 编码的 CA 包。 +

            +
            + +## `StatefulSetControllerConfiguration` {#kubecontrollermanager-config-k8s-io-v1alpha1-StatefulSetControllerConfiguration} + + + +**出现在:** + +- [KubeControllerManagerConfiguration](#kubecontrollermanager-config-k8s-io-v1alpha1-KubeControllerManagerConfiguration) + + +

            + +StatefulSetControllerConfiguration 包含描述 StatefulSetController 的元素。 +

            + + + + + + + + + + + +
            字段描述
            ConcurrentStatefulSetSyncs [必需]
            +int32 +
            +

            + + concurrentStatefulSetSyncs 是允许并发同步的 StatefulSet 对象的数量。 + 数字越大意味着 StatefulSet 响应越快,但 CPU(和网络)负载也越高。 +

            +
            + +## `TTLAfterFinishedControllerConfiguration` {#kubecontrollermanager-config-k8s-io-v1alpha1-TTLAfterFinishedControllerConfiguration} + + + +**出现在:** + +- [KubeControllerManagerConfiguration](#kubecontrollermanager-config-k8s-io-v1alpha1-KubeControllerManagerConfiguration) + + +

            + +TTLAfterFinishedControllerConfiguration 包含描述 TTLAfterFinishedController 的元素。 +

            + + + + + + + + + + + +
            字段描述
            ConcurrentTTLSyncs [必需]
            +int32 +
            +

            + + concurrentTTLSyncs 是允许并发同步的 TTL-after-finished 收集器工作线程的数量。 +

            +
            + +## `ValidatingAdmissionPolicyStatusControllerConfiguration` {#kubecontrollermanager-config-k8s-io-v1alpha1-ValidatingAdmissionPolicyStatusControllerConfiguration} + + + +**出现在:** + +- [KubeControllerManagerConfiguration](#kubecontrollermanager-config-k8s-io-v1alpha1-KubeControllerManagerConfiguration) + + +

            + +ValidatingAdmissionPolicyStatusControllerConfiguration 包含描述 ValidatingAdmissionPolicyStatusController 的元素。 +

            + + + + + + + + + + + +
            字段描述
            ConcurrentPolicySyncs [必需]
            +int32 +
            +

            + + ConcurrentPolicySyncs 是允许并发同步的策略对象的数量。 + 数字越大意味着类型检查越快,但 CPU(和网络)负载越高。 + 默认值为 5。 +

            +
            + +## `VolumeConfiguration` {#kubecontrollermanager-config-k8s-io-v1alpha1-VolumeConfiguration} + + + +**出现在:** + +- [PersistentVolumeBinderControllerConfiguration](#kubecontrollermanager-config-k8s-io-v1alpha1-PersistentVolumeBinderControllerConfiguration) + + +

            + +VolumeConfiguration 包含所有用于配置各个卷插件的所有参数。 +从这个配置中,控制器管理器可执行文件将创建许多 volume.VolumeConfig 的实例。 +每个只包含该插件所需的配置,然后将其传递给相应的插件。 +控制器管理器可执行文件是代码中唯一知道支持哪些插件以及每个插件对应哪些标志的部分。 +

            + + + + + + + + + + + + + + + + + + + + +
            字段描述
            EnableHostPathProvisioning [必需]
            +bool +
            +

            + + enableHostPathProvisioning 在没有云驱动的情况下允许制备 HostPath PV。 + 此特性用来测试和开发 PV 卷制备特性。HostPath 配置完全不受支持,在多节点集群中无法工作, + 除了测试或开发之外不应该用于任何其他用途。 +

            +
            EnableDynamicProvisioning [必需]
            +bool +
            +

            + + enableDynamicProvisioning 在支持动态配置的环境中运行时允许制备新卷。默认为 true。 +

            +
            PersistentVolumeRecyclerConfiguration [必需]
            +PersistentVolumeRecyclerConfiguration +
            +

            + + persistentVolumeRecyclerConfiguration 保存持久卷插件的配置。 +

            +
            FlexVolumePluginDir [必需]
            +string +
            +

            + + volumePluginDir 是一个完整路径,FlexVolume 插件在这一目录中搜索额外的第三方卷插件。 +

            +
            + \ No newline at end of file diff --git a/content/zh-cn/docs/reference/config-api/kube-scheduler-config.v1.md b/content/zh-cn/docs/reference/config-api/kube-scheduler-config.v1.md index 636c76269af49..8ec219a90ed21 100644 --- a/content/zh-cn/docs/reference/config-api/kube-scheduler-config.v1.md +++ b/content/zh-cn/docs/reference/config-api/kube-scheduler-config.v1.md @@ -32,8 +32,6 @@ auto_generated: true --> **出现在:** -- [KubeSchedulerConfiguration](#kubescheduler-config-k8s-io-v1beta3-KubeSchedulerConfiguration) - - [KubeSchedulerConfiguration](#kubescheduler-config-k8s-io-v1-KubeSchedulerConfiguration) **出现在:** -- [KubeSchedulerConfiguration](#kubescheduler-config-k8s-io-v1beta3-KubeSchedulerConfiguration) - - [KubeSchedulerConfiguration](#kubescheduler-config-k8s-io-v1-KubeSchedulerConfiguration) **出现在:** -- [KubeSchedulerConfiguration](#kubescheduler-config-k8s-io-v1beta3-KubeSchedulerConfiguration) - - [KubeSchedulerConfiguration](#kubescheduler-config-k8s-io-v1-KubeSchedulerConfiguration)

            ClusterConfiguration 包含一个 kubeadm 集群的集群范围配置信息。

            @@ -818,10 +818,12 @@ interface and use that, but in case that process fails you may set the desired v

            certificateKey 用来设置一个密钥,该密钥将对 uploadcerts init -阶段上传到集群中某 Secret 内的密钥和证书加密。

            +阶段上传到集群中某 Secret 内的密钥和证书加密。 +证书密钥是十六进制编码的字符串,是长度为 32 字节的 AES 密钥。

            skipPhases
            @@ -1074,7 +1076,7 @@ APIServer 包含集群中 API 服务器部署所必需的设置。

            BootstrapTokenDiscovery 用来设置基于引导令牌的服务发现选项。

            @@ -1529,7 +1531,7 @@ HostPathMount contains elements describing volumes that are mounted from the hos pathType
            -core/v1.HostPathType +core/v1.HostPathType

            certificateKey 是在添加新的控制面节点时用来解密所下载的 -Secret 中的证书的密钥。对应的加密密钥在 InitConfiguration 结构中。

            +Secret 中的证书的密钥。对应的加密密钥在 InitConfiguration 结构中。 +证书密钥是十六进制编码的字符串,是长度为 32 字节的 AES 密钥。

            @@ -1645,7 +1649,7 @@ Secret 中的证书的密钥。对应的加密密钥在 InitConfiguration 结构 - [Etcd](#kubeadm-k8s-io-v1beta3-Etcd)

            LocalEtcd 描述的是 kubeadm 要使用的本地 etcd 集群。

            @@ -1729,7 +1733,7 @@ signing certificate. - [ClusterConfiguration](#kubeadm-k8s-io-v1beta3-ClusterConfiguration)

            Networking 中包含描述集群网络配置的元素。

            @@ -1784,7 +1788,7 @@ Networking contains elements describing cluster's networking configuration

            NodeRegistrationOptions 包含向集群中注册新的控制面或节点所需要的信息; 节点注册可能通过 "kubeadm init" 或 "kubeadm join" 完成。

            @@ -1823,7 +1827,7 @@ This information will be annotated to the Node API object, for later re-use. taints [必需]
            -[]core/v1.Taint +[]core/v1.Taint 字段描述 -json [必需]
            +json [必需]
            JSONOptions @@ -47,7 +47,7 @@ FormatOptions 包含为不同日志格式提供的选项。 [Alpha] JSON contains options for logging format "json". Only available when the LoggingAlphaOptions feature gate is enabled. --> -

            [Alpha] json 包含 "json" 日志格式的选项。 +

            [Alpha] json 包含 "json" 日志格式的选项。 只有 LoggingAlphaOptions 特性门控被启用时才可用。

            @@ -73,12 +73,13 @@ JSONOptions 包含为 "json" 日志格式提供的选项。 - - - - - -
            字段描述
            splitStream [必需]
            +
            splitStream [必需]
            bool

            - [必需]
            k8s.io/apimachinery/pkg/api/resource.QuantityValue

            @@ -135,7 +136,7 @@ LoggingConfiguration 包含日志选项。
            字段描述
            format [必需]
            +
            format [必需]
            string
            @@ -149,7 +150,7 @@ default value of format is `text`
            flushFrequency [必需]
            +
            flushFrequency [必需]
            TimeOrMetaDuration
            @@ -168,7 +169,7 @@ Ignored if the selected logging backend writes log messages without buffering.
            verbosity [必需]
            +
            verbosity [必需]
            VerbosityLevel
            @@ -185,7 +186,7 @@ are always logged.
            vmodule [必需]
            +
            vmodule [必需]
            VModuleConfiguration
            @@ -200,7 +201,7 @@ Only supported for "text" log format.
            options [必需]
            +
            options [必需]
            FormatOptions
            @@ -324,12 +325,10 @@ TracingConfiguration provides versioned configuration for OpenTelemetry tracing -->

            TracingConfiguration 为 OpenTelemetry 追踪客户端提供版本化的配置信息。

            - - - + @@ -352,7 +351,7 @@ Recommended is unset, and endpoint is the otlp grpc default, localhost:4317. Recommended is unset. If unset, sampler respects its parent span's sampling rate, but otherwise never samples. --> -

            samplingRatePerMillion 是每百万 span 要采集的样本数。推荐不设置。 +

            samplingRatePerMillion 是每百万 span 要采集的样本数。推荐不设置。 如果不设置,则采样器优先使用其父级 span 的采样率,否则不采样。

            @@ -412,11 +411,10 @@ Kubelet 从磁盘上读取这些配置信息,并根据 CredentialProvider 类
            字段描述
            endpoint
            string
            - + - - + @@ -452,7 +450,7 @@ KubeletConfiguration 中包含 Kubelet 的配置。 - @@ -652,12 +651,13 @@ Default: "" string @@ -666,7 +666,8 @@ Default: "" bool + + + + + @@ -1180,7 +1200,8 @@ Default: nil meta/v1.Duration @@ -1582,7 +1602,8 @@ Default: map[string]string - - @@ -2370,7 +2396,7 @@ Default: true 默认值:true

            - - - - - @@ -542,15 +544,15 @@ When set to true, external plugins can be used as subcommands for builtin comman - + @@ -560,104 +562,111 @@ When set to true, the --interactive flag in the kubectl delete command will be a ## {{% heading "seealso" %}} -* [kubectl annotate](/docs/reference/generated/kubectl/kubectl-commands#annotate) - 更新资源所关联的注解 -* [kubectl api-resources](/docs/reference/generated/kubectl/kubectl-commands#api-resources) - 打印服务器上所支持的 API 资源 -* [kubectl api-versions](/docs/reference/generated/kubectl/kubectl-commands#api-versions) - 以“组/版本”的格式输出服务端所支持的 API 版本 -* [kubectl apply](/docs/reference/generated/kubectl/kubectl-commands#apply) - 基于文件名或标准输入,将新的配置应用到资源上 -* [kubectl attach](/docs/reference/generated/kubectl/kubectl-commands#attach) - 连接到一个正在运行的容器 +* [kubectl annotate](/zh-cn/docs/reference/kubectl/generated/kubectl_annotate/) - 更新资源所关联的注解 +* [kubectl api-resources](/docs/reference/kubectl/generated/kubectl_api-resources/) - 打印服务器上所支持的 API 资源 +* [kubectl api-versions](/docs/reference/kubectl/generated/kubectl_api-versions/) - 以“组/版本”的格式输出服务端所支持的 API 版本 +* [kubectl apply](/docs/reference/kubectl/generated/kubectl_apply/) - 基于文件名或标准输入,将新的配置应用到资源上 +* [kubectl attach](/docs/reference/kubectl/generated/kubectl_attach/) - 挂接到一个正在运行的容器 -* [kubectl auth](/docs/reference/generated/kubectl/kubectl-commands#auth) - 检查授权信息 -* [kubectl autoscale](/docs/reference/generated/kubectl/kubectl-commands#autoscale) - 对一个资源对象(Deployment、ReplicaSet 或 ReplicationController )进行扩缩 -* [kubectl certificate](/docs/reference/generated/kubectl/kubectl-commands#certificate) - 修改证书资源 -* [kubectl cluster-info](/docs/reference/generated/kubectl/kubectl-commands#cluster-info) - 显示集群信息 -* [kubectl completion](/docs/reference/generated/kubectl/kubectl-commands#completion) - 根据已经给出的 Shell(bash 或 zsh),输出 Shell 补全后的代码 -* [kubectl config](/docs/reference/generated/kubectl/kubectl-commands#config) - 修改 kubeconfig 配置文件 +* [kubectl auth](/docs/reference/kubectl/generated/kubectl_auth/) - 检查授权信息 +* [kubectl autoscale](/docs/reference/kubectl/generated/kubectl_autoscale/) - 对一个资源对象 + (Deployment、ReplicaSet 或 ReplicationController)进行自动扩缩 +* [kubectl certificate](/docs/reference/kubectl/generated/kubectl_certificate/) - 修改证书资源 +* [kubectl cluster-info](/docs/reference/kubectl/generated/kubectl_cluster-info/) - 显示集群信息 +* [kubectl completion](/docs/reference/kubectl/generated/kubectl_completion/) - 根据已经给出的 Shell(bash 或 zsh), + 输出 Shell 补全后的代码 +* [kubectl config](/docs/reference/kubectl/generated/kubectl_config/) - 修改 kubeconfig 配置文件 -* [kubectl convert](/docs/reference/generated/kubectl/kubectl-commands#convert) - 在不同的 API 版本之间转换配置文件 -* [kubectl cordon](/docs/reference/generated/kubectl/kubectl-commands#cordon) - 标记节点为不可调度的 -* [kubectl cp](/docs/reference/generated/kubectl/kubectl-commands#cp) - 将文件和目录拷入/拷出容器 -* [kubectl create](/docs/reference/generated/kubectl/kubectl-commands#create) - 通过文件或标准输入来创建资源 -* [kubectl debug](/docs/reference/generated/kubectl/kubectl-commands#debug) - 创建用于排查工作负载和节点故障的调试会话 -* [kubectl delete](/docs/reference/generated/kubectl/kubectl-commands#delete) - 通过文件名、标准输入、资源和名字删除资源,或者通过资源和标签选择算符来删除资源 +* [kubectl cordon](/docs/reference/kubectl/generated/kubectl_cordon/) - 标记节点为不可调度的 +* [kubectl cp](/docs/reference/kubectl/generated/kubectl_cp/) - 将文件和目录拷入/拷出容器 +* [kubectl create](/docs/reference/kubectl/generated/kubectl_create/) - 通过文件或标准输入来创建资源 +* [kubectl debug](/docs/reference/kubectl/generated/kubectl_debug/) - 创建用于排查工作负载和节点故障的调试会话 +* [kubectl delete](/docs/reference/kubectl/generated/kubectl_delete/) - 通过文件名、标准输入、资源和名字删除资源, + 或者通过资源和标签选择算符来删除资源 -* [kubectl describe](/docs/reference/generated/kubectl/kubectl-commands#describe) - 显示某个资源或某组资源的详细信息 -* [kubectl diff](/docs/reference/generated/kubectl/kubectl-commands#diff) - 显示目前版本与将要应用的版本之间的差异 -* [kubectl drain](/docs/reference/generated/kubectl/kubectl-commands#drain) - 腾空节点,准备维护 -* [kubectl edit](/docs/reference/generated/kubectl/kubectl-commands#edit) - 修改服务器上的某资源 -* [kubectl events](/docs/reference/generated/kubectl/kubectl-commands#events) - 列举事件 -* [kubectl exec](/docs/reference/generated/kubectl/kubectl-commands#exec) - 在容器中执行相关命令 -* [kubectl explain](/docs/reference/generated/kubectl/kubectl-commands#explain) - 显示资源文档说明 -* [kubectl expose](/docs/reference/generated/kubectl/kubectl-commands#expose) - 给定副本控制器、服务、Deployment 或 Pod,将其暴露为新的 kubernetes Service +* [kubectl describe](/docs/reference/kubectl/generated/kubectl_describe/) - 显示某个资源或某组资源的详细信息 +* [kubectl diff](/docs/reference/kubectl/generated/kubectl_diff/) - 显示目前版本与将要应用的版本之间的差异 +* [kubectl drain](/docs/reference/kubectl/generated/kubectl_drain/) - 腾空节点,准备维护 +* [kubectl edit](/docs/reference/kubectl/generated/kubectl_edit/) - 修改服务器上的某资源 +* [kubectl events](/docs/reference/kubectl/generated/kubectl_events/) - 列举事件 +* [kubectl exec](/docs/reference/kubectl/generated/kubectl_exec/) - 在容器中执行相关命令 +* [kubectl explain](/docs/reference/kubectl/generated/kubectl_explain/) - 显示资源文档说明 +* [kubectl expose](/docs/reference/kubectl/generated/kubectl_expose/) - 给定副本控制器、服务、Deployment 或 Pod, + 将其暴露为新的 kubernetes Service -* [kubectl get](/docs/reference/generated/kubectl/kubectl-commands#get) - 显示一个或者多个资源信息 -* [kubectl kustomize](/docs/reference/generated/kubectl/kubectl-commands#kustomize) - 从目录或远程 URL 中构建 kustomization -* [kubectl label](/docs/reference/generated/kubectl/kubectl-commands#label) - 更新资源的标签 -* [kubectl logs](/docs/reference/generated/kubectl/kubectl-commands#logs) - 输出 Pod 中某容器的日志 -* [kubectl options](/docs/reference/generated/kubectl/kubectl-commands#options) - 打印所有命令都支持的共有参数列表 -* [kubectl patch](/docs/reference/generated/kubectl/kubectl-commands#patch) - 基于策略性合并修补(Stategic Merge Patch)规则更新某资源中的字段 +* [kubectl get](/docs/reference/kubectl/generated/kubectl_get/) - 显示一个或者多个资源信息 +* [kubectl kustomize](/docs/reference/kubectl/generated/kubectl_kustomize/) - 从目录或远程 URL 中构建 kustomization +* [kubectl label](/docs/reference/kubectl/generated/kubectl_label/) - 更新资源的标签 +* [kubectl logs](/docs/reference/kubectl/generated/kubectl_logs/) - 输出 Pod 中某容器的日志 +* [kubectl options](/docs/reference/kubectl/generated/kubectl_options/) - 打印所有命令都支持的共有参数列表 +* [kubectl patch](/docs/reference/kubectl/generated/kubectl_patch/) - 更新某资源中的字段 -* [kubectl plugin](/docs/reference/generated/kubectl/kubectl-commands#plugin) - 运行命令行插件 -* [kubectl port-forward](/docs/reference/generated/kubectl/kubectl-commands#port-forward) - 将一个或者多个本地端口转发到 Pod -* [kubectl proxy](/docs/reference/generated/kubectl/kubectl-commands#proxy) - 运行一个 kubernetes API 服务器代理 -* [kubectl replace](/docs/reference/generated/kubectl/kubectl-commands#replace) - 基于文件名或标准输入替换资源 -* [kubectl rollout](/docs/reference/generated/kubectl/kubectl-commands#rollout) - 管理资源的上线 -* [kubectl run](/docs/reference/generated/kubectl/kubectl-commands#run) - 在集群中使用指定镜像启动容器 +* [kubectl plugin](/docs/reference/kubectl/generated/kubectl_plugin/) - 运行命令行插件 +* [kubectl port-forward](/docs/reference/kubectl/generated/kubectl_port-forward/) - 将一个或者多个本地端口转发到 Pod +* [kubectl proxy](/docs/reference/kubectl/generated/kubectl_proxy/) - 运行一个 kubernetes API 服务器代理 +* [kubectl replace](/docs/reference/kubectl/generated/kubectl_replace/) - 基于文件名或标准输入替换资源 +* [kubectl rollout](/docs/reference/kubectl/generated/kubectl_rollout/) - 管理资源的上线 +* [kubectl run](/docs/reference/kubectl/generated/kubectl_run/) - 在集群中使用指定镜像启动容器 -* [kubectl scale](/docs/reference/generated/kubectl/kubectl-commands#scale) - 为一个 Deployment、ReplicaSet 或 ReplicationController 设置一个新的规模值 -* [kubectl set](/docs/reference/generated/kubectl/kubectl-commands#set) - 为对象设置功能特性 -* [kubectl taint](/docs/reference/generated/kubectl/kubectl-commands#taint) - 在一个或者多个节点上更新污点配置 -* [kubectl top](/docs/reference/generated/kubectl/kubectl-commands#top) - 显示资源(CPU/内存/存储)使用率 -* [kubectl uncordon](/docs/reference/generated/kubectl/kubectl-commands#uncordon) - 标记节点为可调度的 -* [kubectl version](/docs/reference/generated/kubectl/kubectl-commands#version) - 打印客户端和服务器的版本信息 -* [kubectl wait](/docs/reference/generated/kubectl/kubectl-commands#wait) - 实验级特性:等待一个或多个资源达到某种状态 +* [kubectl scale](/docs/reference/kubectl/generated/kubectl_scale/) - 为一个 Deployment、ReplicaSet 或 + ReplicationController 设置一个新的规模值 +* [kubectl set](/docs/reference/kubectl/generated/kubectl_set/) - 为对象设置功能特性 +* [kubectl taint](/docs/reference/kubectl/generated/kubectl_taint/) - 在一个或者多个节点上更新污点配置 +* [kubectl top](/docs/reference/kubectl/generated/kubectl_top/) - 显示资源(CPU/内存/存储)使用率 +* [kubectl uncordon](/docs/reference/kubectl/generated/kubectl_uncordon/) - 标记节点为可调度的 +* [kubectl version](/docs/reference/kubectl/generated/kubectl_version/) - 打印客户端和服务器的版本信息 +* [kubectl wait](/docs/reference/kubectl/generated/kubectl_wait/) - 实验级特性:等待一个或多个资源达到某种状态 diff --git a/content/zh-cn/docs/reference/kubectl/quick-reference.md b/content/zh-cn/docs/reference/kubectl/quick-reference.md index 7037c5512b962..94685d1271259 100644 --- a/content/zh-cn/docs/reference/kubectl/quick-reference.md +++ b/content/zh-cn/docs/reference/kubectl/quick-reference.md @@ -81,12 +81,16 @@ echo '[[ $commands[kubectl] ]] && source <(kubectl completion zsh)' >> ~/.zshrc 需要 kubectl 版本 1.23 或更高版本。 ```bash -+echo 'kubectl completion fish | source' >> ~/.config/fish/config.fish # 将 kubectl 自动补全永久添加到你的 Fish shell 中 +echo 'kubectl completion fish | source' >> ~/.config/fish/config.fish # 将 kubectl 自动补全永久添加到你的 Fish shell 中 ``` ```bash -kubectl apply -f ./my-manifest.yaml # 创建资源 -kubectl apply -f ./my1.yaml -f ./my2.yaml # 使用多个文件创建 -kubectl apply -f ./dir # 基于目录下的所有清单文件创建资源 -kubectl apply -f https://git.io/vPieo # 从 URL 中创建资源 -kubectl create deployment nginx --image=nginx # 启动单实例 nginx +kubectl apply -f ./my-manifest.yaml # 创建资源 +kubectl apply -f ./my1.yaml -f ./my2.yaml # 使用多个文件创建 +kubectl apply -f ./dir # 基于目录下的所有清单文件创建资源 +kubectl apply -f https://example.com/manifest.yaml # 从 URL 中创建资源(注意:这是一个示例域名,不包含有效的清单) +kubectl create deployment nginx --image=nginx # 启动单实例 nginx # 创建一个打印 “Hello World” 的 Job kubectl create job hello --image=busybox:1.28 -- echo "Hello World" @@ -546,7 +564,7 @@ kubectl label pods my-pod new-label=awesome # Add a Label kubectl label pods my-pod new-label- # Remove a label kubectl label pods my-pod new-label=new-value --overwrite # Overwrite an existing value kubectl annotate pods my-pod icon-url=http://goo.gl/XXBTWq # Add an annotation -kubectl annotate pods my-pod icon- # Remove annotation +kubectl annotate pods my-pod icon-url- # Remove annotation kubectl autoscale deployment foo --min=2 --max=10 # Auto scale a deployment "foo" ``` --> @@ -573,7 +591,7 @@ kubectl label pods my-pod new-label=awesome # 添加标签 kubectl label pods my-pod new-label- # 移除标签 kubectl label pods my-pod new-label=new-value --overwrite # 覆盖现有的值 kubectl annotate pods my-pod icon-url=http://goo.gl/XXBTWq # 添加注解 -kubectl annotate pods my-pod icon- # 移除注解 +kubectl annotate pods my-pod icon-url- # 移除注解 kubectl autoscale deployment foo --min=2 --max=10 # 对 "foo" Deployment 自动扩缩容 ``` @@ -714,6 +732,7 @@ kubectl port-forward my-pod 5000:6000 # Listen on port 5000 on the kubectl exec my-pod -- ls / # Run command in existing pod (1 container case) kubectl exec --stdin --tty my-pod -- /bin/sh # Interactive shell access to a running pod (1 container case) kubectl exec my-pod -c my-container -- ls / # Run command in existing pod (multi-container case) +kubectl top pod # Show metrics for all pods in the default namespace kubectl top pod POD_NAME --containers # Show metrics for a given pod and its containers kubectl top pod POD_NAME --sort-by=cpu # Show metrics for a given pod and sort it by 'cpu' or 'memory' ``` @@ -738,7 +757,8 @@ kubectl port-forward my-pod 5000:6000 # 在本地计算机上侦 kubectl exec my-pod -- ls / # 在已有的 Pod 中运行命令(单容器场景) kubectl exec --stdin --tty my-pod -- /bin/sh # 使用交互 shell 访问正在运行的 Pod (一个容器场景) kubectl exec my-pod -c my-container -- ls / # 在已有的 Pod 中运行命令(多容器场景) -kubectl top pod POD_NAME --containers # 显示给定 Pod 和其中容器的监控数据 +kubectl top pod # 显示默认命名空间中所有 Pod 的度量值 +kubectl top pod POD_NAME --containers # 显示给定 Pod 和其中容器的度量值 kubectl top pod POD_NAME --sort-by=cpu # 显示给定 Pod 的指标并且按照 'cpu' 或者 'memory' 排序 ``` @@ -820,6 +840,7 @@ kubectl exec deploy/my-deployment -- ls # 在 Deployment 里 kubectl cordon my-node # Mark my-node as unschedulable kubectl drain my-node # Drain my-node in preparation for maintenance kubectl uncordon my-node # Mark my-node as schedulable +kubectl top node # Show metrics for all nodes kubectl top node my-node # Show metrics for a given node kubectl cluster-info # Display addresses of the master and services kubectl cluster-info dump # Dump current cluster state to stdout @@ -836,6 +857,7 @@ kubectl taint nodes foo dedicated=special-user:NoSchedule kubectl cordon my-node # 标记 my-node 节点为不可调度 kubectl drain my-node # 对 my-node 节点进行清空操作,为节点维护做准备 kubectl uncordon my-node # 标记 my-node 节点为可以调度 +kubectl top node # 显示所有节点的度量值 kubectl top node my-node # 显示给定节点的度量值 kubectl cluster-info # 显示主控节点和服务的地址 kubectl cluster-info dump # 将当前集群状态转储到标准输出 diff --git a/content/zh-cn/docs/reference/kubernetes-api/common-parameters/common-parameters.md b/content/zh-cn/docs/reference/kubernetes-api/common-parameters/common-parameters.md index 88bf47d391e40..3195e44c735de 100644 --- a/content/zh-cn/docs/reference/kubernetes-api/common-parameters/common-parameters.md +++ b/content/zh-cn/docs/reference/kubernetes-api/common-parameters/common-parameters.md @@ -70,10 +70,10 @@ When present, indicates that modifications should not be persisted. An invalid o ## fieldManager {#fieldManager} fieldManager 是与进行这些更改的参与者或实体相关联的名称。 -长度小于或128个字符且仅包含可打印字符,如 https://golang.org/pkg/unicode/#IsPrint 所定义。 +长度小于或128个字符且仅包含可打印字符,如 https://pkg.go.dev/unicode#IsPrint 所定义。
            diff --git a/content/zh-cn/docs/reference/kubernetes-api/extend-resources/mutating-webhook-configuration-v1.md b/content/zh-cn/docs/reference/kubernetes-api/extend-resources/mutating-webhook-configuration-v1.md index df95a52429782..c8fa3519f15f4 100644 --- a/content/zh-cn/docs/reference/kubernetes-api/extend-resources/mutating-webhook-configuration-v1.md +++ b/content/zh-cn/docs/reference/kubernetes-api/extend-resources/mutating-webhook-configuration-v1.md @@ -1,8 +1,8 @@ --- api_metadata: -apiVersion: "admissionregistration.k8s.io/v1" -import: "k8s.io/api/admissionregistration/v1" -kind: "MutatingWebhookConfiguration" + apiVersion: "admissionregistration.k8s.io/v1" + import: "k8s.io/api/admissionregistration/v1" + kind: "MutatingWebhookConfiguration" content_type: "api_reference" description: "MutatingWebhookConfiguration 描述准入 Webhook 的配置,该 Webhook 可在更改对象的情况下接受或拒绝对象请求" title: "MutatingWebhookConfiguration" diff --git a/content/zh-cn/docs/reference/kubernetes-api/other-resources/validating-admission-policy-binding-list-v1alpha1.md b/content/zh-cn/docs/reference/kubernetes-api/other-resources/validating-admission-policy-binding-list-v1beta1.md similarity index 55% rename from content/zh-cn/docs/reference/kubernetes-api/other-resources/validating-admission-policy-binding-list-v1alpha1.md rename to content/zh-cn/docs/reference/kubernetes-api/other-resources/validating-admission-policy-binding-list-v1beta1.md index dffd13e539838..1c9700de6b271 100644 --- a/content/zh-cn/docs/reference/kubernetes-api/other-resources/validating-admission-policy-binding-list-v1alpha1.md +++ b/content/zh-cn/docs/reference/kubernetes-api/other-resources/validating-admission-policy-binding-list-v1beta1.md @@ -8,18 +8,9 @@ description: "" title: "ValidatingAdmissionPolicyBindingList v1beta1" weight: 1 --- - `apiVersion: admissionregistration.k8s.io/v1beta1` `import "k8s.io/api/admissionregistration/v1beta1"` + + diff --git a/content/zh-cn/docs/reference/kubernetes-api/workload-resources/job-v1.md b/content/zh-cn/docs/reference/kubernetes-api/workload-resources/job-v1.md index 478f91e123b61..a283c01425cc5 100644 --- a/content/zh-cn/docs/reference/kubernetes-api/workload-resources/job-v1.md +++ b/content/zh-cn/docs/reference/kubernetes-api/workload-resources/job-v1.md @@ -1,8 +1,8 @@ --- api_metadata: -apiVersion: "batch/v1" -import: "k8s.io/api/batch/v1" -kind: "Job" + apiVersion: "batch/v1" + import: "k8s.io/api/batch/v1" + kind: "Job" content_type: "api_reference" description: "Job 表示单个任务的配置。" title: "Job" diff --git a/content/zh-cn/docs/reference/labels-annotations-taints/audit-annotations.md b/content/zh-cn/docs/reference/labels-annotations-taints/audit-annotations.md index 61dfe89cd007d..ad42aaba030b6 100644 --- a/content/zh-cn/docs/reference/labels-annotations-taints/audit-annotations.md +++ b/content/zh-cn/docs/reference/labels-annotations-taints/audit-annotations.md @@ -219,7 +219,7 @@ Example: `validation.policy.admission.k8s.io/validation_failure: '[{"message": " diff --git a/content/zh-cn/docs/reference/node/_index.md b/content/zh-cn/docs/reference/node/_index.md index e2f4aa17486d3..93a394fb0d390 100644 --- a/content/zh-cn/docs/reference/node/_index.md +++ b/content/zh-cn/docs/reference/node/_index.md @@ -15,21 +15,34 @@ This section contains the following reference topics about nodes: * the kubelet's [checkpoint API](/docs/reference/node/kubelet-checkpoint-api/) * a list of [Articles on dockershim Removal and on Using CRI-compatible Runtimes](/docs/reference/node/topics-on-dockershim-and-cri-compatible-runtimes/) -* [Node `.status` information](/docs/reference/node/node-status/) -You can also read node reference details from elsewhere in the -Kubernetes documentation, including: +* [Kubelet Device Manager API Versions](/docs/reference/node/device-plugin-api-versions) -* [Node Metrics Data](/docs/reference/instrumentation/node-metrics). -* [CRI Pod & Container Metrics](/docs/reference/instrumentation/cri-pod-container-metrics). +* [Node Labels Populated By The Kubelet](/docs/reference/node/node-labels) + +* [Node `.status` information](/docs/reference/node/node-status/) --> 本部分包含以下有关节点的参考主题: * Kubelet 的 [Checkpoint API](/zh-cn/docs/reference/node/kubelet-checkpoint-api/) * 一系列[关于 dockershim 移除和使用兼容 CRI 运行时的文章](/zh-cn/docs/reference/node/topics-on-dockershim-and-cri-compatible-runtimes/) + +* [Kubelet 设备管理器 API 版本](/zh-cn/docs/reference/node/device-plugin-api-versions) + +* [由 kubelet 填充的节点标签](/zh-cn/docs/reference/node/node-labels) + * [节点 `.status` 信息](/zh-cn/docs/reference/node/node-status/) * + + 你还可以从 Kubernetes 文档的其他地方阅读节点的详细参考信息,包括: * [节点指标数据](/zh-cn/docs/reference/instrumentation/node-metrics)。 -* [CRI Pod & 容器指标](/docs/reference/instrumentation/cri-pod-container-metrics). + +* [CRI Pod & 容器指标](/zh-cn/docs/reference/instrumentation/cri-pod-container-metrics)。 diff --git a/content/zh-cn/docs/reference/node/node-labels.md b/content/zh-cn/docs/reference/node/node-labels.md index 543d1aafedc2a..7a27954c9c567 100644 --- a/content/zh-cn/docs/reference/node/node-labels.md +++ b/content/zh-cn/docs/reference/node/node-labels.md @@ -1,7 +1,8 @@ +--- content_type: "reference" title: 由 kubelet 填充的节点标签 weight: 40 - +--- -## 预设标签 +## 预设标签 {#preset-labels} Kubernetes 在节点上设置的预设标签有: diff --git a/content/zh-cn/docs/reference/scheduling/config.md b/content/zh-cn/docs/reference/scheduling/config.md index 7d6679e9bf2f3..352e5b77ad322 100644 --- a/content/zh-cn/docs/reference/scheduling/config.md +++ b/content/zh-cn/docs/reference/scheduling/config.md @@ -52,11 +52,10 @@ clientConnection: {{< note >}} -KubeSchedulerConfiguration [v1beta3](/zh-cn/docs/reference/config-api/kube-scheduler-config.v1beta3/) 在 v1.26 中已被弃用, +KubeSchedulerConfiguration v1beta3 在 v1.26 中已被弃用, 并将在 v1.29 中被移除。请将 KubeSchedulerConfiguration 迁移到 [v1](/zh-cn/docs/reference/config-api/kube-scheduler-config.v1/)。 {{< /note >}} @@ -839,12 +838,8 @@ to achieve similar behavior. * 阅读 [kube-scheduler 参考](/zh-cn/docs/reference/command-line-tools-reference/kube-scheduler/) * 了解[调度](/zh-cn/docs/concepts/scheduling-eviction/kube-scheduler/) -* 阅读 [kube-scheduler 配置 (v1beta2)](/zh-cn/docs/reference/config-api/kube-scheduler-config.v1beta2/) 参考 -* 阅读 [kube-scheduler 配置 (v1beta3)](/zh-cn/docs/reference/config-api/kube-scheduler-config.v1beta3/) 参考 * 阅读 [kube-scheduler 配置 (v1)](/zh-cn/docs/reference/config-api/kube-scheduler-config.v1/) 参考 diff --git a/content/zh-cn/docs/reference/setup-tools/kubeadm/generated/kubeadm_certs_renew_super-admin.conf.md b/content/zh-cn/docs/reference/setup-tools/kubeadm/generated/kubeadm_certs_renew_super-admin.conf.md index 641fb57763769..e0ebe45aeec3b 100644 --- a/content/zh-cn/docs/reference/setup-tools/kubeadm/generated/kubeadm_certs_renew_super-admin.conf.md +++ b/content/zh-cn/docs/reference/setup-tools/kubeadm/generated/kubeadm_certs_renew_super-admin.conf.md @@ -76,9 +76,9 @@ Path to a kubeadm configuration file. +

            super-admin.conf 的帮助信息。

            diff --git a/content/zh-cn/docs/reference/setup-tools/kubeadm/generated/kubeadm_config_print_join-defaults.md b/content/zh-cn/docs/reference/setup-tools/kubeadm/generated/kubeadm_config_print_join-defaults.md index 6ef05b0c33f32..6fb3870b3fb43 100644 --- a/content/zh-cn/docs/reference/setup-tools/kubeadm/generated/kubeadm_config_print_join-defaults.md +++ b/content/zh-cn/docs/reference/setup-tools/kubeadm/generated/kubeadm_config_print_join-defaults.md @@ -36,21 +36,6 @@ kubeadm config print join-defaults [flags] - - - - - - diff --git a/content/zh-cn/docs/reference/setup-tools/kubeadm/generated/kubeadm_config_print_reset-defaults.md b/content/zh-cn/docs/reference/setup-tools/kubeadm/generated/kubeadm_config_print_reset-defaults.md index 8378007a3a2b6..e0e15e62569d2 100644 --- a/content/zh-cn/docs/reference/setup-tools/kubeadm/generated/kubeadm_config_print_reset-defaults.md +++ b/content/zh-cn/docs/reference/setup-tools/kubeadm/generated/kubeadm_config_print_reset-defaults.md @@ -29,29 +29,13 @@ kubeadm config print reset-defaults [flags] --> ### 选项 -
            字段描述
            apiVersion
            string
            kubelet.config.k8s.io/v1beta1
            kind
            string
            CredentialProviderConfig
            providers [必需]
            []CredentialProvider
            apiVersion
            string
            kubelet.config.k8s.io/v1beta1
            kind
            string
            KubeletConfiguration
            enableServer [必需]
            +
            enableServer [必需]
            bool
            @@ -622,7 +620,8 @@ Default:"quot; string -

            tlsPrivateKeyFile 是一个包含与 tlsCertFile @@ -638,12 +637,12 @@ Default: ""

            tlsCipherSuites 是一个字符串列表,其中包含服务器所接受的加密包名称。 请注意,TLS 1.3 密码套件是不可配置的。 - 列表中的每个值来自于 tls 包中定义的常数(https://golang.org/pkg/crypto/tls/#pkg-constants)。

            + 列表中的每个值来自于 tls 包中定义的常数(https://pkg.go.dev/crypto/tls#pkg-constants)。

            默认值:nil

            -

            tlsMinVersion 给出所支持的最小 TLS 版本。 -字段取值来自于 tls 包中的常数定义(https://golang.org/pkg/crypto/tls/#pkg-constants)。

            +字段取值来自于 tls 包中的常数定义(https://pkg.go.dev/crypto/tls#pkg-constants)。

            默认值:""

            - -

            imageMinimumGCAge 是对未使用镜像进行垃圾搜集之前允许其存在的时长。

            +

            imageMinimumGCAge 是对未使用镜像进行垃圾收集之前允许其存在的时长。

            默认值:"2m"

            +imageMaximumGCAge
            +meta/v1.Duration +
            + +

            imageMaximumGCAge 是对未使用镜像进行垃圾收集之前允许其存在的时长。 + 此字段的默认值为 "0s",表示禁用此字段,这意味着镜像不会因为过长时间不使用而被垃圾收集。 + 默认值:"0s"(已禁用)

            +
            imageGCHighThresholdPercent
            int32
            - @@ -1333,7 +1354,7 @@ themselves if they should try to access their own Service. Values:

            Generally, one must set --hairpin-mode=hairpin-veth to achieve hairpin NAT, because promiscuous-bridge assumes the existence of a container bridge named cbr0. Default: "promiscuous-bridge" - --> + -->

            一般而言,用户必须设置 --hairpin-mode=hairpin-veth 才能实现发夹模式的网络地址转译 (NAT),因为混杂模式的网桥要求存在一个名为 cbr0 的容器网桥。

            默认值:"promiscuous-bridge"

            @@ -1393,8 +1414,7 @@ If set to the empty string, will override the default and effectively disable DN Default: "/etc/resolv.conf" -->

            resolvConf 是一个域名解析配置文件,用作容器 DNS 解析配置的基础。

            -

            如果此值设置为空字符串,则会覆盖 DNS 解析的默认配置, -本质上相当于禁用了 DNS 查询。

            +

            如果此值设置为空字符串,则会覆盖 DNS 解析的默认配置,本质上相当于禁用了 DNS 查询。

            默认值:"/etc/resolv.conf"

            - @@ -1596,7 +1617,8 @@ Default: nil map[string]string - @@ -1892,12 +1914,12 @@ Default: nil

            kubeReserved 是一组资源名称=资源数量对, 用来描述为 Kubernetes 系统组件预留的资源(例如:'cpu=200m,memory=150G')。 目前支持 CPU、内存和根文件系统的本地存储。 -更多细节可参见 https://kubernetes.io/zh/docs/concepts/configuration/manage-resources-containers/。

            +更多细节可参见 https://kubernetes.io/zh-cn/docs/concepts/configuration/manage-resources-containers/。

            默认值:Nil

            reservedSystemCPUs [必需]
            +
            reservedSystemCPUs [必需]
            string
            @@ -2069,7 +2091,7 @@ memcg 通知机制来确定是否超出内存逐出阈值,而不是使用轮
            logging [必需]
            +
            logging [必需]
            LoggingConfiguration
            @@ -2080,7 +2102,7 @@ for more information. Default: Format: text --> -

            logging设置日志机制选项。更多的详细信息科参阅 +

            logging设置日志机制选项。更多的详细信息可参阅 日志选项

            默认值:

            Format: text
            @@ -2118,7 +2140,8 @@ EnableSystemLogHandler has to be enabled in addition for this feature to work. meta/v1.Duration
            - @@ -2132,7 +2155,8 @@ Pod 提供的宽限期限的总时长。

            meta/v1.Duration
            - +

            tracing 为 OpenTelemetry 追踪客户端设置版本化的配置信息。 参阅 https://kep.k8s.io/2832 了解更多细节。

            containerRuntimeEndpoint [必需]
            +
            containerRuntimeEndpoint [必需]
            string
            @@ -2422,7 +2448,7 @@ SerializedNodeConfigSource 允许对 `v1.NodeConfigSource` 执行序列化操作
            kind
            string
            SerializedNodeConfigSource
            source
            -core/v1.NodeConfigSource +core/v1.NodeConfigSource

            matchImages 中的每个条目都是一个模式字符串,其中可以包含端口号和路径。 域名部分可以包含统配符,但端口或路径部分不可以。通配符可以用作子域名,例如 @@ -2896,7 +2922,7 @@ MemoryReservation 为每个 NUMA 节点设置不同类型的内存预留。

            字段描述
            numaNode [必需]
            +
            numaNode [必需]
            int32
            @@ -2905,8 +2931,8 @@ MemoryReservation 为每个 NUMA 节点设置不同类型的内存预留。
            limits [必需]
            -core/v1.ResourceList +
            limits [必需]
            +core/v1.ResourceList
            @@ -2987,7 +3013,7 @@ ShutdownGracePeriodByPodPriority 基于 Pod 关联的优先级类数值来为其
            字段描述
            priority [必需]
            +
            priority [必需]
            int32
            @@ -2998,7 +3024,7 @@ ShutdownGracePeriodByPodPriority 基于 Pod 关联的优先级类数值来为其
            shutdownGracePeriodSeconds [必需]
            +
            shutdownGracePeriodSeconds [必需]
            int64
            diff --git a/content/zh-cn/docs/reference/config-api/kubelet-credentialprovider.v1.md b/content/zh-cn/docs/reference/config-api/kubelet-credentialprovider.v1.md index d2f0c621f03a8..68ad743f4d20e 100644 --- a/content/zh-cn/docs/reference/config-api/kubelet-credentialprovider.v1.md +++ b/content/zh-cn/docs/reference/config-api/kubelet-credentialprovider.v1.md @@ -114,7 +114,7 @@ kubelet 将使用此字段为 AuthConfig 中的凭据设置内存中缓存持续
            auth
            -map[string]k8s.io/kubelet/pkg/apis/credentialprovider/v1.AuthConfig +map[string]AuthConfig
            Init 容器像常规应用容器一样,只有一点不同:Init 容器必须在应用容器启动前运行完成。 Init 容器的运行顺序:一个 Init 容器必须在下一个 Init 容器开始前运行完成。 + + +与{{< glossary_tooltip text="边车容器" term_id="sidecar-container" >}}不同,Init 容器在 Pod 启动后不会继续运行。 + +有关更多信息,请阅读 [Init 容器](/zh-cn/docs/concepts/workloads/pods/init-containers/)。 diff --git a/content/zh-cn/docs/reference/glossary/replica.md b/content/zh-cn/docs/reference/glossary/replica.md new file mode 100644 index 0000000000000..50df8addc13dc --- /dev/null +++ b/content/zh-cn/docs/reference/glossary/replica.md @@ -0,0 +1,53 @@ +--- +title: 副本(Replica) +id: replica +date: 2023-06-11 +full_link: +short_description: > + Replicas 是 Pod 的副本,通过维护相同的实例确保可用性、可扩缩性和容错性。 +aka: +tags: +- fundamental +- workload +--- + + + + +单个 {{< glossary_tooltip text="Pod" term_id="pod" >}} 或一组 Pod 的复制拷贝。 +Replicas 通过维护多个相同的 Pod 实例保证了高可用性、可扩缩性和容错性。 + + + +Kubernetes 中通常使用副本来实现期望的应用状态和可靠性。 +它们可以在集群的多个节点上扩缩和分配工作负载。 + +在 Deployment 或 ReplicaSet 中定义副本数量, Kubernetes 确保了所期望数量的实例正在运行, +并且会根据需要自动调整这个数量。 + +副本管理可以在 Kubernetes 集群中提供了高效的负载均衡、滚动更新和自愈能力。 + diff --git a/content/zh-cn/docs/reference/instrumentation/slis.md b/content/zh-cn/docs/reference/instrumentation/slis.md index af5a811d9069c..560f1dc7d08f2 100644 --- a/content/zh-cn/docs/reference/instrumentation/slis.md +++ b/content/zh-cn/docs/reference/instrumentation/slis.md @@ -15,7 +15,7 @@ weight: 20 -{{< feature-state for_k8s_version="v1.27" state="beta" >}} +{{< feature-state for_k8s_version="v1.29" state="stable" >}} + +## {{% heading "synopsis" %}} + + +更新一个或多个资源上的注解。 + +所有 Kubernetes 对象都支持以注解(Annotation)的形式为对象存储额外的数据。 +注解是一些键/值对,可以比标签的数据量更大,可以包含诸如结构化 JSON 这类任意字符串值。 +各种工具和系统扩展可以使用注解来存储自己的数据。 + +尝试设置已存在的注解的操作将会失败,除非设置了 --overwrite 选项。 +如果 --resource-version 被指定且与服务器上当前资源版本不匹配,命令将会失败。 + +使用 "kubectl api-resources" 获取可支持的资源完整列表。 + +```shell +kubectl annotate [--overwrite] (-f FILENAME | TYPE NAME) KEY_1=VAL_1 ... KEY_N=VAL_N [--resource-version=version] +``` + +## {{% heading "examples" %}} + + +```shell +# 使用注解 'description' 和值 'my frontend' 更新 Pod 'foo' +# 如果同一注解被设置多次,则只使用最后一个值 +kubectl annotate pods foo description='my frontend' + +# 更新在 "pod.json" 中指定 type 和 name 的 Pod +kubectl annotate -f pod.json description='my frontend' + +# 更新 Pod 'foo',设置注解 'description' 和值 'my frontend running nginx',覆盖其当前值 +kubectl annotate --overwrite pods foo description='my frontend running nginx' + +# 更新命名空间中的所有 Pod +kubectl annotate pods --all description='my frontend running nginx' + +# 仅在资源版本仍为 1 时更新 Pod 'foo' +kubectl annotate pods foo description='my frontend running nginx' --resource-version=1 + +# 通过删除名为 'description' 的注解(如果存在)来更新 Pod 'foo' +# 不需要 --overwrite 标志 +kubectl annotate pods foo description- +``` + +## {{% heading "options" %}} + + ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
            --all

            + +在指定资源类型的命名空间中,选择所有资源。 +

            -A, --all-namespaces

            + +如果为 true,则在所有命名空间中执行指定的操作。 +

            --allow-missing-template-keys     默认值:true

            + +如果为 true,在模板中字段或映射键缺失时忽略模板中的错误。 +仅适用于 golang 和 jsonpath 输出格式。 +

            --dry-run string[="unchanged"]     默认值:"none"

            + +必须是 "none"、"server" 或 "client"。如果是 client 策略,仅打印将要发送的对象,而不实际发送。 +如果是 server 策略,提交服务器端请求而不持久化资源。 +

            --field-manager string     默认值:"kubectl-annotate"

            + +用于跟踪字段属主关系的管理器的名称。 +

            --field-selector string

            + +过滤所用的选择算符(字段查询),支持 '='、'==' 和 '!='。 +(例如 --field-selector key1=value1,key2=value2)。服务器针对每种类型仅支持有限数量的字段查询。 +

            -f, --filename strings

            + +文件名、目录或文件 URL,用于标识要更新注解的资源。 +

            -h, --help

            + +annotate 的帮助命令。 +

            -k, --kustomize string

            + +处理 kustomization 目录。此标志不能与 -f 或 -R 一起使用。 +

            --list

            + +如果为 true,则显示给定资源的注解。 +

            --local

            + +如果为 true,则注解不会与 api-server 通信,而是在本地运行。 +

            -o, --output string

            + +输出格式。可选值为: +json、yaml、name、go-template、go-template-file、template、templatefile、jsonpath、jsonpath-as-json、jsonpath-file。 +

            --overwrite

            + +如果为 true,则允许注解被覆盖,否则拒绝覆盖现有注解的更新。 +

            -R, --recursive

            + +递归处理在 -f、--filename 中给出的目录。当你想要管理位于同一目录中的相关清单时很有用。 +

            --resource-version string

            + +如果非空,则只有在所给值是对象的当前资源版本时,注解更新才会成功。仅在指定单个资源时有效。 +

            -l, --selector string

            + +过滤所用的选择算符(标签查询),支持 '='、'==' 和 '!='。 +(例如 -l key1=value1,key2=value2)。匹配的对象必须满足所有指定的标签约束。 +

            --show-managed-fields

            + +如果为 true,在以 JSON 或 YAML 格式打印对象时保留 managedFields。 +

            --template string

            + +当 -o=go-template、-o=go-template-file 时使用的模板字符串或模板文件路径。 +模板格式为 golang 模板 [http://golang.org/pkg/text/template/#pkg-overview]。 +

            + +## {{% heading "parentoptions" %}} + + ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
            --as string

            + +操作所用的伪装用户名。用户可以是常规用户或命名空间中的服务账号。 +

            --as-group strings

            + +操作所用的伪装用户组,此标志可以被重复设置以指定多个组。 +

            --as-uid string

            + +操作所用的伪装 UID。 +

            --azure-container-registry-config string

            + +含 Azure 容器镜像库配置信息的文件的路径。 +

            --cache-dir string     默认值:"$HOME/.kube/cache"

            + +默认缓存目录。 +

            --certificate-authority string

            + +证书机构的证书文件的路径。 +

            --client-certificate string

            + +TLS 客户端证书文件的路径。 +

            --client-key string

            + +TLS 客户端密钥文件的路径。 +

            --cloud-provider-gce-l7lb-src-cidrs cidrs     默认值:130.211.0.0/22,35.191.0.0/16

            + +GCE 防火墙中为 L7 负载均衡流量代理和健康检查开放的 CIDR。 +

            --cloud-provider-gce-lb-src-cidrs cidrs     默认值:130.211.0.0/22,209.85.152.0/22,209.85.204.0/22,35.191.0.0/16

            + +GCE 防火墙中为 L4 负载均衡流量代理和健康检查开放的 CIDR。 +

            --cluster string

            + +kubeconfig 中要使用的集群的名称。 +

            --context string

            + +kubeconfig 要使用的上下文的名称。 +

            --default-not-ready-toleration-seconds int     默认值:300

            + +设置针对 notReady:NoExecute 的容忍度的 tolerationSeconds,默认添加到所有尚未设置此容忍度的 Pod。 +

            --default-unreachable-toleration-seconds int     默认值:300

            + +设置针对 unreachable:NoExecute 的容忍度的 tolerationSeconds,默认添加到所有尚未设置此容忍度的 Pod。 +

            --disable-compression

            + +如果为 true,则对服务器所有请求的响应不再压缩。 +

            --insecure-skip-tls-verify

            + +如果为 true,则不检查服务器证书的有效性。这将使你的 HTTPS 连接不安全。 +

            --kubeconfig string

            + +CLI 请求要使用的 kubeconfig 文件的路径。 +

            --match-server-version

            + +要求服务器版本与客户端版本匹配。 +

            -n, --namespace string

            + +如果存在,则是此 CLI 请求的命名空间范围。 +

            --password string

            + +对 API 服务器进行基本身份验证所用的密码。 +

            --profile string     默认值:"none"

            + +要记录的性能分析信息。可选值为(none|cpu|heap|goroutine|threadcreate|block|mutex)。 +

            --profile-output string     默认值:"profile.pprof"

            + +性能分析信息要写入的目标文件的名称。 +

            --request-timeout string     默认值:"0"

            + +在放弃某个服务器请求之前等待的时长。非零值应包含相应的时间单位(例如 1s、2m、3h)。 +值为零表示请求不会超时。 +

            -s, --server string

            + +Kubernetes API 服务器的地址和端口。 +

            --storage-driver-buffer-duration duration     默认值:1m0s

            + +对存储驱动的写入操作将被缓存的时长;缓存的操作会作为一个事务提交给非内存后端。 +

            --storage-driver-db string     默认值:"cadvisor"

            + +数据库名称。 +

            --storage-driver-host string     默认值:"localhost:8086"

            + +数据库 host:port。 +

            --storage-driver-password string     默认值:"root"

            + +数据库密码。 +

            --storage-driver-secure

            + +使用与数据库的安全连接。 +

            --storage-driver-table string     默认值:"stats"

            + +表名。 +

            --storage-driver-user string     默认值:"root"

            + +数据库用户名。 +

            --tls-server-name string

            + +服务器证书验证所用的服务器名称。如果未提供,则使用与服务器通信所用的主机名。 +

            --token string

            + +向 API 服务器进行身份验证的持有者令牌。 +

            --user string

            + +要使用的 kubeconfig 用户的名称。 +

            --username string

            + +对 API 服务器进行基本身份验证时所用的用户名。 +

            --version version[=true]

            + +--version, --version=raw 打印版本信息并退出;--version=vX.Y.Z... 设置报告的版本。 +

            --warnings-as-errors

            + +将从服务器收到的警告视为错误,并以非零退出码退出。 +

            + +## {{% heading "seealso" %}} + + +* [kubectl](../kubectl/) - kubectl 控制 Kubernetes 集群管理器 diff --git a/content/zh-cn/docs/reference/kubectl/kubectl-cmds.md b/content/zh-cn/docs/reference/kubectl/kubectl-cmds.md index 81370aa616052..6e62084d567fc 100644 --- a/content/zh-cn/docs/reference/kubectl/kubectl-cmds.md +++ b/content/zh-cn/docs/reference/kubectl/kubectl-cmds.md @@ -2,11 +2,12 @@ title: kubectl 命令 weight: 20 --- - - +--> - -[kubectl 命令参考](/docs/reference/generated/kubectl/kubectl-commands/) + +[kubectl 命令参考](/zh-cn/docs/reference/kubectl/generated/kubectl/) diff --git a/content/zh-cn/docs/reference/kubectl/kubectl.md b/content/zh-cn/docs/reference/kubectl/kubectl.md index a4b4da943bb10..09d6bdfe5ebd6 100644 --- a/content/zh-cn/docs/reference/kubectl/kubectl.md +++ b/content/zh-cn/docs/reference/kubectl/kubectl.md @@ -17,11 +17,11 @@ kubectl controls the Kubernetes cluster manager. kubectl 管理控制 Kubernetes 集群。 -获取更多信息,请访问 [kubectl 概述](/zh-cn/docs/reference/kubectl/)。 +更多信息请查阅[命令行工具](/zh-cn/docs/kubectl/)(`kubectl`)。 -``` +```shell kubectl [flags] ``` @@ -321,7 +321,9 @@ kubectl [flags]
            - + 如果为 true,则只将日志写入初始严重级别(而不是同时写入所有较低的严重级别)。
            KUBECTL_INTERACTIVE_DELETEKUBECTL_REMOTE_COMMAND_WEBSOCKETS
            -当设置为 true 时,`kubectl delete` 命令中的 `--interactive` 标志将被激活, -允许用户在通过传递此标志进行删除之前预览并确认资源。 +当设置为 true 时,kubectl exec、cp 和 attach 命令将尝试使用 WebSocket 协议进行流式传输。 +如果升级到 WebSocket 失败,这些命令将回退为使用当前的 SPDY 协议。
            -

            admin.conf 的帮助信息。

            --component-configs strings/td> -
            - -

            -以逗号分隔的组件配置 API 对象的列表,打印其默认值。可用值:[KubeProxyConfiguration KubeletConfiguration]。 -如果未设置此参数,则不会打印任何组件配置。 -

            -
            -h, --help
            +
            - - - - - - - @@ -74,7 +58,7 @@ reset-defaults 操作的帮助命令。 --> ### 从父命令继承的选项 -
            --component-configs strings
            -

            - -组件配置 API 对象的逗号分隔列表,打印其默认值。 -可用值:[KubeProxyConfiguration KubeletConfiguration]。 -如果此参数未被设置,则不会打印任何组件配置。 -

            -
            -h, --help
            +
            diff --git a/content/zh-cn/docs/reference/setup-tools/kubeadm/generated/kubeadm_init_phase_certs_etcd-ca.md b/content/zh-cn/docs/reference/setup-tools/kubeadm/generated/kubeadm_init_phase_certs_etcd-ca.md index 1c20e2bded86f..3428e876f1035 100644 --- a/content/zh-cn/docs/reference/setup-tools/kubeadm/generated/kubeadm_init_phase_certs_etcd-ca.md +++ b/content/zh-cn/docs/reference/setup-tools/kubeadm/generated/kubeadm_init_phase_certs_etcd-ca.md @@ -19,11 +19,6 @@ If both files already exist, kubeadm skips the generation step and existing file 如果两个文件都已存在,则 kubeadm 将跳过生成步骤,使用现有文件。 - -Alpha 免责声明:此命令目前处于 Alpha 阶段。 - ``` kubeadm init phase certs etcd-ca [flags] ``` diff --git a/content/zh-cn/docs/reference/setup-tools/kubeadm/generated/kubeadm_init_phase_certs_etcd-healthcheck-client.md b/content/zh-cn/docs/reference/setup-tools/kubeadm/generated/kubeadm_init_phase_certs_etcd-healthcheck-client.md index b96dd9c286179..41d8a3c3ef1af 100644 --- a/content/zh-cn/docs/reference/setup-tools/kubeadm/generated/kubeadm_init_phase_certs_etcd-healthcheck-client.md +++ b/content/zh-cn/docs/reference/setup-tools/kubeadm/generated/kubeadm_init_phase_certs_etcd-healthcheck-client.md @@ -18,11 +18,6 @@ If both files already exist, kubeadm skips the generation step and existing file --> 如果两个文件都已存在,则 kubeadm 将跳过生成步骤,使用现有文件。 - -Alpha 免责声明:此命令当前为 Alpha 功能。 - ``` kubeadm init phase certs etcd-healthcheck-client [flags] ``` diff --git a/content/zh-cn/docs/reference/setup-tools/kubeadm/generated/kubeadm_init_phase_certs_sa.md b/content/zh-cn/docs/reference/setup-tools/kubeadm/generated/kubeadm_init_phase_certs_sa.md index 7d38760b2a814..5a07ec0eeb854 100644 --- a/content/zh-cn/docs/reference/setup-tools/kubeadm/generated/kubeadm_init_phase_certs_sa.md +++ b/content/zh-cn/docs/reference/setup-tools/kubeadm/generated/kubeadm_init_phase_certs_sa.md @@ -9,15 +9,14 @@ Generate a private key for signing service account tokens along with its public ### 概要 生成用来签署服务账号令牌的私钥及其公钥,并将其保存到 sa.key 和 sa.pub 文件中。 -如果两个文件都已存在,则 kubeadm 会跳过生成步骤,而将使用现有文件。 -Alpha 免责声明:此命令当前为 Alpha 阶段。 +如果两个文件都已存在,则 kubeadm 会跳过生成步骤,而将使用现有文件。 ``` kubeadm init phase certs sa [flags] diff --git a/content/zh-cn/docs/reference/using-api/cel.md b/content/zh-cn/docs/reference/using-api/cel.md index dde390d46f29c..5879481c871cd 100644 --- a/content/zh-cn/docs/reference/using-api/cel.md +++ b/content/zh-cn/docs/reference/using-api/cel.md @@ -30,7 +30,7 @@ control plane's API server component remains available. [通用表达式语言 (Common Expression Language, CEL)](https://github.com/google/cel-go) 用于声明 Kubernetes API 的验证规则、策略规则和其他限制或条件。 -CEL 表达式在{{< glossary_tooltip text="API 服务器" term_id="kube-apiserver" >}}中直接进行评估, +CEL 表达式在 {{< glossary_tooltip text="API 服务器" term_id="kube-apiserver" >}}中直接进行处理, 这使得 CEL 成为许多可扩展性用例的便捷替代方案,而无需使用类似 Webhook 这种进程外机制。 只要控制平面的 API 服务器组件保持可用状态,你的 CEL 表达式就会继续执行。 @@ -49,7 +49,7 @@ single expression that evaluates to a single value. CEL expressions are typically short "one-liners" that inline well into the string fields of Kubernetes API resources. --> -## 语言概述 {#language-overview} +## 语言概述 {#language-overview} [CEL 语言](https://github.com/google/cel-spec/blob/master/doc/langdef.md)的语法直观简单, 类似于 C、C++、Java、JavaScript 和 Go 中的表达式。 @@ -68,7 +68,7 @@ different variables. See the API documentation of the API fields to learn which variables are available for that field. --> 对 CEL 程序的输入是各种 “变量”。包含 CEL 的每个 Kubernetes API 字段都在 API -文档中声明了字段可使用哪些变量。例如,在 CustomResourceDefinitions 的 +文档中声明了字段可使用哪些变量。例如,在 CustomResourceDefinition 的 `x-kubernetes-validations[i].rules` 字段中,`self` 和 `oldSelf` 变量可用, 并且分别指代要由 CEL 表达式验证的自定义资源数据的前一个状态和当前状态。 其他 Kubernetes API 字段可能声明不同的变量。请查阅 API 字段的 API 文档以了解该字段可使用哪些变量。 @@ -112,23 +112,60 @@ CEL 表达式示例: {{< /table >}} -## CEL 社区库 {#cel-community-libraries} - -Kubernetes CEL 表达式能够访问以下 CEL 社区库: - - -- [标准定义列表](https://github.com/google/cel-spec/blob/master/doc/langdef.md#list-of-standard-definitions)中定义的 - CEL 标准函数 -- CEL 标准[宏](https://github.com/google/cel-spec/blob/v0.7.0/doc/langdef.md#macros) -- CEL [扩展字符串函数库](https://pkg.go.dev/github.com/google/cel-go/ext#Strings) +## CEL options, language features, and libraries + +CEL is configured with the following options, libraries and language features, introduced at the specified Kubernetes versions: +--> +## CEL 选项、语言特性和库 {#cel-options-language-features-and-libraries} + +CEL 配置了以下选项、库和语言特性,这些特性是在所列的 Kubernetes 版本中引入的: + + +| CEL 选项、库或语言特性 | 包含的内容 | 可用性 | +| ------------------- | -------- | ----- | +| [标准宏](https://github.com/google/cel-spec/blob/v0.7.0/doc/langdef.md#macros) | `has`、`all`、`exists`、`exists_one`、`map`、`filter` | 所有 Kubernetes 版本 | +| [标准函数](https://github.com/google/cel-spec/blob/master/doc/langdef.md#list-of-standard-definitions) | 参见[官方标准定义列表](https://github.com/google/cel-spec/blob/master/doc/langdef.md#list-of-standard-definitions) | 所有 Kubernetes 版本 | +| [同质聚合字面量](https://pkg.go.dev/github.com/google/cel-go@v0.17.4/cel#HomogeneousAggregateLiterals) | | 所有 Kubernetes 版本 | +| [默认 UTC 时区](https://pkg.go.dev/github.com/google/cel-go@v0.17.4/cel#DefaultUTCTimeZone) | | 所有 Kubernetes 版本 | +| [迫切验证声明](https://pkg.go.dev/github.com/google/cel-go@v0.17.4/cel#EagerlyValidateDeclarations) | | 所有 Kubernetes 版本 | +| [扩展字符串库](https://pkg.go.dev/github.com/google/cel-go/ext#Strings),v1 | `charAt`、`indexOf`、`lastIndexOf`、`lowerAscii`、`upperAscii`、`replace`、`split`、`join`、`substring`、`trim` | 所有 Kubernetes 版本 | +| Kubernetes 列表库 | 参见 [Kubernetes 列表库](#kubernetes-list-library) | 所有 Kubernetes 版本 | +| Kubernetes 正则表达式库 | 参见 [Kubernetes 正则表达式库](#kubernetes-regex-library) | 所有 Kubernetes 版本 | +| [Kubernetes URL 库] | 参见 [Kubernetes URL 库](#kubernetes-url-library) | 所有 Kubernetes 版本 | +| Kubernetes 鉴权组件库 | 参见 [Kubernetes 鉴权组件库](#kubernetes-authorizer-library) | 所有 Kubernetes 版本 | +| Kubernetes 数量库 | 参见 [Kubernetes 数量库](#kubernetes-quantity-library) | Kubernetes v1.29+ | +| CEL 可选类型 | 参见 [CEL 可选类型](https://pkg.go.dev/github.com/google/cel-go@v0.17.4/cel#OptionalTypes) | Kubernetes v1.29+ | +| CEL CrossTypeNumericComparisons | 参见 [CEL CrossTypeNumericComparisons](https://pkg.go.dev/github.com/google/cel-go@v0.17.4/cel#CrossTypeNumericComparisons) | Kubernetes v1.29+ | + + +CEL 函数、特性和语言设置支持 Kubernetes 控制平面回滚。 +例如,__CEL 可选值(Optional Values)__ 是在 Kubernetes 1.29 引入的,因此只有该版本或更新的 +API 服务器才会接受使用 __CEL Optional Values__ 的 CEL 表达式的写入请求。 +但是,当集群回滚到 Kubernetes 1.28 时,已经存储在 API 资源中的使用了 +"CEL Optional Values" 的 CEL 表达式将继续正确评估。 -## Kubernetes CEL 库 {#kubernetes-cel-libraries} +## Kubernetes CEL 库 {#kubernetes-cel-libraries} 除了 CEL 社区库之外,Kubernetes 还包括在 Kubernetes 中使用 CEL 时所有可用的 CEL 库。 @@ -151,7 +188,7 @@ The list library also includes `min`, `max` and `sum`. Sum is supported on all number types as well as the duration type. Min and max are supported on all comparable types. --> -### Kubernetes 列表库 {#kubernetes-list-library} +### Kubernetes 列表库 {#kubernetes-list-library} 列表库包括 `indexOf` 和 `lastIndexOf`,这两个函数的功能类似于同名的字符串函数。 这些函数返回提供的元素在列表中的第一个或最后一个位置索引。 @@ -205,7 +242,7 @@ regex operations. Examples: --> -### Kubernetes 正则表达式库 {#kubernete-regex-library} +### Kubernetes 正则表达式库 {#kubernete-regex-library} 除了 CEL 标准库提供的 `matches` 函数外,正则表达式库还提供了 `find` 和 `findAll`, 使得更多种类的正则表达式运算成为可能。 @@ -245,7 +282,7 @@ To make it easier and safer to process URLs, the following functions have been a - `url(string) URL` converts a string to a URL or results in an error if the string is not a valid URL. --> -### Kubernetes URL 库 {#kubernetes-url-library} +### Kubernetes URL 库 {#kubernetes-url-library} 为了更轻松、更安全地处理 URL,添加了以下函数: @@ -296,7 +333,7 @@ the authorizer may be used to perform authorization checks for the principal API resource checks are performed as follows: --> -### Kubernetes 鉴权组件库 +### Kubernetes 鉴权组件库 {#kubernetes-authorizer-library} 在 API 中使用 CEL 表达式,可以使用类型为 `Authorizer` 的变量, 这个鉴权组件可用于对请求的主体(已认证用户)执行鉴权检查。 @@ -318,7 +355,7 @@ API 资源检查的过程如下: 注意这些函数将返回接收者的类型,并且可以串接起来: - `ResourceCheck.subresource(string) ResourceCheck` - `ResourceCheck.namespace(string) ResourceCheck` - - `ResourceCheck.name(string) ResourceCheck` + - `ResourceCheck.name(string) ResourceCheck` 3. 调用 `ResourceCheck.check(verb string) Decision` 来执行鉴权检查。 4. 调用 `allowed() bool` 或 `reason() string` 来查验鉴权检查的结果。 @@ -331,7 +368,7 @@ Non-resource authorization performed are used as follows: --> 对非资源访问的鉴权过程如下: -1. 仅指定路径:`Authorizer.path(string) PathCheck` +1. 仅指定路径:`Authorizer.path(string) PathCheck`。 1. 调用 `PathCheck.check(httpVerb string) Decision` 来执行鉴权检查。 1. 调用 `allowed() bool` 或 `reason() string` 来查验鉴权检查的结果。 @@ -366,6 +403,98 @@ godoc for more information. 更多信息请参阅 Go 文档: [Kubernetes Authz library](https://pkg.go.dev/k8s.io/apiserver/pkg/cel/library#Authz)。 + +### Kubernetes 数量库 {#kubernetes-quantity-library} + +Kubernetes 1.28 添加了对数量字符串(例如 1.5G、512k、20Mi)的操作支持。 + + +- `isQuantity(string)` 根据 [Kubernetes 的 resource.Quantity](https://pkg.go.dev/k8s.io/apimachinery/pkg/api/resource#Quantity), + 检查字符串是否是有效的 Quantity。 +- `quantity(string) Quantity` 将字符串转换为 Quantity,如果字符串不是有效的数量,则会报错。 + + +一旦通过 `quantity` 函数解析,得到的 Quantity 对象将具有以下成员函数库: + + +{{< table caption="Quantity 的可用成员函数" >}} +| 成员函数 | CEL 返回值 | 描述 | +| ------------------------ | --------- | --- | +| `isInteger()` | bool | 仅当 asInteger 可以被安全调用且不出错时,才返回 true | +| `asInteger()` | int | 将当前值作为 int64 的表示返回,如果转换会导致溢出或精度丢失,则会报错 | +| `asApproximateFloat()` | float | 返回数量的 float64 表示,可能会丢失精度。如果数量的值超出了 float64 的范围,则返回 +Inf/-Inf | +| `sign()` | int | 如果数量为正,则返回 1;如果数量为负,则返回 -1;如果数量为零,则返回 0 | +| `add()` | Quantity | 返回两个数量的和 | +| `add()` | Quantity | 返回数量和整数的和 | +| `sub()` | Quantity | 返回两个数量的差 | +| `sub()` | Quantity | 返回数量减去整数的差 | +| `isLessThan()` | bool | 如果接收值小于操作数,则返回 true | +| `isGreaterThan()`| bool | 如果接收值大于操作数,则返回 true | +| `compareTo()` | int | 将接收值与操作数进行比较,如果它们相等,则返回 0;如果接收值大于操作数,则返回 1;如果接收值小于操作数,则返回 -1 | +{{< /table >}} + + +例如: + + +{{< table caption="使用 URL 库函数的 CEL 表达式示例" >}} +| CEL 表达式 | 用途 | +|---------------------------------------------------------------------------| -------------------- | +| `quantity("500000G").isInteger()` | 测试转换为整数是否会报错 | +| `quantity("50k").asInteger()` | 精确转换为整数 | +| `quantity("9999999999999999999999999999999999999G").asApproximateFloat()` | 松散转换为浮点数 | +| `quantity("50k").add("20k")` | 两个数量相加 | +| `quantity("50k").sub(20000)` | 从数量中减去整数 | +| `quantity("50k").add(20).sub(quantity("100k")).sub(-50000)` | 链式相加和减去整数和数量 | +| `quantity("200M").compareTo(quantity("0.2G"))` | 比较两个数量 | +| `quantity("150Mi").isGreaterThan(quantity("100Mi"))` | 测试数量是否大于接收值 | +| `quantity("50M").isLessThan(quantity("100M"))` | 测试数量是否小于接收值 | +{{< /table >}} + -## 类型检查 {#type-checking} +## 类型检查 {#type-checking} CEL 是一种[逐渐类型化的语言](https://github.com/google/cel-spec/blob/master/doc/langdef.md#gradual-type-checking)。 一些 Kubernetes API 字段包含完全经过类型检查的 CEL 表达式。 -例如,[CustomResourceDefinitions 验证规则](/zh-cn/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/#validation-rules)就是完全经过类型检查的。 +例如,[CustomResourceDefinition 验证规则](/zh-cn/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/#validation-rules)就是完全经过类型检查的。 一些 Kubernetes API 字段包含部分经过类型检查的 CEL 表达式。 部分经过类型检查的表达式是指一些变量是静态类型,而另一些变量是动态类型的表达式。 -例如在 [ValidatingAdmissionPolicies](/zh-cn/docs/reference/access-authn-authz/validating-admission-policy/) +例如在 [ValidatingAdmissionPolicy](/zh-cn/docs/reference/access-authn-authz/validating-admission-policy/) 的 CEL 表达式中,`request` 变量是有类型的,但 `object` 变量是动态类型的。 因此,包含 `request.namex` 的表达式将无法通过类型检查,因为 `namex` 字段未定义。 然而,即使对于 `object` 所引用的资源种类没有定义 `namex` 字段, @@ -418,7 +547,7 @@ has(object.namex) ? object.namex == 'special' : request.name == 'special' -## 类型系统集成 {#type-system-integration} +## 类型系统集成 {#type-system-integration} -## 转义 {#escaping} +## 转义 {#escaping} 仅形如 `[a-zA-Z_.-/][a-zA-Z0-9_.-/]*` 的 Kubernetes 资源属性名可以从 CEL 中访问。 当在表达式中访问可访问的属性名时,会根据以下规则进行转义: @@ -578,7 +707,7 @@ excessive resource consumption during evaluation. CEL's resource constraint features are used to prevent CEL evaluation from consuming excessive API server resources. --> -## 资源约束 {#resource-constraints} +## 资源约束 {#resource-constraints} CEL 不是图灵完备的,提供了多种生产安全控制手段来限制执行时间。 CEL 的**资源约束**特性提供了关于表达式复杂性的反馈,并帮助保护 API 服务器免受过度的资源消耗。 @@ -625,7 +754,7 @@ expression. If the CEL interpreter executes too many instructions, the runtime cost budget will be exceeded, execution of the expressions will be halted, and an error will result. --> -### 运行时成本预算 {#runtime-cost-budget} +### 运行时成本预算 {#runtime-cost-budget} 所有由 Kubernetes 评估的 CEL 表达式都受到运行时成本预算的限制。 运行时成本预算是通过在解释 CEL 表达式时增加成本单元计数器来计算实际 CPU 利用率的估算值。 @@ -657,7 +786,7 @@ expression to the API resources. This feature offers a stronger assurance that CEL expressions written to the API resource will be evaluate at runtime without exceeding the runtime cost budget. --> -### 估算的成本限制 {#estimated-cost-limits} +### 估算的成本限制 {#estimated-cost-limits} 对于某些 Kubernetes 资源,API 服务器还可能检查 CEL 表达式的最坏情况估计运行时间是否过于昂贵而无法执行。 如果是,则 API 服务器会拒绝包含 CEL 表达式的创建或更新操作,以防止 CEL 表达式被写入 API 资源。 diff --git a/content/zh-cn/docs/reference/using-api/server-side-apply.md b/content/zh-cn/docs/reference/using-api/server-side-apply.md index f40fc802c950f..8eedbe818b1cf 100644 --- a/content/zh-cn/docs/reference/using-api/server-side-apply.md +++ b/content/zh-cn/docs/reference/using-api/server-side-apply.md @@ -2,7 +2,6 @@ title: 服务器端应用(Server-Side Apply) content_type: concept weight: 25 -min-kubernetes-server-version: 1.16 --- {{< feature-state for_k8s_version="v1.22" state="stable" >}} - -## 简介 {#introduction} +Kubernetes 支持多个应用程序协作管理一个[对象](/zh-cn/docs/concepts/overview/working-with-objects/)的字段。 +服务器端应用为集群的控制平面提供了一种可选机制,用于跟踪对对象字段的更改。 +在特定资源级别,服务器端应用记录并跟踪有关控制该对象字段的信息。 -服务器端应用协助用户、控制器通过声明式配置的方式管理他们的资源。 -客户端可以发送完整描述的目标(A fully specified intent), -声明式地创建和修改{{< glossary_tooltip text="对象" term_id="object" >}}。 + +服务器端应用协助用户和{{< glossary_tooltip text="控制器" term_id="controller" >}}通过声明式配置的方式管理他们的资源。 +客户提交他们**完整描述的意图**,声明式地创建和修改{{< glossary_tooltip text="对象" term_id="object" >}}。 -一个完整描述的目标并不是一个完整的对象,仅包括能体现用户意图的字段和值。 -该目标(intent)可以用来创建一个新对象, -也可以通过服务器来实现与现有对象的[合并](#merge-strategy)。 +一个完整描述的意图并不是一个完整的对象,仅包括能体现用户意图的字段和值。 +该意图可以用来创建一个新对象(未指定的字段使用默认值), +也可以通过 API 服务器来实现与现有对象的[合并](#merge-strategy)。 -系统支持多个应用者(appliers)在同一个对象上开展协作。 +[与客户端应用对比](#comparison-with-client-side-apply)小节解释了服务器端应用与最初的客户端 +`kubectl apply` 实现的区别。 - -“[字段管理(field management)](#field-management)”机制追踪对象字段的变化。 -当一个字段值改变时,其所有权从当前管理器(manager)转移到施加变更的管理器。 -当尝试将新配置应用到一个对象时,如果字段有不同的值,且由其他管理器管理, -将会引发[冲突](#conflicts)。 -冲突引发警告信号:此操作可能抹掉其他协作者的修改。 -冲突可以被刻意忽略,这种情况下,值将会被改写,所有权也会发生转移。 + -当你从配置文件中删除一个字段,然后应用这个配置文件, -将触发服务器端应用检查此字段是否还被其他字段管理器拥有。 -如果没有,那就从活动对象中删除该字段;如果有,那就重置为默认值。 -该规则同样适用于 list 或 map 项目。 +## Field Management - -服务器端应用既是原有 `kubectl apply` 的替代品, -也是控制器发布自身变化的一个简化机制。 +## 字段管理 {#field-management} -如果你启用了服务器端应用,控制平面就会跟踪被所有新创建对象管理的字段。 +Kubernetes API 服务器跟踪所有新建对象的**受控字段(Managed Fields)**。 - -## 字段管理 {#field-management} +每当字段的值确实发生变化时,所有权就会从其当前管理器转移到进行更改的管理器。 -相对于通过 `kubectl` 管理的注解 `last-applied`, -服务器端应用使用了一种更具声明式特点的方法: -它持续的跟踪用户的字段管理,而不仅仅是最后一次的执行状态。 -这就意味着,作为服务器端应用的一个副作用, -关于用哪一个字段管理器负责管理对象中的哪个字段的这类信息,都要对外界开放了。 +服务器端应用会检查是否存在其他字段管理器也拥有该字段。 +如果该字段不属于任何其他字段管理器,则该字段将被设置为其默认值(如果有),或者以其他方式从对象中删除。 +同样的规则也适用于作为列表(list)、关联列表或键值对(map)的字段。 用户管理字段这件事,在服务器端应用的场景中,意味着用户依赖并期望字段的值不要改变。 最后一次对字段值做出断言的用户将被记录到当前字段管理器。 -这可以通过发送 `POST`、 `PUT`、 -或非应用(non-apply)方式的 `PATCH` 等命令来修改字段值的方式实现, -或通过把字段放在配置文件中,然后发送到服务器端应用的服务端点的方式实现。 -当使用服务器端应用,尝试着去改变一个被其他人管理的字段, -会导致请求被拒绝(在没有设置强制执行时,参见[冲突](#conflicts))。 +这可以通过发送 `POST`(**create**)、`PUT`(**update**)、或非应用的 `PATCH`(**patch**) +显式更改字段管理器详细信息来实现。 +还可以通过在服务器端应用操作中包含字段的值来声明和记录字段管理器。 如果两个或以上的应用者均把同一个字段设置为相同值,他们将共享此字段的所有权。 后续任何改变共享字段值的尝试,不管由那个应用者发起,都会导致冲突。 -共享字段的所有者可以放弃字段的所有权,这只需从配置文件中删除该字段即可。 +共享字段的所有者可以放弃字段的所有权,这只需发出不包含该字段的服务器端应用 **patch** 请求即可。 字段管理的信息存储在 `managedFields` 字段中,该字段是对象的 -[`metadata`](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#objectmeta-v1-meta) +[`metadata`](/zh-cn/docs/reference/kubernetes-api/common-definitions/object-meta/)。 中的一部分。 + +如果从清单中删除某个字段并应用该清单,则服务器端应用会检查是否有其他字段管理器也拥有该字段。 +如果该字段不属于任何其他字段管理器,则服务器会将其从活动对象中删除,或者重置为其默认值(如果有)。 +同样的规则也适用于关联列表(list)或键值对(map)。 + + +与(旧版)由 `kubectl` 所管理的注解 +[`kubectl.kubernetes.io/last-applied configuration`](/zh-cn/docs/reference/labels-annotations-taints/#kubectl-kubernetes-io-last-applied-configuration) +相比,服务器端应用使用了一种更具声明式的方法, +它跟踪用户(或客户端)的字段管理,而不是用户上次应用的状态。 +作为服务器端应用的副作用,哪个字段管理器管理的对象的哪个字段的相关信息也会变得可用。 + + +### 示例 {#ssa-example-configmap} + 服务器端应用创建对象的简单示例如下: ```yaml +--- apiVersion: v1 kind: ConfigMap metadata: @@ -154,7 +172,7 @@ metadata: test-label: test managedFields: - manager: kubectl - operation: Apply + operation: Apply # 注意大写: “Apply” (或者 “Update”) apiVersion: v1 time: "2010-10-10T0:00:00Z" fieldsType: FieldsV1 @@ -168,51 +186,64 @@ data: key: some value ``` - -上述对象在 `metadata.managedFields` 中包含了唯一的管理器。 -管理器由管理实体自身的基本信息组成,比如操作类型、API 版本、以及它管理的字段。 - -{{< note >}} - -该字段由 API 服务器管理,用户不应该改动它。 -{{< /note >}} - - -不过,执行 `Update` 操作修改 `metadata.managedFields` 也是可实现的。 +但是,可以通过 **update** 或不使用服务器端应用的 **patch** 操作去更新 `.metadata.managedFields`。 强烈不鼓励这么做,但当发生如下情况时, 比如 `managedFields` 进入不一致的状态(显然不应该发生这种情况), 这么做也是一个合理的尝试。 -`managedFields` 的格式在 -[API](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#fieldsv1-v1-meta) -文档中描述。 + +`managedFields` 的格式在 Kubernetes API 参考中[描述](/zh-cn/docs/reference/kubernetes-api/common-definitions/object-meta/#System)。 + +{{< caution >}} +`.metadata.managedFields` 字段由 API 服务器管理。 +你不应该手动更新它。 +{{< /caution >}} ## 冲突 {#conflicts} -冲突是一种特定的错误状态, +**冲突**是一种特定的错误状态, 发生在执行 `Apply` 改变一个字段,而恰巧该字段被其他用户声明过主权时。 这可以防止一个应用者不小心覆盖掉其他用户设置的值。 冲突发生时,应用者有三种办法来解决它: @@ -220,70 +251,78 @@ this occurs, the applier has 3 options to resolve the conflicts: * **覆盖前值,成为唯一的管理器:** 如果打算覆盖该值(或应用者是一个自动化部件,比如控制器), - 应用者应该设置查询参数 `force` 为 true(在 kubectl 中,可以通过在 - apply 命令中使用 `--force-conflicts` 标志来完成),然后再发送一次请求。 - 这将强制操作成功,改变字段的值,从所有其他管理器的 managedFields 条目中删除指定字段。 + 应用者应该设置查询参数 `force` 为 true(对 `kubectl apply` 来说,你可以使用命令行参数 + `--force-conflicts`),然后再发送一次请求。 + 这将强制操作成功,改变字段的值,从所有其他管理器的 `managedFields` 条目中删除指定字段。 * **不覆盖前值,放弃管理权:** 如果应用者不再关注该字段的值, - 可以从配置文件中删掉它,再重新发送请求。 - 这就保持了原值不变,并从 managedFields 的应用者条目中删除该字段。 + 应用者可以从资源的本地模型中删掉它,并在省略该字段的情况下发送请求。 + 这就保持了原值不变,并从 `managedFields` 的应用者条目中删除该字段。 * **不覆盖前值,成为共享的管理器:** 如果应用者仍然关注字段值,并不想覆盖它, - 他们可以在配置文件中把字段的值改为和服务器对象一样,再重新发送请求。 - 这样在不改变字段值的前提下, - 就实现了字段管理被应用者和所有声明了管理权的其他的字段管理器共享。 + 他们可以更改资源的本地模型中该字段的值,以便与服务器上对象的值相匹配, + 然后基于本地更新发出新请求。这样做会保持值不变, + 并使得该字段的管理由应用者与已经声称管理该字段的所有其他字段管理者共享。 -## 管理器 {#managers} +## 字段管理器 {#managers} 管理器识别出正在修改对象的工作流程(在冲突时尤其有用), -管理器可以通过修改请求的参数 `fieldManager` 指定。 -虽然 kubectl 默认发往 `kubectl` 服务端点,但它则请求到应用的服务端点(apply endpoint)。 -对于其他的更新,它默认的是从用户代理计算得来。 +并且可以作为修改请求的一部分,通过 +[`fieldManager`](/zh-cn/docs/reference/kubernetes-api/common-parameters/common-parameters/#fieldManager) +查询参数来指定。 +当你 Apply 某个资源时,需要指定 `fieldManager` 参数。 +对于其他更新,API 服务器使用 “User-Agent:” HTTP 头(如果存在)推断字段管理器标识。 - -## 应用和更新 {#apply-and-update} +## 序列化 {#serialization} -此特性涉及两类操作,分别是 `Apply` -(内容类型为 `application/apply-patch+yaml` 的 `PATCH` 请求) -和 `Update` (所有修改对象的其他操作)。 -这两类操作都会更新字段 `managedFields`,但行为表现有一点不同。 +在协议层面,Kubernetes 用 [YAML](https://yaml.org/) 来表示 Server-Side Apply 的消息体, +媒体类型为 `application/apply-patch+yaml`。 {{< note >}} - +序列化与 Kubernetes 对象相同,只是客户端不需要发送完整的对象。 + +以下是服务器端应用消息正文的示例(完整描述的意图): + +```yaml +{ + "apiVersion": "v1", + "kind": "ConfigMap" +} +``` + + +(这个请求将导致无更改的更新,前提是它作为 **patch** 请求的主体发送到有效的 `v1/configmaps` 资源, +并且请求中设置了合适的 `Content-Type`)。 + + +## 字段管理范围内的操作 {#apply-and-update} + +考虑字段管理的 Kubernetes API 操作包括: + +1. 服务器端应用(HTTP `PATCH`,内容类型为 `application/apply-patch+yaml`) +2. 替换现有对象(对 Kubernetes 而言是 **update**;HTTP 层面表现为 `PUT`) + + +这两种操作都会更新 `.metadata.managedFields`,但行为略有不同。 + +除非你指定要强制重写,否则应用操作在遇到字段级冲突时总是会失败; +相比之下,如果你使用 **update** 进行的更改会影响托管字段,那么冲突从来不会导致操作失败。 + + -例如,在冲突发生的时候,只有 `apply` 操作失败,而 `update` 则不会。 -此外,`apply` 操作必须通过提供一个 `fieldManager` 查询参数来标识自身, -而此查询参数对于 `update` 操作则是可选的。 -最后,当使用 `apply` 命令时,你不能在应用中的对象中持有 `managedFields`。 +所有服务器端应用的 **patch** 请求都必须提供 `fieldManager` 查询参数来标识自己, +而此参数对于 **update** 操作是可选的。 +最后,使用 `Apply` 操作时,不能在提交的请求主体中设置 `managedFields`。 一个包含多个管理器的对象,示例如下: ```yaml +--- apiVersion: v1 kind: ConfigMap metadata: @@ -339,19 +429,19 @@ data: ``` 在这个例子中, -第二个操作被管理器 `kube-controller-manager` 以 `Update` 的方式运行。 -此 `update` 更改 data 字段的值, -并使得字段管理器被改为 `kube-controller-manager`。 +第二个操作被管理器 `kube-controller-manager` 以 **update** 的方式运行。 +更新操作执行成功,并更改了 data 字段中的一个值, +并使得该字段的管理器被改为 `kube-controller-manager`。 -如果把 `update` 操作改为 `Apply`,那就会因为所有权冲突的原因,导致操作失败。 +如果尝试把更新操作改为服务器端应用,那么这一尝试会因为所有权冲突的原因,导致操作失败。 -当用户发送一个“完整描述的目标”对象到服务器端应用的服务端点, -服务器会将它和活动对象做一次合并,如果两者中有重复定义的值,那就以配置文件的为准。 -如果配置文件中的项目集合不是此用户上一次操作项目的超集, -所有缺少的、没有其他应用者管理的项目会被删除。 +当用户发送一个**完整描述的意图**对象到服务器端应用的服务端点时, +服务器会将它和当前对象做一次合并,如果两者中有重复定义的值,那就以请求体中的为准。 +如果请求体中条目的集合不是此用户上一次操作条目的超集, +所有缺失的、没有其他应用者管理的条目会被删除。 关于合并时用来做决策的对象规格的更多信息,参见 [sigs.k8s.io/structured-merge-diff](https://sigs.k8s.io/structured-merge-diff). +Kubernetes API(以及为 Kubernetes 实现该 API 的 Go 代码)都允许定义**合并策略标记(Merge Strategy Markers)**。 +这些标记描述 Kubernetes 对象中各字段所支持的合并策略。 Kubernetes 1.16 和 1.17 中添加了一些标记, -允许 API 开发人员描述由 list、map、和 structs 支持的合并策略。 -这些标记可应用到相应类型的对象,在 Go 文件或在 -[CRD](/docs/reference/generated/kubernetes-api/{{< param "version" >}}#jsonschemaprops-v1-apiextensions-k8s-io) -的 OpenAPI 的模式中定义: +对一个 {{< glossary_tooltip term_id="CustomResourceDefinition" text="CustomResourceDefinition" >}} +来说,你可以在定义自定义资源时设置这些标记。 -| Golang 标记 | OpenAPI extension | 可接受的值 | 描述 | 引入版本 | -|---|---|---|---|---| -| `//+listType` | `x-kubernetes-list-type` | `atomic`/`set`/`map` | 适用于 list。`set` 适用于仅包含标量元素的列表。这些元素必须是不重复的。`map` 仅适用于包含嵌套类型的列表。列表中的键(参见 `listMapKey`)不可以重复。`atomic` 适用于任何类型的列表。如果配置为 `atomic`,则合并时整个列表会被替换掉。任何时候,只有一个管理器负责管理指定列表。如果配置为 `set` 或 `map`,不同的管理器也可以分开管理条目。 | 1.16 | -| `//+listMapKey` | `x-kubernetes-list-map-keys` | 字段名称的列表,例如,`["port", "protocol"]` | 仅当 `+listType=map` 时适用。取值为字段名称的列表,这些字段值的组合能够唯一标识列表中的条目。尽管可以存在多个键,`listMapKey` 是单数的,这是因为键名需要在 Go 类型中各自独立指定。键字段必须是标量。 | 1.16 | -| `//+mapType` | `x-kubernetes-map-type` | `atomic`/`granular` | 适用于 map。 `atomic` 指 map 只能被单个的管理器整个的替换。 `granular` 指 map 支持多个管理器各自更新自己的字段。 | 1.17 | -| `//+structType` | `x-kubernetes-map-type` | `atomic`/`granular` | 适用于 structs;否则就像 `//+mapType` 有相同的用法和 openapi 注释.| 1.17 | +| Golang 标记 | OpenAPI 扩展 | 可接受的值 | 描述 | +|---|---|---|---| +| `//+listType` | `x-kubernetes-list-type` | `atomic`/`set`/`map` | 适用于 list。`set` 适用于仅包含标量元素的列表。其中的元素不可重复。`map` 仅适用于嵌套了其他类型的列表。列表中的键(参见 `listMapKey`)不可以重复。`atomic` 适用于所有类型的列表。如果配置为 `atomic`,则合并时整个列表会被替换掉。任何时候,只有一个管理器负责管理指定列表。如果配置为 `set` 或 `map`,不同的管理器也可以分开管理不同条目。 | +| `//+listMapKey` | `x-kubernetes-list-map-keys` | 字段名称的列表,例如,`["port", "protocol"]` | 仅当 `+listType=map` 时适用。取值为字段名称的列表,这些字段值的组合能够唯一标识列表中的条目。尽管可以存在多个键,`listMapKey` 是单数的,这是因为键名需要在 Go 类型中各自独立指定。键字段必须是标量。 | +| `//+mapType` | `x-kubernetes-map-type` | `atomic`/`granular` | 适用于 map。 `atomic` 表示 map 只能被某个管理器整体替换。 `granular` 表示 map 支持多个管理器各自更新自己的字段。 | +| `//+structType` | `x-kubernetes-map-type` | `atomic`/`granular` | 适用于 structs;此外,起用法和 OpenAPI 注释与 `//+mapType` 相同。| -若未指定 `listType`,API 服务器将 `patchMergeStrategy=merge` 标记解释为 +若未指定 `listType`,API 服务器将 `patchStrategy=merge` 标记解释为 `listType=map` 并且视对应的 `patchMergeKey` 标记为 `listMapKey` 取值。 `atomic` 列表类型是递归的。 -这些标记都是用源代码注释的方式给出的,不必作为字段标签(tag)再重复。 +(在 Kubernetes 的 [Go](https://go.dev/) 代码中, +这些标记以注释的形式给出,代码作者不需要用字段标记的形式重复指定它们)。 -### 拓扑变化时的兼容性 {#compatibility-across-toplogy-changes} +### 自定义资源和服务器端应用 {#custom-resources-and-server-side-apply} + +默认情况下,服务器端应用将自定义资源视为无结构的数据。 +所有键被视为 struct 数据类型的字段,所有列表都被视为 atomic 形式。 + + +如果 CustomResourceDefinition 定义了的 +[schema](/zh-cn/docs/reference/generated/kubernetes-api/{{< param "version" >}}#jsonschemaprops-v1-apiextensions-k8s-io) +包含在上一小节[合并策略](#merge-strategy)中定义的注解, +那么在合并此类型的对象时,就会使用这些注解。 -在极少的情况下,CRD 或者内置类型的作者可能希望更改其资源中的某个字段的 +### 拓扑变化时的兼容性 {#compatibility-across-toplogy-changes} + +在极少的情况下,CustomResourceDefinition(CRD)的作者或者内置类型可能希望更改其资源中的某个字段的 拓扑配置,同时又不提升版本号。 -通过升级集群或者更新 CRD 来更改类型的拓扑信息与更新现有对象的结果不同。 +通过升级集群或者更新 CRD 来更改类型的拓扑信息,与更新现有对象的结果不同。 变更的类型有两种:一种是将字段从 `map`/`set`/`granular` 更改为 `atomic`, 另一种是做逆向改变。 @@ -460,22 +573,23 @@ would cause a conflict. 元素之一的属主。这意味着,对这些对象的进一步变更会引发冲突。 -当一个列表、映射或结构从 `atomic` 改为 `map`/`set`/`granular` 之一 -时,API 服务器无法推导这些字段的新的属主。因此,当对象的这些字段 +当某 `listType`、`mapType` 或 `structType` 从 `atomic` 改为 `map`/`set`/`granular` 之一时, +API 服务器无法推导这些字段的新的属主。因此,当对象的这些字段 再次被更新时不会引发冲突。出于这一原因,不建议将某类型从 `atomic` 改为 `map`/`set`/`granular`。 以下面的自定义资源为例: ```yaml +--- apiVersion: example.com/v1 kind: Foo metadata: @@ -502,52 +616,28 @@ Before `spec.data` gets changed from `atomic` to `granular`, without a conflict), but it no longer owns `key1` and `key2`, so another manager can then modify or delete those fields without conflict. --> -在 `spec.data` 从 `atomic` 改为 `granular` 之前,`manager-one` 是 -`spec.data` 字段及其所包含字段(`key1` 和 `key2`)的属主。 +在 `spec.data` 从 `atomic` 改为 `granular` 之前, +`manager-one` 是 `spec.data` 字段及其所包含字段(`key1` 和 `key2`)的属主。 当对应的 CRD 被更改,使得 `spec.data` 变为 `granular` 拓扑时, -`manager-one` 继续拥有顶层字段 `spec.data`(这意味着其他管理者想删除名为 -`data` 的映射而不引起冲突是不可能的),但不再拥有 -`key1` 和 `key2`。因此,其他管理者可以在不引起冲突的情况下更改 -或删除这些字段。 - - -## 自定义资源 {#custom-resources} - -默认情况下,服务器端应用把自定义资源看做非结构化数据。 -所有的键值(keys)就像 struct 的字段一样被处理, -所有的 list 被认为是原子性的。 - -如果自定义资源定义(Custom Resource Definition,CRD)定义了一个 -[模式](/docs/reference/generated/kubernetes-api/{{< param "version" >}}#jsonschemaprops-v1-apiextensions-k8s-io), -它包含类似以前“合并策略”章节中定义过的注解, -这些注解将在合并此类型的对象时使用。 +`manager-one` 继续拥有顶层字段 `spec.data`(这意味着其他管理器想删除名为 +`data` 的映射而不引起冲突是不可能的),但不再拥有 `key1` 和 `key2`。 +因此,其他管理器可以在不引起冲突的情况下更改或删除这些字段。 ## 在控制器中使用服务器端应用 {#using-server-side-apply-in-controller} @@ -556,10 +646,10 @@ might not be able to resolve or act on these conflicts. * 应用的对象必须包含控制器关注的所有字段。 * 对于在控制器没有执行过应用操作之前就已经存在的字段,不能删除。 - (控制器在这种用例环境下,依然可以发送一个 PATCH/UPDATE) + (控制器在这种用例环境下,依然可以发送一个 **patch** 或 **update**) * 对象不必事先读取,`resourceVersion` 不必指定。 -强烈推荐:设置控制器在冲突时强制执行,这是因为冲突发生时,它们没有其他解决方案或措施。 +强烈推荐:设置控制器始终在其拥有和管理的对象上强制冲突,这是因为冲突发生时,它们没有其他解决方案或措施。 ## 转移所有权 {#transferring-ownership} @@ -587,10 +677,10 @@ Say a user has defined deployment with `replicas` set to the desired value: 假设用户定义了 Deployment,且 `replicas` 字段已经设置为期望的值: -{{< codenew file="application/ssa/nginx-deployment.yaml" >}} +{{% code_sample file="application/ssa/nginx-deployment.yaml" %}} 并且,用户使用服务器端应用,像这样创建 Deployment: @@ -599,9 +689,9 @@ kubectl apply -f https://k8s.io/examples/application/ssa/nginx-deployment.yaml - ``` -然后,为 Deployment 启用 HPA,例如: +然后,为 Deployment 启用自动扩缩,例如: ```shell kubectl autoscale deployment nginx-deployment --cpu-percent=50 --min=1 --max=10 @@ -609,32 +699,34 @@ kubectl autoscale deployment nginx-deployment --cpu-percent=50 --min=1 --max=10 -现在,用户希望从他们的配置中删除 `replicas`,所以他们总是和 HPA 控制器冲突。 -然而,这里存在一个竟态: -在 HPA 需要调整 `replicas` 之前会有一个时间窗口, -如果在 HPA 写入字段成为所有者之前,用户删除了`replicas`, -那 API 服务器就会把 `replicas` 的值设为 1, 也就是默认值。 -这不是用户希望发生的事情,即使是暂时的。 +现在,用户希望从他们的配置中删除 `replicas`,从而避免与 HorizontalPodAutoscaler(HPA)及其控制器发生冲突。 +然而,这里存在一个竞态: +在 HPA 需要调整 `.spec.replicas` 之前会有一个时间窗口, +如果在 HPA 写入字段并成为新的属主之前,用户删除了 `.spec.replicas`, +那 API 服务器就会把 `.spec.replicas` 的值设为 1(Deployment 的默认副本数)。 +这不是用户希望发生的事情,即使是暂时的——它很可能会导致正在运行的工作负载降级。 这里有两个解决方案: @@ -643,7 +735,7 @@ First, the user defines a new configuration containing only the `replicas` field - (高级操作)然而,如果用户不想等待,比如他们想为合作伙伴保持集群清晰, 那他们就可以执行以下步骤,安全的从配置文件中删除 `replicas`。 -首先,用户新定义一个只包含 `replicas` 字段的配置文件: +首先,用户新定义一个只包含 `replicas` 字段的新清单: ```yaml # 将此文件另存为 'nginx-deployment-replicas-only.yaml' @@ -666,9 +758,10 @@ want to modify the `spec.replicas` field using SSA. {{< /note >}} -用户使用名为 `handover-to-hpa` 的字段管理器,应用此配置文件。 +用户使用私有字段管理器名称应用该清单。在本例中,用户选择了 `handover-to-hpa`: ```shell kubectl apply -f nginx-deployment-replicas-only.yaml \ @@ -681,67 +774,86 @@ If the apply results in a conflict with the HPA controller, then do nothing. The conflict indicates the controller has claimed the field earlier in the process than it sometimes does. -At this point the user may remove the `replicas` field from their configuration. +At this point the user may remove the `replicas` field from their manifest: --> 如果应用操作和 HPA 控制器产生冲突,那什么都不做。 冲突表明控制器在更早的流程中已经对字段声明过所有权。 -在此时间点,用户可以从配置文件中删除 `replicas` 。 +在此时间点,用户可以从清单中删除 `replicas` 。 -{{< codenew file="application/ssa/nginx-deployment-no-replicas.yaml" >}} +{{% code_sample file="application/ssa/nginx-deployment-no-replicas.yaml" %}} 注意,只要 HPA 控制器为 `replicas` 设置了一个新值, 该临时字段管理器将不再拥有任何字段,会被自动删除。 -这里不需要执行清理工作。 +这里无需进一步清理。 -### 在用户之间转移所有权 {#transferring-ownership-between-users} +### 在管理器之间转移所有权 {#transferring-ownership-between-managers} -通过在配置文件中把一个字段设置为相同的值,用户可以在他们之间转移字段的所有权, -从而共享了字段的所有权。 -当用户共享了字段的所有权,任何一个用户可以从他的配置文件中删除该字段, -并应用该变更,从而放弃所有权,并实现了所有权向其他用户的转移。 +通过在配置文件中把一个字段设置为相同的值,多个字段管理器可以在彼此之间转移字段的所有权, +从而实现字段所有权的共享。 +当某管理器共享了字段的所有权,管理器中任何一个成员都可以从其应用的配置中删除该字段, +从而放弃所有权,并完成了所有权向其他字段管理器的转移。 +## 与客户端应用的对比 {#comparison-with-client-side-apply} + +服务器端应用意味着既可以替代原来 `kubectl apply` 子命令的客户端实现, +也可供{{< glossary_tooltip term_id="controller" text="控制器" >}}作为实施变更的简单有效机制。 +与 `kubectl` 管理的 `last-applied` 注解相比, +服务器端应用使用一种更具声明性的方法来跟踪对象的字段管理,而不是记录用户最后一次应用的状态。 +这意味着,使用服务器端应用的副作用,就是字段管理器所管理的对象的每个字段的相关信息也会变得可用。 + + -## 与客户端应用的对比 {#comparison-with-client-side-apply} - 由服务器端应用实现的冲突检测和解决方案的一个结果就是, 应用者总是可以在本地状态中得到最新的字段值。 如果得不到最新值,下次执行应用操作时就会发生冲突。 解决冲突三个选项的任意一个都会保证:此应用过的配置文件是服务器上对象字段的最新子集。 -这和客户端应用(Client Side Apply) 不同,如果有其他用户覆盖了此值, +这和客户端应用(Client-Side Apply)不同,如果有其他用户覆盖了此值, 过期的值被留在了应用者本地的配置文件中。 除非用户更新了特定字段,此字段才会准确, 应用者没有途径去了解下一次应用操作是否会覆盖其他用户的修改。 @@ -749,12 +861,16 @@ case. 另一个区别是使用客户端应用的应用者不能改变他们正在使用的 API 版本,但服务器端应用支持这个场景。 -## 从客户端应用升级到服务器端应用 {#upgrading-from-client-side-apply-to-server-side-apply} +## 客户端应用和服务器端应用的迁移 {#migration-between-client-side-and-server-side-apply} + +### 从客户端应用升级到服务器端应用 {#upgrading-from-client-side-apply-to-server-side-apply} 客户端应用方式时,用户使用 `kubectl apply` 管理资源, 可以通过使用下面标记切换为使用服务器端应用。 @@ -764,14 +880,14 @@ kubectl apply --server-side [--dry-run=server] ``` 默认情况下,对象的字段管理从客户端应用方式迁移到 kubectl 触发的服务器端应用时,不会发生冲突。 {{< caution >}} -## 从服务器端应用降级到客户端应用 {#downgrading-from-server-side-apply-to-client-side-apply} +### 从服务器端应用降级到客户端应用 {#downgrading-from-server-side-apply-to-client-side-apply} 如果你用 `kubectl apply --server-side` 管理一个资源, 可以直接用 `kubectl apply` 命令将其降级为客户端应用。 @@ -834,81 +950,118 @@ kubectl apply --server-side --field-manager=my-manager [--dry-run=server] ``` -## API 端点 {#api-endpoint} +## API 实现 {#api-implementation} -启用了服务器端应用特性之后, -`PATCH` 服务端点接受额外的内容类型 `application/apply-patch+yaml`。 -服务器端应用的用户就可以把 YAMl -格式的部分定义对象(partially specified objects)发送到此端点。 -当一个配置文件被应用时,它应该包含所有体现你意图的字段。 +支持服务器端应用的资源的 `PATCH` 动词可以接受非官方的 `application/apply-patch+yaml` 内容类型。 +服务器端应用的用户可以将部分指定的对象以 YAML 格式作为 `PATCH` 请求的主体发送到资源的 URI。 +应用配置时,你应该始终包含对要定义的结果(如所需状态)重要的所有字段。 - -### RBAC 和权限 {#rbac-and-permissions} +### 访问控制和权限 {#rbac-and-permissions} -因为服务器端应用是一种 `PATCH` 操作,所以一个角色编辑资源需要 `PATCH` 权限, -但要用服务器端应用创建资源还需要 `CREATE` 动作权限。 +由于服务端应用是一种 `PATCH` 类型的操作, +所以一个主体(例如 Kubernetes {{< glossary_tooltip text="RBAC" term_id="rbac" >}} 的 Role)需要 +**patch** 权限才能编辑存量资源,还需要 **create** 权限才能使用服务器端应用创建新资源。 -## 清除 ManagedFields {#clearing-managedfields} +## 清除 `managedFields` {#clearing-managedfields} -可以从对象中剥离所有 managedField, -实现方法是通过使用 `MergePatch`、 `StrategicMergePatch`、 -`JSONPatch`、 `Update`、以及所有的非应用方式的操作来覆盖它。 -这可以通过用空条目覆盖 managedFields 字段的方式实现。以下是两个示例: +通过使用 **patch**(JSON Merge Patch, Strategic Merge Patch, JSON Patch)覆盖对象, +或者通过 **update**(HTTP `PUT`),可以从对象中剥离所有 `managedFields`; +换句话说,通过除了 **apply** 之外的所有写操作均可实现这点。 +清除 `managedFields` 字段的操作可以通过用空条目覆盖 `managedFields` 字段的方式实现。以下是两个示例: ```console PATCH /api/v1/namespaces/default/configmaps/example-cm -Content-Type: application/merge-patch+json Accept: application/json -Data: {"metadata":{"managedFields": [{}]}} +Content-Type: application/merge-patch+json + +{ + "metadata": { + "managedFields": [ + {} + ] + } +} ``` ```console PATCH /api/v1/namespaces/default/configmaps/example-cm -Content-Type: application/json-patch+json Accept: application/json -Data: [{"op": "replace", "path": "/metadata/managedFields", "value": [{}]}] +Content-Type: application/json-patch+json +If-Match: 1234567890123456789 + +[{"op": "replace", "path": "/metadata/managedFields", "value": [{}]}] ``` -这一操作将用只包含一个空条目的列表覆写 managedFields, -来实现从对象中整个的去除 managedFields。 -注意,只把 managedFields 设置为空列表并不会重置字段。 -这么做是有目的的,所以 managedFields 将永远不会被与该字段无关的客户删除。 +这一操作将用只包含一个空条目的列表来覆盖 `managedFields`, +从而实现从对象中整体去除 `managedFields`。 +注意,只把 `managedFields` 设置为空列表并不会重置该字段。 +这一设计是有意为之的,目的是避免 `managedFields` 被与该字段无关的客户删除。 -在重置操作结合 managedFields 以外其他字段更改的场景中, -将导致 managedFields 首先被重置,其他改变被押后处理。 +在某些场景中,执行重置操作的同时还会给出对 `managedFields` 之外的别的字段的变更, +对于这类操作,`managedFields` 首先会被重置,其他变更被压后处理。 其结果是,应用者取得了同一个请求中所有字段的所有权。 +{{< note >}} + +对于无法接收资源对象类型的子资源,服务器端应用无法正确跟踪其所有权。 +如果你将针对此类子资源使用服务器端应用,则可能无法跟踪被变更的字段。 +{{< /note >}} + +## {{% heading "whatsnext" %}} + + +你可以阅读 Kubernetes API 参考中的 +[`metadata`](/zh-cn/docs/reference/kubernetes-api/common-definitions/object-meta/) +顶级字段的 `managedFields`。 diff --git a/content/zh-cn/docs/setup/best-practices/cluster-large.md b/content/zh-cn/docs/setup/best-practices/cluster-large.md index 1368a03b46c81..21c75c5b91312 100644 --- a/content/zh-cn/docs/setup/best-practices/cluster-large.md +++ b/content/zh-cn/docs/setup/best-practices/cluster-large.md @@ -224,16 +224,13 @@ Learn more about [Vertical Pod Autoscaler](https://github.com/kubernetes/autosca and how you can use it to scale cluster components, including cluster-critical addons. -* The [cluster autoscaler](https://github.com/kubernetes/autoscaler/tree/master/cluster-autoscaler#readme) -integrates with a number of cloud providers to help you run the right number of -nodes for the level of resource demand in your cluster. +* Read about [cluster autoscaling](/docs/concepts/cluster-administration/cluster-autoscaling/) --> * `VerticalPodAutoscaler` 是一种自定义资源,你可以将其部署到集群中,帮助你管理 Pod 的资源请求和资源限制。 了解有关 [Vertical Pod Autoscaler](https://github.com/kubernetes/autoscaler/tree/master/vertical-pod-autoscaler#readme) 的更多信息,了解如何用它扩展集群组件(包括对集群至关重要的插件)的信息。 -* [集群自动扩缩器](https://github.com/kubernetes/autoscaler/tree/master/cluster-autoscaler#readme) - 与许多云供应商集成在一起,帮助你在你的集群中,按照资源需求级别运行正确数量的节点。 +* 阅读关于[集群自动扩缩容](/zh-cn/docs/concepts/cluster-administration/cluster-autoscaling/)的信息。 @@ -18,7 +18,7 @@ content_type: concept -本页描述如何跨多个区(Zone)中运行集群。 +本页描述如何跨多个区(Zone)运行集群。 @@ -35,11 +35,11 @@ APIs and services. Typical cloud architectures aim to minimize the chance that a failure in one zone also impairs services in another zone. --> -## 背景 +## 背景 {#background} Kubernetes 从设计上允许同一个 Kubernetes 集群跨多个失效区来运行, -通常这些区位于某个称作 _区域(region)_ 逻辑分组中。 -主要的云提供商都将区域定义为一组失效区的集合(也称作 _可用区(Availability Zones)_), +通常这些区位于某个称作 **区域(Region)** 逻辑分组中。 +主要的云提供商都将区域定义为一组失效区的集合(也称作 **可用区(Availability Zones**)), 能够提供一组一致的功能特性:每个区域内,各个可用区提供相同的 API 和服务。 典型的云体系结构都会尝试降低某个区中的失效影响到其他区中服务的概率。 @@ -66,10 +66,10 @@ If you are running a cloud controller manager then you should also replicate this across all the failure zones you selected. --> 当你部署集群控制面时,应将控制面组件的副本跨多个失效区来部署。 -如果可用性是一个很重要的指标,应该选择至少三个失效区,并将每个 -控制面组件(API 服务器、调度器、etcd、控制器管理器)复制多个副本, -跨至少三个失效区来部署。如果你在运行云控制器管理器,则也应该将 -该组件跨所选的三个失效区来部署。 +如果可用性是一个很重要的指标,应该选择至少三个失效区, +并将每个控制面组件(API 服务器、调度器、etcd、控制器管理器)复制多个副本, +跨至少三个失效区来部署。如果你在运行云控制器管理器, +则也应该将该组件跨所选的三个失效区来部署。 {{< note >}} ## 节点行为 {#node-behavior} -Kubernetes 自动为负载资源(如{{< glossary_tooltip text="Deployment" term_id="deployment" >}} -或 {{< glossary_tooltip text="StatefulSet" term_id="statefulset" >}})) -跨集群中不同节点来部署其 Pods。 +Kubernetes 自动为负载资源(如 {{< glossary_tooltip text="Deployment" term_id="deployment" >}} +或 {{< glossary_tooltip text="StatefulSet" term_id="statefulset" >}}) +跨集群中不同节点来部署其 Pod。 这种分布逻辑有助于降低失效带来的影响。 -节点启动时,每个节点上的 kubelet 会向 Kubernetes API 中代表该 kubelet 的 Node 对象 -添加 {{< glossary_tooltip text="标签" term_id="label" >}}。 +节点启动时,每个节点上的 kubelet 会向 Kubernetes API 中代表该 kubelet 的 Node +对象添加{{< glossary_tooltip text="标签" term_id="label" >}}。 这些标签可能包含[区信息](/zh-cn/docs/reference/labels-annotations-taints/#topologykubernetesiozone)。 如果你的集群跨了多个可用区或者地理区域,你可以使用节点标签,结合 [Pod 拓扑分布约束](/zh-cn/docs/concepts/scheduling-eviction/topology-spread-constraints/) -来控制如何在你的集群中多个失效域之间分布 Pods。这里的失效域可以是 -地理区域、可用区甚至是特定节点。 -这些提示信息使得{{< glossary_tooltip text="调度器" term_id="kube-scheduler" >}} -能够更好地分布 Pods,以实现更好的可用性,降低因为某种失效给整个工作负载 -带来的风险。 +来控制如何在你的集群中多个失效域之间分布 Pod。这里的失效域可以是地理区域、可用区甚至是特定节点。 +这些提示信息使得{{< glossary_tooltip text="调度器" term_id="kube-scheduler" >}}能够更好地调度 +Pod,以实现更好的可用性,降低因为某种失效给整个工作负载带来的风险。 -例如,你可以设置一种约束,确保某个 StatefulSet 中的三个副本都运行在 -不同的可用区中,只要其他条件允许。你可以通过声明的方式来定义这种约束, +例如,你可以设置一种约束,确保某个 StatefulSet 中的 3 个副本都运行在不同的可用区中, +只要其他条件允许。你可以通过声明的方式来定义这种约束, 而不需要显式指定每个工作负载使用哪些可用区。 -### 跨多个区分布节点 {#distributing-nodes-across-zones} +### 跨多个区分布节点 {#distributing-nodes-across-zones} -Kubernetes 的核心逻辑并不会帮你创建节点,你需要自行完成此操作,或者使用 -类似 [Cluster API](https://cluster-api.sigs.k8s.io/) 这类工具来替你管理节点。 +Kubernetes 的核心逻辑并不会帮你创建节点,你需要自行完成此操作,或者使用类似 +[Cluster API](https://cluster-api.sigs.k8s.io/) 这类工具来替你管理节点。 -使用类似 Cluster API 这类工具,你可以跨多个失效域来定义一组用做你的集群 -工作节点的机器,以及当整个区的服务出现中断时如何自动治愈集群的策略。 +使用类似 Cluster API 这类工具,你可以跨多个失效域来定义一组用做你的集群工作节点的机器, +以及当整个区的服务出现中断时如何自动治愈集群的策略。 -## 为 Pods 手动指定区 +## 为 Pod 手动指定区 {#manual-zone-assignment-for-pods} -你可以应用[节点选择算符约束](/zh-cn/docs/concepts/scheduling-eviction/assign-pod-node/#nodeselector) -到你所创建的 Pods 上,或者为 Deployment、StatefulSet 或 Job 这类工作负载资源 -中的 Pod 模板设置此类约束。 +你可以应用[节点选择算符约束](/zh-cn/docs/concepts/scheduling-eviction/assign-pod-node/#nodeselector)到你所创建的 +Pod 上,或者为 Deployment、StatefulSet 或 Job 这类工作负载资源中的 Pod 模板设置此类约束。 -## 跨区的存储访问 +## 跨区的存储访问 {#storage-access-for-zones} -当创建持久卷时,`PersistentVolumeLabel` -[准入控制器](/zh-cn/docs/reference/access-authn-authz/admission-controllers/) -会自动向那些链接到特定区的 PersistentVolume 添加区标签。 +当创建持久卷时,Kubernetes 会自动向那些链接到特定区的 PersistentVolume 添加区标签。 {{< glossary_tooltip text="调度器" term_id="kube-scheduler" >}}通过其 -`NoVolumeZoneConflict` 断言确保申领给定 PersistentVolume 的 Pods 只会 -被调度到该卷所在的可用区。 +`NoVolumeZoneConflict` 断言确保申领给定 PersistentVolume 的 Pod +只会被调度到该卷所在的可用区。 + + +请注意,添加区标签的方法可能取决于你的云提供商和存储制备器。 +请参阅具体的环境文档,确保配置正确。 + +请注意,添加区标签的方法可能会根据你所使用的云提供商和存储制备器而有所不同。 +为确保配置正确,请始终参阅你的环境的特定文档。 -你可以为 PersistentVolumeClaim 指定{{< glossary_tooltip text="StorageClass" term_id="storage-class" >}} +你可以为 PersistentVolumeClaim 指定 +{{< glossary_tooltip text="StorageClass" term_id="storage-class" >}} 以设置该类中的存储可以使用的失效域(区)。 -要了解如何配置能够感知失效域或区的 StorageClass,请参阅 -[可用的拓扑逻辑](/zh-cn/docs/concepts/storage/storage-classes/#allowed-topologies)。 +要了解如何配置能够感知失效域或区的 StorageClass, +请参阅[可用的拓扑逻辑](/zh-cn/docs/concepts/storage/storage-classes/#allowed-topologies)。 -## 网络 {#networking} +## 网络 {#networking} Kubernetes 自身不提供与可用区相关的联网配置。 你可以使用[网络插件](/zh-cn/docs/concepts/extend-kubernetes/compute-storage-net/network-plugins/) 来配置集群的联网,该网络解决方案可能拥有一些与可用区相关的元素。 -例如,如果你的云提供商支持 `type=LoadBalancer` 的 Service,则负载均衡器 -可能仅会将请求流量发送到运行在负责处理给定连接的负载均衡器组件所在的区。 +例如,如果你的云提供商支持 `type=LoadBalancer` 的 Service, +则负载均衡器可能仅会将请求流量发送到运行在负责处理给定连接的负载均衡器组件所在的区。 请查阅云提供商的文档了解详细信息。 -对于自定义的或本地集群部署,也可以考虑这些因素 -{{< glossary_tooltip text="Service" term_id="service" >}} +对于自定义的或本地集群部署,也可以考虑这些因素。 +{{< glossary_tooltip text="Service" term_id="service" >}} 和 {{< glossary_tooltip text="Ingress" term_id="ingress" >}} 的行为, 包括处理不同失效区的方法,在很大程度上取决于你的集群是如何搭建的。 @@ -262,11 +272,11 @@ something to consider. --> ## 失效恢复 {#fault-recovery} -在搭建集群时,你可能需要考虑当某区域中的所有失效区都同时掉线时,是否以及如何 -恢复服务。例如,你是否要求在某个区中至少有一个节点能够运行 Pod? +在搭建集群时,你可能需要考虑当某区域中的所有失效区都同时掉线时,是否以及如何恢复服务。 +例如,你是否要求在某个区中至少有一个节点能够运行 Pod? 请确保任何对集群很关键的修复工作都不要指望集群中至少有一个健康节点。 例如:当所有节点都不健康时,你可能需要运行某个修复性的 Job, -该 Job 要设置特定的{{< glossary_tooltip text="容忍度" term_id="toleration" >}} +该 Job 要设置特定的{{< glossary_tooltip text="容忍度" term_id="toleration" >}}, 以便修复操作能够至少将一个节点恢复为可用状态。 Kubernetes 对这类问题没有现成的解决方案;不过这也是要考虑的因素之一。 @@ -277,6 +287,5 @@ Kubernetes 对这类问题没有现成的解决方案;不过这也是要考虑 To learn how the scheduler places Pods in a cluster, honoring the configured constraints, visit [Scheduling and Eviction](/docs/concepts/scheduling-eviction/). --> -要了解调度器如何在集群中放置 Pods 并遵从所配置的约束,可参阅 -[调度与驱逐](/zh-cn/docs/concepts/scheduling-eviction/)。 - +要了解调度器如何在集群中放置 Pod 并遵从所配置的约束, +可参阅[调度与驱逐](/zh-cn/docs/concepts/scheduling-eviction/)。 diff --git a/content/zh-cn/docs/setup/production-environment/_index.md b/content/zh-cn/docs/setup/production-environment/_index.md index d245de1d1e529..7fe0c9fa7225f 100644 --- a/content/zh-cn/docs/setup/production-environment/_index.md +++ b/content/zh-cn/docs/setup/production-environment/_index.md @@ -361,24 +361,12 @@ simply as *nodes*). 这一规模是基于你要运行的 Pod 和容器个数来确定的。 如果你自行管理集群节点,这可能意味着要购买和安装你自己的物理设备。 -- **节点自动扩缩容**:大多数云供应商支持 - [集群自动扩缩器(Cluster Autoscaler)](https://github.com/kubernetes/autoscaler/tree/master/cluster-autoscaler#readme) - 以便替换不健康的节点、根据需求来增加或缩减节点个数。 - 参阅[常见问题](https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/FAQ.md) - 了解自动扩缩器的工作方式,并参阅 - [Deployment](https://github.com/kubernetes/autoscaler/tree/master/cluster-autoscaler#deployment) - 了解不同云供应商是如何实现集群自动扩缩器的。 - 对于本地集群,有一些虚拟化平台可以通过脚本来控制按需启动新节点。 +- *Autoscale nodes*: Read [Cluster Autoscaling](/docs/concepts/cluster-administration/cluster-autoscaling) to learn about the + tools available to automatically manage your nodes and the capacity they + provide. +--> +- **节点自动扩缩容**:查阅[集群自动扩缩容](/zh-cn/docs/concepts/cluster-administration/cluster-autoscaling), + 了解可以自动管理节点的工具及其提供的能力。 ## 安装和配置先决条件 {#install-and-configure-prerequisites} -以下步骤将通用设置应用于 Linux 上的 Kubernetes 节点。 - -如果你确定不需要某个特定设置,则可以跳过它。 - -有关更多信息,请参阅[网络插件要求](/zh-cn/docs/concepts/extend-kubernetes/compute-storage-net/network-plugins/#network-plugin-requirements)或特定容器运行时的文档。 + +默认情况下,Linux 内核不允许 IPv4 数据包在接口之间路由。 +大多数 Kubernetes 集群网络实现都会更改此设置(如果需要),但有些人可能希望管理员为他们执行此操作。 +(有些人可能还期望设置其他 sysctl 参数、加载内核模块等;请参阅你的特定网络实施的文档。) -### 转发 IPv4 并让 iptables 看到桥接流量 +### 启用 IPv4 数据包转发 {#prerequisite-ipv4-forwarding-optional} -执行下述指令: +手动启用 IPv4 数据包转发: ```bash -cat < -通过运行以下指令确认 `br_netfilter` 和 `overlay` 模块被加载: - -```bash -lsmod | grep br_netfilter -lsmod | grep overlay -``` - - -通过运行以下指令确认 `net.bridge.bridge-nf-call-iptables`、`net.bridge.bridge-nf-call-ip6tables` -和 `net.ipv4.ip_forward` 系统变量在你的 `sysctl` 配置中被设置为 1: +使用以下命令验证 `net.ipv4.ip_forward` 是否设置为 1: ```bash -sysctl net.bridge.bridge-nf-call-iptables net.bridge.bridge-nf-call-ip6tables net.ipv4.ip_forward +sysctl net.ipv4.ip_forward ``` -以下操作假设你使用 [`cri-dockerd`](https://github.com/Mirantis/cri-dockerd) 适配器来将 +以下操作假设你使用 [`cri-dockerd`](https://mirantis.github.io/cri-dockerd/) 适配器来将 Docker Engine 与 Kubernetes 集成。 {{< /note >}} @@ -585,10 +564,9 @@ Docker Engine 与 Kubernetes 集成。 指南为你的 Linux 发行版安装 Docker。 -2. 按照源代码仓库中的说明安装 [`cri-dockerd`](https://github.com/Mirantis/cri-dockerd)。 +2. 请按照文档中的安装部分指示来安装 [`cri-dockerd`](https://mirantis.github.io/cri-dockerd/usage/install)。 请参阅实现 -[Kubernetes 网络模型](/zh-cn/docs/concepts/cluster-administration/networking/#how-to-implement-the-kubernetes-networking-model)的附加组件列表。 +[Kubernetes 网络模型](/zh-cn/docs/concepts/cluster-administration/networking/#how-to-implement-the-kubernetes-network-model)的附加组件列表。 +请参阅[安装插件](/zh-cn/docs/concepts/cluster-administration/addons/#networking-and-network-policy)页面, +了解 Kubernetes 支持的网络插件的非详尽列表。 + 你可以使用以下命令在控制平面节点或具有 kubeconfig 凭据的节点上安装 Pod 网络附加组件: ```bash @@ -707,6 +713,19 @@ scheduler will then be able to schedule Pods everywhere. 污点的节点(包括控制平面节点)上移除该污点。 这意味着调度程序将能够在任何地方调度 Pod。 + +此外,你可以执行以下命令从控制平面节点中删除 +[`node.kubernetes.io/exclude-from-external-load-balancers`](/zh-cn/docs/reference/labels-annotations-taints/#node-kubernetes-io-exclude-from-external-load-balancers) +标签,这会将其从后端服务器列表中排除: + +```bash +kubectl label nodes --all node.kubernetes.io/exclude-from-external-load-balancers- +``` + @@ -1006,64 +1025,6 @@ options. 有关此子命令及其选项的更多信息,请参见 [`kubeadm reset`](/zh-cn/docs/reference/setup-tools/kubeadm/kubeadm-reset/) 参考文档。 - - - -## 下一步 {#whats-next} - - -* 使用 [Sonobuoy](https://github.com/heptio/sonobuoy) 验证集群是否正常运行。 -* 有关使用 kubeadm 升级集群的详细信息, - 请参阅[升级 kubeadm 集群](/zh-cn/docs/tasks/administer-cluster/kubeadm/kubeadm-upgrade/)。 -* 在 [kubeadm 参考文档](/zh-cn/docs/reference/setup-tools/kubeadm/)中了解有关 `kubeadm` 进阶用法的信息。 -* 了解有关 Kubernetes [概念](/zh-cn/docs/concepts/)和 [`kubectl`](/zh-cn/docs/reference/kubectl/)的更多信息。 -* 有关 Pod 网络附加组件的更多列表,请参见[集群网络](/zh-cn/docs/concepts/cluster-administration/networking/)页面。 -* 请参阅[附加组件列表](/zh-cn/docs/concepts/cluster-administration/addons/)以探索其他附加组件, - 包括用于 Kubernetes 集群的日志记录、监视、网络策略、可视化和控制的工具。 -* 配置集群如何处理集群事件的日志以及在 Pod 中运行的应用程序。 - 有关所涉及内容的概述,请参见[日志架构](/zh-cn/docs/concepts/cluster-administration/logging/)。 - - -### 反馈 {#feedback} - - -* 有关漏洞,访问 [kubeadm GitHub issue tracker](https://github.com/kubernetes/kubeadm/issues) -* 有关支持,访问 - [#kubeadm](https://kubernetes.slack.com/messages/kubeadm/) Slack 频道 -* 常规的 SIG Cluster Lifecycle 开发 Slack 频道: - [#sig-cluster-lifecycle](https://kubernetes.slack.com/messages/sig-cluster-lifecycle/) -* SIG Cluster Lifecycle 的 [SIG 资料](https://github.com/kubernetes/community/tree/master/sig-cluster-lifecycle#readme) -* SIG Cluster Lifecycle 邮件列表: - [kubernetes-sig-cluster-lifecycle](https://groups.google.com/forum/#!forum/kubernetes-sig-cluster-lifecycle) - @@ -1111,11 +1072,11 @@ Example: ### kubeadm 中 kubelet 的版本偏差 {#kubeadm-s-skew-against-the-kubelet} 与 Kubernetes 版本类似,kubeadm 可以使用与 kubeadm 相同版本的 kubelet, -或者比 kubeadm 老一个版本的 kubelet。 +或者比 kubeadm 老三个版本的 kubelet。 如果你在使用 kubeadm 时遇到困难, 请查阅我们的[故障排除文档](/zh-cn/docs/setup/production-environment/tools/kubeadm/troubleshooting-kubeadm/)。 + + + + +## 下一步 {#whats-next} + + +* 使用 [Sonobuoy](https://github.com/heptio/sonobuoy) 验证集群是否正常运行。 +* 有关使用 kubeadm 升级集群的详细信息, + 请参阅[升级 kubeadm 集群](/zh-cn/docs/tasks/administer-cluster/kubeadm/kubeadm-upgrade/)。 +* 在 [kubeadm 参考文档](/zh-cn/docs/reference/setup-tools/kubeadm/)中了解有关 `kubeadm` 进阶用法的信息。 +* 了解有关 Kubernetes [概念](/zh-cn/docs/concepts/)和 [`kubectl`](/zh-cn/docs/reference/kubectl/)的更多信息。 +* 有关 Pod 网络附加组件的更多列表,请参见[集群网络](/zh-cn/docs/concepts/cluster-administration/networking/)页面。 +* 请参阅[附加组件列表](/zh-cn/docs/concepts/cluster-administration/addons/)以探索其他附加组件, + 包括用于 Kubernetes 集群的日志记录、监视、网络策略、可视化和控制的工具。 +* 配置集群如何处理集群事件的日志以及在 Pod 中运行的应用程序。 + 有关所涉及内容的概述,请参见[日志架构](/zh-cn/docs/concepts/cluster-administration/logging/)。 + + +### 反馈 {#feedback} + + +* 有关漏洞,访问 [kubeadm GitHub issue tracker](https://github.com/kubernetes/kubeadm/issues) +* 有关支持,访问 + [#kubeadm](https://kubernetes.slack.com/messages/kubeadm/) Slack 频道 +* 常规的 SIG Cluster Lifecycle 开发 Slack 频道: + [#sig-cluster-lifecycle](https://kubernetes.slack.com/messages/sig-cluster-lifecycle/) +* SIG Cluster Lifecycle 的 [SIG 资料](https://github.com/kubernetes/community/tree/master/sig-cluster-lifecycle#readme) +* SIG Cluster Lifecycle 邮件列表: + [kubernetes-sig-cluster-lifecycle](https://groups.google.com/forum/#!forum/kubernetes-sig-cluster-lifecycle) diff --git a/content/zh-cn/docs/setup/production-environment/tools/kubeadm/install-kubeadm.md b/content/zh-cn/docs/setup/production-environment/tools/kubeadm/install-kubeadm.md index ce500600e1dd8..0cca4291f177d 100644 --- a/content/zh-cn/docs/setup/production-environment/tools/kubeadm/install-kubeadm.md +++ b/content/zh-cn/docs/setup/production-environment/tools/kubeadm/install-kubeadm.md @@ -116,15 +116,15 @@ route, we recommend you add IP route(s) so Kubernetes cluster addresses go via t These These [required ports](/docs/reference/networking/ports-and-protocols/) need to be open in order for Kubernetes components to communicate with each other. -You can use tools like netcat to check if a port is open. For example: +You can use tools like [netcat](https://netcat.sourceforge.net) to check if a port is open. For example: --> ## 检查所需端口{#check-required-ports} 启用这些[必要的端口](/zh-cn/docs/reference/networking/ports-and-protocols/)后才能使 Kubernetes 的各组件相互通信。 -可以使用 netcat 之类的工具来检查端口是否启用,例如: +可以使用 [netcat](https://netcat.sourceforge.net) 之类的工具来检查端口是否开放,例如: ```shell -nc 127.0.0.1 6443 +nc 127.0.0.1 6443 -v ``` 通过 `kubeadm` [包](https://github.com/kubernetes/release/blob/cd53840/cmd/krel/templates/latest/kubeadm/10-kubeadm.conf) -安装的配置文件被写入 `/etc/systemd/system/kubelet.service.d/10-kubeadm.conf` +安装的配置文件被写入 `/usr/lib/systemd/system/kubelet.service.d/10-kubeadm.conf` 并由 systemd 使用。它对原来的 -[`kubelet.service`](https://github.com/kubernetes/release/blob/cd53840/cmd/krel/templates/latest/kubelet/kubelet.service) 作了增强: +[`kubelet.service`](https://github.com/kubernetes/release/blob/cd53840/cmd/krel/templates/latest/kubelet/kubelet.service) 作了增强。 + + +如果你想进一步覆盖它,可以创建一个目录`/etc/systemd/system/kubelet.service.d/` +(而不是`/usr/lib/systemd/kubelet.service.d/`),并将你自己的自定义配置写入到该目录下的一个文件中。 + +例如,您可以添加一个新的本地文件`/etc/systemd/system/kubelet.service.d/local-overrides.conf` +以覆盖“kubeadm”配置的单元设置。 + +以下是你可能在“/usr/lib/systemd/kubelet.service.d/10 kubeadm.conf”中找到的内容: {{< note >}} + ```sh cat << EOF > /etc/systemd/system/kubelet.service.d/kubelet.conf # 将下面的 "systemd" 替换为你的容器运行时所使用的 cgroup 驱动。 @@ -194,6 +195,7 @@ on Kubernetes dual-stack support see [Dual-stack support with kubeadm](/docs/set # Create temp directories to store files that will end up on other hosts mkdir -p /tmp/${HOST0}/ /tmp/${HOST1}/ /tmp/${HOST2}/ --> + ```sh # 使用你的主机 IP 更新 HOST0、HOST1 和 HOST2 的 IP 地址 export HOST0=10.0.0.6 diff --git a/content/zh-cn/docs/setup/production-environment/tools/kubeadm/troubleshooting-kubeadm.md b/content/zh-cn/docs/setup/production-environment/tools/kubeadm/troubleshooting-kubeadm.md index 20c8170931d8a..18aa238323079 100644 --- a/content/zh-cn/docs/setup/production-environment/tools/kubeadm/troubleshooting-kubeadm.md +++ b/content/zh-cn/docs/setup/production-environment/tools/kubeadm/troubleshooting-kubeadm.md @@ -227,7 +227,7 @@ before CoreDNS may be deployed fully. Hence the `Pending` state before the netwo --> ## `coredns` 停滞在 `Pending` 状态 -这一行为是 **预期之中** 的,因为系统就是这么设计的。kubeadm 的网络供应商是中立的, +这一行为是**预期之中**的,因为系统就是这么设计的。kubeadm 的网络供应商是中立的, 因此管理员应该选择[安装 Pod 的网络插件](/zh-cn/docs/concepts/cluster-administration/addons/)。 你必须完成 Pod 的网络配置,然后才能完全部署 CoreDNS。 在网络被配置好之前,DNS 组件会一直处于 `Pending` 状态。 @@ -258,8 +258,8 @@ or use `HostNetwork=true`. 有关更多信息,请参考 [CNI portmap 文档](https://github.com/containernetworking/plugins/blob/master/plugins/meta/portmap/README.md). 如果你的网络提供商不支持 portmap CNI 插件,你或许需要使用 -[NodePort 服务的功能](/zh-cn/docs/concepts/services-networking/service/#type-nodeport) -或者使用 `HostNetwork=true`。 +[NodePort 服务的功能](/zh-cn/docs/concepts/services-networking/service/#type-nodeport)或者使用 +`HostNetwork=true`。 1. 从故障节点备份和删除 `/etc/kubernetes/kubelet.conf` 和 `/var/lib/kubelet/pki/kubelet-client*`。 @@ -367,7 +368,8 @@ in kube-apiserver logs. To fix the issue you must follow these steps: 执行 `kubeadm kubeconfig user --org system:nodes --client-name system:node:$NODE > kubelet.conf`。 `$NODE` 必须设置为集群中现有故障节点的名称。 手动修改生成的 `kubelet.conf` 以调整集群名称和服务器端点, - 或传递 `kubeconfig user --config`(此命令接受 `InitConfiguration`)。 + 或传递 `kubeconfig user --config` + (请参阅[为其他用户生成 kubeconfig 文件](/zh-cn/docs/tasks/administer-cluster/kubeadm/kubeadm-certs/#kubeconfig-additional-users))。 如果你的集群没有 `ca.key`,你必须在外部对 `kubelet.conf` 中的嵌入式证书进行签名。 - 27017 是分配给 MongoDB 的互联网 TCP 端口。 + 27017 是 MongoDB 的官方 TCP 端口。 - 注意服务中的 NodePort 值。例如在上面的输出中,NodePort 值是 31496。 + 注意 Service 中的 NodePort 值。例如在上面的输出中,NodePort 值是 31496。 +## 部署 Dashboard UI {#deploying-the-dashboard-ui} +{{< note >}} + +Kubernetes Dashboard 目前仅支持基于 Helm 的安装,因为它速度更快, +并且可以让我们更好地控制 Dashboard 运行所需的所有依赖项。 +{{< /note >}} + + -## 部署 Dashboard UI {#deploying-the-dashboard-ui} -默认情况下不会部署 Dashboard。可以通过以下命令部署: +默认情况下不会部署 Dashboard,可以通过以下命令部署: + ``` -kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.7.0/aio/deploy/recommended.yaml +# 添加 kubernetes-dashboard 仓库 +helm repo add kubernetes-dashboard https://kubernetes.github.io/dashboard/ +# 使用 kubernetes-dashboard Chart 部署名为 `kubernetes-dashboard` 的 Helm Release +helm upgrade --install kubernetes-dashboard kubernetes-dashboard/kubernetes-dashboard --create-namespace --namespace kubernetes-dashboard ``` -UI _只能_ 通过执行这条命令的机器进行访问。更多选项参见 `kubectl proxy --help`。 +UI **只能**通过执行这条命令的机器进行访问。更多选项参见 `kubectl proxy --help`。 {{< note >}} - **标签**:应用默认使用的 - [标签](/zh-cn/docs/concepts/overview/working-with-objects/labels/) 是应用名称和版本。 + [标签](/zh-cn/docs/concepts/overview/working-with-objects/labels/)是应用名称和版本。 你可以为 Deployment、Service(如果有)定义额外的标签,比如 release(版本)、 environment(环境)、tier(层级)、partition(分区) 和 release track(版本跟踪)。 @@ -281,8 +299,7 @@ If needed, you can expand the **Advanced options** section where you can specify They let you partition resources into logically named groups. --> - **名字空间**:Kubernetes 支持多个虚拟集群依附于同一个物理集群。 - 这些虚拟集群被称为 - [名字空间](/zh-cn/docs/tasks/administer-cluster/namespaces/), + 这些虚拟集群被称为[名字空间](/zh-cn/docs/tasks/administer-cluster/namespaces/), 可以让你将资源划分为逻辑命名的组。 -- **运行命令**和**运行命令参数**:默认情况下,你的容器会运行 Docker 镜像的默认 - [入口命令](/zh-cn/docs/tasks/inject-data-application/define-command-argument-container/)。 +- **运行命令**和**运行命令参数**:默认情况下,你的容器会运行 Docker + 镜像的默认[入口命令](/zh-cn/docs/tasks/inject-data-application/define-command-argument-container/)。 你可以使用 command 选项覆盖默认值。 -更多信息,参见 [Kubernetes Dashboard 项目页面](https://github.com/kubernetes/dashboard). +更多信息,参见 [Kubernetes Dashboard 项目页面](https://github.com/kubernetes/dashboard)。 diff --git a/content/zh-cn/docs/tasks/administer-cluster/configure-upgrade-etcd.md b/content/zh-cn/docs/tasks/administer-cluster/configure-upgrade-etcd.md index f7526efb76119..af1f786c84d18 100644 --- a/content/zh-cn/docs/tasks/administer-cluster/configure-upgrade-etcd.md +++ b/content/zh-cn/docs/tasks/administer-cluster/configure-upgrade-etcd.md @@ -19,17 +19,15 @@ weight: 270 ## {{% heading "prerequisites" %}} -{{< include "task-tutorial-prereqs.md" >}} {{< version-check >}} - 你需要有一个 Kubernetes 集群,并且必须配置 kubectl 命令行工具以与你的集群通信。 -建议在至少有两个不充当控制平面的节点上运行此任务。如果你还没有集群, +建议参照本指南在至少有两个不充当控制平面的节点上运行此任务。如果你还没有集群, 你可以使用 [minikube](https://minikube.sigs.k8s.io/docs/tutorials/multi_node/) 创建一个。 @@ -42,7 +40,14 @@ nodes . If you do not already have a cluster, you can create one by using * etcd is a leader-based distributed system. Ensure that the leader periodically send heartbeats on time to all followers to keep the cluster stable. +--> +## 先决条件 {#prerequisites} + +* 运行的 etcd 集群个数成员为奇数。 + +* etcd 是一个基于领导者(Leader-Based)的分布式系统。确保主节点定期向所有从节点发送心跳,以保持集群稳定。 + -## 先决条件 {#prerequisites} - -* 运行的 etcd 集群个数成员为奇数。 - -* etcd 是一个 leader-based 分布式系统。确保主节点定期向所有从节点发送心跳,以保持集群稳定。 - * 确保不发生资源不足。 集群的性能和稳定性对网络和磁盘 I/O 非常敏感。任何资源匮乏都会导致心跳超时, 从而导致集群的不稳定。不稳定的情况表明没有选出任何主节点。 在这种情况下,集群不能对其当前状态进行任何更改,这意味着不能调度新的 Pod。 + * 保持 etcd 集群的稳定对 Kubernetes 集群的稳定性至关重要。 因此,请在专用机器或隔离环境上运行 etcd 集群, 以满足[所需资源需求](https://etcd.io/docs/current/op-guide/hardware/)。 @@ -100,7 +100,7 @@ This section covers starting a single-node and multi-node etcd cluster. -配置安全通信后,限制只有 Kubernetes API 服务器可以访问 etcd 集群。使用 TLS 身份验证来完成此任务。 +配置安全通信后,使用 TLS 身份验证来限制只有 Kubernetes API 服务器可以访问 etcd 集群。 -Kubernetes 目前不支持 etcd 身份验证。 -想要了解更多信息,请参阅相关的问题[支持 etcd v2 的基本认证](https://github.com/kubernetes/kubernetes/issues/23398)。 +Kubernetes 没有为 etcd 提供身份验证的计划。 {{< /note >}} 3. 停止故障节点上的 etcd 服务器。除了 Kubernetes API 服务器之外的其他客户端可能会造成流向 etcd 的流量, 可以停止所有流量以防止写入数据目录。 4. 移除失败的成员: @@ -400,7 +397,7 @@ replace it with `member4=http://10.0.0.4`. ``` 5. 增加新成员: @@ -418,7 +415,7 @@ replace it with `member4=http://10.0.0.4`. ``` 6. 在 IP 为 `10.0.0.4` 的机器上启动新增加的成员: @@ -430,7 +427,7 @@ replace it with `member4=http://10.0.0.4`. ``` ## 备份 etcd 集群 {#backing-up-an-etcd-cluster} -所有 Kubernetes 对象都存储在 etcd 上。 +所有 Kubernetes 对象都存储在 etcd 中。 定期备份 etcd 集群数据对于在灾难场景(例如丢失所有控制平面节点)下恢复 Kubernetes 集群非常重要。 快照文件包含所有 Kubernetes 状态和关键信息。为了保证敏感的 Kubernetes 数据的安全,可以对快照文件进行加密。 @@ -482,22 +479,22 @@ snapshot and volume snapshot. ### 内置快照 {#built-in-snapshot} -etcd 支持内置快照。快照可以从使用 `etcdctl snapshot save` 命令的活动成员中获取, +etcd 支持内置快照。快照可以从使用 `etcdctl snapshot save` 命令的活动成员中创建, 也可以通过从 etcd [数据目录](https://etcd.io/docs/current/op-guide/configuration/#--data-dir) -复制 `member/snap/db` 文件,该 etcd 数据目录目前没有被 etcd 进程使用。获取快照不会影响成员的性能。 +复制 `member/snap/db` 文件,该 etcd 数据目录目前没有被 etcd 进程使用。创建快照不会影响成员的性能。 -下面是一个示例,用于获取 `$ENDPOINT` 所提供的键空间的快照到文件 `snapshot.db`: +下面是一个示例,用于创建 `$ENDPOINT` 所提供的键空间的快照到文件 `snapshot.db`: ```shell ETCDCTL_API=3 etcdctl --endpoints $ENDPOINT snapshot save snapshot.db @@ -527,11 +524,11 @@ ETCDCTL_API=3 etcdctl --write-out=table snapshot status snapshot.db 如果 etcd 运行在支持备份的存储卷(如 Amazon Elastic Block -存储)上,则可以通过获取存储卷的快照来备份 etcd 数据。 +存储)上,则可以通过创建存储卷的快照来备份 etcd 数据。 我们还可以使用 etcdctl 提供的各种选项来制作快照。例如: @@ -548,10 +545,10 @@ ETCDCTL_API=3 etcdctl -h ``` -列出 etcdctl 可用的各种选项。例如,你可以通过指定端点、证书等来制作快照,如下所示: +列出 etcdctl 可用的各种选项。例如,你可以通过指定端点、证书和密钥来制作快照,如下所示: ```shell ETCDCTL_API=3 etcdctl --endpoints=https://127.0.0.1:2379 \ @@ -573,7 +570,7 @@ where `trusted-ca-file`, `cert-file` and `key-file` can be obtained from the des Scaling out etcd clusters increases availability by trading off performance. Scaling does not increase cluster performance nor capability. A general rule is not to scale out or in etcd clusters. Do not configure any auto scaling -groups for etcd clusters. It is highly recommended to always run a static +groups for etcd clusters. It is strongly recommended to always run a static five-member etcd cluster for production Kubernetes clusters at any officially supported scale. --> @@ -599,7 +596,7 @@ for information on how to add members into an existing cluster. etcd 支持从 [major.minor](http://semver.org/) 或其他不同 patch 版本的 etcd 进程中获取的快照进行恢复。 @@ -609,29 +606,23 @@ etcd 支持从 [major.minor](http://semver.org/) 或其他不同 patch 版本的 Before starting the restore operation, a snapshot file must be present. It can either be a snapshot file from a previous backup operation, or from a remaining [data directory](https://etcd.io/docs/current/op-guide/configuration/#--data-dir). -Here is an example: --> 在启动还原操作之前,必须有一个快照文件。它可以是来自以前备份操作的快照文件, 也可以是来自剩余[数据目录](https://etcd.io/docs/current/op-guide/configuration/#--data-dir)的快照文件。 -例如: - -```shell -ETCDCTL_API=3 etcdctl --endpoints 10.2.0.9:2379 snapshot restore snapshot.db -``` -恢复时使用 `etcdctl` 选项的另一个示例: +在恢复集群时,使用 `--data-dir` 选项来指定集群应被恢复到哪个文件夹。 ```shell -ETCDCTL_API=3 etcdctl snapshot restore --data-dir snapshot.db +ETCDCTL_API=3 etcdctl --data-dir snapshot restore snapshot.db ``` 其中 `` 是将在恢复过程中创建的目录。 @@ -639,9 +630,15 @@ Yet another example would be to first export the `ETCDCTL_API` environment varia ```shell export ETCDCTL_API=3 -etcdctl snapshot restore --data-dir snapshot.db +etcdctl --data-dir snapshot restore snapshot.db ``` + +如果 `` 与之前的文件夹相同,请先删除此文件夹并停止 etcd 进程,再恢复集群。 +否则,需要在恢复后更改 etcd 配置并重新启动 etcd 进程才能使用新的数据目录。 + 碎片整理是一种昂贵的操作,因此应尽可能少地执行此操作。 -另一方面,也有必要确保任何 etcd 成员都不会用尽存储配额。 +另一方面,也有必要确保任何 etcd 成员都不会超过存储配额。 Kubernetes 项目建议在执行碎片整理时, 使用诸如 [etcd-defrag](https://github.com/ahrtr/etcd-defrag) 之类的工具。 {{< /note >}} diff --git a/content/zh-cn/docs/tasks/administer-cluster/dns-horizontal-autoscaling.md b/content/zh-cn/docs/tasks/administer-cluster/dns-horizontal-autoscaling.md index bbf435633aee4..2a625b480882f 100644 --- a/content/zh-cn/docs/tasks/administer-cluster/dns-horizontal-autoscaling.md +++ b/content/zh-cn/docs/tasks/administer-cluster/dns-horizontal-autoscaling.md @@ -29,7 +29,6 @@ your Kubernetes cluster. * 确保 [Kubernetes DNS](/zh-cn/docs/concepts/services-networking/dns-pod-service/) 已启用。 - -## 确定是否 DNS 水平自动扩缩特性已经启用 {#determining-whether-dns-horizontal-autoscaling-is-already-enabled} +## 确定是否 DNS 水平自动扩缩特性已经启用 {#determining-whether-dns-horizontal-autoscaling-is-already-enabled} 在 kube-system {{< glossary_tooltip text="命名空间" term_id="namespace" >}}中列出集群中的 {{< glossary_tooltip text="Deployment" term_id="deployment" >}}: @@ -53,18 +52,18 @@ The output is similar to this: 输出类似如下这样: ``` -NAME READY UP-TO-DATE AVAILABLE AGE +NAME READY UP-TO-DATE AVAILABLE AGE ... -dns-autoscaler 1/1 1 1 ... +kube-dns-autoscaler 1/1 1 1 ... ... ``` -如果在输出中看到 “dns-autoscaler”,说明 DNS 水平自动扩缩已经启用, +如果在输出中看到 “kube-dns-autoscaler”,说明 DNS 水平自动扩缩已经启用, 可以跳到[调优 DNS 自动扩缩参数](#tuning-autoscaling-parameters)。 -## 获取 DNS Deployment 的名称 {#find-scaling-target} +## 获取 DNS Deployment 的名称 {#find-scaling-target} 列出集群内 kube-system 命名空间中的 DNS Deployment: @@ -122,12 +121,12 @@ the name of your Deployment for DNS is coredns, your scale target is Deployment/ 其中 `` 是 DNS Deployment 的名称。 例如,如果你的 DNS Deployment 名称是 `coredns`,则你的扩展目标是 Deployment/coredns。 +{{< note >}} -{{< note >}} CoreDNS 是 Kubernetes 的默认 DNS 服务。CoreDNS 设置标签 `k8s-app=kube-dns`, 以便能够在原来使用 `kube-dns` 的集群中工作。 {{< /note >}} @@ -155,7 +154,7 @@ In the file, replace `` with your scale target. Go to the directory that contains your configuration file, and enter this command to create the Deployment: --> -在文件中,将 `` 替换成扩缩目标。 +在此文件中,将 `` 替换成扩缩目标。 进入到包含配置文件的目录中,输入如下命令创建 Deployment: @@ -166,25 +165,25 @@ kubectl apply -f dns-horizontal-autoscaler.yaml -一个成功的命令输出是: +命令成功执行后的输出为: ``` -deployment.apps/dns-autoscaler created +deployment.apps/kube-dns-autoscaler created ``` -DNS 水平自动扩缩在已经启用了。 +DNS 水平自动扩缩现在已经启用了。 ## 调优 DNS 自动扩缩参数 {#tuning-autoscaling-parameters} -验证 dns-autoscaler {{< glossary_tooltip text="ConfigMap" term_id="configmap" >}} 是否存在: +验证 kube-dns-autoscaler {{< glossary_tooltip text="ConfigMap" term_id="configmap" >}} 是否存在: ```shell kubectl get configmap --namespace=kube-system @@ -198,17 +197,17 @@ The output is similar to this: ``` NAME DATA AGE ... -dns-autoscaler 1 ... +kube-dns-autoscaler 1 ... ... ``` -修改该 ConfigMap 中的数据: +修改此 ConfigMap 中的数据: ```shell -kubectl edit configmap dns-autoscaler --namespace=kube-system +kubectl edit configmap kube-dns-autoscaler --namespace=kube-system ``` - 根据需要修改对应的字段。“min” 字段表明 DNS 后端的最小数量。 实际后端的数量通过使用如下公式来计算: @@ -258,21 +256,21 @@ There are other supported scaling patterns. For details, see There are a few options for tuning DNS horizontal autoscaling. Which option to use depends on different conditions. --> -## 禁用 DNS 水平自动扩缩 +## 禁用 DNS 水平自动扩缩 {#disable-dns-horizontal-autoscaling} 有几个可供调优的 DNS 水平自动扩缩选项。具体使用哪个选项因环境而异。 -### 选项 1:缩容 dns-autoscaler Deployment 至 0 个副本 +### 选项 1:kube-dns-autoscaler Deployment 缩容至 0 个副本 -该选项适用于所有场景。运行如下命令: +此选项适用于所有场景。运行如下命令: ```shell -kubectl scale deployment --replicas=0 dns-autoscaler --namespace=kube-system +kubectl scale deployment --replicas=0 kube-dns-autoscaler --namespace=kube-system ``` -### 选项 2:删除 dns-autoscaler Deployment +### 选项 2:删除 kube-dns-autoscaler Deployment -如果 dns-autoscaler 为你所控制,也就说没有人会去重新创建它,可以选择此选项: +如果 kube-dns-autoscaler 为你所控制,也就说没有人会去重新创建它,可以选择此选项: ```shell -kubectl delete deployment dns-autoscaler --namespace=kube-system +kubectl delete deployment kube-dns-autoscaler --namespace=kube-system ``` +### 选项 3:从主控节点删除 kube-dns-autoscaler 清单文件 -### 选项 3:从主控节点删除 dns-autoscaler 清单文件 - -如果 dns-autoscaler 在[插件管理器](https://git.k8s.io/kubernetes/cluster/addons/README.md) -的控制之下,并且具有操作 master 节点的写权限,可以使用此选项。 +如果 kube-dns-autoscaler 在[插件管理器](https://git.k8s.io/kubernetes/cluster/addons/README.md) +的控制之下,并且具有操作主控节点的写权限,可以使用此选项。 -登录到主控节点,删除对应的清单文件。 -dns-autoscaler 对应的路径一般为: +登录到主控节点,删除对应的清单文件。 +kube-dns-autoscaler 对应的路径一般为: ``` /etc/kubernetes/addons/dns-horizontal-autoscaler/dns-horizontal-autoscaler.yaml @@ -354,9 +351,9 @@ dns-autoscaler 对应的路径一般为: -当清单文件被删除后,插件管理器将删除 dns-autoscaler Deployment。 +当清单文件被删除后,插件管理器将删除 kube-dns-autoscaler Deployment。 @@ -369,7 +366,7 @@ the DNS service. * An autoscaler Pod runs a client that polls the Kubernetes API server for the number of nodes and cores in the cluster. --> -## 理解 DNS 水平自动扩缩工作原理 +## 理解 DNS 水平自动扩缩工作原理 {#understanding-how-dns-horizontal-autoscaling-works} * cluster-proportional-autoscaler 应用独立于 DNS 服务部署。 @@ -405,7 +402,6 @@ patterns: *linear* and *ladder*. * Read about [Guaranteed Scheduling For Critical Add-On Pods](/docs/tasks/administer-cluster/guaranteed-scheduling-critical-addon-pods/). * Learn more about the [implementation of cluster-proportional-autoscaler](https://github.com/kubernetes-sigs/cluster-proportional-autoscaler). - --> * 阅读[为关键插件 Pod 提供的调度保障](/zh-cn/docs/tasks/administer-cluster/guaranteed-scheduling-critical-addon-pods/)。 * 进一步了解 [cluster-proportional-autoscaler 实现](https://github.com/kubernetes-sigs/cluster-proportional-autoscaler)。 diff --git a/content/zh-cn/docs/tasks/administer-cluster/encrypt-data.md b/content/zh-cn/docs/tasks/administer-cluster/encrypt-data.md index 27dfd7151b468..8ce2b2bff3831 100644 --- a/content/zh-cn/docs/tasks/administer-cluster/encrypt-data.md +++ b/content/zh-cn/docs/tasks/administer-cluster/encrypt-data.md @@ -85,18 +85,45 @@ to either: -## 配置并确定是否已启用静态数据加密 {#configuration-and-determing-wheter-encryption-at-rest-is-already-enabled} +## 确定是否已启用静态数据加密 {#determining-whether-encryption-at-rest-is-already-enabled} + +默认情况下,API 服务器将资源的明文表示存储在 etcd 中,没有静态加密。 -`kube-apiserver` 的参数 `--encryption-provider-config` 控制 API 数据在 etcd 中的加密方式。 -该配置作为一个名为 [`EncryptionConfiguration`](/zh-cn/docs/reference/config-api/apiserver-encryption.v1/) -的 API 提供。下面提供了一个示例配置。 + +`kube-apiserver` 进程使用 `--encryption-provider-config` 参数指定配置文件的路径, +所指定的配置文件的内容将控制 Kubernetes API 数据在 etcd 中的加密方式。 +如果你在运行 kube-apiserver 时没有使用 `--encryption-provider-config` 命令行参数, +则你未启用静态加密。如果你在运行 kube-apiserver 时使用了 `--encryption-provider-config` +命令行参数,并且此参数所引用的文件指定 `identity` 提供程序作为加密提供程序列表中的第一个, +则你未启用静态加密(**默认的 `identity` 提供程序不提供任何机密性保护**)。 + + +如果你在运行 kube-apiserver 时使用了 `--encryption-provider-config` 命令行参数, +并且此参数所引用的文件指定一个不是 `identity` 的提供程序作为加密提供程序列表中的第一个, +则你已启用静态加密。然而此项检查并未告知你先前向加密存储的迁移是否成功。如果你不确定, +请参阅[确保所有相关数据都已加密](#ensure-all-secrets-are-encrypted)。 {{< caution >}} ## 理解静态数据加密 {#understanding-the-encryption-at-rest-configuration} + + + - - - {{< highlight yaml "linenos=false,hl_lines=2-5" >}} --- # @@ -242,28 +314,57 @@ are determined by the order it's listed in the configuration. {{< /note >}} -如果启用了通配符,但想要针对特定资源退出加密,则可以通过添加带有资源名称的新 `resources` 数组项, -后跟附带 `identity` 提供商的 `providers` 数组项。例如,如果启用了 “`*.*`”, -但想要排除对 `events` 资源的加密,则应向 `resources` 数组添加一个新项(以 `events` 为资源名称), -后跟包含 `identity` 的提供程序数组。新项应如下所示: +如果你有一个涵盖资源(resource)的通配符,并且想要过滤掉静态加密的特定类型资源, +则可以通过添加一个单独的 `resources` 数组项来实现此目的, +其中包含要豁免的资源的名称,还可以在其后跟一个 `providers` 数组项来指定 `identity` 提供商。 +你可以将此数组项添加到列表中,以便它早于你指定加密的配置(不是 `identity` 的提供商)出现。 + + +例如,如果启用了 '`*.*`',并且你想要选择不加密 Event 和 ConfigMap, +请在 `resources` 中**靠前**的位置添加一个新的条目,后跟带有 `identity` +的 providers 数组项作为提供程序。较为特定的条目必须位于通配符条目之前。 + +新项目看起来类似于: + + ```yaml -- resources: - - events - providers: - - identity: {} + ... + - resources: + - configmaps. # 特定于来自核心 API 组的资源,因为结尾是 “.” + - events + providers: + - identity: {} + # 然后是资源中的其他条目 ``` -确保新项列在资源数组中的通配符 “`*.*`” 项之前,使新项优先。 +确保新项列在资源数组中的通配符 “`*.*`” 项**之前**,使新项优先。 不加密写入的资源。当设置为第一个提供程序时,已加密的资源将在新值写入时被解密。 @@ -549,7 +652,7 @@ The following steps assume that you are not using KMS, and therefore the steps a assume that you need to generate an encryption key. If you already have an encryption key, skip to [Write an encryption configuration file](#write-an-encryption-configuration-file). --> -以下步骤假设你没有使用 KMS,因此这些步骤还假设您需要生成加密密钥。 +以下步骤假设你没有使用 KMS,因此这些步骤还假设你需要生成加密密钥。 如果你已有加密密钥,请跳至[编写加密配置文件](#write-an-encryption-configuration-file)。 {{< caution >}} @@ -654,7 +757,7 @@ so that you're relying on KMS encryption. 使用安全的文件传输机制,将该加密密钥的副本提供给所有其他控制平面主机。 至少,使用传输加密 - 例如,安全 shell(SSH)。为了提高安全性, -请在主机之间使用非对称加密,或更改您正在使用的方法,以便依赖 KMS 加密。 +请在主机之间使用非对称加密,或更改你正在使用的方法,以便依赖 KMS 加密。 ```yaml --- @@ -980,7 +1098,6 @@ When you have configured encryption at rest for an API (for example: the API kin that all those resources in this cluster really are encrypted at rest. Check this before you carry on with the next steps. --> - 此更改可防止 API 服务器检索标记为静态加密但实际上以明文形式存储的资源。 当你为某个 API 配置静态加密时(例如:API 种类 `Secret`,代表核心 API 组中的 `secrets` 资源), @@ -995,7 +1112,20 @@ part of the encryption configuration. For example: 一旦集群中的所有 Secret 都被加密,你就可以删除加密配置中的 `identity` 部分。例如: {{< highlight yaml "linenos=false,hl_lines=12" >}} --- @@ -1019,7 +1149,7 @@ from accessing a plain-text Secret, even by accident. …然后依次重新启动每个 API 服务器。此更改可防止 API 服务器访问纯文本 Secret,即使是意外访问也是如此。 ```yaml --- diff --git a/content/zh-cn/docs/tasks/administer-cluster/kubeadm/kubeadm-upgrade.md b/content/zh-cn/docs/tasks/administer-cluster/kubeadm/kubeadm-upgrade.md index a6ff7b54676cc..560b6ef9e0452 100644 --- a/content/zh-cn/docs/tasks/administer-cluster/kubeadm/kubeadm-upgrade.md +++ b/content/zh-cn/docs/tasks/administer-cluster/kubeadm/kubeadm-upgrade.md @@ -81,11 +81,18 @@ The upgrade workflow at high level is the following: first drain the node (or nodes) that you are upgrading. In the case of control plane nodes, they could be running CoreDNS Pods or other critical workloads. For more information see [Draining nodes](/docs/tasks/administer-cluster/safely-drain-node/). +- The Kubernetes project recommends that you match your kubelet and kubeadm versions. + You can instead use a version of kubelet that is older than kubeadm, provided it is within the + range of supported versions. + For more details, please visit [kubeadm's skew against the kubelet](/docs/setup/production-environment/tools/kubeadm/create-cluster-kubeadm/#kubeadm-s-skew-against-the-kubelet). - All containers are restarted after upgrade, because the container spec hash value is changed. --> - 下述说明了在升级过程中何时腾空每个节点。如果你正在对任何 kubelet 进行小版本升级, 你需要先腾空待升级的节点(或多个节点)。对于控制面节点,其上可能运行着 CoreDNS Pod 或者其它非常重要的负载。更多信息见[腾空节点](/zh-cn/docs/tasks/administer-cluster/safely-drain-node/)。 +- Kubernetes 项目推荐你使用版本匹配的 kubelet 和 kubeadm。 + 但你也可以使用比 kubeadm 版本更低的 kubelet 版本,前提是该版本仍处于支持的版本范围内。 + 欲了解更多信息,请访问 [kubeadm 与 kubelet 的版本差异](/zh-cn/docs/setup/production-environment/tools/kubeadm/create-cluster-kubeadm/#kubeadm-s-skew-against-the-kubelet)。 - 升级后,因为容器规约的哈希值已更改,所有容器都会被重新启动。 +### 升级 etcd 时的注意事项 + +由于 `kube-apiserver` 静态 Pod 始终在运行(即使你已经执行了腾空节点的操作), +因此当你执行包括 etcd 升级在内的 kubeadm 升级时,对服务器正在进行的请求将停滞, +因为要重新启动新的 etcd 静态 Pod。作为一种解决方法,可以在运行 `kubeadm upgrade apply` +命令之前主动停止 `kube-apiserver` 进程几秒钟。这样可以允许正在进行的请求完成处理并关闭现有连接, +并最大限度地减少 etcd 停机的后果。此操作可以在控制平面节点上按如下方式完成: + + +```shell +killall -s SIGTERM kube-apiserver # 触发 kube-apiserver 体面关闭 +sleep 20 # 等待一下,以完成进行中的请求 +kubeadm upgrade ... # 执行 kubeadm 升级命令 +``` + ```shell # 在列表中查找最新的 {{< skew currentVersion >}} 版本 # 它看起来应该是 {{< skew currentVersion >}}.x-*,其中 x 是最新的补丁版本 -apt update -apt-cache madison kubeadm +sudo apt update +sudo apt-cache madison kubeadm ``` {{% /tab %}} -{{% tab name="CentOS, RHEL or Fedora" %}} +{{% tab name="CentOS、RHEL 或 Fedora" %}} + ```shell # 在列表中查找最新的 {{< skew currentVersion >}} 版本 # 它看起来应该是 {{< skew currentVersion >}}.x-*,其中 x 是最新的补丁版本 -yum list --showduplicates kubeadm --disableexcludes=kubernetes +sudo yum list --showduplicates kubeadm --disableexcludes=kubernetes ``` {{% /tab %}} @@ -188,27 +236,35 @@ Pick a control plane node that you wish to upgrade first. It must have the `/etc 1. 升级 kubeadm: {{< tabs name="k8s_install_kubeadm_first_cp" >}} - {{% tab name="Ubuntu, Debian or HypriotOS" %}} + {{% tab name="Ubuntu、Debian 或 HypriotOS" %}} ```shell # 用最新的补丁版本号替换 {{< skew currentVersion >}}.x-* 中的 x - apt-mark unhold kubeadm && \ - apt-get update && apt-get install -y kubeadm='{{< skew currentVersion >}}.x-*' && \ - apt-mark hold kubeadm + sudo apt-mark unhold kubeadm && \ + sudo apt-get update && sudo apt-get install -y kubeadm='{{< skew currentVersion >}}.x-*' && \ + sudo apt-mark hold kubeadm ``` {{% /tab %}} - {{% tab name="CentOS, RHEL or Fedora" %}} + {{% tab name="CentOS、RHEL 或 Fedora" %}} ```shell # 用最新的补丁版本号替换 {{< skew currentVersion >}}.x-* 中的 x - yum install -y kubeadm-'{{< skew currentVersion >}}.x-*' --disableexcludes=kubernetes + sudo yum install -y kubeadm-'{{< skew currentVersion >}}.x-*' --disableexcludes=kubernetes ``` {{% /tab %}} @@ -229,7 +285,7 @@ Pick a control plane node that you wish to upgrade first. It must have the `/etc 3. 验证升级计划: ```shell - kubeadm upgrade plan + sudo kubeadm upgrade plan ``` ```shell # 用最新的补丁版本替换 {{< skew currentVersion >}}.x-* 中的 x - apt-mark unhold kubelet kubectl && \ - apt-get update && apt-get install -y kubelet='{{< skew currentVersion >}}.x-*' kubectl='{{< skew currentVersion >}}.x-*' && \ - apt-mark hold kubelet kubectl + sudo apt-mark unhold kubelet kubectl && \ + sudo apt-get update && sudo apt-get install -y kubelet='{{< skew currentVersion >}}.x-*' kubectl='{{< skew currentVersion >}}.x-*' && \ + sudo apt-mark hold kubelet kubectl ``` {{% /tab %}} - {{% tab name="CentOS, RHEL or Fedora" %}} + {{% tab name="CentOS、RHEL 或 Fedora" %}} ```shell # 用最新的补丁版本号替换 {{< skew currentVersion >}}.x-* 中的 x - yum install -y kubelet-'{{< skew currentVersion >}}.x-*' kubectl-'{{< skew currentVersion >}}.x-*' --disableexcludes=kubernetes + sudo yum install -y kubelet-'{{< skew currentVersion >}}.x-*' kubectl-'{{< skew currentVersion >}}.x-*' --disableexcludes=kubernetes ``` {{% /tab %}} @@ -510,9 +574,9 @@ This command is idempotent and eventually makes sure that the actual state is th 此命令是幂等的,并最终确保实际状态是你声明的期望状态。 -要从故障状态恢复,你还可以运行 `kubeadm upgrade apply --force` 而无需更改集群正在运行的版本。 +要从故障状态恢复,你还可以运行 `sudo kubeadm upgrade apply --force` 而无需更改集群正在运行的版本。 ```shell # 将 {{< skew currentVersion >}}.x-* 中的 x 替换为最新的补丁版本 -apt-mark unhold kubeadm && \ -apt-get update && apt-get install -y kubeadm='{{< skew currentVersion >}}.x-*' && \ -apt-mark hold kubeadm +sudo apt-mark unhold kubeadm && \ +sudo apt-get update && sudo apt-get install -y kubeadm='{{< skew currentVersion >}}.x-*' && \ +sudo apt-mark hold kubeadm ``` {{% /tab %}} {{% tab name="CentOS、RHEL 或 Fedora" %}} ```shell # 将 {{< skew currentVersion >}}.x-* 中的 x 替换为最新的补丁版本 -yum install -y kubeadm-'{{< skew currentVersion >}}.x-*' --disableexcludes=kubernetes +sudo yum install -y kubeadm-'{{< skew currentVersion >}}.x-*' --disableexcludes=kubernetes ``` {{% /tab %}} {{< /tabs >}} @@ -105,8 +113,11 @@ Prepare the node for maintenance by marking it unschedulable and evicting the wo 将节点标记为不可调度并驱逐所有负载,准备节点的维护: ```shell # 在控制平面节点上执行此命令 @@ -126,22 +137,30 @@ kubectl drain --ignore-daemonsets {{< tabs name="k8s_kubelet_and_kubectl" >}} {{% tab name="Ubuntu、Debian 或 HypriotOS" %}} ```shell # 将 {{< skew currentVersion >}}.x-* 中的 x 替换为最新的补丁版本 - apt-mark unhold kubelet kubectl && \ - apt-get update && apt-get install -y kubelet='{{< skew currentVersion >}}.x-*' kubectl='{{< skew currentVersion >}}.x-*' && \ - apt-mark hold kubelet kubectl + sudo apt-mark unhold kubelet kubectl && \ + sudo apt-get update && sudo apt-get install -y kubelet='{{< skew currentVersion >}}.x-*' kubectl='{{< skew currentVersion >}}.x-*' && \ + sudo apt-mark hold kubelet kubectl ``` {{% /tab %}} {{% tab name="CentOS、RHEL 或 Fedora" %}} ```shell # 将 {{< skew currentVersion >}}.x-* 中的 x 替换为最新的补丁版本 - yum install -y kubelet-'{{< skew currentVersion >}}.x-*' kubectl-'{{< skew currentVersion >}}.x-*' --disableexcludes=kubernetes + sudo yum install -y kubelet-'{{< skew currentVersion >}}.x-*' kubectl-'{{< skew currentVersion >}}.x-*' --disableexcludes=kubernetes ``` {{% /tab %}} {{< /tabs >}} @@ -166,8 +185,11 @@ Bring the node back online by marking it schedulable: 通过将节点标记为可调度,让节点重新上线: ```shell # 在控制平面节点上执行此命令 diff --git a/content/zh-cn/docs/tasks/administer-cluster/migrating-from-dockershim/migrate-dockershim-dockerd.md b/content/zh-cn/docs/tasks/administer-cluster/migrating-from-dockershim/migrate-dockershim-dockerd.md index ffab0a40c1b72..a7055088094d6 100644 --- a/content/zh-cn/docs/tasks/administer-cluster/migrating-from-dockershim/migrate-dockershim-dockerd.md +++ b/content/zh-cn/docs/tasks/administer-cluster/migrating-from-dockershim/migrate-dockershim-dockerd.md @@ -93,11 +93,11 @@ to `cri-dockerd`. ## {{% heading "prerequisites" %}} -* 安装了 [`cri-dockerd`](https://github.com/mirantis/cri-dockerd#build-and-install) +* 安装了 [`cri-dockerd`](https://mirantis.github.io/cri-dockerd/usage/install) 并且该服务已经在各节点上启动; * 一个[网络插件](/zh-cn/docs/concepts/extend-kubernetes/compute-storage-net/network-plugins/)。 diff --git a/content/zh-cn/docs/tasks/administer-cluster/network-policy-provider/weave-network-policy.md b/content/zh-cn/docs/tasks/administer-cluster/network-policy-provider/weave-network-policy.md index 283fe06305abc..58b9719fe17b3 100644 --- a/content/zh-cn/docs/tasks/administer-cluster/network-policy-provider/weave-network-policy.md +++ b/content/zh-cn/docs/tasks/administer-cluster/network-policy-provider/weave-network-policy.md @@ -35,20 +35,20 @@ You need to have a Kubernetes cluster. Follow the ## 安装 Weave Net 插件 {#install-the-weave-net-addon} -按照[通过插件集成 Kubernetes](https://www.weave.works/docs/net/latest/kubernetes/kube-addon/) +按照[通过插件集成 Kubernetes](https://github.com/weaveworks/weave/blob/master/site/kubernetes/kube-addon.md#-installation) 指南执行安装。 Kubernetes 的 Weave Net 插件带有 -[网络策略控制器](https://www.weave.works/docs/net/latest/kubernetes/kube-addon/#npc), +[网络策略控制器](https://github.com/weaveworks/weave/blob/master/site/kubernetes/kube-addon.md#network-policy), 可自动监控 Kubernetes 所有名字空间的 NetworkPolicy 注释, 配置 `iptables` 规则以允许或阻止策略指示的流量。 diff --git a/content/zh-cn/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes.md b/content/zh-cn/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes.md index 15301dd2a5e90..33adbeb81ef16 100644 --- a/content/zh-cn/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes.md +++ b/content/zh-cn/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes.md @@ -222,12 +222,12 @@ liveness-exec 1/1 Running 1 1m ## Define a liveness HTTP request Another kind of liveness probe uses an HTTP GET request. Here is the configuration -file for a Pod that runs a container based on the `registry.k8s.io/liveness` image. +file for a Pod that runs a container based on the `registry.k8s.io/e2e-test-images/agnhost` image. --> ## 定义一个存活态 HTTP 请求接口 {#define-a-liveness-HTTP-request} 另外一种类型的存活探测方式是使用 HTTP GET 请求。 -下面是一个 Pod 的配置文件,其中运行一个基于 `registry.k8s.io/liveness` 镜像的容器。 +下面是一个 Pod 的配置文件,其中运行一个基于 `registry.k8s.io/e2e-test-images/agnhost` 镜像的容器。 {{% code_sample file="pods/probe/http-liveness.yaml" %}} @@ -486,7 +486,6 @@ For example: ports: - name: liveness-port containerPort: 8080 - hostPort: 8080 livenessProbe: httpGet: @@ -520,7 +519,6 @@ So, the previous example would become: ports: - name: liveness-port containerPort: 8080 - hostPort: 8080 livenessProbe: httpGet: @@ -883,7 +881,6 @@ spec: ports: - name: liveness-port containerPort: 8080 - hostPort: 8080 livenessProbe: httpGet: diff --git a/content/zh-cn/docs/tasks/configure-pod-container/configure-pod-configmap.md b/content/zh-cn/docs/tasks/configure-pod-container/configure-pod-configmap.md index 13be9b0d17151..7b792c3a387cf 100644 --- a/content/zh-cn/docs/tasks/configure-pod-container/configure-pod-configmap.md +++ b/content/zh-cn/docs/tasks/configure-pod-container/configure-pod-configmap.md @@ -1511,6 +1511,9 @@ or move it into the trash can / deleted files location. * 浏览[使用 ConfigMap 配置 Redis](/zh-cn/docs/tutorials/configuration/configure-redis-using-configmap/) 真实示例。 +* 参照一个[通过 ConfigMap 更新配置](/zh-cn/docs/tutorials/configuration/updating-configuration-via-a-configmap/) + 的示例. diff --git a/content/zh-cn/docs/tasks/configure-pod-container/security-context.md b/content/zh-cn/docs/tasks/configure-pod-container/security-context.md index d5bfb0eed1583..371deecd27ad8 100644 --- a/content/zh-cn/docs/tasks/configure-pod-container/security-context.md +++ b/content/zh-cn/docs/tasks/configure-pod-container/security-context.md @@ -710,7 +710,27 @@ To assign SELinux labels, the SELinux security module must be loaded on the host --> ### 高效重打 SELinux 卷标签 -{{< feature-state for_k8s_version="v1.27" state="beta" >}} +{{< feature-state feature_gate_name="SELinuxMountReadWriteOncePod" >}} + +{{< note >}} + +Kubernetes v1.27 引入了此行为的早期受限形式,仅适用于使用 `ReadWriteOncePod` +访问模式的卷(和 PersistentVolumeClaim)。 + + +作为一项 Alpha 特性,你可以启用 `SELinuxMount` +[特性门控](/zh-cn/docs/reference/command-line-tools-reference/feature-gates/), +将性能改进扩展到其他类型的 PersistentVolumeClaim,如下文详细解释。 +{{< /note >}} + -* Pod 必须以 `accessModes: ["ReadWriteOncePod"]` 模式使用 PersistentVolumeClaim。 +* Pod 必须使用带有对应的 `accessModes` 和[特性门控](/zh-cn/docs/reference/command-line-tools-reference/feature-gates/) + 的 PersistentVolumeClaim。 + * 卷具有 `accessModes: ["ReadWriteOncePod"]`,并且 `SELinuxMountReadWriteOncePod` 特性门控已启用。 + * 或者卷可以使用任何其他访问模式,并且必须启用 `SELinuxMountReadWriteOncePod` 和 `SELinuxMount` 特性门控。 +## 管理对 `/proc` 文件系统的访问 {#proc-access} + +{{< feature-state feature_gate_name="ProcMountType" >}} + + +对于遵循 OCI 运行时规范的运行时,容器默认运行模式下,存在多个被屏蔽且只读的路径。 +这样做的结果是在容器的 mount 命名空间内会存在这些路径,并且这些路径的工作方式与容器是隔离主机时类似, +但容器进程无法写入它们。 +被屏蔽的和只读的路径列表如下: + + +- 被屏蔽的路径: + + - `/proc/asound` + - `/proc/acpi` + - `/proc/kcore` + - `/proc/keys` + - `/proc/latency_stats` + - `/proc/timer_list` + - `/proc/timer_stats` + - `/proc/sched_debug` + - `/proc/scsi` + - `/sys/firmware` + + +- 只读的路径: + + - `/proc/bus` + - `/proc/fs` + - `/proc/irq` + - `/proc/sys` + - `/proc/sysrq-trigger` + + +对于某些 Pod,你可能希望绕过默认的路径屏蔽。 +最常见的情况是你尝试在 Kubernetes 容器内(在 Pod 内)运行容器。 + + +`securityContext` 字段 `procMount` 允许用户请求容器的 `/proc` 为 `Unmasked`, +或者由容器进程以读写方式挂载。这一设置也适用于不在 `/proc` 内的 `/sys/firmware` 路径。 + +```yaml +... +securityContext: + procMount: Unmasked +``` + {{< note >}} - - -如果你的 Kubernetes 版本是 v1.25,请参阅此任务页面的 v1.25 版本: -[为 Pod 或 Container 配置安全上下文](https://v1-25.docs.kubernetes.io/docs/tasks/configure-pod-container/security-context/)(v1.25)。 -该文档中有一个重要的说明:kubelet 在重启后会丢失对卷标签的追踪记录。 -这个缺陷已经在 Kubernetes 1.26 中修复。 + +将 `procMount` 设置为 Unmasked 需要将 Pod 规约中的 `spec.hostUsers` +的值设置为 `false`。换句话说:希望使用未被屏蔽的 `/proc` 或 `/sys` +路径的容器也必须位于 [user 命名空间](/zh-cn/docs/concepts/workloads/pods/user-namespaces/)中。 +Kubernetes v1.12 到 v1.29 没有强制执行该要求。 {{< /note >}} * [PodSecurityContext](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#podsecuritycontext-v1-core) API 定义 * [SecurityContext](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#securitycontext-v1-core) API 定义 @@ -872,3 +968,5 @@ kubectl delete pod security-context-demo-4 * [AllowPrivilegeEscalation 的设计文档(英文)](https://github.com/kubernetes/design-proposals-archive/blob/main/auth/no-new-privs.md) * 关于在 Linux 系统中的安全机制的更多信息,可参阅 [Linux 内核安全性能力概述](https://www.linux.com/learn/overview-linux-kernel-security-features)(注意:部分信息已过时)。 +* 了解 Linux Pod 的 [user 命名空间](/zh-cn/docs/concepts/workloads/pods/user-namespaces/)。 +* [OCI 运行时规范中的被屏蔽的路径](https://github.com/opencontainers/runtime-spec/blob/f66aad47309/config-linux.md#masked-paths) diff --git a/content/zh-cn/docs/tasks/configure-pod-container/user-namespaces.md b/content/zh-cn/docs/tasks/configure-pod-container/user-namespaces.md index f82a33de3ccf4..15ffaf0b6f407 100644 --- a/content/zh-cn/docs/tasks/configure-pod-container/user-namespaces.md +++ b/content/zh-cn/docs/tasks/configure-pod-container/user-namespaces.md @@ -1,5 +1,5 @@ --- -title: 为 Pod 配置用户名字空间 +title: 为 Pod 配置 user 名字空间 reviewers: content_type: task weight: 210 @@ -15,14 +15,14 @@ min-kubernetes-server-version: v1.25 --> -{{< feature-state for_k8s_version="v1.25" state="alpha" >}} +{{< feature-state for_k8s_version="v1.25" state="beta" >}} -本页展示如何为无状态 Pod 配置用户名字空间。可以将容器内的用户与主机上的用户隔离开来。 +本页展示如何为无状态 Pod 配置 user 名字空间。可以将容器内的用户与主机上的用户隔离开来。 在容器中以 root 用户运行的进程可以以不同的(非 root)用户在宿主机上运行;换句话说, -进程在用户名字空间内部拥有执行操作的全部特权,但在用户名字空间外部并没有执行操作的特权。 +进程在 user 名字空间内部拥有执行操作的全部特权,但在 user 名字空间外部并没有执行操作的特权。 你可以使用这个特性来减少有害的容器对同一宿主机上其他容器的影响。 -[有些安全脆弱性问题][KEP-vulns]被评为 **HIGH** or **CRITICAL**,但当用户名字空间被启用时, -它们是无法被利用的。相信用户名字空间也能减轻一些未来的漏洞的影响。 +[有些安全脆弱性问题][KEP-vulns]被评为 **HIGH** 或 **CRITICAL**,但当 user 名字空间被启用时, +它们是无法被利用的。相信 user 名字空间也能减轻一些未来的漏洞影响。 -在不使用用户名字空间的情况下,对于以 root 用户运行的容器而言,发生容器逃逸时, +在不使用 user 名字空间的情况下,对于以 root 用户运行的容器而言,发生容器逃逸时, 容器将拥有在宿主机上的 root 特权。如果容器被赋予了某些权限,则这些权限在宿主机上同样有效。 -当使用用户名字空间时这些都不可能发生。 +当使用 user 名字空间时这些都不可能发生。 [KEP-vulns]: https://github.com/kubernetes/enhancements/tree/217d790720c5aef09b8bd4d6ca96284a0affe6c2/keps/sig-node/127-user-namespaces#motivation @@ -70,10 +70,10 @@ this is true when user namespaces are used. * You need to enable the `UserNamespacesSupport` [feature gate](/docs/reference/command-line-tools-reference/feature-gates/) --> -* 节点上的操作系统必须为 Linux +* 节点的操作系统必须为 Linux * 你需要在宿主机上执行命令 * 你需要能够通过 exec 操作进入 Pod -* 你需要启用 `UserNamespacesSupport` [特性门控](/zh-cn/docs/reference/command-line-tools-reference/feature-gates/)。 +* 你需要启用 `UserNamespacesSupport` [特性门控](/zh-cn/docs/reference/command-line-tools-reference/feature-gates/) {{< note >}} -在用户名字空间原来仅支持无状态的 Pod 时,启用用户名字空间的特性门控先前被命名为 `UserNamespacesStatelessPodsSupport`。 +在 user 名字空间原来仅支持无状态的 Pod 时,启用 user 名字空间的特性门控先前被命名为 `UserNamespacesStatelessPodsSupport`。 只有 Kubernetes v1.25 到 v1.27 才能识别 `UserNamespacesStatelessPodsSupport`。 {{}} @@ -92,39 +92,29 @@ for using user namespaces with Pods. --> 你所使用的集群**必须**包括至少一个符合 [要求](/zh-cn/docs/concepts/workloads/pods/user-namespaces/#before-you-begin) -的节点,以便为 Pod 配置用户名字空间。 +的节点,以便为 Pod 配置 user 名字空间。 -如果你有混合节点,并且只有部分节点支持为 Pod 配置用户名字空间, -你还需要确保配置了用户名字空间的 Pod +如果你有混合节点,并且只有部分节点支持为 Pod 配置 user 名字空间, +你还需要确保配置了 user 名字空间的 Pod 被[调度](/zh-cn/docs/concepts/scheduling-eviction/assign-pod-node/)到合适的节点。 -* CRI-O: v1.25 支持用户名字空间。 - - -请注意 **如果你的容器运行时环境不支持用户名字空间,那么 Pod 规约中的 `hostUsers` 字段将被静默忽略, -并且系统会在没有用户名字空间的环境中创建 Pod。** - -## 运行一个使用用户名字空间的 Pod {#create-pod} +## 运行一个使用 user 名字空间的 Pod {#create-pod} -为一个 Pod 启用用户名字空间需要设置 `.spec` 的 `hostUsers` 字段为 `false`. 例如: +为一个 Pod 启用 user 名字空间需要设置 `.spec` 的 `hostUsers` 字段为 `false`。例如: {{% code_sample file="pods/user-namespaces-stateless.yaml" %}} @@ -147,15 +137,39 @@ to `false`. For example: ``` -执行命令的输出类似于: +运行这个命令: -```none +```shell readlink /proc/self/ns/user +``` + + +输出类似于: + +```shell user:[4026531837] +``` + + +还运行: + +```shell cat /proc/self/uid_map -0 0 4294967295 +``` + + +输出类似于: + +```shell +0 833617920 65536 ``` -输出一定是不同的。这意味着主机和 Pod 使用不同的用户名字空间。当未启用用户名字空间时, -宿主机和 Pod 使用相同的用户名字空间。 +`readlink` 命令显示进程运行所在的用户命名空间。在主机上和容器内运行时应该有所不同。 + + +容器内 `uid_map` 文件的最后一个数字必须是 65536,在主机上它必须是更大的数字。 -如果你在用户名字空间中运行 kubelet,则需要将在 Pod 中运行命令的输出与在主机中运行的输出进行比较: +如果你在 user 名字空间中运行 kubelet,则需要将在 Pod 中运行命令的输出与在主机中运行的输出进行比较: - -```none -readlink /proc/$pid/ns/user -user:[4026534732] -``` -使用 kubelet 的进程号代替 `$pid` +使用 kubelet 的进程号代替 `$pid`。 diff --git a/content/zh-cn/docs/tasks/debug/debug-application/determine-reason-pod-failure.md b/content/zh-cn/docs/tasks/debug/debug-application/determine-reason-pod-failure.md index 1e6663d60551d..9699868bc5747 100644 --- a/content/zh-cn/docs/tasks/debug/debug-application/determine-reason-pod-failure.md +++ b/content/zh-cn/docs/tasks/debug/debug-application/determine-reason-pod-failure.md @@ -202,11 +202,18 @@ is empty and the container exited with an error. The log output is limited to * 参考 [Container](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#container-v1-core) 资源的 `terminationMessagePath` 字段。 +* 参考[镜像](/zh-cn/docs/concepts/containers/images/)中的 [ImagePullBackOff](/zh-cn/docs/concepts/containers/images/#imagepullbackoff)。 * 了解[检索日志](/zh-cn/docs/concepts/cluster-administration/logging/)。 * 了解 [Go 模板](https://pkg.go.dev/text/template)。 +* 了解 [Pod 状态](/zh-cn/docs/tasks/debug/debug-application/debug-init-containers/#understanding-pod-status)和 + [Pod 阶段](/zh-cn/docs/concepts/workloads/pods/pod-lifecycle/#pod-phase)。 +* 了解[容器状态](/zh-cn/docs/concepts/workloads/pods/pod-lifecycle/#container-states)。 \ No newline at end of file diff --git a/content/zh-cn/docs/tasks/debug/debug-cluster/resource-usage-monitoring.md b/content/zh-cn/docs/tasks/debug/debug-cluster/resource-usage-monitoring.md index 100ac34637542..55bf59e4c109b 100644 --- a/content/zh-cn/docs/tasks/debug/debug-cluster/resource-usage-monitoring.md +++ b/content/zh-cn/docs/tasks/debug/debug-cluster/resource-usage-monitoring.md @@ -150,7 +150,7 @@ solutions. The choice of monitoring platform depends heavily on your needs, budget, and technical resources. Kubernetes does not recommend any specific metrics pipeline; [many options](https://landscape.cncf.io/?group=projects-and-products&view-mode=card#observability-and-analysis--monitoring) are available. Your monitoring system should be capable of handling the [OpenMetrics](https://openmetrics.io/) metrics -transmission standard, and needs to chosen to best fit in to your overall design and deployment of +transmission standard and needs to be chosen to best fit into your overall design and deployment of your infrastructure platform. --> 将完整的指标管道集成到 Kubernetes 实现中超出了 Kubernetes diff --git a/content/zh-cn/docs/tasks/extend-kubernetes/socks5-proxy-access-api.md b/content/zh-cn/docs/tasks/extend-kubernetes/socks5-proxy-access-api.md index 9d25d1f87fb01..872b391e621cf 100644 --- a/content/zh-cn/docs/tasks/extend-kubernetes/socks5-proxy-access-api.md +++ b/content/zh-cn/docs/tasks/extend-kubernetes/socks5-proxy-access-api.md @@ -64,7 +64,7 @@ Figure 1 represents what you're going to achieve in this task. graph LR; subgraph local[Local client machine] - client([client])-- local
            traffic .-> local_ssh[Local SSH
            SOCKS5 proxy]; + client([client])-. local
            traffic .-> local_ssh[Local SSH
            SOCKS5 proxy]; end local_ssh[SSH
            SOCKS5
            proxy]-- SSH Tunnel --\>sshd @@ -86,9 +86,9 @@ graph LR; graph LR; subgraph local[本地客户端机器] - client([客户端])-- 本地
            流量.-> local_ssh[本地 SSH
            SOCKS5 代理]; + client([客户端])-. 本地
            流量.-> local_ssh[本地 SSH
            SOCKS5 代理]; end - ocal_ssh[SSH
            SOCKS5
            代理]-- SSH 隧道 -->sshd + local_ssh[SSH
            SOCKS5
            代理]-- SSH 隧道 -->sshd subgraph remote[远程服务器] sshd[SSH
            服务器]-- 本地流量 -->service1; diff --git a/content/zh-cn/docs/tasks/inject-data-application/define-command-argument-container.md b/content/zh-cn/docs/tasks/inject-data-application/define-command-argument-container.md index 6f667269863d1..6b0548356b832 100644 --- a/content/zh-cn/docs/tasks/inject-data-application/define-command-argument-container.md +++ b/content/zh-cn/docs/tasks/inject-data-application/define-command-argument-container.md @@ -52,7 +52,7 @@ with your new arguments. -在有些容器运行时中,`command` 字段对应 `entrypoint`,请参阅下面的[说明事项](#notes)。 +在有些容器运行时中,`command` 字段对应 `entrypoint`。 {{< /note >}} +环境变量名由字母、数字、下划线、点或连字符组成,但第一个字符不能是数字。 +如果启用了 `RelaxedEnvironmentVariableValidation` 特性门控, +则所有可打印的 ASCII 字符("=" 除外)都可以用于环境变量名。 + ```yaml apiVersion: v1 kind: Pod diff --git a/content/zh-cn/docs/tasks/job/coarse-parallel-processing-work-queue.md b/content/zh-cn/docs/tasks/job/coarse-parallel-processing-work-queue.md index 80a193750d5cd..0a5bfc79e39b0 100644 --- a/content/zh-cn/docs/tasks/job/coarse-parallel-processing-work-queue.md +++ b/content/zh-cn/docs/tasks/job/coarse-parallel-processing-work-queue.md @@ -92,14 +92,14 @@ Start RabbitMQ as follows: --> ```shell # 为 StatefulSet 创建一个 Service 来使用 -kubectl create -f https://kubernetes.io/examples/application/job/rabbitmq-service.yaml +kubectl create -f https://kubernetes.io/examples/application/job/rabbitmq/rabbitmq-service.yaml ``` ``` service "rabbitmq-service" created ``` ```shell -kubectl create -f https://kubernetes.io/examples/application/job/rabbitmq-statefulset.yaml +kubectl create -f https://kubernetes.io/examples/application/job/rabbitmq/rabbitmq-statefulset.yaml ``` ``` @@ -143,7 +143,7 @@ The next commands show what you need to run inside the interactive shell in that 下面是在该 Pod 的交互式 shell 中需要运行的命令: ```shell -apt-get update && apt-get install -y curl ca-certificates amqp-tools python dnsutils +apt-get update && apt-get install -y curl ca-certificates amqp-tools python3 dnsutils ``` +要启动一个 Redis 实例,你需要创建 Redis Pod 和 Redis 服务: + +```shell +kubectl apply -f https://k8s.io/examples/application/job/redis/redis-pod.yaml +kubectl apply -f https://k8s.io/examples/application/job/redis/redis-service.yaml +``` + 在这个例子中,每个 Pod 处理了队列中的多个项目,直到队列中没有项目时便退出。 @@ -286,8 +296,7 @@ the other pods to complete too. 这依赖于工作程序在完成工作时发出信号。 工作程序以成功退出的形式发出信号表示工作队列已经为空。 所以,只要有**任意**一个工作程序成功退出,控制器就知道工作已经完成了,所有的 Pod 将很快会退出。 -因此,我们需要将 Job 的完成计数(Completion Count)设置为 1。 -尽管如此,Job 控制器还是会等待其它 Pod 完成。 +因此,你不需要设置 Job 的完成次数。Job 控制器还是会等待其它 Pod 完成。 -## 集群内存在不同类型的 GPU {#clusters-containing-different-types-of-gpus} +## 管理配有不同类型 GPU 的集群 {#manage-clusters-with-different-types-of-gpus} 如果集群内部的不同节点上有不同类型的 NVIDIA GPU, 那么你可以使用[节点标签和节点选择器](/zh-cn/docs/tasks/configure-pod-container/assign-pods-nodes/)来将 @@ -116,6 +116,13 @@ Pod 调度到合适的节点上。 例如: + ```shell # 为你的节点加上它们所拥有的加速器类型的标签 kubectl label nodes node1 accelerator=example-gpu-x100 @@ -134,18 +141,92 @@ a different label key if you prefer. ## 自动节点标签 {#node-labeller} +作为管理员,你可以通过部署 Kubernetes +[Node Feature Discovery](https://github.com/kubernetes-sigs/node-feature-discovery) (NFD) +来自动发现所有启用 GPU 的节点并为其打标签。NFD 检测 Kubernetes 集群中每个节点上可用的硬件特性。 +通常,NFD 被配置为以节点标签广告这些特性,但 NFD 也可以添加扩展的资源、注解和节点污点。 +NFD 兼容所有[支持版本](/zh-cn/releases/version-skew-policy/#supported-versions)的 Kubernetes。 +NFD 默认会为检测到的特性创建[特性标签](https://kubernetes-sigs.github.io/node-feature-discovery/master/usage/features.html)。 +管理员可以利用 NFD 对具有某些具体特性的节点添加污点,以便只有请求这些特性的 Pod 可以被调度到这些节点上。 + + +你还需要一个 NFD 插件,将适当的标签添加到你的节点上; +这些标签可以是通用的,也可以是供应商特定的。你的 GPU 供应商可能会为 NFD 提供第三方插件; +更多细节请查阅他们的文档。 + + +{{< highlight yaml "linenos=false,hl_lines=7-18" >}} +apiVersion: v1 +kind: Pod +metadata: + name: example-vector-add +spec: + restartPolicy: OnFailure + # 你可以使用 Kubernetes 节点亲和性将此 Pod 调度到提供其容器所需的那种 GPU 的节点上 + affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: "gpu.gpu-vendor.example/installed-memory" + operator: Gt #(大于) + values: ["40535"] + - key: "feature.node.kubernetes.io/pci-10.present" # NFD 特性标签 + values: ["true"] #(可选)仅调度到具有 PCI 设备 10 的节点上 + containers: + - name: example-vector-add + image: "registry.example/example-vector-add:v42" + resources: + limits: + gpu-vendor.example/example-gpu: 1 # 请求 1 个 GPU +{{< /highlight >}} + + -如果你在使用 AMD GPU,你可以部署 -[Node Labeller](https://github.com/RadeonOpenCompute/k8s-device-plugin/tree/master/cmd/k8s-node-labeller), -它是一个 {{< glossary_tooltip text="控制器" term_id="controller" >}}, -会自动给节点打上 GPU 设备属性标签。 +#### GPU 供应商实现 -对于 NVIDIA GPU,[GPU feature discovery](https://github.com/NVIDIA/gpu-feature-discovery/blob/main/README.md) -提供了类似功能。 +- [Intel](https://intel.github.io/intel-device-plugins-for-kubernetes/cmd/gpu_plugin/README.html) +- [NVIDIA](https://github.com/NVIDIA/gpu-feature-discovery/#readme) diff --git a/content/zh-cn/docs/tasks/run-application/configure-pdb.md b/content/zh-cn/docs/tasks/run-application/configure-pdb.md index 385ef4a20e771..224c7e01fada9 100644 --- a/content/zh-cn/docs/tasks/run-application/configure-pdb.md +++ b/content/zh-cn/docs/tasks/run-application/configure-pdb.md @@ -429,7 +429,7 @@ These pods are tracked via `.status.currentHealthy` field in the PDB status. --> ## 不健康的 Pod 驱逐策略 {#unhealthy-pod-eviction-policy} -{{< feature-state for_k8s_version="v1.26" state="beta" >}} +{{< feature-state for_k8s_version="v1.27" state="beta" >}} {{< note >}} ### 容器资源指标 {#container-resource-metrics} -{{< feature-state for_k8s_version="v1.27" state="beta" >}} +{{< feature-state feature_gate_name="HPAContainerMetrics" >}} HorizontalPodAutoscaler API 也支持容器指标源,这时 HPA 可以跟踪记录一组 Pod 中各个容器的资源用量,进而触发扩缩目标对象的操作。 容器资源指标的支持使得你可以为特定 Pod 中最重要的容器配置规模扩缩阈值。 -例如,如果你有一个 Web 应用和一个执行日志操作的边车容器,你可以基于 Web +例如,如果你有一个 Web 应用和一个提供记录日志功能的边车容器,你可以基于 Web 应用的资源用量来执行扩缩,忽略边车容器的存在及其资源用量。 -如果你在集群中配置自动扩缩,你可能还需要考虑运行集群级别的自动扩缩器, -例如 [Cluster Autoscaler](https://github.com/kubernetes/autoscaler/tree/master/cluster-autoscaler)。 +如果你在集群中配置自动扩缩, +你可能还需要考虑使用[集群自动扩缩](/zh-cn/docs/concepts/cluster-administration/cluster-autoscaling/)来确保所运行的节点数目合适。 有关 HorizontalPodAutoscaler 的更多信息: diff --git a/content/zh-cn/docs/tasks/tools/included/verify-kubectl.md b/content/zh-cn/docs/tasks/tools/included/verify-kubectl.md index 3a806256f7ccb..2791c69cc5feb 100644 --- a/content/zh-cn/docs/tasks/tools/included/verify-kubectl.md +++ b/content/zh-cn/docs/tasks/tools/included/verify-kubectl.md @@ -57,12 +57,12 @@ The connection to the server was refused - did you specify th -例如,如果你想在自己的笔记本上(本地)运行 Kubernetes 集群,你需要先安装一个 Minikube +例如,如果你想在自己的笔记本上(本地)运行 Kubernetes 集群,你需要先安装一个 [Minikube](https://minikube.sigs.k8s.io/docs/start/) 这样的工具,然后再重新运行上面的命令。 如果命令 `kubectl cluster-info` 返回了 URL,但你还不能访问集群,那可以用以下命令来检查配置是否妥当: diff --git a/content/zh-cn/docs/tasks/tools/install-kubectl-linux.md b/content/zh-cn/docs/tasks/tools/install-kubectl-linux.md index aa696ae0fcb0e..5e843827e2f33 100644 --- a/content/zh-cn/docs/tasks/tools/install-kubectl-linux.md +++ b/content/zh-cn/docs/tasks/tools/install-kubectl-linux.md @@ -98,12 +98,12 @@ The following methods exist for installing kubectl on Linux: 下载 kubectl 校验和文件: - {{< tabs name="download_checksum_linux" >}} + {{< tabs name="download_checksum_linux" >}} {{< tab name="x86-64" codelang="bash" >}} - curl -LO "https://dl.k8s.io/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl.sha256" + curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl.sha256" {{< /tab >}} {{< tab name="ARM64" codelang="bash" >}} - curl -LO "https://dl.k8s.io/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/arm64/kubectl.sha256" + curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/arm64/kubectl.sha256" {{< /tab >}} {{< /tabs >}} @@ -225,6 +225,7 @@ Or use this for detailed view of version: # 如果 `/etc/apt/keyrings` 目录不存在,则应在 curl 命令之前创建它,请阅读下面的注释。 # sudo mkdir -p -m 755 /etc/apt/keyrings curl -fsSL https://pkgs.k8s.io/core:/stable:/{{< param "version" >}}/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg + sudo chmod 644 /etc/apt/keyrings/kubernetes-apt-keyring.gpg # allow unprivileged APT programs to read this keyring ``` {{< note >}} @@ -246,23 +247,22 @@ In releases older than Debian 12 and Ubuntu 22.04, folder `/etc/apt/keyrings` do ```shell # This overwrites any existing configuration in /etc/apt/sources.list.d/kubernetes.list echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/{{< param "version" >}}/deb/ /' | sudo tee /etc/apt/sources.list.d/kubernetes.list + sudo chmod 644 /etc/apt/sources.list.d/kubernetes.list # helps tools such as command-not-found to work correctly ``` --> ```shell # 这会覆盖 /etc/apt/sources.list.d/kubernetes.list 中的所有现存配置 echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/{{< param "version" >}}/deb/ /' | sudo tee /etc/apt/sources.list.d/kubernetes.list + sudo chmod 644 /etc/apt/sources.list.d/kubernetes.list # 有助于让诸如 command-not-found 等工具正常工作 ``` {{< note >}} - -要升级 kubectl 到别的次要版本,你需要先升级 `/etc/apt/sources.list.d/kubernetes.list` 中的版本, -再运行 `apt-get update` 和 `apt-get upgrade`。 -更详细的步骤可以在[更改 Kubernetes 软件包仓库](/zh-cn/docs/tasks/administer-cluster/kubeadm/change-package-repository/)中找到。 + +要将 kubectl 升级到别的次要版本,你需要先升级 `/etc/apt/sources.list.d/kubernetes.list` 中的版本, +再运行 `apt-get update` 和 `apt-get upgrade` 命令。 +更详细的步骤可以在[更改 Kubernetes 软件包存储库](/zh-cn/docs/tasks/administer-cluster/kubeadm/change-package-repository/)中找到。 {{< /note >}} +本教程假设你已经安装了 `minikube`。 +有关安装说明,请参阅 [minikube start](https://minikube.sigs.k8s.io/docs/start/) 的**步骤 1**。 +{{< note >}} + +仅执行**步骤 1:安装**中的说明,其余内容均包含在本页中。 +{{< /note >}} + + -本教程假设你已经安装了 `minikube`。 -有关安装说明,请参阅 [minikube start](https://minikube.sigs.k8s.io/docs/start/)。 - 你还需要安装 `kubectl`。 有关安装说明,请参阅[安装工具](/zh-cn/docs/tasks/tools/#kubectl)。 @@ -394,7 +402,7 @@ Minikube 有一组内置的{{< glossary_tooltip text="插件" term_id="addons" > ``` 2. 启用插件,例如 `metrics-server`: @@ -413,7 +421,7 @@ Minikube 有一组内置的{{< glossary_tooltip text="插件" term_id="addons" > ``` 3. 查看通过安装该插件所创建的 Pod 和 Service: @@ -449,9 +457,37 @@ Minikube 有一组内置的{{< glossary_tooltip text="插件" term_id="addons" > ``` -4. 禁用 `metrics-server`: +4. 检查 `metrics-server` 的输出: + + ```shell + kubectl top pods + ``` + + + 输出类似于: + + ``` + NAME CPU(cores) MEMORY(bytes) + hello-node-ccf4b9788-4jn97 1m 6Mi + ``` + + + 如果你看到以下消息,请等待并重试: + + ``` + error: Metrics API not available + ``` + + +5. 禁用 `metrics-server`: ```shell minikube addons disable metrics-server @@ -505,6 +541,15 @@ If you want to use minikube again to learn more about Kubernetes, you don't need --> 如果你还想使用 Minikube 进一步学习 Kubernetes,那就不需要删除 Minikube。 + +## 结论 + +本页介绍了启动和运行 minikube 集群的基本知识,现在部署应用的准备工作已经完成。 + ## {{% heading "whatsnext" %}}

            扩缩 是通过改变 Deployment 中的副本数量来实现的。

            -

            注意 如果你是在 上一节 之后尝试此操作, - 你可能需要从 创建一个集群 开始, - 因为 Service 可能已被删除。

            - + {{< note >}} +

            如果你是在 上一节 之后尝试此操作, + 那么你可能已经删除了公开 Deployment 的 Service。在这种情况下,请使用以下命令再次公开 Deployment:

            +

            kubectl expose deployment/kubernetes-bootcamp --type="NodePort" --port 8080

            + {{< /note >}}
            @@ -187,7 +188,7 @@

            扩容 Deployment

            我们应该有 1 个 Pod。如果没有,请再次运行该命令。结果显示:

            • NAME 列出 Deployment 在集群中的名称。
            • -
            • READY 显示当前/预期(CURRENT/DESIRED)副本数的比例/li> +
            • READY 显示当前/预期(CURRENT/DESIRED)副本数的比例。
            • UP-TO-DATE 显示为了达到预期状态,而被更新的副本的数量。
            • AVAILABLE 显示应用程序有多少个副本对你的用户可用。
            • AGE 显示应用程序的运行时间。
            • @@ -269,23 +270,20 @@

              负载均衡

              We hit a different Pod with every request. This demonstrates that the load-balancing is working.

              -->

              我们每个请求都命中了不同的 Pod,这证明负载均衡正在工作。

              - {{< note >}} + {{< note >}}

              如果你使用 Docker Desktop 作为容器驱动程序运行 minikube,则需要 minikube 隧道。 这是因为 Docker Desktop 内的容器与主机隔离。

              在单独的终端窗口中,执行:
              minikube service kubernetes-bootcamp --url

              -

              输出看起来像这样:

              http://127.0.0.1:51082
              ! Because you are using a Docker driver on darwin, the terminal needs to be open to run it.

              然后使用给定的 URL 访问应用程序: diff --git a/content/zh-cn/docs/tutorials/security/apparmor.md b/content/zh-cn/docs/tutorials/security/apparmor.md index 0c063d9154918..da286ba83b499 100644 --- a/content/zh-cn/docs/tutorials/security/apparmor.md +++ b/content/zh-cn/docs/tutorials/security/apparmor.md @@ -16,7 +16,7 @@ weight: 30 {{< feature-state for_k8s_version="v1.4" state="beta" >}} -AppArmor 是一个 Linux 内核安全模块, +[AppArmor](https://apparmor.net/) 是一个 Linux 内核安全模块, 它补充了基于标准 Linux 用户和组的权限,将程序限制在一组有限的资源中。 AppArmor 可以配置为任何应用程序减少潜在的攻击面,并且提供更加深入的防御。 它通过调整配置文件进行配置,以允许特定程序或容器所需的访问, @@ -33,13 +33,13 @@ AppArmor 可以配置为任何应用程序减少潜在的攻击面,并且提 模式(阻止访问不允许的资源)或 **投诉(complain)** 模式(仅报告冲突)下运行。 -AppArmor 可以通过限制允许容器执行的操作, +在 Kubernetes 中,AppArmor 可以通过限制允许容器执行的操作, 和/或通过系统日志提供更好的审计来帮助你运行更安全的部署。 但是,重要的是要记住 AppArmor 不是灵丹妙药, 只能做部分事情来防止应用程序代码中的漏洞。 @@ -48,7 +48,7 @@ AppArmor 可以通过限制允许容器执行的操作, ## {{% heading "objectives" %}} -确保: +AppArmor 是一个可选的内核模块和 Kubernetes 特性,因此请在继续之前验证你的节点是否支持它: -1. Kubernetes 版本至少是 v1.4 —— AppArmor 在 Kubernetes v1.4 版本中才添加了对 AppArmor 的支持。 - 早于 v1.4 版本的 Kubernetes 组件不知道新的 AppArmor - 注解并且将会 **默认忽略** 提供的任何 AppArmor 设置。 - 为了确保你的 Pod 能够得到预期的保护,必须验证节点的 Kubelet 版本: - - ```shell - kubectl get nodes -o=jsonpath=$'{range .items[*]}{@.metadata.name}: {@.status.nodeInfo.kubeletVersion}\n{end}' - ``` - - ``` - gke-test-default-pool-239f5d02-gyn2: v1.4.0 - gke-test-default-pool-239f5d02-x1kf: v1.4.0 - gke-test-default-pool-239f5d02-xwux: v1.4.0 - ``` - - -2. AppArmor 内核模块已启用 —— 要使 Linux 内核强制执行 AppArmor 配置文件, +1. AppArmor 内核模块已启用 —— 要使 Linux 内核强制执行 AppArmor 配置文件, 必须安装并且启动 AppArmor 内核模块。默认情况下,有几个发行版支持该模块, 如 Ubuntu 和 SUSE,还有许多发行版提供可选支持。要检查模块是否已启用,请检查 `/sys/module/apparmor/parameters/enabled` 文件: @@ -105,43 +85,30 @@ Make sure: ``` - 如果 Kubelet 包含 AppArmor 支持(>= v1.4), - 但是内核模块未启用,它将拒绝运行带有 AppArmor 选项的 Pod。 - - {{< note >}} - - Ubuntu 携带了许多没有合并到上游 Linux 内核中的 AppArmor 补丁, - 包括添加附加钩子和特性的补丁。Kubernetes 只在上游版本中测试过,不承诺支持其他特性。 - {{< /note >}} - - -3. 容器运行时支持 AppArmor —— 目前所有常见的 Kubernetes 支持的容器运行时都应该支持 AppArmor, - 像 {{< glossary_tooltip term_id="docker">}}、{{< glossary_tooltip term_id="cri-o" >}} - 或 {{< glossary_tooltip term_id="containerd" >}}。 + kubelet 会先验证主机上是否已启用 AppArmor,然后再接纳显式配置了 AppArmor 的 Pod。 + + +2. 容器运行时支持 AppArmor —— 所有常见的 Kubernetes 支持的容器运行时都应该支持 AppArmor, + 包括 {{< glossary_tooltip term_id="cri-o" >}} 和 {{< glossary_tooltip term_id="containerd" >}}。 请参考相应的运行时文档并验证集群是否满足使用 AppArmor 的要求。 -4. 配置文件已加载 —— 通过指定每个容器都应使用的 AppArmor 配置文件, - AppArmor 会被应用到 Pod 上。如果指定的任何配置文件尚未加载到内核, - Kubelet(>= v1.4)将拒绝 Pod。 +3. 配置文件已加载 —— 通过指定每个容器应使用的 AppArmor 配置文件, + AppArmor 会被应用到 Pod 上。如果所指定的配置文件未加载到内核, + kubelet 将拒绝 Pod。 通过检查 `/sys/kernel/security/apparmor/profiles` 文件, 可以查看节点加载了哪些配置文件。例如: @@ -163,26 +130,6 @@ Make sure: 有关在节点上加载配置文件的详细信息,请参见[使用配置文件设置节点](#setting-up-nodes-with-profiles)。 - -只要 Kubelet 版本包含 AppArmor 支持(>=v1.4), -如果不满足这些先决条件,Kubelet 将拒绝带有 AppArmor 选项的 Pod。 -你还可以通过检查节点就绪状况消息来验证节点上的 AppArmor 支持(尽管这可能会在以后的版本中删除): - -```shell -kubectl get nodes -o=jsonpath='{range .items[*]}{@.metadata.name}: {.status.conditions[?(@.reason=="KubeletReady")].message}{"\n"}{end}' -``` - -``` -gke-test-default-pool-239f5d02-gyn2: kubelet is posting ready status. AppArmor enabled -gke-test-default-pool-239f5d02-x1kf: kubelet is posting ready status. AppArmor enabled -gke-test-default-pool-239f5d02-xwux: kubelet is posting ready status. AppArmor enabled -``` - `` 的名称是配置文件所针对的容器的名称,`` 则设置要应用的配置文件。 `` 可以是以下取值之一: @@ -232,26 +179,24 @@ See the [API Reference](#api-reference) for the full details on the annotation a 有关注解和配置文件名称格式的详细信息,请参阅 [API 参考](#api-reference)。 -Kubernetes AppArmor 强制执行机制首先检查所有先决条件都已满足, -然后将所选的配置文件转发到容器运行时进行强制执行。 -如果未满足先决条件,Pod 将被拒绝,并且不会运行。 - - -要验证是否应用了配置文件,可以在容器创建事件中查找所列出的 AppArmor 安全选项: +要验证是否应用了配置文件, +你可以通过检查容器根进程的进程属性来检查该进程是否正在使用正确的配置文件运行: ```shell -kubectl get events | grep Created +kubectl exec -- cat /proc/1/attr/current ``` -``` -22s 22s 1 hello-apparmor Pod spec.containers{hello} Normal Created {kubelet e2e-test-stclair-node-pool-31nt} Created container with docker id 269a53b202d3; Security:[seccomp=unconfined apparmor=k8s-apparmor-example-deny-write] -``` + +输出应如下所示: + + ``` + k8s-apparmor-example-deny-write (enforce) + ``` -首先,我们需要将要使用的配置文件加载到节点上。配置文件拒绝所有文件写入: +首先,将要使用的配置文件加载到节点上,此配置文件拒绝所有文件写入: -```shell +``` #include profile k8s-apparmor-example-deny-write flags=(attach_disconnected) { @@ -295,20 +240,20 @@ profile k8s-apparmor-example-deny-write flags=(attach_disconnected) { ``` -由于我们不知道 Pod 将被调度到哪里,我们需要在所有节点上加载配置文件。 +由于不知道 Pod 将被调度到哪里,该配置文件需要加载到所有节点上。 在本例中,我们将使用 SSH 来安装概要文件, 但是在[使用配置文件设置节点](#setting-up-nodes-with-profiles)中讨论了其他方法。 + ```shell -NODES=( - # 你的节点的可通过 SSH 访问的域名 - gke-test-default-pool-239f5d02-gyn2.us-central1-a.my-k8s - gke-test-default-pool-239f5d02-x1kf.us-central1-a.my-k8s - gke-test-default-pool-239f5d02-xwux.us-central1-a.my-k8s) +# 此示例假设节点名称与主机名称匹配,并且可通过 SSH 访问。 +NODES=($(kubectl get nodes -o name)) for NODE in ${NODES[*]}; do ssh $NODE 'sudo apparmor_parser -q < @@ -325,52 +270,38 @@ done ``` -接下来,我们将运行一个带有拒绝写入配置文件的简单 “Hello AppArmor” Pod: +接下来,运行一个带有拒绝写入配置文件的简单 “Hello AppArmor” Pod: {{% code_sample file="pods/security/hello-apparmor.yaml" %}} ```shell -kubectl create -f ./hello-apparmor.yaml +kubectl create -f hello-apparmor.yaml ``` -如果我们查看 Pod 事件,我们可以看到 Pod 容器是用 AppArmor -配置文件 “k8s-apparmor-example-deny-write” 所创建的: +你可以通过检查其 `/proc/1/attr/current` 来验证容器是否确实使用该配置文件运行: ```shell -kubectl get events | grep hello-apparmor -``` - -``` -14s 14s 1 hello-apparmor Pod Normal Scheduled {default-scheduler } Successfully assigned hello-apparmor to gke-test-default-pool-239f5d02-gyn2 -14s 14s 1 hello-apparmor Pod spec.containers{hello} Normal Pulling {kubelet gke-test-default-pool-239f5d02-gyn2} pulling image "busybox" -13s 13s 1 hello-apparmor Pod spec.containers{hello} Normal Pulled {kubelet gke-test-default-pool-239f5d02-gyn2} Successfully pulled image "busybox" -13s 13s 1 hello-apparmor Pod spec.containers{hello} Normal Created {kubelet gke-test-default-pool-239f5d02-gyn2} Created container with docker id 06b6cd1c0989; Security:[seccomp=unconfined apparmor=k8s-apparmor-example-deny-write] -13s 13s 1 hello-apparmor Pod spec.containers{hello} Normal Started {kubelet gke-test-default-pool-239f5d02-gyn2} Started container with docker id 06b6cd1c0989 +kubectl exec hello-apparmor -- cat /proc/1/attr/current ``` -我们可以通过检查该配置文件的 proc attr 来验证容器是否实际使用该配置文件运行: - -```shell -kubectl exec hello-apparmor -- cat /proc/1/attr/current -``` +输出应该是: ``` k8s-apparmor-example-deny-write (enforce) ``` -最后,我们可以看到,如果我们尝试通过写入文件来违反配置文件会发生什么: +最后,你可以看到,如果你通过写入文件来违反配置文件会发生什么: ```shell kubectl exec hello-apparmor -- touch /tmp/test @@ -382,15 +313,12 @@ error: error executing remote command: command terminated with non-zero exit cod ``` -最后,让我们看看如果我们试图指定一个尚未加载的配置文件会发生什么: +最后,看看如果你尝试指定尚未加载的配置文件会发生什么: ```shell kubectl create -f /dev/stdin < +虽然 Pod 创建成功,但进一步检查会发现它陷入 pending 状态: + ```shell kubectl describe pod hello-apparmor-2 ``` @@ -413,59 +348,30 @@ kubectl describe pod hello-apparmor-2 ``` Name: hello-apparmor-2 Namespace: default -Node: gke-test-default-pool-239f5d02-x1kf/ +Node: gke-test-default-pool-239f5d02-x1kf/10.128.0.27 Start Time: Tue, 30 Aug 2016 17:58:56 -0700 Labels: Annotations: container.apparmor.security.beta.kubernetes.io/hello=localhost/k8s-apparmor-example-allow-write Status: Pending -Reason: AppArmor -Message: Pod Cannot enforce AppArmor: profile "k8s-apparmor-example-allow-write" is not loaded -IP: -Controllers: -Containers: - hello: - Container ID: - Image: busybox - Image ID: - Port: - Command: - sh - -c - echo 'Hello AppArmor!' && sleep 1h - State: Waiting - Reason: Blocked - Ready: False - Restart Count: 0 - Environment: - Mounts: - /var/run/secrets/kubernetes.io/serviceaccount from default-token-dnz7v (ro) -Conditions: - Type Status - Initialized True - Ready False - PodScheduled True -Volumes: - default-token-dnz7v: - Type: Secret (a volume populated by a Secret) - SecretName: default-token-dnz7v - Optional: false -QoS Class: BestEffort -Node-Selectors: -Tolerations: +... Events: - FirstSeen LastSeen Count From SubobjectPath Type Reason Message - --------- -------- ----- ---- ------------- -------- ------ ------- - 23s 23s 1 {default-scheduler } Normal Scheduled Successfully assigned hello-apparmor-2 to e2e-test-stclair-node-pool-t1f5 - 23s 23s 1 {kubelet e2e-test-stclair-node-pool-t1f5} Warning AppArmor Cannot enforce AppArmor: profile "k8s-apparmor-example-allow-write" is not loaded + Type Reason Age From Message + ---- ------ ---- ---- ------- + Normal Scheduled 10s default-scheduler Successfully assigned default/hello-apparmor to gke-test-default-pool-239f5d02-x1kf + Normal Pulled 8s kubelet Successfully pulled image "busybox:1.28" in 370.157088ms (370.172701ms including waiting) + Normal Pulling 7s (x2 over 9s) kubelet Pulling image "busybox:1.28" + Warning Failed 7s (x2 over 8s) kubelet Error: failed to get container spec opts: failed to generate apparmor spec opts: apparmor profile not found k8s-apparmor-example-allow-write + Normal Pulled 7s kubelet Successfully pulled image "busybox:1.28" in 90.980331ms (91.005869ms including waiting) ``` -注意 Pod 呈现 Pending 状态,并且显示一条有用的错误信息: -`Pod Cannot enforce AppArmor: profile "k8s-apparmor-example-allow-write" is not loaded`。 -还用相同的消息记录了一个事件。 +事件提供错误消息及其原因,具体措辞与运行时相关: + +``` + Warning Failed 7s (x2 over 8s) kubelet Error: failed to get container spec opts: failed to generate apparmor spec opts: apparmor profile not found +``` ### 使用配置文件设置节点 {#setting-up-nodes-with-profiles} Kubernetes 目前不提供任何本地机制来将 AppArmor 配置文件加载到节点上。 -有很多方法可以设置配置文件,例如: +可以通过自定义基础设施或工具(例如 [Kubernetes Security Profiles Operator](https://github.com/kubernetes-sigs/security-profiles-operator)) +加载配置文件。 -* 通过在每个节点上运行 Pod 的 - [DaemonSet](/zh-cn/docs/concepts/workloads/controllers/daemonset/) 来确保加载了正确的配置文件。 - 可以在[这里](https://git.k8s.io/kubernetes/test/images/apparmor-loader)找到实现示例。 -* 在节点初始化时,使用节点初始化脚本(例如 Salt、Ansible 等)或镜像。 -* 通过将配置文件复制到每个节点并通过 SSH 加载它们,如[示例](#example)。 - - 调度程序不知道哪些配置文件加载到哪个节点上,因此必须将全套配置文件加载到每个节点上。 另一种方法是为节点上的每个配置文件(或配置文件类)添加节点标签, 并使用[节点选择器](/zh-cn/docs/concepts/scheduling-eviction/assign-pod-node/)确保 Pod 在具有所需配置文件的节点上运行。 - -### 禁用 AppArmor {#disabling-apparmor} - - -如果你不希望 AppArmor 在集群上可用,可以通过命令行标志禁用它: - -``` ---feature-gates=AppArmor=false -``` - - -禁用时,任何包含 AppArmor 配置文件的 Pod 都将导致验证失败,且返回 “Forbidden” 错误。 - -{{}} - -即使此 Kubernetes 特性被禁用,运行时仍可能强制执行默认配置文件。 -当 AppArmor 升级为正式版 (GA) 时,禁用 AppArmor 功能的选项将被删除。 -{{}} - @@ -609,8 +472,7 @@ Specifying the profile a container will run with: [NAT](https://zh.wikipedia.org/wiki/%E7%BD%91%E7%BB%9C%E5%9C%B0%E5%9D%80%E8%BD%AC%E6%8D%A2) : 网络地址转换 @@ -89,6 +89,7 @@ IP of requests it receives through an HTTP header. You can create it as follows: ```shell kubectl create deployment source-ip-app --image=registry.k8s.io/echoserver:1.4 ``` + @@ -130,6 +131,7 @@ kube-proxy,则从集群内发送到 ClusterIP 的数据包永远不会进行 ```console kubectl get nodes ``` + @@ -341,6 +343,7 @@ Visually: * Pod 的回复被发送回给客户端 用图表示: + {{< figure src="/zh-cn/docs/images/tutor-service-nodePort-fig01.svg" alt="图 1:源 IP NodePort" class="diagram-large" caption="如图。使用 SNAT 的源 IP(Type=NodePort)" link="https://mermaid.live/edit#pako:eNqNkV9rwyAUxb-K3LysYEqS_WFYKAzat9GHdW9zDxKvi9RoMIZtlH732ZjSbE970cu5v3s86hFqJxEYfHjRNeT5ZcUtIbXRaMNN2hZ5vrYRqt52cSXV-4iMSuwkZiYtyX739EqWaahMQ-V1qPxDVLNOvkYrO6fj2dupWMR2iiT6foOKdEZoS5Q2hmVSStoH7w7IMqXUVOefWoaG3XVftHbGeZYVRbH6ZXJ47CeL2-qhxvt_ucTe1SUlpuMN6CX12XeGpLdJiaMMFFr0rdAyvvfxjHEIDbbIgcVSohKDCRy4PUV06KQIuJU6OA9MCdMjBTEEt_-2NbDgB7xAGy3i97VJPP0ABRmcqg" >}} @@ -385,6 +389,7 @@ Now, re-run the test: ```shell for node in $NODES; do curl --connect-timeout 1 -s $node:$NODEPORT | grep -i client_address; done ``` + @@ -447,6 +452,7 @@ You can test this by exposing the source-ip-app through a load balancer: ```shell kubectl expose deployment source-ip-app --name=loadbalancer --port=80 --target-port=8080 --type=LoadBalancer ``` + @@ -550,6 +556,7 @@ serving the health check at `/healthz`. You can test this: ```shell kubectl get pod -o wide -l app=source-ip-app ``` + diff --git a/content/zh-cn/docs/tutorials/stateful-application/basic-stateful-set.md b/content/zh-cn/docs/tutorials/stateful-application/basic-stateful-set.md index 259162e678fae..346ac3d884e9e 100644 --- a/content/zh-cn/docs/tutorials/stateful-application/basic-stateful-set.md +++ b/content/zh-cn/docs/tutorials/stateful-application/basic-stateful-set.md @@ -894,21 +894,21 @@ Pod 时,挂载到 StatefulSet 的 Pod 的 PersistentVolume 卷不会被删除 ## 更新 StatefulSet {#updating-statefulsets} -从 Kubernetes 1.7 版本开始,StatefulSet 控制器支持自动更新。 +StatefulSet 控制器支持自动更新。 更新策略由 StatefulSet API 对象的 `spec.updateStrategy` 字段决定。这个特性能够用来更新一个 -StatefulSet 中 Pod 的的容器镜像、资源请求和限制、标签和注解。 +StatefulSet 中 Pod 的容器镜像、资源请求和限制、标签和注解。 -`RollingUpdate` 更新策略是 StatefulSet 默认策略。 +有两个有效的更新策略:`RollingUpdate`(默认)和 `OnDelete`。 -对 `web` StatefulSet 应用 Patch 操作来应用 `RollingUpdate` 更新策略: +你可以通过指定 `.spec.updateStrategy.rollingUpdate.partition` 将使用 `RollingUpdate` +策略的 StatefulSet 的更新拆分为多个**分区** 。你将在本教程中稍后练习此操作。 -```shell -kubectl patch statefulset web -p '{"spec":{"updateStrategy":{"type":"RollingUpdate"}}}' -``` -``` -statefulset.apps/web patched -``` +首先,尝试一个简单的滚动更新。 StatefulSet 里的 Pod 采用和序号相反的顺序更新。在更新下一个 Pod 前,StatefulSet 控制器终止每个 Pod 并等待它们变成 Running 和 Ready。 请注意,虽然在顺序后继者变成 Running 和 Ready 之前 StatefulSet 控制器不会更新下一个 -Pod,但它仍然会重建任何在更新过程中发生故障的 Pod,使用的是它们当前的版本。 +Pod,但它仍然会重建任何在更新过程中发生故障的 Pod,使用的是它们现有的版本。 +你可以通过指定 `.spec.updateStrategy.rollingUpdate.partition` 将使用 `RollingUpdate` 策略的 +StatefulSet 的更新拆分为多个**分区** 。 + + -你可以使用 `RollingUpdate` 更新策略的 `partition` 参数来分段更新一个 StatefulSet。 -分段的更新将会使 StatefulSet 中的其余所有 Pod 保持当前版本的同时允许改变 -StatefulSet 的 `.spec.template`。 +有关更多上下文,你可以阅读 StatefulSet +概念页面中的[分区滚动更新](/zh-cn/docs/concepts/workloads/controllers/statefulset/#partitions)。 -对 `web` StatefulSet 执行 Patch 操作为 `updateStrategy` 字段添加一个分区: +你可以使用 `.spec.updateStrategy.rollingUpdate` 中的 `partition` 字段对 StatefulSet 执行更新的分段操作。 +对于此更新,你将保持 StatefulSet 中现有 Pod 不变,同时更改 StatefulSet 的 Pod 模板。 +然后,你(或通过教程之外的一些外部自动化工具)可以触发准备好的更新。 + +对 `web` StatefulSet 执行 Patch 操作,为 `updateStrategy` 字段添加一个分区: + + ```shell +# "partition" 的值决定更改适用于哪些序号 +# 确保使用比 StatefulSet 的最后一个序号更大的数字 kubectl patch statefulset web -p '{"spec":{"updateStrategy":{"type":"RollingUpdate","rollingUpdate":{"partition":3}}}}' ``` ``` @@ -1082,9 +1105,10 @@ statefulset.apps/web patched ``` -再次 Patch StatefulSet 来改变容器镜像: +再次 Patch StatefulSet 来改变此 StatefulSet 使用的容器镜像: ```shell kubectl patch statefulset web --type='json' -p='[{"op": "replace", "path": "/spec/template/spec/containers/0/image", "value":"registry.k8s.io/nginx-slim:0.7"}]' @@ -1106,9 +1130,9 @@ pod "web-2" deleted ``` -等待 Pod 变成 Running 和 Ready。 +等待替代的 Pod 变成 Running 和 Ready。 -请注意,虽然更新策略是 `RollingUpdate`,StatefulSet 还是会使用原始的容器恢复 Pod。 +请注意,虽然更新策略是 `RollingUpdate`,StatefulSet 还是会使用原始的容器镜像恢复 Pod。 这是因为 Pod 的序号比 `updateStrategy` 指定的 `partition` 更小。 +现在,你将尝试对分段的变更进行[金丝雀发布](https://glossary.cncf.io/canary-deployment/)。 + + -你可以通过减少[上文](#staging-an-update)指定的 -`partition` 来进行金丝雀发布,以此来测试你的程序的改动。 +你可以通过减少[上文](#staging-an-update)指定的 `partition` 来进行金丝雀发布,以测试修改后的模板。 ```shell -# “partition” 的值应与 StatefulSet 现有的最高序数相匹配 +# “partition” 的值应与 StatefulSet 现有的最高序号相匹配 kubectl patch statefulset web -p '{"spec":{"updateStrategy":{"type":"RollingUpdate","rollingUpdate":{"partition":2}}}}' ``` ``` @@ -1176,9 +1205,13 @@ statefulset.apps/web patched ``` -等待 `web-2` 变成 Running 和 Ready。 +控制平面会触发 `web-2` 的替换(先优雅地 **删除** 现有 Pod,然后在删除完成后创建一个新的 Pod)。 +等待新的 `web-2` Pod 变成 Running 和 Ready。 +通过将 `.spec.template.updateStrategy.type` 设置为 `OnDelete`,你可以为 StatefulSet 选择此更新策略。 + +对 `web` StatefulSet 执行 patch 操作,以使用 `OnDelete` 更新策略: + +```shell +kubectl patch statefulset web -p '{"spec":{"updateStrategy":{"type":"OnDelete"}}}' +``` +``` +statefulset.apps/web patched +``` + + -`OnDelete` 更新策略实现了传统(1.7 之前)行为,它也是默认的更新策略。 当你选择这个更新策略并修改 StatefulSet 的 `.spec.template` 字段时,StatefulSet 控制器将不会自动更新 Pod。 +你需要自己手动管理发布,或使用单独的自动化工具来管理发布。 -StatefulSet 同时支持级联和非级联删除。使用非级联方式删除 StatefulSet 时,StatefulSet -的 Pod 不会被删除。使用级联删除时,StatefulSet 和它的 Pod 都会被删除。 +StatefulSet 同时支持**非级联**和**级联**删除。使用非级联方式**删除** StatefulSet 时,StatefulSet +的 Pod 不会被删除。使用级联**删除**时,StatefulSet 和它的 Pod 都会被删除。 + + +阅读[在集群中使用级联删除](/zh-cn/docs/tasks/administer-cluster/use-cascading-deletion/), +以了解通用的级联删除。 使用 [`kubectl delete`](/docs/reference/generated/kubectl/kubectl-commands/#delete) 删除 StatefulSet。请确保提供了 `--cascade=orphan` 参数给命令。这个参数告诉 -Kubernetes 只删除 StatefulSet 而不要删除它的任何 Pod。 +Kubernetes 只删除 StatefulSet 而**不要**删除它的任何 Pod。 ```shell kubectl delete statefulset web --cascade=orphan @@ -1556,10 +1612,10 @@ StatefulSet 会接收这个 Pod。由于你重新创建的 StatefulSet 的 `repl 一旦 `web-0` 被重新创建并且 `web-1` 被认为已经处于 Running 和 Ready 状态时,`web-2` 将会被终止。 -让我们再看看被 Pod 的 Web 服务器加载的 `index.html` 的内容: +现在再看看被 Pod 的 Web 服务器加载的 `index.html` 的内容: ```shell for i in 0 1; do kubectl exec -i -t "web-$i" -- curl http://localhost/; done @@ -1654,10 +1710,10 @@ the Pod's successor to be completely terminated. {{< note >}} -尽管级联删除会删除 StatefulSet 及其 Pod,但级联不会删除与 StatefulSet +尽管级联删除会删除 StatefulSet 及其 Pod,但级联**不会**删除与 StatefulSet 关联的 Headless Service。你必须手动删除 `nginx` Service。 {{< /note >}} @@ -1740,13 +1796,19 @@ statefulset "web" deleted 对于某些分布式系统来说,StatefulSet 的顺序性保证是不必要和/或者不应该的。 -这些系统仅仅要求唯一性和身份标志。为了解决这个问题,在 Kubernetes 1.7 -中我们针对 StatefulSet API 对象引入了 `.spec.podManagementPolicy`。 -此选项仅影响扩缩操作的行为。更新不受影响。 +这些系统仅仅要求唯一性和身份标志。 + + +你可以指定 Pod 管理策略以避免这个严格的顺序; +你可以选择 [`OrderedReady`](/zh-cn/docs/concepts/workloads/controllers/statefulset/#orderedready-pod-management)(默认)或 +[`Parallel`](/zh-cn/docs/concepts/workloads/controllers/statefulset/#parallel-pod-management)。 -StatefulSet 控制器同时启动了 `web-0` 和 `web-1`。 +StatefulSet 控制器几乎同时启动了 `web-0` 和 `web-1`。 -| 月度补丁发布 | Cherry Pick 截止日期 | 目标日期 | -|--------------|---------------------|-------------| -| 2023 年 12 月 | 2023-12-15 | 2023-12-19 | -| 2024 年 1 月 | 2024-01-12 | 2024-01-17 | -| 2024 年 2 月 | 2024-02-09 | 2024-02-14 | -| 2024 年 3 月 | 2024-03-08 | 2024-03-13 | +{{< upcoming-releases >}} + {{- if ne $feed nil -}} {{ time.Format "Mon, 02 Jan 2006 15:04:05 -0700" $feed._kubernetes_io.updated_at | safeHTML }} + {{- end -}} {{ with .OutputFormats.Get "RSS" -}} {{ printf "" .Permalink .MediaType | safeHTML }} {{ end -}} diff --git a/layouts/blog/baseof.html b/layouts/blog/baseof.html index bfb8792e4bd51..dd29c120160f7 100644 --- a/layouts/blog/baseof.html +++ b/layouts/blog/baseof.html @@ -13,12 +13,12 @@ {{ partial "announcement.html" . }} {{ block "hero" . }}

              -

              + {{ if .IsSection }}

              {{ else }}

              {{ end }} {{ $sectionHeading := .Site.GetPage "section" .Section }} {{ with $sectionHeading }} {{ .Title }} {{ end }} -

              + {{ if .IsSection }}{{ else }}{{ end }}
              {{ block "hero-more" . }}{{ end }} {{ end }} diff --git a/layouts/blog/list.html b/layouts/blog/list.html index b012ebe234caa..37d152ef5e391 100644 --- a/layouts/blog/list.html +++ b/layouts/blog/list.html @@ -21,7 +21,12 @@

              {{ T "post_posts_in" }} {{ .Key }}

            • {{ .LinkTitle }}
              -

              {{ .Date.Format ($.Param "time_format_blog") }} {{ T "ui_in"}} {{ .CurrentSection.LinkTitle }}

              +

              + + {{ with .Params.author }}{{ T "post_byline_by" }} {{ . | markdownify }} |{{ end}} + {{ .Date.Format ($.Param "time_format_blog") }} {{ T "ui_in"}} {{ .CurrentSection.LinkTitle }} + +

              {{ partial "featured-image.html" (dict "p" . "w" 250 "h" 125 "class" "float-left mr-3 pt-1 d-none d-md-block") }}

              {{ .Plain | safeHTML | truncate 250 }}

              {{ T "ui_read_more"}}

              diff --git a/layouts/case-studies/single.html b/layouts/case-studies/single.html index b5bf43b7b8ba7..ab0451dc1b707 100644 --- a/layouts/case-studies/single.html +++ b/layouts/case-studies/single.html @@ -6,7 +6,7 @@
            • {{ range $remainingPages }} {{ if .IsPage }} diff --git a/layouts/partials/docs/api-reference-links.html b/layouts/partials/docs/api-reference-links.html new file mode 100644 index 0000000000000..7181c975d3a69 --- /dev/null +++ b/layouts/partials/docs/api-reference-links.html @@ -0,0 +1,60 @@ + +{{- $apiReferenceMetaLinks := slice -}} +{{- $apiReferenceText := T "api_reference_title" -}} + + +{{ $.Store.Delete "apiReferenceMetaLinks" }} +{{ $.Store.Delete "pageApiReferenceLinksMap" }} + + +{{- $ignoreCondition := (printf "%T" .Page.Params.api_metadata | eq "[]interface {}") -}} + + +{{- if and .Page.Params.api_metadata $ignoreCondition (not .Page.Params.simple_list) -}} + + + {{- range $metadata := .Page.Params.api_metadata -}} + + {{- $apiVersion := $metadata.apiVersion -}} + {{- $kind := $metadata.kind -}} + {{- $version := $apiVersion -}} + {{- $linkText := $metadata.override_link_text | default $kind -}} + + + {{- $apiRefBaseDir := "docs/reference/kubernetes-api/" -}} + {{- $apiRefSections := site.GetPage "section" $apiRefBaseDir -}} + + + {{- range $apiRefSection := $apiRefSections.Sections -}} + {{- $apiRefDir := $apiRefSection.RelPermalink -}} + {{- $fragmentApiRefDir := split $apiRefDir "/docs" -}} + {{- $apiRefDir := printf "/docs%s" (index ($fragmentApiRefDir) 1) -}} + {{- $apiReferenceFiles := site.GetPage $apiRefDir -}} + + + {{- range $apiRefFile := $apiReferenceFiles.RegularPages -}} + {{- $apiRefFileDirPath:= printf "/%s" $apiRefFile.File.Dir -}} + + {{- if and (ne $apiRefFile.Section "") (in $apiRefFileDirPath $apiRefDir) -}} + + {{- with $apiRefFile.Params.api_metadata -}} + {{- if and (eq .kind $kind) (eq .apiVersion $version) -}} + + {{- $link := printf "%s %s" $apiRefFile.Permalink $linkText $apiReferenceText -}} + {{- $apiReferenceMetaLinks = $apiReferenceMetaLinks | append $link -}} + + {{- $.Store.SetInMap "pageApiReferenceLinksMap" $kind $link -}} + {{- end -}} + {{- end -}} + {{- end -}} + {{- end -}} + {{- end -}} + {{- end -}} +{{- end -}} + +{{- if gt (len $apiReferenceMetaLinks) 0 -}} + + {{ $.Store.Add "apiReferenceMetaLinks" $apiReferenceMetaLinks }} +{{- end -}} + diff --git a/layouts/partials/footer.html b/layouts/partials/footer.html index 3b4d17833c096..cb499ab4d2288 100644 --- a/layouts/partials/footer.html +++ b/layouts/partials/footer.html @@ -30,7 +30,7 @@
              {{ with .Site.Params.copyright_linux }}Copyright © {{ now.Year }} {{ T "main_copyright_notice" | safeHTML }}{{ end }}
              - ICP license: 京ICP备17074266号-3 + {{ T "china_icp_license" }} 京ICP备17074266号-3 {{ with .Site.Params.privacy_policy }}{{ T "footer_privacy_policy" }}{{ end }} {{ if not .Site.Params.ui.footer_about_disable }} {{ with .Site.GetPage "about" }}

              {{ .Title }}

              {{ end }} diff --git a/layouts/partials/head.html b/layouts/partials/head.html index addf0a098fe06..236ffac759f11 100644 --- a/layouts/partials/head.html +++ b/layouts/partials/head.html @@ -75,14 +75,18 @@ {{ if .HasShortcode "mermaid" }} - - + + {{ end }} + + + + {{- if or (.HasShortcode "table") (.HasShortcode "feature-gate-table") -}} {{- end -}} @@ -91,6 +95,10 @@ {{- end -}} +{{- if .HasShortcode "cncf-landscape" -}} + +{{- end -}} + {{- if eq (lower .Params.cid) "community" -}} {{- if eq .Params.community_styles_migrated true -}} diff --git a/layouts/partials/navbar.html b/layouts/partials/navbar.html index 06306fc489f06..48edf64be91be 100644 --- a/layouts/partials/navbar.html +++ b/layouts/partials/navbar.html @@ -24,6 +24,9 @@ {{ partial "navbar-lang-selector.html" . }} {{ end }} +
            diff --git a/layouts/partials/page-meta-links.html b/layouts/partials/page-meta-links.html index 9eb59ba8da66f..f11801ea4f671 100644 --- a/layouts/partials/page-meta-links.html +++ b/layouts/partials/page-meta-links.html @@ -23,6 +23,16 @@ {{ $newPageQS := querify "value" $newPageStub.Content "filename" "change-me.md" | safeURL }} {{ $newPageURL := printf "%s/new/%s?%s" $gh_repo $gh_repo_path $newPageQS }} + + {{- $apiReferenceMetaLinks := $.Store.Get "apiReferenceMetaLinks" -}} + {{- if $apiReferenceMetaLinks -}} + + {{- range $apiReferenceMetaLinks -}} + {{- $apiRefPageLink := . -}} + {{- $apiRefPageLink | replaceRE "]*)>" " " | safeHTML -}} + {{- end -}} + {{- end -}} + {{ if not (.Param "auto_generated") }} {{ T "post_edit_this" }} {{- if .HasShortcode "thirdparty-content" -}} diff --git a/layouts/partials/scripts.html b/layouts/partials/scripts.html index 304fd2241e445..1c8dce0d65df9 100644 --- a/layouts/partials/scripts.html +++ b/layouts/partials/scripts.html @@ -2,7 +2,6 @@ - {{ $jsBase := resources.Get "js/base.js" }} {{ $jsAnchor := resources.Get "js/anchor.js" }} diff --git a/layouts/shortcodes/cncf-landscape.html b/layouts/shortcodes/cncf-landscape.html index 5324ea1ee3f0c..10d9fe31dcadc 100644 --- a/layouts/shortcodes/cncf-landscape.html +++ b/layouts/shortcodes/cncf-landscape.html @@ -57,7 +57,6 @@ {{- end -}}
            - {{ if ( .Get "category" ) }} + + + + + diff --git a/static/images/announcements/kccnc-eu-2024-white.svg b/static/images/announcements/kccnc-eu-2024-white.svg new file mode 100644 index 0000000000000..8a675dd37b3dc --- /dev/null +++ b/static/images/announcements/kccnc-eu-2024-white.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/static/images/blog/2024-04-17-kubernetes-1.30-release/k8s-1.30.png b/static/images/blog/2024-04-17-kubernetes-1.30-release/k8s-1.30.png new file mode 100644 index 0000000000000..2e55c8a9b7c1d Binary files /dev/null and b/static/images/blog/2024-04-17-kubernetes-1.30-release/k8s-1.30.png differ diff --git a/static/images/blog/2024-04-22-userns-beta/userns-ids.png b/static/images/blog/2024-04-22-userns-beta/userns-ids.png new file mode 100644 index 0000000000000..1d7adc3e0c0cb Binary files /dev/null and b/static/images/blog/2024-04-22-userns-beta/userns-ids.png differ diff --git a/static/images/docs/kubernetes-cluster-architecture.svg b/static/images/docs/kubernetes-cluster-architecture.svg index 841c8cf277f72..ecc24448e59db 100644 --- a/static/images/docs/kubernetes-cluster-architecture.svg +++ b/static/images/docs/kubernetes-cluster-architecture.svg @@ -1,4 +1,3 @@ - -
            Node 1
            Node 1
            Node 2
            Node 2
            kube-scheduler
            kube-scheduler
            kube-controller-manager
            kube-controller-manager
            CLOUD PROVIDER API
            CLOUD PROVIDER API
            CRI
            CRI
            CRI
            CRI
            CONTROL PLANE
            CONTROL PLANE
            CLUSTER
            CLUSTER
            etcd
            etcd
            kube-api-server
            kube-api-server
            scheduler
            scheduler
            Controller Manager
            Controller Manager
            cloud-controller-manager
            cloud-controller-manager
            kubelet
            kubelet
            kube-proxy
            kube-proxy
            kubelet
            kubelet
            kube-proxy
            kube-proxy
            pod
            pod
            pod
            pod
            pod
            pod
            pod
            pod
            Text is not SVG - cannot display
            \ No newline at end of file +
            Node 1
            Node 1
            Node 2
            Node 2
            kube-scheduler
            kube-scheduler
            kube-controller-manager
            kube-controller-manager
            CLOUD PROVIDER API
            CLOUD PROVIDER API
            CRI
            CRI
            CRI
            CRI
            CONTROL PLANE
            CONTROL PLANE
            CLUSTER
            CLUSTER
            etcd
            etcd
            kube-api-server
            kube-api-server
            scheduler
            scheduler
            Controller Manager
            Controller Manager
            cloud-control-manager
            cloud-control-manager
            kubelet
            kubelet
            kube-proxy
            kube-proxy
            kubelet
            kubelet
            kube-proxy
            kube-proxy
            pod
            pod
            pod
            pod
            pod
            pod
            pod
            pod
            diff --git a/static/js/OWNERS b/static/js/OWNERS new file mode 100644 index 0000000000000..6fd3b00896ed4 --- /dev/null +++ b/static/js/OWNERS @@ -0,0 +1,9 @@ +# Label certain changes as web development + +approvers: +- sig-docs-website-owners # Defined in OWNERS_ALIASES + +filters: + "\\.js": + labels: + - area/web-development diff --git a/static/js/dismiss_banner.js b/static/js/dismiss_banner.js new file mode 100644 index 0000000000000..3d80069beb0ec --- /dev/null +++ b/static/js/dismiss_banner.js @@ -0,0 +1,41 @@ +$(document).ready(function() { + function setCookie(name, value, days) { + let expires = ""; + let date = new Date(); // Create a new Date object + let dateToSecond = 24 * 60 * 60 * 1000; + + if (days) { + date.setTime(date.getTime() + days * dateToSecond); // Modify the existing Date object + expires = "; expires=" + date.toUTCString(); + } + + document.cookie = name + "=" + value + expires + "; path=/"; + } + + function getCookie(name) { + let matches = document.cookie.match(new RegExp( + "(?:^|; )" + name.replace(/([\.$?*|{}\(\)\[\]\\\/\+^])/g, '\\$1') + "=([^;]*)" + )); + return matches ? "true" : undefined; + } + + /* Check the presence of a cookie */ + let announcement = document.querySelector("#announcement"); + let token = `announcement_ack_${announcement.getAttribute('data-announcement-name').replace(/\s/g, '_')}`; // Generate the unique token for announcement + let acknowledged = getCookie(token); + if (acknowledged === "true") { + announcement.remove(); // Remove the announcement if the cookie is set + } + else { + announcement.classList.add('display-announcement') // Display the announcement if the cookie is not set + } + + /* Driver code to set the cookie */ + let button = document.querySelector('#banner-dismiss'); + button.removeAttribute('style'); + button.addEventListener('click', function() { + setCookie(token, "true", + button.getAttribute('data-ttl')); // Set a cookie with time to live parameter + announcement.remove(); + }); +}); diff --git a/static/js/mermaid-10.6.1.min.js b/static/js/mermaid-10.6.1.min.js new file mode 100644 index 0000000000000..7b35a8de822f5 --- /dev/null +++ b/static/js/mermaid-10.6.1.min.js @@ -0,0 +1,1646 @@ +(function(xA,b0){typeof exports=="object"&&typeof module<"u"?module.exports=b0():typeof define=="function"&&define.amd?define(b0):(xA=typeof globalThis<"u"?globalThis:xA||self,xA.mermaid=b0())})(this,function(){"use strict";function xA(i){for(var a=[],f=1;f=It?nt:""+Array(It+1-Bt.length).join(Ot)+nt},mt={s:bt,z:function(nt){var It=-nt.utcOffset(),Ot=Math.abs(It),Bt=Math.floor(Ot/60),Et=Ot%60;return(It<=0?"+":"-")+bt(Bt,2,"0")+":"+bt(Et,2,"0")},m:function nt(It,Ot){if(It.date()1)return nt(Ct[0])}else{var xt=It.name;ft[xt]=It,Et=xt}return!Bt&&Et&&(yt=Et),Et||!Bt&&yt},X=function(nt,It){if(ut(nt))return nt.clone();var Ot=typeof It=="object"?It:{};return Ot.date=nt,Ot.args=arguments,new U(Ot)},pt=mt;pt.l=vt,pt.i=ut,pt.w=function(nt,It){return X(nt,{locale:It.$L,utc:It.$u,x:It.$x,$offset:It.$offset})};var U=function(){function nt(Ot){this.$L=vt(Ot.locale,null,!0),this.parse(Ot)}var It=nt.prototype;return It.parse=function(Ot){this.$d=function(Bt){var Et=Bt.date,Z=Bt.utc;if(Et===null)return new Date(NaN);if(pt.u(Et))return new Date;if(Et instanceof Date)return new Date(Et);if(typeof Et=="string"&&!/Z$/i.test(Et)){var Ct=Et.match(et);if(Ct){var xt=Ct[2]-1||0,Ht=(Ct[7]||"0").substring(0,3);return Z?new Date(Date.UTC(Ct[1],xt,Ct[3]||1,Ct[4]||0,Ct[5]||0,Ct[6]||0,Ht)):new Date(Ct[1],xt,Ct[3]||1,Ct[4]||0,Ct[5]||0,Ct[6]||0,Ht)}}return new Date(Et)}(Ot),this.$x=Ot.x||{},this.init()},It.init=function(){var Ot=this.$d;this.$y=Ot.getFullYear(),this.$M=Ot.getMonth(),this.$D=Ot.getDate(),this.$W=Ot.getDay(),this.$H=Ot.getHours(),this.$m=Ot.getMinutes(),this.$s=Ot.getSeconds(),this.$ms=Ot.getMilliseconds()},It.$utils=function(){return pt},It.isValid=function(){return this.$d.toString()!==W},It.isSame=function(Ot,Bt){var Et=X(Ot);return this.startOf(Bt)<=Et&&Et<=this.endOf(Bt)},It.isAfter=function(Ot,Bt){return X(Ot){},debug:(...i)=>{},info:(...i)=>{},warn:(...i)=>{},error:(...i)=>{},fatal:(...i)=>{}},Xft=function(i="fatal"){let a=p5.fatal;typeof i=="string"?(i=i.toLowerCase(),i in p5&&(a=p5[i])):typeof i=="number"&&(a=i),Ut.trace=()=>{},Ut.debug=()=>{},Ut.info=()=>{},Ut.warn=()=>{},Ut.error=()=>{},Ut.fatal=()=>{},a<=p5.fatal&&(Ut.fatal=console.error?console.error.bind(console,Q2("FATAL"),"color: orange"):console.log.bind(console,"\x1B[35m",Q2("FATAL"))),a<=p5.error&&(Ut.error=console.error?console.error.bind(console,Q2("ERROR"),"color: orange"):console.log.bind(console,"\x1B[31m",Q2("ERROR"))),a<=p5.warn&&(Ut.warn=console.warn?console.warn.bind(console,Q2("WARN"),"color: orange"):console.log.bind(console,"\x1B[33m",Q2("WARN"))),a<=p5.info&&(Ut.info=console.info?console.info.bind(console,Q2("INFO"),"color: lightblue"):console.log.bind(console,"\x1B[34m",Q2("INFO"))),a<=p5.debug&&(Ut.debug=console.debug?console.debug.bind(console,Q2("DEBUG"),"color: lightgreen"):console.log.bind(console,"\x1B[32m",Q2("DEBUG"))),a<=p5.trace&&(Ut.trace=console.debug?console.debug.bind(console,Q2("TRACE"),"color: lightgreen"):console.log.bind(console,"\x1B[32m",Q2("TRACE")))},Q2=i=>`%c${w0().format("ss.SSS")} : ${i} : `;var Qft={};Object.defineProperty(Qft,"__esModule",{value:!0});var ik=Qft.sanitizeUrl=void 0,cxe=/^([^\w]*)(javascript|data|vbscript)/im,uxe=/&#(\w+)(^\w|;)?/g,lxe=/&(newline|tab);/gi,hxe=/[\u0000-\u001F\u007F-\u009F\u2000-\u200D\uFEFF]/gim,fxe=/^.+(:|:)/gim,dxe=[".","/"];function gxe(i){return dxe.indexOf(i[0])>-1}function pxe(i){return i.replace(uxe,function(a,f){return String.fromCharCode(f)})}function bxe(i){var a=pxe(i||"").replace(lxe,"").replace(hxe,"").trim();if(!a)return"about:blank";if(gxe(a))return a;var f=a.match(fxe);if(!f)return a;var p=f[0];return cxe.test(p)?"about:blank":a}ik=Qft.sanitizeUrl=bxe;function EU(i,a){return i==null||a==null?NaN:ia?1:i>=a?0:NaN}function wxe(i,a){return i==null||a==null?NaN:ai?1:a>=i?0:NaN}function Zft(i){let a,f,p;i.length!==2?(a=EU,f=(E,_)=>EU(i(E),_),p=(E,_)=>i(E)-_):(a=i===EU||i===wxe?i:vxe,f=i,p=i);function w(E,_,A=0,I=E.length){if(A>>1;f(E[B],_)<0?A=B+1:I=B}while(A>>1;f(E[B],_)<=0?A=B+1:I=B}while(AA&&p(E[B-1],_)>-p(E[B],_)?B-1:B}return{left:w,center:b,right:m}}function vxe(){return 0}function mxe(i){return i===null?NaN:+i}const yxe=Zft(EU).right;Zft(mxe).center;const xxe=yxe;class $Lt extends Map{constructor(a,f=Txe){if(super(),Object.defineProperties(this,{_intern:{value:new Map},_key:{value:f}}),a!=null)for(const[p,w]of a)this.set(p,w)}get(a){return super.get(zLt(this,a))}has(a){return super.has(zLt(this,a))}set(a,f){return super.set(kxe(this,a),f)}delete(a){return super.delete(Exe(this,a))}}function zLt({_intern:i,_key:a},f){const p=a(f);return i.has(p)?i.get(p):f}function kxe({_intern:i,_key:a},f){const p=a(f);return i.has(p)?i.get(p):(i.set(p,f),f)}function Exe({_intern:i,_key:a},f){const p=a(f);return i.has(p)&&(f=i.get(p),i.delete(p)),f}function Txe(i){return i!==null&&typeof i=="object"?i.valueOf():i}const Cxe=Math.sqrt(50),_xe=Math.sqrt(10),Sxe=Math.sqrt(2);function TU(i,a,f){const p=(a-i)/Math.max(0,f),w=Math.floor(Math.log10(p)),m=p/Math.pow(10,w),b=m>=Cxe?10:m>=_xe?5:m>=Sxe?2:1;let E,_,A;return w<0?(A=Math.pow(10,-w)/b,E=Math.round(i*A),_=Math.round(a*A),E/Aa&&--_,A=-A):(A=Math.pow(10,w)*b,E=Math.round(i/A),_=Math.round(a/A),E*Aa&&--_),_0))return[];if(i===a)return[i];const p=a=w))return[];const E=m-w+1,_=new Array(E);if(p)if(b<0)for(let A=0;A=p)&&(f=p);else{let p=-1;for(let w of i)(w=a(w,++p,i))!=null&&(f=w)&&(f=w)}return f}function Mxe(i,a){let f;if(a===void 0)for(const p of i)p!=null&&(f>p||f===void 0&&p>=p)&&(f=p);else{let p=-1;for(let w of i)(w=a(w,++p,i))!=null&&(f>w||f===void 0&&w>=w)&&(f=w)}return f}function Dxe(i,a,f){i=+i,a=+a,f=(w=arguments.length)<2?(a=i,i=0,1):w<3?1:+f;for(var p=-1,w=Math.max(0,Math.ceil((a-i)/f))|0,m=new Array(w);++p+i(a)}function Nxe(i,a){return a=Math.max(0,i.bandwidth()-a*2)/2,i.round()&&(a=Math.round(a)),f=>+i(f)+a}function Bxe(){return!this.__axis}function HLt(i,a){var f=[],p=null,w=null,m=6,b=6,E=3,_=typeof window<"u"&&window.devicePixelRatio>1?0:.5,A=i===CU||i===_U?-1:1,I=i===_U||i===e1t?"x":"y",B=i===CU||i===n1t?Oxe:Pxe;function N(R){var z=p??(a.ticks?a.ticks.apply(a,f):a.domain()),W=w??(a.tickFormat?a.tickFormat.apply(a,f):Ixe),et=Math.max(m,0)+E,st=a.range(),at=+st[0]+_,bt=+st[st.length-1]+_,mt=(a.bandwidth?Nxe:Fxe)(a.copy(),_),yt=R.selection?R.selection():R,ft=yt.selectAll(".domain").data([null]),ut=yt.selectAll(".tick").data(z,a).order(),vt=ut.exit(),X=ut.enter().append("g").attr("class","tick"),pt=ut.select("line"),U=ut.select("text");ft=ft.merge(ft.enter().insert("path",".tick").attr("class","domain").attr("stroke","currentColor")),ut=ut.merge(X),pt=pt.merge(X.append("line").attr("stroke","currentColor").attr(I+"2",A*m)),U=U.merge(X.append("text").attr("fill","currentColor").attr(I,A*et).attr("dy",i===CU?"0em":i===n1t?"0.71em":"0.32em")),R!==yt&&(ft=ft.transition(R),ut=ut.transition(R),pt=pt.transition(R),U=U.transition(R),vt=vt.transition(R).attr("opacity",qLt).attr("transform",function(Tt){return isFinite(Tt=mt(Tt))?B(Tt+_):this.getAttribute("transform")}),X.attr("opacity",qLt).attr("transform",function(Tt){var nt=this.parentNode.__axis;return B((nt&&isFinite(nt=nt(Tt))?nt:mt(Tt))+_)})),vt.remove(),ft.attr("d",i===_U||i===e1t?b?"M"+A*b+","+at+"H"+_+"V"+bt+"H"+A*b:"M"+_+","+at+"V"+bt:b?"M"+at+","+A*b+"V"+_+"H"+bt+"V"+A*b:"M"+at+","+_+"H"+bt),ut.attr("opacity",1).attr("transform",function(Tt){return B(mt(Tt)+_)}),pt.attr(I+"2",A*m),U.attr(I,A*et).text(W),yt.filter(Bxe).attr("fill","none").attr("font-size",10).attr("font-family","sans-serif").attr("text-anchor",i===e1t?"start":i===_U?"end":"middle"),yt.each(function(){this.__axis=mt})}return N.scale=function(R){return arguments.length?(a=R,N):a},N.ticks=function(){return f=Array.from(arguments),N},N.tickArguments=function(R){return arguments.length?(f=R==null?[]:Array.from(R),N):f.slice()},N.tickValues=function(R){return arguments.length?(p=R==null?null:Array.from(R),N):p&&p.slice()},N.tickFormat=function(R){return arguments.length?(w=R,N):w},N.tickSize=function(R){return arguments.length?(m=b=+R,N):m},N.tickSizeInner=function(R){return arguments.length?(m=+R,N):m},N.tickSizeOuter=function(R){return arguments.length?(b=+R,N):b},N.tickPadding=function(R){return arguments.length?(E=+R,N):E},N.offset=function(R){return arguments.length?(_=+R,N):_},N}function Rxe(i){return HLt(CU,i)}function jxe(i){return HLt(n1t,i)}var $xe={value:()=>{}};function VLt(){for(var i=0,a=arguments.length,f={},p;i=0&&(p=f.slice(w+1),f=f.slice(0,w)),f&&!a.hasOwnProperty(f))throw new Error("unknown type: "+f);return{type:f,name:p}})}SU.prototype=VLt.prototype={constructor:SU,on:function(i,a){var f=this._,p=zxe(i+"",f),w,m=-1,b=p.length;if(arguments.length<2){for(;++m0)for(var f=new Array(w),p=0,w,m;p=0&&(a=i.slice(0,f))!=="xmlns"&&(i=i.slice(f+1)),ULt.hasOwnProperty(a)?{space:ULt[a],local:i}:i}function Hxe(i){return function(){var a=this.ownerDocument,f=this.namespaceURI;return f===r1t&&a.documentElement.namespaceURI===r1t?a.createElement(i):a.createElementNS(f,i)}}function Vxe(i){return function(){return this.ownerDocument.createElementNS(i.space,i.local)}}function WLt(i){var a=AU(i);return(a.local?Vxe:Hxe)(a)}function Gxe(){}function i1t(i){return i==null?Gxe:function(){return this.querySelector(i)}}function Uxe(i){typeof i!="function"&&(i=i1t(i));for(var a=this._groups,f=a.length,p=new Array(f),w=0;w=bt&&(bt=at+1);!(yt=et[bt])&&++bt=0;)(b=p[w])&&(m&&b.compareDocumentPosition(m)^4&&m.parentNode.insertBefore(b,m),m=b);return this}function b6e(i){i||(i=w6e);function a(B,N){return B&&N?i(B.__data__,N.__data__):!B-!N}for(var f=this._groups,p=f.length,w=new Array(p),m=0;ma?1:i>=a?0:NaN}function v6e(){var i=arguments[0];return arguments[0]=this,i.apply(null,arguments),this}function m6e(){return Array.from(this)}function y6e(){for(var i=this._groups,a=0,f=i.length;a1?this.each((a==null?D6e:typeof a=="function"?O6e:I6e)(i,a,f??"")):kA(this.node(),i)}function kA(i,a){return i.style.getPropertyValue(a)||JLt(i).getComputedStyle(i,null).getPropertyValue(a)}function F6e(i){return function(){delete this[i]}}function N6e(i,a){return function(){this[i]=a}}function B6e(i,a){return function(){var f=a.apply(this,arguments);f==null?delete this[i]:this[i]=f}}function R6e(i,a){return arguments.length>1?this.each((a==null?F6e:typeof a=="function"?B6e:N6e)(i,a)):this.node()[i]}function tMt(i){return i.trim().split(/^|\s+/)}function s1t(i){return i.classList||new eMt(i)}function eMt(i){this._node=i,this._names=tMt(i.getAttribute("class")||"")}eMt.prototype={add:function(i){var a=this._names.indexOf(i);a<0&&(this._names.push(i),this._node.setAttribute("class",this._names.join(" ")))},remove:function(i){var a=this._names.indexOf(i);a>=0&&(this._names.splice(a,1),this._node.setAttribute("class",this._names.join(" ")))},contains:function(i){return this._names.indexOf(i)>=0}};function nMt(i,a){for(var f=s1t(i),p=-1,w=a.length;++p=0&&(f=a.slice(p+1),a=a.slice(0,p)),{type:a,name:f}})}function fke(i){return function(){var a=this.__on;if(a){for(var f=0,p=-1,w=a.length,m;f>8&15|a>>4&240,a>>4&15|a&240,(a&15)<<4|a&15,1):f===8?IU(a>>24&255,a>>16&255,a>>8&255,(a&255)/255):f===4?IU(a>>12&15|a>>8&240,a>>8&15|a>>4&240,a>>4&15|a&240,((a&15)<<4|a&15)/255):null):(a=xke.exec(i))?new v0(a[1],a[2],a[3],1):(a=kke.exec(i))?new v0(a[1]*255/100,a[2]*255/100,a[3]*255/100,1):(a=Eke.exec(i))?IU(a[1],a[2],a[3],a[4]):(a=Tke.exec(i))?IU(a[1]*255/100,a[2]*255/100,a[3]*255/100,a[4]):(a=Cke.exec(i))?dMt(a[1],a[2]/100,a[3]/100,1):(a=_ke.exec(i))?dMt(a[1],a[2]/100,a[3]/100,a[4]):aMt.hasOwnProperty(i)?uMt(aMt[i]):i==="transparent"?new v0(NaN,NaN,NaN,0):null}function uMt(i){return new v0(i>>16&255,i>>8&255,i&255,1)}function IU(i,a,f,p){return p<=0&&(i=a=f=NaN),new v0(i,a,f,p)}function lMt(i){return i instanceof U7||(i=W7(i)),i?(i=i.rgb(),new v0(i.r,i.g,i.b,i.opacity)):new v0}function o1t(i,a,f,p){return arguments.length===1?lMt(i):new v0(i,a,f,p??1)}function v0(i,a,f,p){this.r=+i,this.g=+a,this.b=+f,this.opacity=+p}_P(v0,o1t,MU(U7,{brighter(i){return i=i==null?DU:Math.pow(DU,i),new v0(this.r*i,this.g*i,this.b*i,this.opacity)},darker(i){return i=i==null?SP:Math.pow(SP,i),new v0(this.r*i,this.g*i,this.b*i,this.opacity)},rgb(){return this},clamp(){return new v0(Y7(this.r),Y7(this.g),Y7(this.b),OU(this.opacity))},displayable(){return-.5<=this.r&&this.r<255.5&&-.5<=this.g&&this.g<255.5&&-.5<=this.b&&this.b<255.5&&0<=this.opacity&&this.opacity<=1},hex:hMt,formatHex:hMt,formatHex8:Lke,formatRgb:fMt,toString:fMt}));function hMt(){return`#${K7(this.r)}${K7(this.g)}${K7(this.b)}`}function Lke(){return`#${K7(this.r)}${K7(this.g)}${K7(this.b)}${K7((isNaN(this.opacity)?1:this.opacity)*255)}`}function fMt(){const i=OU(this.opacity);return`${i===1?"rgb(":"rgba("}${Y7(this.r)}, ${Y7(this.g)}, ${Y7(this.b)}${i===1?")":`, ${i})`}`}function OU(i){return isNaN(i)?1:Math.max(0,Math.min(1,i))}function Y7(i){return Math.max(0,Math.min(255,Math.round(i)||0))}function K7(i){return i=Y7(i),(i<16?"0":"")+i.toString(16)}function dMt(i,a,f,p){return p<=0?i=a=f=NaN:f<=0||f>=1?i=a=NaN:a<=0&&(i=NaN),new Xv(i,a,f,p)}function gMt(i){if(i instanceof Xv)return new Xv(i.h,i.s,i.l,i.opacity);if(i instanceof U7||(i=W7(i)),!i)return new Xv;if(i instanceof Xv)return i;i=i.rgb();var a=i.r/255,f=i.g/255,p=i.b/255,w=Math.min(a,f,p),m=Math.max(a,f,p),b=NaN,E=m-w,_=(m+w)/2;return E?(a===m?b=(f-p)/E+(f0&&_<1?0:b,new Xv(b,E,_,i.opacity)}function Mke(i,a,f,p){return arguments.length===1?gMt(i):new Xv(i,a,f,p??1)}function Xv(i,a,f,p){this.h=+i,this.s=+a,this.l=+f,this.opacity=+p}_P(Xv,Mke,MU(U7,{brighter(i){return i=i==null?DU:Math.pow(DU,i),new Xv(this.h,this.s,this.l*i,this.opacity)},darker(i){return i=i==null?SP:Math.pow(SP,i),new Xv(this.h,this.s,this.l*i,this.opacity)},rgb(){var i=this.h%360+(this.h<0)*360,a=isNaN(i)||isNaN(this.s)?0:this.s,f=this.l,p=f+(f<.5?f:1-f)*a,w=2*f-p;return new v0(c1t(i>=240?i-240:i+120,w,p),c1t(i,w,p),c1t(i<120?i+240:i-120,w,p),this.opacity)},clamp(){return new Xv(pMt(this.h),PU(this.s),PU(this.l),OU(this.opacity))},displayable(){return(0<=this.s&&this.s<=1||isNaN(this.s))&&0<=this.l&&this.l<=1&&0<=this.opacity&&this.opacity<=1},formatHsl(){const i=OU(this.opacity);return`${i===1?"hsl(":"hsla("}${pMt(this.h)}, ${PU(this.s)*100}%, ${PU(this.l)*100}%${i===1?")":`, ${i})`}`}}));function pMt(i){return i=(i||0)%360,i<0?i+360:i}function PU(i){return Math.max(0,Math.min(1,i||0))}function c1t(i,a,f){return(i<60?a+(f-a)*i/60:i<180?f:i<240?a+(f-a)*(240-i)/60:a)*255}const Dke=Math.PI/180,Ike=180/Math.PI,FU=18,bMt=.96422,wMt=1,vMt=.82521,mMt=4/29,TA=6/29,yMt=3*TA*TA,Oke=TA*TA*TA;function xMt(i){if(i instanceof u3)return new u3(i.l,i.a,i.b,i.opacity);if(i instanceof b5)return kMt(i);i instanceof v0||(i=lMt(i));var a=f1t(i.r),f=f1t(i.g),p=f1t(i.b),w=u1t((.2225045*a+.7168786*f+.0606169*p)/wMt),m,b;return a===f&&f===p?m=b=w:(m=u1t((.4360747*a+.3850649*f+.1430804*p)/bMt),b=u1t((.0139322*a+.0971045*f+.7141733*p)/vMt)),new u3(116*w-16,500*(m-w),200*(w-b),i.opacity)}function Pke(i,a,f,p){return arguments.length===1?xMt(i):new u3(i,a,f,p??1)}function u3(i,a,f,p){this.l=+i,this.a=+a,this.b=+f,this.opacity=+p}_P(u3,Pke,MU(U7,{brighter(i){return new u3(this.l+FU*(i??1),this.a,this.b,this.opacity)},darker(i){return new u3(this.l-FU*(i??1),this.a,this.b,this.opacity)},rgb(){var i=(this.l+16)/116,a=isNaN(this.a)?i:i+this.a/500,f=isNaN(this.b)?i:i-this.b/200;return a=bMt*l1t(a),i=wMt*l1t(i),f=vMt*l1t(f),new v0(h1t(3.1338561*a-1.6168667*i-.4906146*f),h1t(-.9787684*a+1.9161415*i+.033454*f),h1t(.0719453*a-.2289914*i+1.4052427*f),this.opacity)}}));function u1t(i){return i>Oke?Math.pow(i,1/3):i/yMt+mMt}function l1t(i){return i>TA?i*i*i:yMt*(i-mMt)}function h1t(i){return 255*(i<=.0031308?12.92*i:1.055*Math.pow(i,1/2.4)-.055)}function f1t(i){return(i/=255)<=.04045?i/12.92:Math.pow((i+.055)/1.055,2.4)}function Fke(i){if(i instanceof b5)return new b5(i.h,i.c,i.l,i.opacity);if(i instanceof u3||(i=xMt(i)),i.a===0&&i.b===0)return new b5(NaN,0()=>i;function EMt(i,a){return function(f){return i+f*a}}function Nke(i,a,f){return i=Math.pow(i,f),a=Math.pow(a,f)-i,f=1/f,function(p){return Math.pow(i+p*a,f)}}function Bke(i,a){var f=a-i;return f?EMt(i,f>180||f<-180?f-360*Math.round(f/360):f):NU(isNaN(i)?a:i)}function Rke(i){return(i=+i)==1?LP:function(a,f){return f-a?Nke(a,f,i):NU(isNaN(a)?f:a)}}function LP(i,a){var f=a-i;return f?EMt(i,f):NU(isNaN(i)?a:i)}const BU=function i(a){var f=Rke(a);function p(w,m){var b=f((w=o1t(w)).r,(m=o1t(m)).r),E=f(w.g,m.g),_=f(w.b,m.b),A=LP(w.opacity,m.opacity);return function(I){return w.r=b(I),w.g=E(I),w.b=_(I),w.opacity=A(I),w+""}}return p.gamma=i,p}(1);function jke(i,a){a||(a=[]);var f=i?Math.min(a.length,i.length):0,p=a.slice(),w;return function(m){for(w=0;wf&&(m=a.slice(f,m),E[b]?E[b]+=m:E[++b]=m),(p=p[0])===(w=w[0])?E[b]?E[b]+=w:E[++b]=w:(E[++b]=null,_.push({i:b,x:Qv(p,w)})),f=p1t.lastIndex;return f180?I+=360:I-A>180&&(A+=360),N.push({i:B.push(w(B)+"rotate(",null,p)-2,x:Qv(A,I)})):I&&B.push(w(B)+"rotate("+I+p)}function E(A,I,B,N){A!==I?N.push({i:B.push(w(B)+"skewX(",null,p)-2,x:Qv(A,I)}):I&&B.push(w(B)+"skewX("+I+p)}function _(A,I,B,N,R,z){if(A!==B||I!==N){var W=R.push(w(R)+"scale(",null,",",null,")");z.push({i:W-4,x:Qv(A,B)},{i:W-2,x:Qv(I,N)})}else(B!==1||N!==1)&&R.push(w(R)+"scale("+B+","+N+")")}return function(A,I){var B=[],N=[];return A=i(A),I=i(I),m(A.translateX,A.translateY,I.translateX,I.translateY,B,N),b(A.rotate,I.rotate,B,N),E(A.skewX,I.skewX,B,N),_(A.scaleX,A.scaleY,I.scaleX,I.scaleY,B,N),A=I=null,function(R){for(var z=-1,W=N.length,et;++z=0&&i._call.call(void 0,a),i=i._next;--CA}function DMt(){X7=($U=OP.now())+zU,CA=MP=0;try{t8e()}finally{CA=0,n8e(),X7=0}}function e8e(){var i=OP.now(),a=i-$U;a>AMt&&(zU-=a,$U=i)}function n8e(){for(var i,a=jU,f,p=1/0;a;)a._call?(p>a._time&&(p=a._time),i=a,a=a._next):(f=a._next,a._next=null,a=i?i._next=f:jU=f);IP=i,m1t(p)}function m1t(i){if(!CA){MP&&(MP=clearTimeout(MP));var a=i-X7;a>24?(i<1/0&&(MP=setTimeout(DMt,i-OP.now()-zU)),DP&&(DP=clearInterval(DP))):(DP||($U=OP.now(),DP=setInterval(e8e,AMt)),CA=1,LMt(DMt))}}function IMt(i,a,f){var p=new qU;return a=a==null?0:+a,p.restart(w=>{p.stop(),i(w+a)},a,f),p}var r8e=VLt("start","end","cancel","interrupt"),i8e=[],OMt=0,PMt=1,y1t=2,HU=3,FMt=4,x1t=5,VU=6;function GU(i,a,f,p,w,m){var b=i.__transition;if(!b)i.__transition={};else if(f in b)return;s8e(i,f,{name:a,index:p,group:w,on:r8e,tween:i8e,time:m.time,delay:m.delay,duration:m.duration,ease:m.ease,timer:null,state:OMt})}function k1t(i,a){var f=Zv(i,a);if(f.state>OMt)throw new Error("too late; already scheduled");return f}function l3(i,a){var f=Zv(i,a);if(f.state>HU)throw new Error("too late; already running");return f}function Zv(i,a){var f=i.__transition;if(!f||!(f=f[a]))throw new Error("transition not found");return f}function s8e(i,a,f){var p=i.__transition,w;p[a]=f,f.timer=MMt(m,0,f.time);function m(A){f.state=PMt,f.timer.restart(b,f.delay,f.time),f.delay<=A&&b(A-f.delay)}function b(A){var I,B,N,R;if(f.state!==PMt)return _();for(I in p)if(R=p[I],R.name===f.name){if(R.state===HU)return IMt(b);R.state===FMt?(R.state=VU,R.timer.stop(),R.on.call("interrupt",i,i.__data__,R.index,R.group),delete p[I]):+Iy1t&&p.state=0&&(a=a.slice(0,f)),!a||a==="start"})}function N8e(i,a,f){var p,w,m=F8e(a)?k1t:l3;return function(){var b=m(this,i),E=b.on;E!==p&&(w=(p=E).copy()).on(a,f),b.on=w}}function B8e(i,a){var f=this._id;return arguments.length<2?Zv(this.node(),f).on.on(i):this.each(N8e(f,i,a))}function R8e(i){return function(){var a=this.parentNode;for(var f in this.__transition)if(+f!==i)return;a&&a.removeChild(this)}}function j8e(){return this.on("end.remove",R8e(this._id))}function $8e(i){var a=this._name,f=this._id;typeof i!="function"&&(i=i1t(i));for(var p=this._groups,w=p.length,m=new Array(w),b=0;b=0))throw new Error(`invalid digits: ${i}`);if(a>15)return jMt;const f=10**a;return function(p){this._+=p[0];for(let w=1,m=p.length;wQ7)if(!(Math.abs(B*_-A*I)>Q7)||!m)this._append`L${this._x1=a},${this._y1=f}`;else{let R=p-b,z=w-E,W=_*_+A*A,et=R*R+z*z,st=Math.sqrt(W),at=Math.sqrt(N),bt=m*Math.tan((T1t-Math.acos((W+N-et)/(2*st*at)))/2),mt=bt/at,yt=bt/st;Math.abs(mt-1)>Q7&&this._append`L${a+mt*I},${f+mt*B}`,this._append`A${m},${m},0,0,${+(B*R>I*z)},${this._x1=a+yt*_},${this._y1=f+yt*A}`}}arc(a,f,p,w,m,b){if(a=+a,f=+f,p=+p,b=!!b,p<0)throw new Error(`negative radius: ${p}`);let E=p*Math.cos(w),_=p*Math.sin(w),A=a+E,I=f+_,B=1^b,N=b?w-m:m-w;this._x1===null?this._append`M${A},${I}`:(Math.abs(this._x1-A)>Q7||Math.abs(this._y1-I)>Q7)&&this._append`L${A},${I}`,p&&(N<0&&(N=N%C1t+C1t),N>hEe?this._append`A${p},${p},0,1,${B},${a-E},${f-_}A${p},${p},0,1,${B},${this._x1=A},${this._y1=I}`:N>Q7&&this._append`A${p},${p},0,${+(N>=T1t)},${B},${this._x1=a+p*Math.cos(m)},${this._y1=f+p*Math.sin(m)}`)}rect(a,f,p,w){this._append`M${this._x0=this._x1=+a},${this._y0=this._y1=+f}h${p=+p}v${+w}h${-p}Z`}toString(){return this._}};function gEe(i){if(!i.ok)throw new Error(i.status+" "+i.statusText);return i.text()}function pEe(i,a){return fetch(i,a).then(gEe)}function bEe(i){return(a,f)=>pEe(a,f).then(p=>new DOMParser().parseFromString(p,i))}var wEe=bEe("image/svg+xml");function vEe(i){return Math.abs(i=Math.round(i))>=1e21?i.toLocaleString("en").replace(/,/g,""):i.toString(10)}function UU(i,a){if((f=(i=a?i.toExponential(a-1):i.toExponential()).indexOf("e"))<0)return null;var f,p=i.slice(0,f);return[p.length>1?p[0]+p.slice(2):p,+i.slice(f+1)]}function _A(i){return i=UU(Math.abs(i)),i?i[1]:NaN}function mEe(i,a){return function(f,p){for(var w=f.length,m=[],b=0,E=i[0],_=0;w>0&&E>0&&(_+E+1>p&&(E=Math.max(1,p-_)),m.push(f.substring(w-=E,w+E)),!((_+=E+1)>p));)E=i[b=(b+1)%i.length];return m.reverse().join(a)}}function yEe(i){return function(a){return a.replace(/[0-9]/g,function(f){return i[+f]})}}var xEe=/^(?:(.)?([<>=^]))?([+\-( ])?([$#])?(0)?(\d+)?(,)?(\.\d+)?(~)?([a-z%])?$/i;function WU(i){if(!(a=xEe.exec(i)))throw new Error("invalid format: "+i);var a;return new _1t({fill:a[1],align:a[2],sign:a[3],symbol:a[4],zero:a[5],width:a[6],comma:a[7],precision:a[8]&&a[8].slice(1),trim:a[9],type:a[10]})}WU.prototype=_1t.prototype;function _1t(i){this.fill=i.fill===void 0?" ":i.fill+"",this.align=i.align===void 0?">":i.align+"",this.sign=i.sign===void 0?"-":i.sign+"",this.symbol=i.symbol===void 0?"":i.symbol+"",this.zero=!!i.zero,this.width=i.width===void 0?void 0:+i.width,this.comma=!!i.comma,this.precision=i.precision===void 0?void 0:+i.precision,this.trim=!!i.trim,this.type=i.type===void 0?"":i.type+""}_1t.prototype.toString=function(){return this.fill+this.align+this.sign+this.symbol+(this.zero?"0":"")+(this.width===void 0?"":Math.max(1,this.width|0))+(this.comma?",":"")+(this.precision===void 0?"":"."+Math.max(0,this.precision|0))+(this.trim?"~":"")+this.type};function kEe(i){t:for(var a=i.length,f=1,p=-1,w;f0&&(p=0);break}return p>0?i.slice(0,p)+i.slice(w+1):i}var $Mt;function EEe(i,a){var f=UU(i,a);if(!f)return i+"";var p=f[0],w=f[1],m=w-($Mt=Math.max(-8,Math.min(8,Math.floor(w/3)))*3)+1,b=p.length;return m===b?p:m>b?p+new Array(m-b+1).join("0"):m>0?p.slice(0,m)+"."+p.slice(m):"0."+new Array(1-m).join("0")+UU(i,Math.max(0,a+m-1))[0]}function zMt(i,a){var f=UU(i,a);if(!f)return i+"";var p=f[0],w=f[1];return w<0?"0."+new Array(-w).join("0")+p:p.length>w+1?p.slice(0,w+1)+"."+p.slice(w+1):p+new Array(w-p.length+2).join("0")}const qMt={"%":(i,a)=>(i*100).toFixed(a),b:i=>Math.round(i).toString(2),c:i=>i+"",d:vEe,e:(i,a)=>i.toExponential(a),f:(i,a)=>i.toFixed(a),g:(i,a)=>i.toPrecision(a),o:i=>Math.round(i).toString(8),p:(i,a)=>zMt(i*100,a),r:zMt,s:EEe,X:i=>Math.round(i).toString(16).toUpperCase(),x:i=>Math.round(i).toString(16)};function HMt(i){return i}var VMt=Array.prototype.map,GMt=["y","z","a","f","p","n","µ","m","","k","M","G","T","P","E","Z","Y"];function TEe(i){var a=i.grouping===void 0||i.thousands===void 0?HMt:mEe(VMt.call(i.grouping,Number),i.thousands+""),f=i.currency===void 0?"":i.currency[0]+"",p=i.currency===void 0?"":i.currency[1]+"",w=i.decimal===void 0?".":i.decimal+"",m=i.numerals===void 0?HMt:yEe(VMt.call(i.numerals,String)),b=i.percent===void 0?"%":i.percent+"",E=i.minus===void 0?"−":i.minus+"",_=i.nan===void 0?"NaN":i.nan+"";function A(B){B=WU(B);var N=B.fill,R=B.align,z=B.sign,W=B.symbol,et=B.zero,st=B.width,at=B.comma,bt=B.precision,mt=B.trim,yt=B.type;yt==="n"?(at=!0,yt="g"):qMt[yt]||(bt===void 0&&(bt=12),mt=!0,yt="g"),(et||N==="0"&&R==="=")&&(et=!0,N="0",R="=");var ft=W==="$"?f:W==="#"&&/[boxX]/.test(yt)?"0"+yt.toLowerCase():"",ut=W==="$"?p:/[%p]/.test(yt)?b:"",vt=qMt[yt],X=/[defgprs%]/.test(yt);bt=bt===void 0?6:/[gprs]/.test(yt)?Math.max(1,Math.min(21,bt)):Math.max(0,Math.min(20,bt));function pt(U){var Tt=ft,nt=ut,It,Ot,Bt;if(yt==="c")nt=vt(U)+nt,U="";else{U=+U;var Et=U<0||1/U<0;if(U=isNaN(U)?_:vt(Math.abs(U),bt),mt&&(U=kEe(U)),Et&&+U==0&&z!=="+"&&(Et=!1),Tt=(Et?z==="("?z:E:z==="-"||z==="("?"":z)+Tt,nt=(yt==="s"?GMt[8+$Mt/3]:"")+nt+(Et&&z==="("?")":""),X){for(It=-1,Ot=U.length;++ItBt||Bt>57){nt=(Bt===46?w+U.slice(It+1):U.slice(It))+nt,U=U.slice(0,It);break}}}at&&!et&&(U=a(U,1/0));var Z=Tt.length+U.length+nt.length,Ct=Z>1)+Tt+U+nt+Ct.slice(Z);break;default:U=Ct+Tt+U+nt;break}return m(U)}return pt.toString=function(){return B+""},pt}function I(B,N){var R=A((B=WU(B),B.type="f",B)),z=Math.max(-8,Math.min(8,Math.floor(_A(N)/3)))*3,W=Math.pow(10,-z),et=GMt[8+z/3];return function(st){return R(W*st)+et}}return{format:A,formatPrefix:I}}var YU,UMt,WMt;CEe({thousands:",",grouping:[3],currency:["$",""]});function CEe(i){return YU=TEe(i),UMt=YU.format,WMt=YU.formatPrefix,YU}function _Ee(i){return Math.max(0,-_A(Math.abs(i)))}function SEe(i,a){return Math.max(0,Math.max(-8,Math.min(8,Math.floor(_A(a)/3)))*3-_A(Math.abs(i)))}function AEe(i,a){return i=Math.abs(i),a=Math.abs(a)-i,Math.max(0,_A(a)-_A(i))+1}function KU(i,a){switch(arguments.length){case 0:break;case 1:this.range(i);break;default:this.range(a).domain(i);break}return this}const YMt=Symbol("implicit");function XU(){var i=new $Lt,a=[],f=[],p=YMt;function w(m){let b=i.get(m);if(b===void 0){if(p!==YMt)return p;i.set(m,b=a.push(m)-1)}return f[b%f.length]}return w.domain=function(m){if(!arguments.length)return a.slice();a=[],i=new $Lt;for(const b of m)i.has(b)||i.set(b,a.push(b)-1);return w},w.range=function(m){return arguments.length?(f=Array.from(m),w):f.slice()},w.unknown=function(m){return arguments.length?(p=m,w):p},w.copy=function(){return XU(a,f).unknown(p)},KU.apply(w,arguments),w}function S1t(){var i=XU().unknown(void 0),a=i.domain,f=i.range,p=0,w=1,m,b,E=!1,_=0,A=0,I=.5;delete i.unknown;function B(){var N=a().length,R=wa&&(f=i,i=a,a=f),function(p){return Math.max(i,Math.min(a,p))}}function IEe(i,a,f){var p=i[0],w=i[1],m=a[0],b=a[1];return w2?OEe:IEe,_=A=null,B}function B(N){return N==null||isNaN(N=+N)?m:(_||(_=E(i.map(p),a,f)))(p(b(N)))}return B.invert=function(N){return b(w((A||(A=E(a,i.map(p),Qv)))(N)))},B.domain=function(N){return arguments.length?(i=Array.from(N,MEe),I()):i.slice()},B.range=function(N){return arguments.length?(a=Array.from(N),I()):a.slice()},B.rangeRound=function(N){return a=Array.from(N),f=Uke,I()},B.clamp=function(N){return arguments.length?(b=N?!0:SA,I()):b!==SA},B.interpolate=function(N){return arguments.length?(f=N,I()):f},B.unknown=function(N){return arguments.length?(m=N,B):m},function(N,R){return p=N,w=R,I()}}function QMt(){return PEe()(SA,SA)}function FEe(i,a,f,p){var w=t1t(i,a,f),m;switch(p=WU(p??",f"),p.type){case"s":{var b=Math.max(Math.abs(i),Math.abs(a));return p.precision==null&&!isNaN(m=SEe(w,b))&&(p.precision=m),WMt(p,b)}case"":case"e":case"g":case"p":case"r":{p.precision==null&&!isNaN(m=AEe(w,Math.max(Math.abs(i),Math.abs(a))))&&(p.precision=m-(p.type==="e"));break}case"f":case"%":{p.precision==null&&!isNaN(m=_Ee(w))&&(p.precision=m-(p.type==="%")*2);break}}return UMt(p)}function NEe(i){var a=i.domain;return i.ticks=function(f){var p=a();return Axe(p[0],p[p.length-1],f??10)},i.tickFormat=function(f,p){var w=a();return FEe(w[0],w[w.length-1],f??10,p)},i.nice=function(f){f==null&&(f=10);var p=a(),w=0,m=p.length-1,b=p[w],E=p[m],_,A,I=10;for(E0;){if(A=Jft(b,E,f),A===_)return p[w]=b,p[m]=E,a(p);if(A>0)b=Math.floor(b/A)*A,E=Math.ceil(E/A)*A;else if(A<0)b=Math.ceil(b*A)/A,E=Math.floor(E*A)/A;else break;_=A}return i},i}function AA(){var i=QMt();return i.copy=function(){return XMt(i,AA())},KU.apply(i,arguments),NEe(i)}function BEe(i,a){i=i.slice();var f=0,p=i.length-1,w=i[f],m=i[p],b;return m(i(m=new Date(+m)),m),w.ceil=m=>(i(m=new Date(m-1)),a(m,1),i(m),m),w.round=m=>{const b=w(m),E=w.ceil(m);return m-b(a(m=new Date(+m),b==null?1:Math.floor(b)),m),w.range=(m,b,E)=>{const _=[];if(m=w.ceil(m),E=E==null?1:Math.floor(E),!(m0))return _;let A;do _.push(A=new Date(+m)),a(m,E),i(m);while(Aa1(b=>{if(b>=b)for(;i(b),!m(b);)b.setTime(b-1)},(b,E)=>{if(b>=b)if(E<0)for(;++E<=0;)for(;a(b,-1),!m(b););else for(;--E>=0;)for(;a(b,1),!m(b););}),f&&(w.count=(m,b)=>(L1t.setTime(+m),M1t.setTime(+b),i(L1t),i(M1t),Math.floor(f(L1t,M1t))),w.every=m=>(m=Math.floor(m),!isFinite(m)||!(m>0)?null:m>1?w.filter(p?b=>p(b)%m===0:b=>w.count(0,b)%m===0):w)),w}const LA=a1(()=>{},(i,a)=>{i.setTime(+i+a)},(i,a)=>a-i);LA.every=i=>(i=Math.floor(i),!isFinite(i)||!(i>0)?null:i>1?a1(a=>{a.setTime(Math.floor(a/i)*i)},(a,f)=>{a.setTime(+a+f*i)},(a,f)=>(f-a)/i):LA),LA.range;const m5=1e3,Z2=m5*60,y5=Z2*60,x5=y5*24,D1t=x5*7,ZMt=x5*30,I1t=x5*365,sk=a1(i=>{i.setTime(i-i.getMilliseconds())},(i,a)=>{i.setTime(+i+a*m5)},(i,a)=>(a-i)/m5,i=>i.getUTCSeconds());sk.range;const PP=a1(i=>{i.setTime(i-i.getMilliseconds()-i.getSeconds()*m5)},(i,a)=>{i.setTime(+i+a*Z2)},(i,a)=>(a-i)/Z2,i=>i.getMinutes());PP.range,a1(i=>{i.setUTCSeconds(0,0)},(i,a)=>{i.setTime(+i+a*Z2)},(i,a)=>(a-i)/Z2,i=>i.getUTCMinutes()).range;const FP=a1(i=>{i.setTime(i-i.getMilliseconds()-i.getSeconds()*m5-i.getMinutes()*Z2)},(i,a)=>{i.setTime(+i+a*y5)},(i,a)=>(a-i)/y5,i=>i.getHours());FP.range,a1(i=>{i.setUTCMinutes(0,0,0)},(i,a)=>{i.setTime(+i+a*y5)},(i,a)=>(a-i)/y5,i=>i.getUTCHours()).range;const Z7=a1(i=>i.setHours(0,0,0,0),(i,a)=>i.setDate(i.getDate()+a),(i,a)=>(a-i-(a.getTimezoneOffset()-i.getTimezoneOffset())*Z2)/x5,i=>i.getDate()-1);Z7.range;const O1t=a1(i=>{i.setUTCHours(0,0,0,0)},(i,a)=>{i.setUTCDate(i.getUTCDate()+a)},(i,a)=>(a-i)/x5,i=>i.getUTCDate()-1);O1t.range,a1(i=>{i.setUTCHours(0,0,0,0)},(i,a)=>{i.setUTCDate(i.getUTCDate()+a)},(i,a)=>(a-i)/x5,i=>Math.floor(i/x5)).range;function J7(i){return a1(a=>{a.setDate(a.getDate()-(a.getDay()+7-i)%7),a.setHours(0,0,0,0)},(a,f)=>{a.setDate(a.getDate()+f*7)},(a,f)=>(f-a-(f.getTimezoneOffset()-a.getTimezoneOffset())*Z2)/D1t)}const NP=J7(0),BP=J7(1),JMt=J7(2),tDt=J7(3),tT=J7(4),eDt=J7(5),nDt=J7(6);NP.range,BP.range,JMt.range,tDt.range,tT.range,eDt.range,nDt.range;function eT(i){return a1(a=>{a.setUTCDate(a.getUTCDate()-(a.getUTCDay()+7-i)%7),a.setUTCHours(0,0,0,0)},(a,f)=>{a.setUTCDate(a.getUTCDate()+f*7)},(a,f)=>(f-a)/D1t)}const rDt=eT(0),QU=eT(1),REe=eT(2),jEe=eT(3),MA=eT(4),$Ee=eT(5),zEe=eT(6);rDt.range,QU.range,REe.range,jEe.range,MA.range,$Ee.range,zEe.range;const RP=a1(i=>{i.setDate(1),i.setHours(0,0,0,0)},(i,a)=>{i.setMonth(i.getMonth()+a)},(i,a)=>a.getMonth()-i.getMonth()+(a.getFullYear()-i.getFullYear())*12,i=>i.getMonth());RP.range,a1(i=>{i.setUTCDate(1),i.setUTCHours(0,0,0,0)},(i,a)=>{i.setUTCMonth(i.getUTCMonth()+a)},(i,a)=>a.getUTCMonth()-i.getUTCMonth()+(a.getUTCFullYear()-i.getUTCFullYear())*12,i=>i.getUTCMonth()).range;const k5=a1(i=>{i.setMonth(0,1),i.setHours(0,0,0,0)},(i,a)=>{i.setFullYear(i.getFullYear()+a)},(i,a)=>a.getFullYear()-i.getFullYear(),i=>i.getFullYear());k5.every=i=>!isFinite(i=Math.floor(i))||!(i>0)?null:a1(a=>{a.setFullYear(Math.floor(a.getFullYear()/i)*i),a.setMonth(0,1),a.setHours(0,0,0,0)},(a,f)=>{a.setFullYear(a.getFullYear()+f*i)}),k5.range;const nT=a1(i=>{i.setUTCMonth(0,1),i.setUTCHours(0,0,0,0)},(i,a)=>{i.setUTCFullYear(i.getUTCFullYear()+a)},(i,a)=>a.getUTCFullYear()-i.getUTCFullYear(),i=>i.getUTCFullYear());nT.every=i=>!isFinite(i=Math.floor(i))||!(i>0)?null:a1(a=>{a.setUTCFullYear(Math.floor(a.getUTCFullYear()/i)*i),a.setUTCMonth(0,1),a.setUTCHours(0,0,0,0)},(a,f)=>{a.setUTCFullYear(a.getUTCFullYear()+f*i)}),nT.range;function qEe(i,a,f,p,w,m){const b=[[sk,1,m5],[sk,5,5*m5],[sk,15,15*m5],[sk,30,30*m5],[m,1,Z2],[m,5,5*Z2],[m,15,15*Z2],[m,30,30*Z2],[w,1,y5],[w,3,3*y5],[w,6,6*y5],[w,12,12*y5],[p,1,x5],[p,2,2*x5],[f,1,D1t],[a,1,ZMt],[a,3,3*ZMt],[i,1,I1t]];function E(A,I,B){const N=Iet).right(b,N);if(R===b.length)return i.every(t1t(A/I1t,I/I1t,B));if(R===0)return LA.every(Math.max(t1t(A,I,B),1));const[z,W]=b[N/b[R-1][2]53)return null;"w"in re||(re.w=1),"Z"in re?(Pe=F1t(jP(re.y,0,1)),te=Pe.getUTCDay(),Pe=te>4||te===0?QU.ceil(Pe):QU(Pe),Pe=O1t.offset(Pe,(re.V-1)*7),re.y=Pe.getUTCFullYear(),re.m=Pe.getUTCMonth(),re.d=Pe.getUTCDate()+(re.w+6)%7):(Pe=P1t(jP(re.y,0,1)),te=Pe.getDay(),Pe=te>4||te===0?BP.ceil(Pe):BP(Pe),Pe=Z7.offset(Pe,(re.V-1)*7),re.y=Pe.getFullYear(),re.m=Pe.getMonth(),re.d=Pe.getDate()+(re.w+6)%7)}else("W"in re||"U"in re)&&("w"in re||(re.w="u"in re?re.u%7:"W"in re?1:0),te="Z"in re?F1t(jP(re.y,0,1)).getUTCDay():P1t(jP(re.y,0,1)).getDay(),re.m=0,re.d="W"in re?(re.w+6)%7+re.W*7-(te+5)%7:re.w+re.U*7-(te+6)%7);return"Z"in re?(re.H+=re.Z/100|0,re.M+=re.Z%100,F1t(re)):P1t(re)}}function vt(ce,ke,zt,re){for(var se=0,Pe=ke.length,te=zt.length,Me,de;se=te)return-1;if(Me=ke.charCodeAt(se++),Me===37){if(Me=ke.charAt(se++),de=yt[Me in iDt?ke.charAt(se++):Me],!de||(re=de(ce,zt,re))<0)return-1}else if(Me!=zt.charCodeAt(re++))return-1}return re}function X(ce,ke,zt){var re=A.exec(ke.slice(zt));return re?(ce.p=I.get(re[0].toLowerCase()),zt+re[0].length):-1}function pt(ce,ke,zt){var re=R.exec(ke.slice(zt));return re?(ce.w=z.get(re[0].toLowerCase()),zt+re[0].length):-1}function U(ce,ke,zt){var re=B.exec(ke.slice(zt));return re?(ce.w=N.get(re[0].toLowerCase()),zt+re[0].length):-1}function Tt(ce,ke,zt){var re=st.exec(ke.slice(zt));return re?(ce.m=at.get(re[0].toLowerCase()),zt+re[0].length):-1}function nt(ce,ke,zt){var re=W.exec(ke.slice(zt));return re?(ce.m=et.get(re[0].toLowerCase()),zt+re[0].length):-1}function It(ce,ke,zt){return vt(ce,a,ke,zt)}function Ot(ce,ke,zt){return vt(ce,f,ke,zt)}function Bt(ce,ke,zt){return vt(ce,p,ke,zt)}function Et(ce){return b[ce.getDay()]}function Z(ce){return m[ce.getDay()]}function Ct(ce){return _[ce.getMonth()]}function xt(ce){return E[ce.getMonth()]}function Ht(ce){return w[+(ce.getHours()>=12)]}function Le(ce){return 1+~~(ce.getMonth()/3)}function Ft(ce){return b[ce.getUTCDay()]}function gn(ce){return m[ce.getUTCDay()]}function Se(ce){return _[ce.getUTCMonth()]}function me(ce){return E[ce.getUTCMonth()]}function Ve(ce){return w[+(ce.getUTCHours()>=12)]}function Ye(ce){return 1+~~(ce.getUTCMonth()/3)}return{format:function(ce){var ke=ft(ce+="",bt);return ke.toString=function(){return ce},ke},parse:function(ce){var ke=ut(ce+="",!1);return ke.toString=function(){return ce},ke},utcFormat:function(ce){var ke=ft(ce+="",mt);return ke.toString=function(){return ce},ke},utcParse:function(ce){var ke=ut(ce+="",!0);return ke.toString=function(){return ce},ke}}}var iDt={"-":"",_:" ",0:"0"},X1=/^\s*\d+/,UEe=/^%/,WEe=/[\\^$*+?|[\]().{}]/g;function Ic(i,a,f){var p=i<0?"-":"",w=(p?-i:i)+"",m=w.length;return p+(m[a.toLowerCase(),f]))}function KEe(i,a,f){var p=X1.exec(a.slice(f,f+1));return p?(i.w=+p[0],f+p[0].length):-1}function XEe(i,a,f){var p=X1.exec(a.slice(f,f+1));return p?(i.u=+p[0],f+p[0].length):-1}function QEe(i,a,f){var p=X1.exec(a.slice(f,f+2));return p?(i.U=+p[0],f+p[0].length):-1}function ZEe(i,a,f){var p=X1.exec(a.slice(f,f+2));return p?(i.V=+p[0],f+p[0].length):-1}function JEe(i,a,f){var p=X1.exec(a.slice(f,f+2));return p?(i.W=+p[0],f+p[0].length):-1}function sDt(i,a,f){var p=X1.exec(a.slice(f,f+4));return p?(i.y=+p[0],f+p[0].length):-1}function aDt(i,a,f){var p=X1.exec(a.slice(f,f+2));return p?(i.y=+p[0]+(+p[0]>68?1900:2e3),f+p[0].length):-1}function t7e(i,a,f){var p=/^(Z)|([+-]\d\d)(?::?(\d\d))?/.exec(a.slice(f,f+6));return p?(i.Z=p[1]?0:-(p[2]+(p[3]||"00")),f+p[0].length):-1}function e7e(i,a,f){var p=X1.exec(a.slice(f,f+1));return p?(i.q=p[0]*3-3,f+p[0].length):-1}function n7e(i,a,f){var p=X1.exec(a.slice(f,f+2));return p?(i.m=p[0]-1,f+p[0].length):-1}function oDt(i,a,f){var p=X1.exec(a.slice(f,f+2));return p?(i.d=+p[0],f+p[0].length):-1}function r7e(i,a,f){var p=X1.exec(a.slice(f,f+3));return p?(i.m=0,i.d=+p[0],f+p[0].length):-1}function cDt(i,a,f){var p=X1.exec(a.slice(f,f+2));return p?(i.H=+p[0],f+p[0].length):-1}function i7e(i,a,f){var p=X1.exec(a.slice(f,f+2));return p?(i.M=+p[0],f+p[0].length):-1}function s7e(i,a,f){var p=X1.exec(a.slice(f,f+2));return p?(i.S=+p[0],f+p[0].length):-1}function a7e(i,a,f){var p=X1.exec(a.slice(f,f+3));return p?(i.L=+p[0],f+p[0].length):-1}function o7e(i,a,f){var p=X1.exec(a.slice(f,f+6));return p?(i.L=Math.floor(p[0]/1e3),f+p[0].length):-1}function c7e(i,a,f){var p=UEe.exec(a.slice(f,f+1));return p?f+p[0].length:-1}function u7e(i,a,f){var p=X1.exec(a.slice(f));return p?(i.Q=+p[0],f+p[0].length):-1}function l7e(i,a,f){var p=X1.exec(a.slice(f));return p?(i.s=+p[0],f+p[0].length):-1}function uDt(i,a){return Ic(i.getDate(),a,2)}function h7e(i,a){return Ic(i.getHours(),a,2)}function f7e(i,a){return Ic(i.getHours()%12||12,a,2)}function d7e(i,a){return Ic(1+Z7.count(k5(i),i),a,3)}function lDt(i,a){return Ic(i.getMilliseconds(),a,3)}function g7e(i,a){return lDt(i,a)+"000"}function p7e(i,a){return Ic(i.getMonth()+1,a,2)}function b7e(i,a){return Ic(i.getMinutes(),a,2)}function w7e(i,a){return Ic(i.getSeconds(),a,2)}function v7e(i){var a=i.getDay();return a===0?7:a}function m7e(i,a){return Ic(NP.count(k5(i)-1,i),a,2)}function hDt(i){var a=i.getDay();return a>=4||a===0?tT(i):tT.ceil(i)}function y7e(i,a){return i=hDt(i),Ic(tT.count(k5(i),i)+(k5(i).getDay()===4),a,2)}function x7e(i){return i.getDay()}function k7e(i,a){return Ic(BP.count(k5(i)-1,i),a,2)}function E7e(i,a){return Ic(i.getFullYear()%100,a,2)}function T7e(i,a){return i=hDt(i),Ic(i.getFullYear()%100,a,2)}function C7e(i,a){return Ic(i.getFullYear()%1e4,a,4)}function _7e(i,a){var f=i.getDay();return i=f>=4||f===0?tT(i):tT.ceil(i),Ic(i.getFullYear()%1e4,a,4)}function S7e(i){var a=i.getTimezoneOffset();return(a>0?"-":(a*=-1,"+"))+Ic(a/60|0,"0",2)+Ic(a%60,"0",2)}function fDt(i,a){return Ic(i.getUTCDate(),a,2)}function A7e(i,a){return Ic(i.getUTCHours(),a,2)}function L7e(i,a){return Ic(i.getUTCHours()%12||12,a,2)}function M7e(i,a){return Ic(1+O1t.count(nT(i),i),a,3)}function dDt(i,a){return Ic(i.getUTCMilliseconds(),a,3)}function D7e(i,a){return dDt(i,a)+"000"}function I7e(i,a){return Ic(i.getUTCMonth()+1,a,2)}function O7e(i,a){return Ic(i.getUTCMinutes(),a,2)}function P7e(i,a){return Ic(i.getUTCSeconds(),a,2)}function F7e(i){var a=i.getUTCDay();return a===0?7:a}function N7e(i,a){return Ic(rDt.count(nT(i)-1,i),a,2)}function gDt(i){var a=i.getUTCDay();return a>=4||a===0?MA(i):MA.ceil(i)}function B7e(i,a){return i=gDt(i),Ic(MA.count(nT(i),i)+(nT(i).getUTCDay()===4),a,2)}function R7e(i){return i.getUTCDay()}function j7e(i,a){return Ic(QU.count(nT(i)-1,i),a,2)}function $7e(i,a){return Ic(i.getUTCFullYear()%100,a,2)}function z7e(i,a){return i=gDt(i),Ic(i.getUTCFullYear()%100,a,2)}function q7e(i,a){return Ic(i.getUTCFullYear()%1e4,a,4)}function H7e(i,a){var f=i.getUTCDay();return i=f>=4||f===0?MA(i):MA.ceil(i),Ic(i.getUTCFullYear()%1e4,a,4)}function V7e(){return"+0000"}function pDt(){return"%"}function bDt(i){return+i}function wDt(i){return Math.floor(+i/1e3)}var DA,ZU;G7e({dateTime:"%x, %X",date:"%-m/%-d/%Y",time:"%-I:%M:%S %p",periods:["AM","PM"],days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],shortDays:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],months:["January","February","March","April","May","June","July","August","September","October","November","December"],shortMonths:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"]});function G7e(i){return DA=GEe(i),ZU=DA.format,DA.parse,DA.utcFormat,DA.utcParse,DA}function U7e(i){return new Date(i)}function W7e(i){return i instanceof Date?+i:+new Date(+i)}function vDt(i,a,f,p,w,m,b,E,_,A){var I=QMt(),B=I.invert,N=I.domain,R=A(".%L"),z=A(":%S"),W=A("%I:%M"),et=A("%I %p"),st=A("%a %d"),at=A("%b %d"),bt=A("%B"),mt=A("%Y");function yt(ft){return(_(ft)1?0:i<-1?qP:Math.acos(i)}function yDt(i){return i>=1?JU:i<=-1?-JU:Math.asin(i)}function xDt(i){let a=3;return i.digits=function(f){if(!arguments.length)return a;if(f==null)a=null;else{const p=Math.floor(f);if(!(p>=0))throw new RangeError(`invalid digits: ${f}`);a=p}return i},()=>new dEe(a)}function J7e(i){return i.innerRadius}function tTe(i){return i.outerRadius}function eTe(i){return i.startAngle}function nTe(i){return i.endAngle}function rTe(i){return i&&i.padAngle}function iTe(i,a,f,p,w,m,b,E){var _=f-i,A=p-a,I=b-w,B=E-m,N=B*_-I*A;if(!(N*NIt*It+Ot*Ot&&(vt=pt,X=U),{cx:vt,cy:X,x01:-I,y01:-B,x11:vt*(w/yt-1),y11:X*(w/yt-1)}}function OA(){var i=J7e,a=tTe,f=Qh(0),p=null,w=eTe,m=nTe,b=rTe,E=null,_=xDt(A);function A(){var I,B,N=+i.apply(this,arguments),R=+a.apply(this,arguments),z=w.apply(this,arguments)-JU,W=m.apply(this,arguments)-JU,et=mDt(W-z),st=W>z;if(E||(E=I=_()),Ry0))E.moveTo(0,0);else if(et>tW-y0)E.moveTo(R*rT(z),R*h3(z)),E.arc(0,0,R,z,W,!st),N>y0&&(E.moveTo(N*rT(W),N*h3(W)),E.arc(0,0,N,W,z,st));else{var at=z,bt=W,mt=z,yt=W,ft=et,ut=et,vt=b.apply(this,arguments)/2,X=vt>y0&&(p?+p.apply(this,arguments):IA(N*N+R*R)),pt=N1t(mDt(R-N)/2,+f.apply(this,arguments)),U=pt,Tt=pt,nt,It;if(X>y0){var Ot=yDt(X/N*h3(vt)),Bt=yDt(X/R*h3(vt));(ft-=Ot*2)>y0?(Ot*=st?1:-1,mt+=Ot,yt-=Ot):(ft=0,mt=yt=(z+W)/2),(ut-=Bt*2)>y0?(Bt*=st?1:-1,at+=Bt,bt-=Bt):(ut=0,at=bt=(z+W)/2)}var Et=R*rT(at),Z=R*h3(at),Ct=N*rT(yt),xt=N*h3(yt);if(pt>y0){var Ht=R*rT(bt),Le=R*h3(bt),Ft=N*rT(mt),gn=N*h3(mt),Se;if(ety0?Tt>y0?(nt=eW(Ft,gn,Et,Z,R,Tt,st),It=eW(Ht,Le,Ct,xt,R,Tt,st),E.moveTo(nt.cx+nt.x01,nt.cy+nt.y01),Tty0)||!(ft>y0)?E.lineTo(Ct,xt):U>y0?(nt=eW(Ct,xt,Ht,Le,N,-U,st),It=eW(Et,Z,Ft,gn,N,-U,st),E.lineTo(nt.cx+nt.x01,nt.cy+nt.y01),Ui?1:a>=i?0:NaN}function cTe(i){return i}function uTe(){var i=cTe,a=oTe,f=null,p=Qh(0),w=Qh(tW),m=Qh(0);function b(E){var _,A=(E=kDt(E)).length,I,B,N=0,R=new Array(A),z=new Array(A),W=+p.apply(this,arguments),et=Math.min(tW,Math.max(-tW,w.apply(this,arguments)-W)),st,at=Math.min(Math.abs(et)/A,m.apply(this,arguments)),bt=at*(et<0?-1:1),mt;for(_=0;_0&&(N+=mt);for(a!=null?R.sort(function(yt,ft){return a(z[yt],z[ft])}):f!=null&&R.sort(function(yt,ft){return f(E[yt],E[ft])}),_=0,B=N?(et-A*bt)/N:0;_0?mt*B:0)+bt,z[I]={data:E[I],index:_,value:mt,startAngle:W,endAngle:st,padAngle:at};return z}return b.value=function(E){return arguments.length?(i=typeof E=="function"?E:Qh(+E),b):i},b.sortValues=function(E){return arguments.length?(a=E,f=null,b):a},b.sort=function(E){return arguments.length?(f=E,a=null,b):f},b.startAngle=function(E){return arguments.length?(p=typeof E=="function"?E:Qh(+E),b):p},b.endAngle=function(E){return arguments.length?(w=typeof E=="function"?E:Qh(+E),b):w},b.padAngle=function(E){return arguments.length?(m=typeof E=="function"?E:Qh(+E),b):m},b}class TDt{constructor(a,f){this._context=a,this._x=f}areaStart(){this._line=0}areaEnd(){this._line=NaN}lineStart(){this._point=0}lineEnd(){(this._line||this._line!==0&&this._point===1)&&this._context.closePath(),this._line=1-this._line}point(a,f){switch(a=+a,f=+f,this._point){case 0:{this._point=1,this._line?this._context.lineTo(a,f):this._context.moveTo(a,f);break}case 1:this._point=2;default:{this._x?this._context.bezierCurveTo(this._x0=(this._x0+a)/2,this._y0,this._x0,f,a,f):this._context.bezierCurveTo(this._x0,this._y0=(this._y0+f)/2,a,this._y0,a,f);break}}this._x0=a,this._y0=f}}function lTe(i){return new TDt(i,!0)}function hTe(i){return new TDt(i,!1)}function ak(){}function nW(i,a,f){i._context.bezierCurveTo((2*i._x0+i._x1)/3,(2*i._y0+i._y1)/3,(i._x0+2*i._x1)/3,(i._y0+2*i._y1)/3,(i._x0+4*i._x1+a)/6,(i._y0+4*i._y1+f)/6)}function rW(i){this._context=i}rW.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._y0=this._y1=NaN,this._point=0},lineEnd:function(){switch(this._point){case 3:nW(this,this._x1,this._y1);case 2:this._context.lineTo(this._x1,this._y1);break}(this._line||this._line!==0&&this._point===1)&&this._context.closePath(),this._line=1-this._line},point:function(i,a){switch(i=+i,a=+a,this._point){case 0:this._point=1,this._line?this._context.lineTo(i,a):this._context.moveTo(i,a);break;case 1:this._point=2;break;case 2:this._point=3,this._context.lineTo((5*this._x0+this._x1)/6,(5*this._y0+this._y1)/6);default:nW(this,i,a);break}this._x0=this._x1,this._x1=i,this._y0=this._y1,this._y1=a}};function HP(i){return new rW(i)}function CDt(i){this._context=i}CDt.prototype={areaStart:ak,areaEnd:ak,lineStart:function(){this._x0=this._x1=this._x2=this._x3=this._x4=this._y0=this._y1=this._y2=this._y3=this._y4=NaN,this._point=0},lineEnd:function(){switch(this._point){case 1:{this._context.moveTo(this._x2,this._y2),this._context.closePath();break}case 2:{this._context.moveTo((this._x2+2*this._x3)/3,(this._y2+2*this._y3)/3),this._context.lineTo((this._x3+2*this._x2)/3,(this._y3+2*this._y2)/3),this._context.closePath();break}case 3:{this.point(this._x2,this._y2),this.point(this._x3,this._y3),this.point(this._x4,this._y4);break}}},point:function(i,a){switch(i=+i,a=+a,this._point){case 0:this._point=1,this._x2=i,this._y2=a;break;case 1:this._point=2,this._x3=i,this._y3=a;break;case 2:this._point=3,this._x4=i,this._y4=a,this._context.moveTo((this._x0+4*this._x1+i)/6,(this._y0+4*this._y1+a)/6);break;default:nW(this,i,a);break}this._x0=this._x1,this._x1=i,this._y0=this._y1,this._y1=a}};function fTe(i){return new CDt(i)}function _Dt(i){this._context=i}_Dt.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._y0=this._y1=NaN,this._point=0},lineEnd:function(){(this._line||this._line!==0&&this._point===3)&&this._context.closePath(),this._line=1-this._line},point:function(i,a){switch(i=+i,a=+a,this._point){case 0:this._point=1;break;case 1:this._point=2;break;case 2:this._point=3;var f=(this._x0+4*this._x1+i)/6,p=(this._y0+4*this._y1+a)/6;this._line?this._context.lineTo(f,p):this._context.moveTo(f,p);break;case 3:this._point=4;default:nW(this,i,a);break}this._x0=this._x1,this._x1=i,this._y0=this._y1,this._y1=a}};function dTe(i){return new _Dt(i)}function SDt(i,a){this._basis=new rW(i),this._beta=a}SDt.prototype={lineStart:function(){this._x=[],this._y=[],this._basis.lineStart()},lineEnd:function(){var i=this._x,a=this._y,f=i.length-1;if(f>0)for(var p=i[0],w=a[0],m=i[f]-p,b=a[f]-w,E=-1,_;++E<=f;)_=E/f,this._basis.point(this._beta*i[E]+(1-this._beta)*(p+_*m),this._beta*a[E]+(1-this._beta)*(w+_*b));this._x=this._y=null,this._basis.lineEnd()},point:function(i,a){this._x.push(+i),this._y.push(+a)}};const gTe=function i(a){function f(p){return a===1?new rW(p):new SDt(p,a)}return f.beta=function(p){return i(+p)},f}(.85);function iW(i,a,f){i._context.bezierCurveTo(i._x1+i._k*(i._x2-i._x0),i._y1+i._k*(i._y2-i._y0),i._x2+i._k*(i._x1-a),i._y2+i._k*(i._y1-f),i._x2,i._y2)}function B1t(i,a){this._context=i,this._k=(1-a)/6}B1t.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._x2=this._y0=this._y1=this._y2=NaN,this._point=0},lineEnd:function(){switch(this._point){case 2:this._context.lineTo(this._x2,this._y2);break;case 3:iW(this,this._x1,this._y1);break}(this._line||this._line!==0&&this._point===1)&&this._context.closePath(),this._line=1-this._line},point:function(i,a){switch(i=+i,a=+a,this._point){case 0:this._point=1,this._line?this._context.lineTo(i,a):this._context.moveTo(i,a);break;case 1:this._point=2,this._x1=i,this._y1=a;break;case 2:this._point=3;default:iW(this,i,a);break}this._x0=this._x1,this._x1=this._x2,this._x2=i,this._y0=this._y1,this._y1=this._y2,this._y2=a}};const pTe=function i(a){function f(p){return new B1t(p,a)}return f.tension=function(p){return i(+p)},f}(0);function R1t(i,a){this._context=i,this._k=(1-a)/6}R1t.prototype={areaStart:ak,areaEnd:ak,lineStart:function(){this._x0=this._x1=this._x2=this._x3=this._x4=this._x5=this._y0=this._y1=this._y2=this._y3=this._y4=this._y5=NaN,this._point=0},lineEnd:function(){switch(this._point){case 1:{this._context.moveTo(this._x3,this._y3),this._context.closePath();break}case 2:{this._context.lineTo(this._x3,this._y3),this._context.closePath();break}case 3:{this.point(this._x3,this._y3),this.point(this._x4,this._y4),this.point(this._x5,this._y5);break}}},point:function(i,a){switch(i=+i,a=+a,this._point){case 0:this._point=1,this._x3=i,this._y3=a;break;case 1:this._point=2,this._context.moveTo(this._x4=i,this._y4=a);break;case 2:this._point=3,this._x5=i,this._y5=a;break;default:iW(this,i,a);break}this._x0=this._x1,this._x1=this._x2,this._x2=i,this._y0=this._y1,this._y1=this._y2,this._y2=a}};const bTe=function i(a){function f(p){return new R1t(p,a)}return f.tension=function(p){return i(+p)},f}(0);function j1t(i,a){this._context=i,this._k=(1-a)/6}j1t.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._x2=this._y0=this._y1=this._y2=NaN,this._point=0},lineEnd:function(){(this._line||this._line!==0&&this._point===3)&&this._context.closePath(),this._line=1-this._line},point:function(i,a){switch(i=+i,a=+a,this._point){case 0:this._point=1;break;case 1:this._point=2;break;case 2:this._point=3,this._line?this._context.lineTo(this._x2,this._y2):this._context.moveTo(this._x2,this._y2);break;case 3:this._point=4;default:iW(this,i,a);break}this._x0=this._x1,this._x1=this._x2,this._x2=i,this._y0=this._y1,this._y1=this._y2,this._y2=a}};const wTe=function i(a){function f(p){return new j1t(p,a)}return f.tension=function(p){return i(+p)},f}(0);function $1t(i,a,f){var p=i._x1,w=i._y1,m=i._x2,b=i._y2;if(i._l01_a>y0){var E=2*i._l01_2a+3*i._l01_a*i._l12_a+i._l12_2a,_=3*i._l01_a*(i._l01_a+i._l12_a);p=(p*E-i._x0*i._l12_2a+i._x2*i._l01_2a)/_,w=(w*E-i._y0*i._l12_2a+i._y2*i._l01_2a)/_}if(i._l23_a>y0){var A=2*i._l23_2a+3*i._l23_a*i._l12_a+i._l12_2a,I=3*i._l23_a*(i._l23_a+i._l12_a);m=(m*A+i._x1*i._l23_2a-a*i._l12_2a)/I,b=(b*A+i._y1*i._l23_2a-f*i._l12_2a)/I}i._context.bezierCurveTo(p,w,m,b,i._x2,i._y2)}function ADt(i,a){this._context=i,this._alpha=a}ADt.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._x2=this._y0=this._y1=this._y2=NaN,this._l01_a=this._l12_a=this._l23_a=this._l01_2a=this._l12_2a=this._l23_2a=this._point=0},lineEnd:function(){switch(this._point){case 2:this._context.lineTo(this._x2,this._y2);break;case 3:this.point(this._x2,this._y2);break}(this._line||this._line!==0&&this._point===1)&&this._context.closePath(),this._line=1-this._line},point:function(i,a){if(i=+i,a=+a,this._point){var f=this._x2-i,p=this._y2-a;this._l23_a=Math.sqrt(this._l23_2a=Math.pow(f*f+p*p,this._alpha))}switch(this._point){case 0:this._point=1,this._line?this._context.lineTo(i,a):this._context.moveTo(i,a);break;case 1:this._point=2;break;case 2:this._point=3;default:$1t(this,i,a);break}this._l01_a=this._l12_a,this._l12_a=this._l23_a,this._l01_2a=this._l12_2a,this._l12_2a=this._l23_2a,this._x0=this._x1,this._x1=this._x2,this._x2=i,this._y0=this._y1,this._y1=this._y2,this._y2=a}};const vTe=function i(a){function f(p){return a?new ADt(p,a):new B1t(p,0)}return f.alpha=function(p){return i(+p)},f}(.5);function LDt(i,a){this._context=i,this._alpha=a}LDt.prototype={areaStart:ak,areaEnd:ak,lineStart:function(){this._x0=this._x1=this._x2=this._x3=this._x4=this._x5=this._y0=this._y1=this._y2=this._y3=this._y4=this._y5=NaN,this._l01_a=this._l12_a=this._l23_a=this._l01_2a=this._l12_2a=this._l23_2a=this._point=0},lineEnd:function(){switch(this._point){case 1:{this._context.moveTo(this._x3,this._y3),this._context.closePath();break}case 2:{this._context.lineTo(this._x3,this._y3),this._context.closePath();break}case 3:{this.point(this._x3,this._y3),this.point(this._x4,this._y4),this.point(this._x5,this._y5);break}}},point:function(i,a){if(i=+i,a=+a,this._point){var f=this._x2-i,p=this._y2-a;this._l23_a=Math.sqrt(this._l23_2a=Math.pow(f*f+p*p,this._alpha))}switch(this._point){case 0:this._point=1,this._x3=i,this._y3=a;break;case 1:this._point=2,this._context.moveTo(this._x4=i,this._y4=a);break;case 2:this._point=3,this._x5=i,this._y5=a;break;default:$1t(this,i,a);break}this._l01_a=this._l12_a,this._l12_a=this._l23_a,this._l01_2a=this._l12_2a,this._l12_2a=this._l23_2a,this._x0=this._x1,this._x1=this._x2,this._x2=i,this._y0=this._y1,this._y1=this._y2,this._y2=a}};const mTe=function i(a){function f(p){return a?new LDt(p,a):new R1t(p,0)}return f.alpha=function(p){return i(+p)},f}(.5);function MDt(i,a){this._context=i,this._alpha=a}MDt.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._x2=this._y0=this._y1=this._y2=NaN,this._l01_a=this._l12_a=this._l23_a=this._l01_2a=this._l12_2a=this._l23_2a=this._point=0},lineEnd:function(){(this._line||this._line!==0&&this._point===3)&&this._context.closePath(),this._line=1-this._line},point:function(i,a){if(i=+i,a=+a,this._point){var f=this._x2-i,p=this._y2-a;this._l23_a=Math.sqrt(this._l23_2a=Math.pow(f*f+p*p,this._alpha))}switch(this._point){case 0:this._point=1;break;case 1:this._point=2;break;case 2:this._point=3,this._line?this._context.lineTo(this._x2,this._y2):this._context.moveTo(this._x2,this._y2);break;case 3:this._point=4;default:$1t(this,i,a);break}this._l01_a=this._l12_a,this._l12_a=this._l23_a,this._l01_2a=this._l12_2a,this._l12_2a=this._l23_2a,this._x0=this._x1,this._x1=this._x2,this._x2=i,this._y0=this._y1,this._y1=this._y2,this._y2=a}};const yTe=function i(a){function f(p){return a?new MDt(p,a):new j1t(p,0)}return f.alpha=function(p){return i(+p)},f}(.5);function DDt(i){this._context=i}DDt.prototype={areaStart:ak,areaEnd:ak,lineStart:function(){this._point=0},lineEnd:function(){this._point&&this._context.closePath()},point:function(i,a){i=+i,a=+a,this._point?this._context.lineTo(i,a):(this._point=1,this._context.moveTo(i,a))}};function xTe(i){return new DDt(i)}function IDt(i){return i<0?-1:1}function ODt(i,a,f){var p=i._x1-i._x0,w=a-i._x1,m=(i._y1-i._y0)/(p||w<0&&-0),b=(f-i._y1)/(w||p<0&&-0),E=(m*w+b*p)/(p+w);return(IDt(m)+IDt(b))*Math.min(Math.abs(m),Math.abs(b),.5*Math.abs(E))||0}function PDt(i,a){var f=i._x1-i._x0;return f?(3*(i._y1-i._y0)/f-a)/2:a}function z1t(i,a,f){var p=i._x0,w=i._y0,m=i._x1,b=i._y1,E=(m-p)/3;i._context.bezierCurveTo(p+E,w+E*a,m-E,b-E*f,m,b)}function sW(i){this._context=i}sW.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x0=this._x1=this._y0=this._y1=this._t0=NaN,this._point=0},lineEnd:function(){switch(this._point){case 2:this._context.lineTo(this._x1,this._y1);break;case 3:z1t(this,this._t0,PDt(this,this._t0));break}(this._line||this._line!==0&&this._point===1)&&this._context.closePath(),this._line=1-this._line},point:function(i,a){var f=NaN;if(i=+i,a=+a,!(i===this._x1&&a===this._y1)){switch(this._point){case 0:this._point=1,this._line?this._context.lineTo(i,a):this._context.moveTo(i,a);break;case 1:this._point=2;break;case 2:this._point=3,z1t(this,PDt(this,f=ODt(this,i,a)),f);break;default:z1t(this,this._t0,f=ODt(this,i,a));break}this._x0=this._x1,this._x1=i,this._y0=this._y1,this._y1=a,this._t0=f}}};function FDt(i){this._context=new NDt(i)}(FDt.prototype=Object.create(sW.prototype)).point=function(i,a){sW.prototype.point.call(this,a,i)};function NDt(i){this._context=i}NDt.prototype={moveTo:function(i,a){this._context.moveTo(a,i)},closePath:function(){this._context.closePath()},lineTo:function(i,a){this._context.lineTo(a,i)},bezierCurveTo:function(i,a,f,p,w,m){this._context.bezierCurveTo(a,i,p,f,m,w)}};function kTe(i){return new sW(i)}function ETe(i){return new FDt(i)}function BDt(i){this._context=i}BDt.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._x=[],this._y=[]},lineEnd:function(){var i=this._x,a=this._y,f=i.length;if(f)if(this._line?this._context.lineTo(i[0],a[0]):this._context.moveTo(i[0],a[0]),f===2)this._context.lineTo(i[1],a[1]);else for(var p=RDt(i),w=RDt(a),m=0,b=1;b=0;--a)w[a]=(b[a]-w[a+1])/m[a];for(m[f-1]=(i[f]+w[f-1])/2,a=0;a=0&&(this._t=1-this._t,this._line=1-this._line)},point:function(i,a){switch(i=+i,a=+a,this._point){case 0:this._point=1,this._line?this._context.lineTo(i,a):this._context.moveTo(i,a);break;case 1:this._point=2;default:{if(this._t<=0)this._context.lineTo(this._x,a),this._context.lineTo(i,a);else{var f=this._x*(1-this._t)+i*this._t;this._context.lineTo(f,this._y),this._context.lineTo(f,a)}break}}this._x=i,this._y=a}};function CTe(i){return new aW(i,.5)}function _Te(i){return new aW(i,0)}function STe(i){return new aW(i,1)}function VP(i,a,f){this.k=i,this.x=a,this.y=f}VP.prototype={constructor:VP,scale:function(i){return i===1?this:new VP(this.k*i,this.x,this.y)},translate:function(i,a){return i===0&a===0?this:new VP(this.k,this.x+this.k*i,this.y+this.k*a)},apply:function(i){return[i[0]*this.k+this.x,i[1]*this.k+this.y]},applyX:function(i){return i*this.k+this.x},applyY:function(i){return i*this.k+this.y},invert:function(i){return[(i[0]-this.x)/this.k,(i[1]-this.y)/this.k]},invertX:function(i){return(i-this.x)/this.k},invertY:function(i){return(i-this.y)/this.k},rescaleX:function(i){return i.copy().domain(i.range().map(this.invertX,this).map(i.invert,i))},rescaleY:function(i){return i.copy().domain(i.range().map(this.invertY,this).map(i.invert,i))},toString:function(){return"translate("+this.x+","+this.y+") scale("+this.k+")"}},VP.prototype;/*! @license DOMPurify 3.0.5 | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/3.0.5/LICENSE */const{entries:jDt,setPrototypeOf:$Dt,isFrozen:ATe,getPrototypeOf:LTe,getOwnPropertyDescriptor:MTe}=Object;let{freeze:ug,seal:Jv,create:DTe}=Object,{apply:q1t,construct:H1t}=typeof Reflect<"u"&&Reflect;q1t||(q1t=function(a,f,p){return a.apply(f,p)}),ug||(ug=function(a){return a}),Jv||(Jv=function(a){return a}),H1t||(H1t=function(a,f){return new a(...f)});const ITe=J2(Array.prototype.forEach),zDt=J2(Array.prototype.pop),GP=J2(Array.prototype.push),oW=J2(String.prototype.toLowerCase),V1t=J2(String.prototype.toString),OTe=J2(String.prototype.match),tm=J2(String.prototype.replace),PTe=J2(String.prototype.indexOf),FTe=J2(String.prototype.trim),Pb=J2(RegExp.prototype.test),UP=NTe(TypeError);function J2(i){return function(a){for(var f=arguments.length,p=new Array(f>1?f-1:0),w=1;w/gm),zTe=Jv(/\${[\w\W]*}/gm),qTe=Jv(/^data-[\-\w.\u00B7-\uFFFF]/),HTe=Jv(/^aria-[\-\w]+$/),UDt=Jv(/^(?:(?:(?:f|ht)tps?|mailto|tel|callto|sms|cid|xmpp):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i),VTe=Jv(/^(?:\w+script|data):/i),GTe=Jv(/[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205F\u3000]/g),WDt=Jv(/^html$/i);var YDt=Object.freeze({__proto__:null,MUSTACHE_EXPR:jTe,ERB_EXPR:$Te,TMPLIT_EXPR:zTe,DATA_ATTR:qTe,ARIA_ATTR:HTe,IS_ALLOWED_URI:UDt,IS_SCRIPT_OR_DATA:VTe,ATTR_WHITESPACE:GTe,DOCTYPE_NAME:WDt});const UTe=()=>typeof window>"u"?null:window,WTe=function(a,f){if(typeof a!="object"||typeof a.createPolicy!="function")return null;let p=null;const w="data-tt-policy-suffix";f&&f.hasAttribute(w)&&(p=f.getAttribute(w));const m="dompurify"+(p?"#"+p:"");try{return a.createPolicy(m,{createHTML(b){return b},createScriptURL(b){return b}})}catch{return console.warn("TrustedTypes policy "+m+" could not be created."),null}};function KDt(){let i=arguments.length>0&&arguments[0]!==void 0?arguments[0]:UTe();const a=Bi=>KDt(Bi);if(a.version="3.0.5",a.removed=[],!i||!i.document||i.document.nodeType!==9)return a.isSupported=!1,a;const f=i.document,p=f.currentScript;let{document:w}=i;const{DocumentFragment:m,HTMLTemplateElement:b,Node:E,Element:_,NodeFilter:A,NamedNodeMap:I=i.NamedNodeMap||i.MozNamedAttrMap,HTMLFormElement:B,DOMParser:N,trustedTypes:R}=i,z=_.prototype,W=cW(z,"cloneNode"),et=cW(z,"nextSibling"),st=cW(z,"childNodes"),at=cW(z,"parentNode");if(typeof b=="function"){const Bi=w.createElement("template");Bi.content&&Bi.content.ownerDocument&&(w=Bi.content.ownerDocument)}let bt,mt="";const{implementation:yt,createNodeIterator:ft,createDocumentFragment:ut,getElementsByTagName:vt}=w,{importNode:X}=f;let pt={};a.isSupported=typeof jDt=="function"&&typeof at=="function"&&yt&&yt.createHTMLDocument!==void 0;const{MUSTACHE_EXPR:U,ERB_EXPR:Tt,TMPLIT_EXPR:nt,DATA_ATTR:It,ARIA_ATTR:Ot,IS_SCRIPT_OR_DATA:Bt,ATTR_WHITESPACE:Et}=YDt;let{IS_ALLOWED_URI:Z}=YDt,Ct=null;const xt=mo({},[...qDt,...G1t,...U1t,...W1t,...HDt]);let Ht=null;const Le=mo({},[...VDt,...Y1t,...GDt,...uW]);let Ft=Object.seal(Object.create(null,{tagNameCheck:{writable:!0,configurable:!1,enumerable:!0,value:null},attributeNameCheck:{writable:!0,configurable:!1,enumerable:!0,value:null},allowCustomizedBuiltInElements:{writable:!0,configurable:!1,enumerable:!0,value:!1}})),gn=null,Se=null,me=!0,Ve=!0,Ye=!1,ce=!0,ke=!1,zt=!1,re=!1,se=!1,Pe=!1,te=!1,Me=!1,de=!0,on=!1;const ni="user-content-";let Ks=!0,ws=!1,fo={},Xi=null;const Er=mo({},["annotation-xml","audio","colgroup","desc","foreignobject","head","iframe","math","mi","mn","mo","ms","mtext","noembed","noframes","noscript","plaintext","script","style","svg","template","thead","title","video","xmp"]);let Xn=null;const di=mo({},["audio","video","img","source","image","track"]);let Ee=null;const Kn=mo({},["alt","class","for","id","label","name","pattern","placeholder","role","summary","title","value","style","xmlns"]),He="http://www.w3.org/1998/Math/MathML",Ti="http://www.w3.org/2000/svg",pn="http://www.w3.org/1999/xhtml";let Es=pn,qa=!1,Ma=null;const Gs=mo({},[He,Ti,pn],V1t);let Po;const vs=["application/xhtml+xml","text/html"],ru="text/html";let zs,Du=null;const pm=w.createElement("form"),uw=function(cn){return cn instanceof RegExp||cn instanceof Function},Wu=function(cn){if(!(Du&&Du===cn)){if((!cn||typeof cn!="object")&&(cn={}),cn=PA(cn),Po=vs.indexOf(cn.PARSER_MEDIA_TYPE)===-1?Po=ru:Po=cn.PARSER_MEDIA_TYPE,zs=Po==="application/xhtml+xml"?V1t:oW,Ct="ALLOWED_TAGS"in cn?mo({},cn.ALLOWED_TAGS,zs):xt,Ht="ALLOWED_ATTR"in cn?mo({},cn.ALLOWED_ATTR,zs):Le,Ma="ALLOWED_NAMESPACES"in cn?mo({},cn.ALLOWED_NAMESPACES,V1t):Gs,Ee="ADD_URI_SAFE_ATTR"in cn?mo(PA(Kn),cn.ADD_URI_SAFE_ATTR,zs):Kn,Xn="ADD_DATA_URI_TAGS"in cn?mo(PA(di),cn.ADD_DATA_URI_TAGS,zs):di,Xi="FORBID_CONTENTS"in cn?mo({},cn.FORBID_CONTENTS,zs):Er,gn="FORBID_TAGS"in cn?mo({},cn.FORBID_TAGS,zs):{},Se="FORBID_ATTR"in cn?mo({},cn.FORBID_ATTR,zs):{},fo="USE_PROFILES"in cn?cn.USE_PROFILES:!1,me=cn.ALLOW_ARIA_ATTR!==!1,Ve=cn.ALLOW_DATA_ATTR!==!1,Ye=cn.ALLOW_UNKNOWN_PROTOCOLS||!1,ce=cn.ALLOW_SELF_CLOSE_IN_ATTR!==!1,ke=cn.SAFE_FOR_TEMPLATES||!1,zt=cn.WHOLE_DOCUMENT||!1,Pe=cn.RETURN_DOM||!1,te=cn.RETURN_DOM_FRAGMENT||!1,Me=cn.RETURN_TRUSTED_TYPE||!1,se=cn.FORCE_BODY||!1,de=cn.SANITIZE_DOM!==!1,on=cn.SANITIZE_NAMED_PROPS||!1,Ks=cn.KEEP_CONTENT!==!1,ws=cn.IN_PLACE||!1,Z=cn.ALLOWED_URI_REGEXP||UDt,Es=cn.NAMESPACE||pn,Ft=cn.CUSTOM_ELEMENT_HANDLING||{},cn.CUSTOM_ELEMENT_HANDLING&&uw(cn.CUSTOM_ELEMENT_HANDLING.tagNameCheck)&&(Ft.tagNameCheck=cn.CUSTOM_ELEMENT_HANDLING.tagNameCheck),cn.CUSTOM_ELEMENT_HANDLING&&uw(cn.CUSTOM_ELEMENT_HANDLING.attributeNameCheck)&&(Ft.attributeNameCheck=cn.CUSTOM_ELEMENT_HANDLING.attributeNameCheck),cn.CUSTOM_ELEMENT_HANDLING&&typeof cn.CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements=="boolean"&&(Ft.allowCustomizedBuiltInElements=cn.CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements),ke&&(Ve=!1),te&&(Pe=!0),fo&&(Ct=mo({},[...HDt]),Ht=[],fo.html===!0&&(mo(Ct,qDt),mo(Ht,VDt)),fo.svg===!0&&(mo(Ct,G1t),mo(Ht,Y1t),mo(Ht,uW)),fo.svgFilters===!0&&(mo(Ct,U1t),mo(Ht,Y1t),mo(Ht,uW)),fo.mathMl===!0&&(mo(Ct,W1t),mo(Ht,GDt),mo(Ht,uW))),cn.ADD_TAGS&&(Ct===xt&&(Ct=PA(Ct)),mo(Ct,cn.ADD_TAGS,zs)),cn.ADD_ATTR&&(Ht===Le&&(Ht=PA(Ht)),mo(Ht,cn.ADD_ATTR,zs)),cn.ADD_URI_SAFE_ATTR&&mo(Ee,cn.ADD_URI_SAFE_ATTR,zs),cn.FORBID_CONTENTS&&(Xi===Er&&(Xi=PA(Xi)),mo(Xi,cn.FORBID_CONTENTS,zs)),Ks&&(Ct["#text"]=!0),zt&&mo(Ct,["html","head","body"]),Ct.table&&(mo(Ct,["tbody"]),delete gn.tbody),cn.TRUSTED_TYPES_POLICY){if(typeof cn.TRUSTED_TYPES_POLICY.createHTML!="function")throw UP('TRUSTED_TYPES_POLICY configuration option must provide a "createHTML" hook.');if(typeof cn.TRUSTED_TYPES_POLICY.createScriptURL!="function")throw UP('TRUSTED_TYPES_POLICY configuration option must provide a "createScriptURL" hook.');bt=cn.TRUSTED_TYPES_POLICY,mt=bt.createHTML("")}else bt===void 0&&(bt=WTe(R,p)),bt!==null&&typeof mt=="string"&&(mt=bt.createHTML(""));ug&&ug(cn),Du=cn}},th=mo({},["mi","mo","mn","ms","mtext"]),Fa=mo({},["foreignobject","desc","title","annotation-xml"]),Ml=mo({},["title","style","font","a","script"]),ha=mo({},G1t);mo(ha,U1t),mo(ha,BTe);const bc=mo({},W1t);mo(bc,RTe);const Cc=function(cn){let kr=at(cn);(!kr||!kr.tagName)&&(kr={namespaceURI:Es,tagName:"template"});const Ei=oW(cn.tagName),Jo=oW(kr.tagName);return Ma[cn.namespaceURI]?cn.namespaceURI===Ti?kr.namespaceURI===pn?Ei==="svg":kr.namespaceURI===He?Ei==="svg"&&(Jo==="annotation-xml"||th[Jo]):!!ha[Ei]:cn.namespaceURI===He?kr.namespaceURI===pn?Ei==="math":kr.namespaceURI===Ti?Ei==="math"&&Fa[Jo]:!!bc[Ei]:cn.namespaceURI===pn?kr.namespaceURI===Ti&&!Fa[Jo]||kr.namespaceURI===He&&!th[Jo]?!1:!bc[Ei]&&(Ml[Ei]||!ha[Ei]):!!(Po==="application/xhtml+xml"&&Ma[cn.namespaceURI]):!1},pa=function(cn){GP(a.removed,{element:cn});try{cn.parentNode.removeChild(cn)}catch{cn.remove()}},Da=function(cn,kr){try{GP(a.removed,{attribute:kr.getAttributeNode(cn),from:kr})}catch{GP(a.removed,{attribute:null,from:kr})}if(kr.removeAttribute(cn),cn==="is"&&!Ht[cn])if(Pe||te)try{pa(kr)}catch{}else try{kr.setAttribute(cn,"")}catch{}},Ha=function(cn){let kr,Ei;if(se)cn=""+cn;else{const rf=OTe(cn,/^[\r\n\t ]+/);Ei=rf&&rf[0]}Po==="application/xhtml+xml"&&Es===pn&&(cn=''+cn+"");const Jo=bt?bt.createHTML(cn):cn;if(Es===pn)try{kr=new N().parseFromString(Jo,Po)}catch{}if(!kr||!kr.documentElement){kr=yt.createDocument(Es,"template",null);try{kr.documentElement.innerHTML=qa?mt:Jo}catch{}}const wc=kr.body||kr.documentElement;return cn&&Ei&&wc.insertBefore(w.createTextNode(Ei),wc.childNodes[0]||null),Es===pn?vt.call(kr,zt?"html":"body")[0]:zt?kr.documentElement:wc},Dl=function(cn){return ft.call(cn.ownerDocument||cn,cn,A.SHOW_ELEMENT|A.SHOW_COMMENT|A.SHOW_TEXT,null,!1)},_c=function(cn){return cn instanceof B&&(typeof cn.nodeName!="string"||typeof cn.textContent!="string"||typeof cn.removeChild!="function"||!(cn.attributes instanceof I)||typeof cn.removeAttribute!="function"||typeof cn.setAttribute!="function"||typeof cn.namespaceURI!="string"||typeof cn.insertBefore!="function"||typeof cn.hasChildNodes!="function")},lw=function(cn){return typeof E=="object"?cn instanceof E:cn&&typeof cn=="object"&&typeof cn.nodeType=="number"&&typeof cn.nodeName=="string"},eh=function(cn,kr,Ei){pt[cn]&&ITe(pt[cn],Jo=>{Jo.call(a,kr,Ei,Du)})},ed=function(cn){let kr;if(eh("beforeSanitizeElements",cn,null),_c(cn))return pa(cn),!0;const Ei=zs(cn.nodeName);if(eh("uponSanitizeElement",cn,{tagName:Ei,allowedTags:Ct}),cn.hasChildNodes()&&!lw(cn.firstElementChild)&&(!lw(cn.content)||!lw(cn.content.firstElementChild))&&Pb(/<[/\w]/g,cn.innerHTML)&&Pb(/<[/\w]/g,cn.textContent))return pa(cn),!0;if(!Ct[Ei]||gn[Ei]){if(!gn[Ei]&&nd(Ei)&&(Ft.tagNameCheck instanceof RegExp&&Pb(Ft.tagNameCheck,Ei)||Ft.tagNameCheck instanceof Function&&Ft.tagNameCheck(Ei)))return!1;if(Ks&&!Xi[Ei]){const Jo=at(cn)||cn.parentNode,wc=st(cn)||cn.childNodes;if(wc&&Jo){const rf=wc.length;for(let Oc=rf-1;Oc>=0;--Oc)Jo.insertBefore(W(wc[Oc],!0),et(cn))}}return pa(cn),!0}return cn instanceof _&&!Cc(cn)||(Ei==="noscript"||Ei==="noembed"||Ei==="noframes")&&Pb(/<\/no(script|embed|frames)/i,cn.innerHTML)?(pa(cn),!0):(ke&&cn.nodeType===3&&(kr=cn.textContent,kr=tm(kr,U," "),kr=tm(kr,Tt," "),kr=tm(kr,nt," "),cn.textContent!==kr&&(GP(a.removed,{element:cn.cloneNode()}),cn.textContent=kr)),eh("afterSanitizeElements",cn,null),!1)},jd=function(cn,kr,Ei){if(de&&(kr==="id"||kr==="name")&&(Ei in w||Ei in pm))return!1;if(!(Ve&&!Se[kr]&&Pb(It,kr))){if(!(me&&Pb(Ot,kr))){if(!Ht[kr]||Se[kr]){if(!(nd(cn)&&(Ft.tagNameCheck instanceof RegExp&&Pb(Ft.tagNameCheck,cn)||Ft.tagNameCheck instanceof Function&&Ft.tagNameCheck(cn))&&(Ft.attributeNameCheck instanceof RegExp&&Pb(Ft.attributeNameCheck,kr)||Ft.attributeNameCheck instanceof Function&&Ft.attributeNameCheck(kr))||kr==="is"&&Ft.allowCustomizedBuiltInElements&&(Ft.tagNameCheck instanceof RegExp&&Pb(Ft.tagNameCheck,Ei)||Ft.tagNameCheck instanceof Function&&Ft.tagNameCheck(Ei))))return!1}else if(!Ee[kr]){if(!Pb(Z,tm(Ei,Et,""))){if(!((kr==="src"||kr==="xlink:href"||kr==="href")&&cn!=="script"&&PTe(Ei,"data:")===0&&Xn[cn])){if(!(Ye&&!Pb(Bt,tm(Ei,Et,"")))){if(Ei)return!1}}}}}}return!0},nd=function(cn){return cn.indexOf("-")>0},$d=function(cn){let kr,Ei,Jo,wc;eh("beforeSanitizeAttributes",cn,null);const{attributes:rf}=cn;if(!rf)return;const Oc={attrName:"",attrValue:"",keepAttr:!0,allowedAttributes:Ht};for(wc=rf.length;wc--;){kr=rf[wc];const{name:sf,namespaceURI:af}=kr;if(Ei=sf==="value"?kr.value:FTe(kr.value),Jo=zs(sf),Oc.attrName=Jo,Oc.attrValue=Ei,Oc.keepAttr=!0,Oc.forceKeepAttr=void 0,eh("uponSanitizeAttribute",cn,Oc),Ei=Oc.attrValue,Oc.forceKeepAttr||(Da(sf,cn),!Oc.keepAttr))continue;if(!ce&&Pb(/\/>/i,Ei)){Da(sf,cn);continue}ke&&(Ei=tm(Ei,U," "),Ei=tm(Ei,Tt," "),Ei=tm(Ei,nt," "));const Qi=zs(cn.nodeName);if(jd(Qi,Jo,Ei)){if(on&&(Jo==="id"||Jo==="name")&&(Da(sf,cn),Ei=ni+Ei),bt&&typeof R=="object"&&typeof R.getAttributeType=="function"&&!af)switch(R.getAttributeType(Qi,Jo)){case"TrustedHTML":{Ei=bt.createHTML(Ei);break}case"TrustedScriptURL":{Ei=bt.createScriptURL(Ei);break}}try{af?cn.setAttributeNS(af,sf,Ei):cn.setAttribute(sf,Ei),zDt(a.removed)}catch{}}}eh("afterSanitizeAttributes",cn,null)},A0=function Bi(cn){let kr;const Ei=Dl(cn);for(eh("beforeSanitizeShadowDOM",cn,null);kr=Ei.nextNode();)eh("uponSanitizeShadowNode",kr,null),!ed(kr)&&(kr.content instanceof m&&Bi(kr.content),$d(kr));eh("afterSanitizeShadowDOM",cn,null)};return a.sanitize=function(Bi){let cn=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{},kr,Ei,Jo,wc;if(qa=!Bi,qa&&(Bi=""),typeof Bi!="string"&&!lw(Bi))if(typeof Bi.toString=="function"){if(Bi=Bi.toString(),typeof Bi!="string")throw UP("dirty is not a string, aborting")}else throw UP("toString is not a function");if(!a.isSupported)return Bi;if(re||Wu(cn),a.removed=[],typeof Bi=="string"&&(ws=!1),ws){if(Bi.nodeName){const sf=zs(Bi.nodeName);if(!Ct[sf]||gn[sf])throw UP("root node is forbidden and cannot be sanitized in-place")}}else if(Bi instanceof E)kr=Ha(""),Ei=kr.ownerDocument.importNode(Bi,!0),Ei.nodeType===1&&Ei.nodeName==="BODY"||Ei.nodeName==="HTML"?kr=Ei:kr.appendChild(Ei);else{if(!Pe&&!ke&&!zt&&Bi.indexOf("<")===-1)return bt&&Me?bt.createHTML(Bi):Bi;if(kr=Ha(Bi),!kr)return Pe?null:Me?mt:""}kr&&se&&pa(kr.firstChild);const rf=Dl(ws?Bi:kr);for(;Jo=rf.nextNode();)ed(Jo)||(Jo.content instanceof m&&A0(Jo.content),$d(Jo));if(ws)return Bi;if(Pe){if(te)for(wc=ut.call(kr.ownerDocument);kr.firstChild;)wc.appendChild(kr.firstChild);else wc=kr;return(Ht.shadowroot||Ht.shadowrootmode)&&(wc=X.call(f,wc,!0)),wc}let Oc=zt?kr.outerHTML:kr.innerHTML;return zt&&Ct["!doctype"]&&kr.ownerDocument&&kr.ownerDocument.doctype&&kr.ownerDocument.doctype.name&&Pb(WDt,kr.ownerDocument.doctype.name)&&(Oc=" +`+Oc),ke&&(Oc=tm(Oc,U," "),Oc=tm(Oc,Tt," "),Oc=tm(Oc,nt," ")),bt&&Me?bt.createHTML(Oc):Oc},a.setConfig=function(Bi){Wu(Bi),re=!0},a.clearConfig=function(){Du=null,re=!1},a.isValidAttribute=function(Bi,cn,kr){Du||Wu({});const Ei=zs(Bi),Jo=zs(cn);return jd(Ei,Jo,kr)},a.addHook=function(Bi,cn){typeof cn=="function"&&(pt[Bi]=pt[Bi]||[],GP(pt[Bi],cn))},a.removeHook=function(Bi){if(pt[Bi])return zDt(pt[Bi])},a.removeHooks=function(Bi){pt[Bi]&&(pt[Bi]=[])},a.removeAllHooks=function(){pt={}},a}var lW=KDt();const WP=//gi,YTe=i=>i?ZDt(i).replace(/\\n/g,"#br#").split("#br#"):[""],XDt=i=>lW.sanitize(i),QDt=(i,a)=>{var f;if(((f=a.flowchart)==null?void 0:f.htmlLabels)!==!1){const p=a.securityLevel;p==="antiscript"||p==="strict"?i=XDt(i):p!=="loose"&&(i=ZDt(i),i=i.replace(//g,">"),i=i.replace(/=/g,"="),i=ZTe(i))}return i},Q1=(i,a)=>i&&(a.dompurifyConfig?i=lW.sanitize(QDt(i,a),a.dompurifyConfig).toString():i=lW.sanitize(QDt(i,a),{FORBID_TAGS:["style"]}).toString(),i),KTe=(i,a)=>typeof i=="string"?Q1(i,a):i.flat().map(f=>Q1(f,a)),XTe=i=>WP.test(i),QTe=i=>i.split(WP),ZTe=i=>i.replace(/#br#/g,"
            "),ZDt=i=>i.replace(WP,"#br#"),JTe=i=>{let a="";return i&&(a=window.location.protocol+"//"+window.location.host+window.location.pathname+window.location.search,a=a.replaceAll(/\(/g,"\\("),a=a.replaceAll(/\)/g,"\\)")),a},o1=i=>!(i===!1||["false","null","0"].includes(String(i).trim().toLowerCase())),tCe=function(...i){const a=i.filter(f=>!isNaN(f));return Math.max(...a)},eCe=function(...i){const a=i.filter(f=>!isNaN(f));return Math.min(...a)},YP=function(i){const a=i.split(/(,)/),f=[];for(let p=0;p0&&p+1Math.max(0,i.split(a).length-1),nCe=(i,a)=>{const f=K1t(i,"~"),p=K1t(a,"~");return f===1&&p===1},rCe=i=>{const a=K1t(i,"~");let f=!1;if(a<=1)return i;a%2!==0&&i.startsWith("~")&&(i=i.substring(1),f=!0);const p=[...i];let w=p.indexOf("~"),m=p.lastIndexOf("~");for(;w!==-1&&m!==-1&&w!==m;)p[w]="<",p[m]=">",w=p.indexOf("~"),m=p.lastIndexOf("~");return f&&p.unshift("~"),p.join("")},Kr={getRows:YTe,sanitizeText:Q1,sanitizeTextOrArray:KTe,hasBreaks:XTe,splitBreaks:QTe,lineBreakRegex:WP,removeScript:XDt,getUrl:JTe,evaluate:o1,getMax:tCe,getMin:eCe},hW={min:{r:0,g:0,b:0,s:0,l:0,a:0},max:{r:255,g:255,b:255,h:360,s:100,l:100,a:1},clamp:{r:i=>i>=255?255:i<0?0:i,g:i=>i>=255?255:i<0?0:i,b:i=>i>=255?255:i<0?0:i,h:i=>i%360,s:i=>i>=100?100:i<0?0:i,l:i=>i>=100?100:i<0?0:i,a:i=>i>=1?1:i<0?0:i},toLinear:i=>{const a=i/255;return i>.03928?Math.pow((a+.055)/1.055,2.4):a/12.92},hue2rgb:(i,a,f)=>(f<0&&(f+=1),f>1&&(f-=1),f<1/6?i+(a-i)*6*f:f<1/2?a:f<2/3?i+(a-i)*(2/3-f)*6:i),hsl2rgb:({h:i,s:a,l:f},p)=>{if(!a)return f*2.55;i/=360,a/=100,f/=100;const w=f<.5?f*(1+a):f+a-f*a,m=2*f-w;switch(p){case"r":return hW.hue2rgb(m,w,i+1/3)*255;case"g":return hW.hue2rgb(m,w,i)*255;case"b":return hW.hue2rgb(m,w,i-1/3)*255}},rgb2hsl:({r:i,g:a,b:f},p)=>{i/=255,a/=255,f/=255;const w=Math.max(i,a,f),m=Math.min(i,a,f),b=(w+m)/2;if(p==="l")return b*100;if(w===m)return 0;const E=w-m,_=b>.5?E/(2-w-m):E/(w+m);if(p==="s")return _*100;switch(w){case i:return((a-f)/E+(aa>f?Math.min(a,Math.max(f,i)):Math.min(f,Math.max(a,i)),round:i=>Math.round(i*1e10)/1e10},unit:{dec2hex:i=>{const a=Math.round(i).toString(16);return a.length>1?a:`0${a}`}}},ok={};for(let i=0;i<=255;i++)ok[i]=ga.unit.dec2hex(i);const x0={ALL:0,RGB:1,HSL:2};class iCe{constructor(){this.type=x0.ALL}get(){return this.type}set(a){if(this.type&&this.type!==a)throw new Error("Cannot change both RGB and HSL channels at the same time");this.type=a}reset(){this.type=x0.ALL}is(a){return this.type===a}}const sCe=iCe;class aCe{constructor(a,f){this.color=f,this.changed=!1,this.data=a,this.type=new sCe}set(a,f){return this.color=f,this.changed=!1,this.data=a,this.type.type=x0.ALL,this}_ensureHSL(){const a=this.data,{h:f,s:p,l:w}=a;f===void 0&&(a.h=ga.channel.rgb2hsl(a,"h")),p===void 0&&(a.s=ga.channel.rgb2hsl(a,"s")),w===void 0&&(a.l=ga.channel.rgb2hsl(a,"l"))}_ensureRGB(){const a=this.data,{r:f,g:p,b:w}=a;f===void 0&&(a.r=ga.channel.hsl2rgb(a,"r")),p===void 0&&(a.g=ga.channel.hsl2rgb(a,"g")),w===void 0&&(a.b=ga.channel.hsl2rgb(a,"b"))}get r(){const a=this.data,f=a.r;return!this.type.is(x0.HSL)&&f!==void 0?f:(this._ensureHSL(),ga.channel.hsl2rgb(a,"r"))}get g(){const a=this.data,f=a.g;return!this.type.is(x0.HSL)&&f!==void 0?f:(this._ensureHSL(),ga.channel.hsl2rgb(a,"g"))}get b(){const a=this.data,f=a.b;return!this.type.is(x0.HSL)&&f!==void 0?f:(this._ensureHSL(),ga.channel.hsl2rgb(a,"b"))}get h(){const a=this.data,f=a.h;return!this.type.is(x0.RGB)&&f!==void 0?f:(this._ensureRGB(),ga.channel.rgb2hsl(a,"h"))}get s(){const a=this.data,f=a.s;return!this.type.is(x0.RGB)&&f!==void 0?f:(this._ensureRGB(),ga.channel.rgb2hsl(a,"s"))}get l(){const a=this.data,f=a.l;return!this.type.is(x0.RGB)&&f!==void 0?f:(this._ensureRGB(),ga.channel.rgb2hsl(a,"l"))}get a(){return this.data.a}set r(a){this.type.set(x0.RGB),this.changed=!0,this.data.r=a}set g(a){this.type.set(x0.RGB),this.changed=!0,this.data.g=a}set b(a){this.type.set(x0.RGB),this.changed=!0,this.data.b=a}set h(a){this.type.set(x0.HSL),this.changed=!0,this.data.h=a}set s(a){this.type.set(x0.HSL),this.changed=!0,this.data.s=a}set l(a){this.type.set(x0.HSL),this.changed=!0,this.data.l=a}set a(a){this.changed=!0,this.data.a=a}}const oCe=aCe,fW=new oCe({r:0,g:0,b:0,a:0},"transparent"),JDt={re:/^#((?:[a-f0-9]{2}){2,4}|[a-f0-9]{3})$/i,parse:i=>{if(i.charCodeAt(0)!==35)return;const a=i.match(JDt.re);if(!a)return;const f=a[1],p=parseInt(f,16),w=f.length,m=w%4===0,b=w>4,E=b?1:17,_=b?8:4,A=m?0:-1,I=b?255:15;return fW.set({r:(p>>_*(A+3)&I)*E,g:(p>>_*(A+2)&I)*E,b:(p>>_*(A+1)&I)*E,a:m?(p&I)*E/255:1},i)},stringify:i=>{const{r:a,g:f,b:p,a:w}=i;return w<1?`#${ok[Math.round(a)]}${ok[Math.round(f)]}${ok[Math.round(p)]}${ok[Math.round(w*255)]}`:`#${ok[Math.round(a)]}${ok[Math.round(f)]}${ok[Math.round(p)]}`}},KP=JDt,dW={re:/^hsla?\(\s*?(-?(?:\d+(?:\.\d+)?|(?:\.\d+))(?:e-?\d+)?(?:deg|grad|rad|turn)?)\s*?(?:,|\s)\s*?(-?(?:\d+(?:\.\d+)?|(?:\.\d+))(?:e-?\d+)?%)\s*?(?:,|\s)\s*?(-?(?:\d+(?:\.\d+)?|(?:\.\d+))(?:e-?\d+)?%)(?:\s*?(?:,|\/)\s*?\+?(-?(?:\d+(?:\.\d+)?|(?:\.\d+))(?:e-?\d+)?(%)?))?\s*?\)$/i,hueRe:/^(.+?)(deg|grad|rad|turn)$/i,_hue2deg:i=>{const a=i.match(dW.hueRe);if(a){const[,f,p]=a;switch(p){case"grad":return ga.channel.clamp.h(parseFloat(f)*.9);case"rad":return ga.channel.clamp.h(parseFloat(f)*180/Math.PI);case"turn":return ga.channel.clamp.h(parseFloat(f)*360)}}return ga.channel.clamp.h(parseFloat(i))},parse:i=>{const a=i.charCodeAt(0);if(a!==104&&a!==72)return;const f=i.match(dW.re);if(!f)return;const[,p,w,m,b,E]=f;return fW.set({h:dW._hue2deg(p),s:ga.channel.clamp.s(parseFloat(w)),l:ga.channel.clamp.l(parseFloat(m)),a:b?ga.channel.clamp.a(E?parseFloat(b)/100:parseFloat(b)):1},i)},stringify:i=>{const{h:a,s:f,l:p,a:w}=i;return w<1?`hsla(${ga.lang.round(a)}, ${ga.lang.round(f)}%, ${ga.lang.round(p)}%, ${w})`:`hsl(${ga.lang.round(a)}, ${ga.lang.round(f)}%, ${ga.lang.round(p)}%)`}},gW=dW,pW={colors:{aliceblue:"#f0f8ff",antiquewhite:"#faebd7",aqua:"#00ffff",aquamarine:"#7fffd4",azure:"#f0ffff",beige:"#f5f5dc",bisque:"#ffe4c4",black:"#000000",blanchedalmond:"#ffebcd",blue:"#0000ff",blueviolet:"#8a2be2",brown:"#a52a2a",burlywood:"#deb887",cadetblue:"#5f9ea0",chartreuse:"#7fff00",chocolate:"#d2691e",coral:"#ff7f50",cornflowerblue:"#6495ed",cornsilk:"#fff8dc",crimson:"#dc143c",cyanaqua:"#00ffff",darkblue:"#00008b",darkcyan:"#008b8b",darkgoldenrod:"#b8860b",darkgray:"#a9a9a9",darkgreen:"#006400",darkgrey:"#a9a9a9",darkkhaki:"#bdb76b",darkmagenta:"#8b008b",darkolivegreen:"#556b2f",darkorange:"#ff8c00",darkorchid:"#9932cc",darkred:"#8b0000",darksalmon:"#e9967a",darkseagreen:"#8fbc8f",darkslateblue:"#483d8b",darkslategray:"#2f4f4f",darkslategrey:"#2f4f4f",darkturquoise:"#00ced1",darkviolet:"#9400d3",deeppink:"#ff1493",deepskyblue:"#00bfff",dimgray:"#696969",dimgrey:"#696969",dodgerblue:"#1e90ff",firebrick:"#b22222",floralwhite:"#fffaf0",forestgreen:"#228b22",fuchsia:"#ff00ff",gainsboro:"#dcdcdc",ghostwhite:"#f8f8ff",gold:"#ffd700",goldenrod:"#daa520",gray:"#808080",green:"#008000",greenyellow:"#adff2f",grey:"#808080",honeydew:"#f0fff0",hotpink:"#ff69b4",indianred:"#cd5c5c",indigo:"#4b0082",ivory:"#fffff0",khaki:"#f0e68c",lavender:"#e6e6fa",lavenderblush:"#fff0f5",lawngreen:"#7cfc00",lemonchiffon:"#fffacd",lightblue:"#add8e6",lightcoral:"#f08080",lightcyan:"#e0ffff",lightgoldenrodyellow:"#fafad2",lightgray:"#d3d3d3",lightgreen:"#90ee90",lightgrey:"#d3d3d3",lightpink:"#ffb6c1",lightsalmon:"#ffa07a",lightseagreen:"#20b2aa",lightskyblue:"#87cefa",lightslategray:"#778899",lightslategrey:"#778899",lightsteelblue:"#b0c4de",lightyellow:"#ffffe0",lime:"#00ff00",limegreen:"#32cd32",linen:"#faf0e6",magenta:"#ff00ff",maroon:"#800000",mediumaquamarine:"#66cdaa",mediumblue:"#0000cd",mediumorchid:"#ba55d3",mediumpurple:"#9370db",mediumseagreen:"#3cb371",mediumslateblue:"#7b68ee",mediumspringgreen:"#00fa9a",mediumturquoise:"#48d1cc",mediumvioletred:"#c71585",midnightblue:"#191970",mintcream:"#f5fffa",mistyrose:"#ffe4e1",moccasin:"#ffe4b5",navajowhite:"#ffdead",navy:"#000080",oldlace:"#fdf5e6",olive:"#808000",olivedrab:"#6b8e23",orange:"#ffa500",orangered:"#ff4500",orchid:"#da70d6",palegoldenrod:"#eee8aa",palegreen:"#98fb98",paleturquoise:"#afeeee",palevioletred:"#db7093",papayawhip:"#ffefd5",peachpuff:"#ffdab9",peru:"#cd853f",pink:"#ffc0cb",plum:"#dda0dd",powderblue:"#b0e0e6",purple:"#800080",rebeccapurple:"#663399",red:"#ff0000",rosybrown:"#bc8f8f",royalblue:"#4169e1",saddlebrown:"#8b4513",salmon:"#fa8072",sandybrown:"#f4a460",seagreen:"#2e8b57",seashell:"#fff5ee",sienna:"#a0522d",silver:"#c0c0c0",skyblue:"#87ceeb",slateblue:"#6a5acd",slategray:"#708090",slategrey:"#708090",snow:"#fffafa",springgreen:"#00ff7f",tan:"#d2b48c",teal:"#008080",thistle:"#d8bfd8",transparent:"#00000000",turquoise:"#40e0d0",violet:"#ee82ee",wheat:"#f5deb3",white:"#ffffff",whitesmoke:"#f5f5f5",yellow:"#ffff00",yellowgreen:"#9acd32"},parse:i=>{i=i.toLowerCase();const a=pW.colors[i];if(a)return KP.parse(a)},stringify:i=>{const a=KP.stringify(i);for(const f in pW.colors)if(pW.colors[f]===a)return f}},tIt=pW,eIt={re:/^rgba?\(\s*?(-?(?:\d+(?:\.\d+)?|(?:\.\d+))(?:e\d+)?(%?))\s*?(?:,|\s)\s*?(-?(?:\d+(?:\.\d+)?|(?:\.\d+))(?:e\d+)?(%?))\s*?(?:,|\s)\s*?(-?(?:\d+(?:\.\d+)?|(?:\.\d+))(?:e\d+)?(%?))(?:\s*?(?:,|\/)\s*?\+?(-?(?:\d+(?:\.\d+)?|(?:\.\d+))(?:e\d+)?(%?)))?\s*?\)$/i,parse:i=>{const a=i.charCodeAt(0);if(a!==114&&a!==82)return;const f=i.match(eIt.re);if(!f)return;const[,p,w,m,b,E,_,A,I]=f;return fW.set({r:ga.channel.clamp.r(w?parseFloat(p)*2.55:parseFloat(p)),g:ga.channel.clamp.g(b?parseFloat(m)*2.55:parseFloat(m)),b:ga.channel.clamp.b(_?parseFloat(E)*2.55:parseFloat(E)),a:A?ga.channel.clamp.a(I?parseFloat(A)/100:parseFloat(A)):1},i)},stringify:i=>{const{r:a,g:f,b:p,a:w}=i;return w<1?`rgba(${ga.lang.round(a)}, ${ga.lang.round(f)}, ${ga.lang.round(p)}, ${ga.lang.round(w)})`:`rgb(${ga.lang.round(a)}, ${ga.lang.round(f)}, ${ga.lang.round(p)})`}},bW=eIt,em={format:{keyword:tIt,hex:KP,rgb:bW,rgba:bW,hsl:gW,hsla:gW},parse:i=>{if(typeof i!="string")return i;const a=KP.parse(i)||bW.parse(i)||gW.parse(i)||tIt.parse(i);if(a)return a;throw new Error(`Unsupported color format: "${i}"`)},stringify:i=>!i.changed&&i.color?i.color:i.type.is(x0.HSL)||i.data.r===void 0?gW.stringify(i):i.a<1||!Number.isInteger(i.r)||!Number.isInteger(i.g)||!Number.isInteger(i.b)?bW.stringify(i):KP.stringify(i)},nIt=(i,a)=>{const f=em.parse(i);for(const p in a)f[p]=ga.channel.clamp[p](a[p]);return em.stringify(f)},FA=(i,a,f=0,p=1)=>{if(typeof i!="number")return nIt(i,{a});const w=fW.set({r:ga.channel.clamp.r(i),g:ga.channel.clamp.g(a),b:ga.channel.clamp.b(f),a:ga.channel.clamp.a(p)});return em.stringify(w)},cCe=(i,a)=>ga.lang.round(em.parse(i)[a]),uCe=i=>{const{r:a,g:f,b:p}=em.parse(i),w=.2126*ga.channel.toLinear(a)+.7152*ga.channel.toLinear(f)+.0722*ga.channel.toLinear(p);return ga.lang.round(w)},lCe=i=>uCe(i)>=.5,iT=i=>!lCe(i),rIt=(i,a,f)=>{const p=em.parse(i),w=p[a],m=ga.channel.clamp[a](w+f);return w!==m&&(p[a]=m),em.stringify(p)},bs=(i,a)=>rIt(i,"l",a),$s=(i,a)=>rIt(i,"l",-a),xn=(i,a)=>{const f=em.parse(i),p={};for(const w in a)a[w]&&(p[w]=f[w]+a[w]);return nIt(i,p)},hCe=(i,a,f=50)=>{const{r:p,g:w,b:m,a:b}=em.parse(i),{r:E,g:_,b:A,a:I}=em.parse(a),B=f/100,N=B*2-1,R=b-I,W=((N*R===-1?N:(N+R)/(1+N*R))+1)/2,et=1-W,st=p*W+E*et,at=w*W+_*et,bt=m*W+A*et,mt=b*B+I*(1-B);return FA(st,at,bt,mt)},Di=(i,a=100)=>{const f=em.parse(i);return f.r=255-f.r,f.g=255-f.g,f.b=255-f.b,hCe(f,i,a)},lg=(i,a)=>a?xn(i,{s:-40,l:10}):xn(i,{s:-40,l:-10}),wW="#ffffff",vW="#f2f2f2";let fCe=class{constructor(){this.background="#f4f4f4",this.primaryColor="#fff4dd",this.noteBkgColor="#fff5ad",this.noteTextColor="#333",this.THEME_COLOR_LIMIT=12,this.fontFamily='"trebuchet ms", verdana, arial, sans-serif',this.fontSize="16px"}updateColors(){var f,p,w,m,b,E,_,A,I,B,N;if(this.primaryTextColor=this.primaryTextColor||(this.darkMode?"#eee":"#333"),this.secondaryColor=this.secondaryColor||xn(this.primaryColor,{h:-120}),this.tertiaryColor=this.tertiaryColor||xn(this.primaryColor,{h:180,l:5}),this.primaryBorderColor=this.primaryBorderColor||lg(this.primaryColor,this.darkMode),this.secondaryBorderColor=this.secondaryBorderColor||lg(this.secondaryColor,this.darkMode),this.tertiaryBorderColor=this.tertiaryBorderColor||lg(this.tertiaryColor,this.darkMode),this.noteBorderColor=this.noteBorderColor||lg(this.noteBkgColor,this.darkMode),this.noteBkgColor=this.noteBkgColor||"#fff5ad",this.noteTextColor=this.noteTextColor||"#333",this.secondaryTextColor=this.secondaryTextColor||Di(this.secondaryColor),this.tertiaryTextColor=this.tertiaryTextColor||Di(this.tertiaryColor),this.lineColor=this.lineColor||Di(this.background),this.arrowheadColor=this.arrowheadColor||Di(this.background),this.textColor=this.textColor||this.primaryTextColor,this.border2=this.border2||this.tertiaryBorderColor,this.nodeBkg=this.nodeBkg||this.primaryColor,this.mainBkg=this.mainBkg||this.primaryColor,this.nodeBorder=this.nodeBorder||this.primaryBorderColor,this.clusterBkg=this.clusterBkg||this.tertiaryColor,this.clusterBorder=this.clusterBorder||this.tertiaryBorderColor,this.defaultLinkColor=this.defaultLinkColor||this.lineColor,this.titleColor=this.titleColor||this.tertiaryTextColor,this.edgeLabelBackground=this.edgeLabelBackground||(this.darkMode?$s(this.secondaryColor,30):this.secondaryColor),this.nodeTextColor=this.nodeTextColor||this.primaryTextColor,this.actorBorder=this.actorBorder||this.primaryBorderColor,this.actorBkg=this.actorBkg||this.mainBkg,this.actorTextColor=this.actorTextColor||this.primaryTextColor,this.actorLineColor=this.actorLineColor||"grey",this.labelBoxBkgColor=this.labelBoxBkgColor||this.actorBkg,this.signalColor=this.signalColor||this.textColor,this.signalTextColor=this.signalTextColor||this.textColor,this.labelBoxBorderColor=this.labelBoxBorderColor||this.actorBorder,this.labelTextColor=this.labelTextColor||this.actorTextColor,this.loopTextColor=this.loopTextColor||this.actorTextColor,this.activationBorderColor=this.activationBorderColor||$s(this.secondaryColor,10),this.activationBkgColor=this.activationBkgColor||this.secondaryColor,this.sequenceNumberColor=this.sequenceNumberColor||Di(this.lineColor),this.sectionBkgColor=this.sectionBkgColor||this.tertiaryColor,this.altSectionBkgColor=this.altSectionBkgColor||"white",this.sectionBkgColor=this.sectionBkgColor||this.secondaryColor,this.sectionBkgColor2=this.sectionBkgColor2||this.primaryColor,this.excludeBkgColor=this.excludeBkgColor||"#eeeeee",this.taskBorderColor=this.taskBorderColor||this.primaryBorderColor,this.taskBkgColor=this.taskBkgColor||this.primaryColor,this.activeTaskBorderColor=this.activeTaskBorderColor||this.primaryColor,this.activeTaskBkgColor=this.activeTaskBkgColor||bs(this.primaryColor,23),this.gridColor=this.gridColor||"lightgrey",this.doneTaskBkgColor=this.doneTaskBkgColor||"lightgrey",this.doneTaskBorderColor=this.doneTaskBorderColor||"grey",this.critBorderColor=this.critBorderColor||"#ff8888",this.critBkgColor=this.critBkgColor||"red",this.todayLineColor=this.todayLineColor||"red",this.taskTextColor=this.taskTextColor||this.textColor,this.taskTextOutsideColor=this.taskTextOutsideColor||this.textColor,this.taskTextLightColor=this.taskTextLightColor||this.textColor,this.taskTextColor=this.taskTextColor||this.primaryTextColor,this.taskTextDarkColor=this.taskTextDarkColor||this.textColor,this.taskTextClickableColor=this.taskTextClickableColor||"#003163",this.personBorder=this.personBorder||this.primaryBorderColor,this.personBkg=this.personBkg||this.mainBkg,this.transitionColor=this.transitionColor||this.lineColor,this.transitionLabelColor=this.transitionLabelColor||this.textColor,this.stateLabelColor=this.stateLabelColor||this.stateBkg||this.primaryTextColor,this.stateBkg=this.stateBkg||this.mainBkg,this.labelBackgroundColor=this.labelBackgroundColor||this.stateBkg,this.compositeBackground=this.compositeBackground||this.background||this.tertiaryColor,this.altBackground=this.altBackground||this.tertiaryColor,this.compositeTitleBackground=this.compositeTitleBackground||this.mainBkg,this.compositeBorder=this.compositeBorder||this.nodeBorder,this.innerEndBackground=this.nodeBorder,this.errorBkgColor=this.errorBkgColor||this.tertiaryColor,this.errorTextColor=this.errorTextColor||this.tertiaryTextColor,this.transitionColor=this.transitionColor||this.lineColor,this.specialStateColor=this.lineColor,this.cScale0=this.cScale0||this.primaryColor,this.cScale1=this.cScale1||this.secondaryColor,this.cScale2=this.cScale2||this.tertiaryColor,this.cScale3=this.cScale3||xn(this.primaryColor,{h:30}),this.cScale4=this.cScale4||xn(this.primaryColor,{h:60}),this.cScale5=this.cScale5||xn(this.primaryColor,{h:90}),this.cScale6=this.cScale6||xn(this.primaryColor,{h:120}),this.cScale7=this.cScale7||xn(this.primaryColor,{h:150}),this.cScale8=this.cScale8||xn(this.primaryColor,{h:210,l:150}),this.cScale9=this.cScale9||xn(this.primaryColor,{h:270}),this.cScale10=this.cScale10||xn(this.primaryColor,{h:300}),this.cScale11=this.cScale11||xn(this.primaryColor,{h:330}),this.darkMode)for(let R=0;R{this[p]=a[p]}),this.updateColors(),f.forEach(p=>{this[p]=a[p]})}};const dCe=i=>{const a=new fCe;return a.calculate(i),a};let gCe=class{constructor(){this.background="#333",this.primaryColor="#1f2020",this.secondaryColor=bs(this.primaryColor,16),this.tertiaryColor=xn(this.primaryColor,{h:-160}),this.primaryBorderColor=Di(this.background),this.secondaryBorderColor=lg(this.secondaryColor,this.darkMode),this.tertiaryBorderColor=lg(this.tertiaryColor,this.darkMode),this.primaryTextColor=Di(this.primaryColor),this.secondaryTextColor=Di(this.secondaryColor),this.tertiaryTextColor=Di(this.tertiaryColor),this.lineColor=Di(this.background),this.textColor=Di(this.background),this.mainBkg="#1f2020",this.secondBkg="calculated",this.mainContrastColor="lightgrey",this.darkTextColor=bs(Di("#323D47"),10),this.lineColor="calculated",this.border1="#81B1DB",this.border2=FA(255,255,255,.25),this.arrowheadColor="calculated",this.fontFamily='"trebuchet ms", verdana, arial, sans-serif',this.fontSize="16px",this.labelBackground="#181818",this.textColor="#ccc",this.THEME_COLOR_LIMIT=12,this.nodeBkg="calculated",this.nodeBorder="calculated",this.clusterBkg="calculated",this.clusterBorder="calculated",this.defaultLinkColor="calculated",this.titleColor="#F9FFFE",this.edgeLabelBackground="calculated",this.actorBorder="calculated",this.actorBkg="calculated",this.actorTextColor="calculated",this.actorLineColor="calculated",this.signalColor="calculated",this.signalTextColor="calculated",this.labelBoxBkgColor="calculated",this.labelBoxBorderColor="calculated",this.labelTextColor="calculated",this.loopTextColor="calculated",this.noteBorderColor="calculated",this.noteBkgColor="#fff5ad",this.noteTextColor="calculated",this.activationBorderColor="calculated",this.activationBkgColor="calculated",this.sequenceNumberColor="black",this.sectionBkgColor=$s("#EAE8D9",30),this.altSectionBkgColor="calculated",this.sectionBkgColor2="#EAE8D9",this.excludeBkgColor=$s(this.sectionBkgColor,10),this.taskBorderColor=FA(255,255,255,70),this.taskBkgColor="calculated",this.taskTextColor="calculated",this.taskTextLightColor="calculated",this.taskTextOutsideColor="calculated",this.taskTextClickableColor="#003163",this.activeTaskBorderColor=FA(255,255,255,50),this.activeTaskBkgColor="#81B1DB",this.gridColor="calculated",this.doneTaskBkgColor="calculated",this.doneTaskBorderColor="grey",this.critBorderColor="#E83737",this.critBkgColor="#E83737",this.taskTextDarkColor="calculated",this.todayLineColor="#DB5757",this.personBorder=this.primaryBorderColor,this.personBkg=this.mainBkg,this.labelColor="calculated",this.errorBkgColor="#a44141",this.errorTextColor="#ddd"}updateColors(){var a,f,p,w,m,b,E,_,A,I,B;this.secondBkg=bs(this.mainBkg,16),this.lineColor=this.mainContrastColor,this.arrowheadColor=this.mainContrastColor,this.nodeBkg=this.mainBkg,this.nodeBorder=this.border1,this.clusterBkg=this.secondBkg,this.clusterBorder=this.border2,this.defaultLinkColor=this.lineColor,this.edgeLabelBackground=bs(this.labelBackground,25),this.actorBorder=this.border1,this.actorBkg=this.mainBkg,this.actorTextColor=this.mainContrastColor,this.actorLineColor=this.mainContrastColor,this.signalColor=this.mainContrastColor,this.signalTextColor=this.mainContrastColor,this.labelBoxBkgColor=this.actorBkg,this.labelBoxBorderColor=this.actorBorder,this.labelTextColor=this.mainContrastColor,this.loopTextColor=this.mainContrastColor,this.noteBorderColor=this.secondaryBorderColor,this.noteBkgColor=this.secondBkg,this.noteTextColor=this.secondaryTextColor,this.activationBorderColor=this.border1,this.activationBkgColor=this.secondBkg,this.altSectionBkgColor=this.background,this.taskBkgColor=bs(this.mainBkg,23),this.taskTextColor=this.darkTextColor,this.taskTextLightColor=this.mainContrastColor,this.taskTextOutsideColor=this.taskTextLightColor,this.gridColor=this.mainContrastColor,this.doneTaskBkgColor=this.mainContrastColor,this.taskTextDarkColor=this.darkTextColor,this.transitionColor=this.transitionColor||this.lineColor,this.transitionLabelColor=this.transitionLabelColor||this.textColor,this.stateLabelColor=this.stateLabelColor||this.stateBkg||this.primaryTextColor,this.stateBkg=this.stateBkg||this.mainBkg,this.labelBackgroundColor=this.labelBackgroundColor||this.stateBkg,this.compositeBackground=this.compositeBackground||this.background||this.tertiaryColor,this.altBackground=this.altBackground||"#555",this.compositeTitleBackground=this.compositeTitleBackground||this.mainBkg,this.compositeBorder=this.compositeBorder||this.nodeBorder,this.innerEndBackground=this.primaryBorderColor,this.specialStateColor="#f4f4f4",this.errorBkgColor=this.errorBkgColor||this.tertiaryColor,this.errorTextColor=this.errorTextColor||this.tertiaryTextColor,this.fillType0=this.primaryColor,this.fillType1=this.secondaryColor,this.fillType2=xn(this.primaryColor,{h:64}),this.fillType3=xn(this.secondaryColor,{h:64}),this.fillType4=xn(this.primaryColor,{h:-64}),this.fillType5=xn(this.secondaryColor,{h:-64}),this.fillType6=xn(this.primaryColor,{h:128}),this.fillType7=xn(this.secondaryColor,{h:128}),this.cScale1=this.cScale1||"#0b0000",this.cScale2=this.cScale2||"#4d1037",this.cScale3=this.cScale3||"#3f5258",this.cScale4=this.cScale4||"#4f2f1b",this.cScale5=this.cScale5||"#6e0a0a",this.cScale6=this.cScale6||"#3b0048",this.cScale7=this.cScale7||"#995a01",this.cScale8=this.cScale8||"#154706",this.cScale9=this.cScale9||"#161722",this.cScale10=this.cScale10||"#00296f",this.cScale11=this.cScale11||"#01629c",this.cScale12=this.cScale12||"#010029",this.cScale0=this.cScale0||this.primaryColor,this.cScale1=this.cScale1||this.secondaryColor,this.cScale2=this.cScale2||this.tertiaryColor,this.cScale3=this.cScale3||xn(this.primaryColor,{h:30}),this.cScale4=this.cScale4||xn(this.primaryColor,{h:60}),this.cScale5=this.cScale5||xn(this.primaryColor,{h:90}),this.cScale6=this.cScale6||xn(this.primaryColor,{h:120}),this.cScale7=this.cScale7||xn(this.primaryColor,{h:150}),this.cScale8=this.cScale8||xn(this.primaryColor,{h:210}),this.cScale9=this.cScale9||xn(this.primaryColor,{h:270}),this.cScale10=this.cScale10||xn(this.primaryColor,{h:300}),this.cScale11=this.cScale11||xn(this.primaryColor,{h:330});for(let N=0;N{this[p]=a[p]}),this.updateColors(),f.forEach(p=>{this[p]=a[p]})}};const pCe=i=>{const a=new gCe;return a.calculate(i),a};let bCe=class{constructor(){this.background="#f4f4f4",this.primaryColor="#ECECFF",this.secondaryColor=xn(this.primaryColor,{h:120}),this.secondaryColor="#ffffde",this.tertiaryColor=xn(this.primaryColor,{h:-160}),this.primaryBorderColor=lg(this.primaryColor,this.darkMode),this.secondaryBorderColor=lg(this.secondaryColor,this.darkMode),this.tertiaryBorderColor=lg(this.tertiaryColor,this.darkMode),this.primaryTextColor=Di(this.primaryColor),this.secondaryTextColor=Di(this.secondaryColor),this.tertiaryTextColor=Di(this.tertiaryColor),this.lineColor=Di(this.background),this.textColor=Di(this.background),this.background="white",this.mainBkg="#ECECFF",this.secondBkg="#ffffde",this.lineColor="#333333",this.border1="#9370DB",this.border2="#aaaa33",this.arrowheadColor="#333333",this.fontFamily='"trebuchet ms", verdana, arial, sans-serif',this.fontSize="16px",this.labelBackground="#e8e8e8",this.textColor="#333",this.THEME_COLOR_LIMIT=12,this.nodeBkg="calculated",this.nodeBorder="calculated",this.clusterBkg="calculated",this.clusterBorder="calculated",this.defaultLinkColor="calculated",this.titleColor="calculated",this.edgeLabelBackground="calculated",this.actorBorder="calculated",this.actorBkg="calculated",this.actorTextColor="black",this.actorLineColor="grey",this.signalColor="calculated",this.signalTextColor="calculated",this.labelBoxBkgColor="calculated",this.labelBoxBorderColor="calculated",this.labelTextColor="calculated",this.loopTextColor="calculated",this.noteBorderColor="calculated",this.noteBkgColor="#fff5ad",this.noteTextColor="calculated",this.activationBorderColor="#666",this.activationBkgColor="#f4f4f4",this.sequenceNumberColor="white",this.sectionBkgColor="calculated",this.altSectionBkgColor="calculated",this.sectionBkgColor2="calculated",this.excludeBkgColor="#eeeeee",this.taskBorderColor="calculated",this.taskBkgColor="calculated",this.taskTextLightColor="calculated",this.taskTextColor=this.taskTextLightColor,this.taskTextDarkColor="calculated",this.taskTextOutsideColor=this.taskTextDarkColor,this.taskTextClickableColor="calculated",this.activeTaskBorderColor="calculated",this.activeTaskBkgColor="calculated",this.gridColor="calculated",this.doneTaskBkgColor="calculated",this.doneTaskBorderColor="calculated",this.critBorderColor="calculated",this.critBkgColor="calculated",this.todayLineColor="calculated",this.sectionBkgColor=FA(102,102,255,.49),this.altSectionBkgColor="white",this.sectionBkgColor2="#fff400",this.taskBorderColor="#534fbc",this.taskBkgColor="#8a90dd",this.taskTextLightColor="white",this.taskTextColor="calculated",this.taskTextDarkColor="black",this.taskTextOutsideColor="calculated",this.taskTextClickableColor="#003163",this.activeTaskBorderColor="#534fbc",this.activeTaskBkgColor="#bfc7ff",this.gridColor="lightgrey",this.doneTaskBkgColor="lightgrey",this.doneTaskBorderColor="grey",this.critBorderColor="#ff8888",this.critBkgColor="red",this.todayLineColor="red",this.personBorder=this.primaryBorderColor,this.personBkg=this.mainBkg,this.labelColor="black",this.errorBkgColor="#552222",this.errorTextColor="#552222",this.updateColors()}updateColors(){var a,f,p,w,m,b,E,_,A,I,B;this.cScale0=this.cScale0||this.primaryColor,this.cScale1=this.cScale1||this.secondaryColor,this.cScale2=this.cScale2||this.tertiaryColor,this.cScale3=this.cScale3||xn(this.primaryColor,{h:30}),this.cScale4=this.cScale4||xn(this.primaryColor,{h:60}),this.cScale5=this.cScale5||xn(this.primaryColor,{h:90}),this.cScale6=this.cScale6||xn(this.primaryColor,{h:120}),this.cScale7=this.cScale7||xn(this.primaryColor,{h:150}),this.cScale8=this.cScale8||xn(this.primaryColor,{h:210}),this.cScale9=this.cScale9||xn(this.primaryColor,{h:270}),this.cScale10=this.cScale10||xn(this.primaryColor,{h:300}),this.cScale11=this.cScale11||xn(this.primaryColor,{h:330}),this["cScalePeer1"]=this["cScalePeer1"]||$s(this.secondaryColor,45),this["cScalePeer2"]=this["cScalePeer2"]||$s(this.tertiaryColor,40);for(let N=0;N{this[p]=a[p]}),this.updateColors(),f.forEach(p=>{this[p]=a[p]})}};const X1t=i=>{const a=new bCe;return a.calculate(i),a};let wCe=class{constructor(){this.background="#f4f4f4",this.primaryColor="#cde498",this.secondaryColor="#cdffb2",this.background="white",this.mainBkg="#cde498",this.secondBkg="#cdffb2",this.lineColor="green",this.border1="#13540c",this.border2="#6eaa49",this.arrowheadColor="green",this.fontFamily='"trebuchet ms", verdana, arial, sans-serif',this.fontSize="16px",this.tertiaryColor=bs("#cde498",10),this.primaryBorderColor=lg(this.primaryColor,this.darkMode),this.secondaryBorderColor=lg(this.secondaryColor,this.darkMode),this.tertiaryBorderColor=lg(this.tertiaryColor,this.darkMode),this.primaryTextColor=Di(this.primaryColor),this.secondaryTextColor=Di(this.secondaryColor),this.tertiaryTextColor=Di(this.primaryColor),this.lineColor=Di(this.background),this.textColor=Di(this.background),this.THEME_COLOR_LIMIT=12,this.nodeBkg="calculated",this.nodeBorder="calculated",this.clusterBkg="calculated",this.clusterBorder="calculated",this.defaultLinkColor="calculated",this.titleColor="#333",this.edgeLabelBackground="#e8e8e8",this.actorBorder="calculated",this.actorBkg="calculated",this.actorTextColor="black",this.actorLineColor="grey",this.signalColor="#333",this.signalTextColor="#333",this.labelBoxBkgColor="calculated",this.labelBoxBorderColor="#326932",this.labelTextColor="calculated",this.loopTextColor="calculated",this.noteBorderColor="calculated",this.noteBkgColor="#fff5ad",this.noteTextColor="calculated",this.activationBorderColor="#666",this.activationBkgColor="#f4f4f4",this.sequenceNumberColor="white",this.sectionBkgColor="#6eaa49",this.altSectionBkgColor="white",this.sectionBkgColor2="#6eaa49",this.excludeBkgColor="#eeeeee",this.taskBorderColor="calculated",this.taskBkgColor="#487e3a",this.taskTextLightColor="white",this.taskTextColor="calculated",this.taskTextDarkColor="black",this.taskTextOutsideColor="calculated",this.taskTextClickableColor="#003163",this.activeTaskBorderColor="calculated",this.activeTaskBkgColor="calculated",this.gridColor="lightgrey",this.doneTaskBkgColor="lightgrey",this.doneTaskBorderColor="grey",this.critBorderColor="#ff8888",this.critBkgColor="red",this.todayLineColor="red",this.personBorder=this.primaryBorderColor,this.personBkg=this.mainBkg,this.labelColor="black",this.errorBkgColor="#552222",this.errorTextColor="#552222"}updateColors(){var a,f,p,w,m,b,E,_,A,I,B;this.actorBorder=$s(this.mainBkg,20),this.actorBkg=this.mainBkg,this.labelBoxBkgColor=this.actorBkg,this.labelTextColor=this.actorTextColor,this.loopTextColor=this.actorTextColor,this.noteBorderColor=this.border2,this.noteTextColor=this.actorTextColor,this.cScale0=this.cScale0||this.primaryColor,this.cScale1=this.cScale1||this.secondaryColor,this.cScale2=this.cScale2||this.tertiaryColor,this.cScale3=this.cScale3||xn(this.primaryColor,{h:30}),this.cScale4=this.cScale4||xn(this.primaryColor,{h:60}),this.cScale5=this.cScale5||xn(this.primaryColor,{h:90}),this.cScale6=this.cScale6||xn(this.primaryColor,{h:120}),this.cScale7=this.cScale7||xn(this.primaryColor,{h:150}),this.cScale8=this.cScale8||xn(this.primaryColor,{h:210}),this.cScale9=this.cScale9||xn(this.primaryColor,{h:270}),this.cScale10=this.cScale10||xn(this.primaryColor,{h:300}),this.cScale11=this.cScale11||xn(this.primaryColor,{h:330}),this["cScalePeer1"]=this["cScalePeer1"]||$s(this.secondaryColor,45),this["cScalePeer2"]=this["cScalePeer2"]||$s(this.tertiaryColor,40);for(let N=0;N{this[p]=a[p]}),this.updateColors(),f.forEach(p=>{this[p]=a[p]})}};const vCe=i=>{const a=new wCe;return a.calculate(i),a};class mCe{constructor(){this.primaryColor="#eee",this.contrast="#707070",this.secondaryColor=bs(this.contrast,55),this.background="#ffffff",this.tertiaryColor=xn(this.primaryColor,{h:-160}),this.primaryBorderColor=lg(this.primaryColor,this.darkMode),this.secondaryBorderColor=lg(this.secondaryColor,this.darkMode),this.tertiaryBorderColor=lg(this.tertiaryColor,this.darkMode),this.primaryTextColor=Di(this.primaryColor),this.secondaryTextColor=Di(this.secondaryColor),this.tertiaryTextColor=Di(this.tertiaryColor),this.lineColor=Di(this.background),this.textColor=Di(this.background),this.mainBkg="#eee",this.secondBkg="calculated",this.lineColor="#666",this.border1="#999",this.border2="calculated",this.note="#ffa",this.text="#333",this.critical="#d42",this.done="#bbb",this.arrowheadColor="#333333",this.fontFamily='"trebuchet ms", verdana, arial, sans-serif',this.fontSize="16px",this.THEME_COLOR_LIMIT=12,this.nodeBkg="calculated",this.nodeBorder="calculated",this.clusterBkg="calculated",this.clusterBorder="calculated",this.defaultLinkColor="calculated",this.titleColor="calculated",this.edgeLabelBackground="white",this.actorBorder="calculated",this.actorBkg="calculated",this.actorTextColor="calculated",this.actorLineColor="calculated",this.signalColor="calculated",this.signalTextColor="calculated",this.labelBoxBkgColor="calculated",this.labelBoxBorderColor="calculated",this.labelTextColor="calculated",this.loopTextColor="calculated",this.noteBorderColor="calculated",this.noteBkgColor="calculated",this.noteTextColor="calculated",this.activationBorderColor="#666",this.activationBkgColor="#f4f4f4",this.sequenceNumberColor="white",this.sectionBkgColor="calculated",this.altSectionBkgColor="white",this.sectionBkgColor2="calculated",this.excludeBkgColor="#eeeeee",this.taskBorderColor="calculated",this.taskBkgColor="calculated",this.taskTextLightColor="white",this.taskTextColor="calculated",this.taskTextDarkColor="calculated",this.taskTextOutsideColor="calculated",this.taskTextClickableColor="#003163",this.activeTaskBorderColor="calculated",this.activeTaskBkgColor="calculated",this.gridColor="calculated",this.doneTaskBkgColor="calculated",this.doneTaskBorderColor="calculated",this.critBkgColor="calculated",this.critBorderColor="calculated",this.todayLineColor="calculated",this.personBorder=this.primaryBorderColor,this.personBkg=this.mainBkg,this.labelColor="black",this.errorBkgColor="#552222",this.errorTextColor="#552222"}updateColors(){var a,f,p,w,m,b,E,_,A,I,B;this.secondBkg=bs(this.contrast,55),this.border2=this.contrast,this.actorBorder=bs(this.border1,23),this.actorBkg=this.mainBkg,this.actorTextColor=this.text,this.actorLineColor=this.lineColor,this.signalColor=this.text,this.signalTextColor=this.text,this.labelBoxBkgColor=this.actorBkg,this.labelBoxBorderColor=this.actorBorder,this.labelTextColor=this.text,this.loopTextColor=this.text,this.noteBorderColor="#999",this.noteBkgColor="#666",this.noteTextColor="#fff",this.cScale0=this.cScale0||"#555",this.cScale1=this.cScale1||"#F4F4F4",this.cScale2=this.cScale2||"#555",this.cScale3=this.cScale3||"#BBB",this.cScale4=this.cScale4||"#777",this.cScale5=this.cScale5||"#999",this.cScale6=this.cScale6||"#DDD",this.cScale7=this.cScale7||"#FFF",this.cScale8=this.cScale8||"#DDD",this.cScale9=this.cScale9||"#BBB",this.cScale10=this.cScale10||"#999",this.cScale11=this.cScale11||"#777";for(let N=0;N{this[p]=a[p]}),this.updateColors(),f.forEach(p=>{this[p]=a[p]})}}const T5={base:{getThemeVariables:dCe},dark:{getThemeVariables:pCe},default:{getThemeVariables:X1t},forest:{getThemeVariables:vCe},neutral:{getThemeVariables:i=>{const a=new mCe;return a.calculate(i),a}}},C5={flowchart:{useMaxWidth:!0,titleTopMargin:25,diagramPadding:8,htmlLabels:!0,nodeSpacing:50,rankSpacing:50,curve:"basis",padding:15,defaultRenderer:"dagre-wrapper",wrappingWidth:200},sequence:{useMaxWidth:!0,hideUnusedParticipants:!1,activationWidth:10,diagramMarginX:50,diagramMarginY:10,actorMargin:50,width:150,height:65,boxMargin:10,boxTextMargin:5,noteMargin:10,messageMargin:35,messageAlign:"center",mirrorActors:!0,forceMenus:!1,bottomMarginAdj:1,rightAngles:!1,showSequenceNumbers:!1,actorFontSize:14,actorFontFamily:'"Open Sans", sans-serif',actorFontWeight:400,noteFontSize:14,noteFontFamily:'"trebuchet ms", verdana, arial, sans-serif',noteFontWeight:400,noteAlign:"center",messageFontSize:16,messageFontFamily:'"trebuchet ms", verdana, arial, sans-serif',messageFontWeight:400,wrap:!1,wrapPadding:10,labelBoxWidth:50,labelBoxHeight:20},gantt:{useMaxWidth:!0,titleTopMargin:25,barHeight:20,barGap:4,topPadding:50,rightPadding:75,leftPadding:75,gridLineStartPadding:35,fontSize:11,sectionFontSize:11,numberSectionStyles:4,axisFormat:"%Y-%m-%d",topAxis:!1,displayMode:"",weekday:"sunday"},journey:{useMaxWidth:!0,diagramMarginX:50,diagramMarginY:10,leftMargin:150,width:150,height:50,boxMargin:10,boxTextMargin:5,noteMargin:10,messageMargin:35,messageAlign:"center",bottomMarginAdj:1,rightAngles:!1,taskFontSize:14,taskFontFamily:'"Open Sans", sans-serif',taskMargin:50,activationWidth:10,textPlacement:"fo",actorColours:["#8FBC8F","#7CFC00","#00FFFF","#20B2AA","#B0E0E6","#FFFFE0"],sectionFills:["#191970","#8B008B","#4B0082","#2F4F4F","#800000","#8B4513","#00008B"],sectionColours:["#fff"]},class:{useMaxWidth:!0,titleTopMargin:25,arrowMarkerAbsolute:!1,dividerMargin:10,padding:5,textHeight:10,defaultRenderer:"dagre-wrapper",htmlLabels:!1},state:{useMaxWidth:!0,titleTopMargin:25,dividerMargin:10,sizeUnit:5,padding:8,textHeight:10,titleShift:-15,noteMargin:10,forkWidth:70,forkHeight:7,miniPadding:2,fontSizeFactor:5.02,fontSize:24,labelHeight:16,edgeLengthFactor:"20",compositTitleSize:35,radius:5,defaultRenderer:"dagre-wrapper"},er:{useMaxWidth:!0,titleTopMargin:25,diagramPadding:20,layoutDirection:"TB",minEntityWidth:100,minEntityHeight:75,entityPadding:15,stroke:"gray",fill:"honeydew",fontSize:12},pie:{useMaxWidth:!0,textPosition:.75},quadrantChart:{useMaxWidth:!0,chartWidth:500,chartHeight:500,titleFontSize:20,titlePadding:10,quadrantPadding:5,xAxisLabelPadding:5,yAxisLabelPadding:5,xAxisLabelFontSize:16,yAxisLabelFontSize:16,quadrantLabelFontSize:16,quadrantTextTopPadding:5,pointTextPadding:5,pointLabelFontSize:12,pointRadius:5,xAxisPosition:"top",yAxisPosition:"left",quadrantInternalBorderStrokeWidth:1,quadrantExternalBorderStrokeWidth:2},xyChart:{useMaxWidth:!0,width:700,height:500,titleFontSize:20,titlePadding:10,showTitle:!0,xAxis:{$ref:"#/$defs/XYChartAxisConfig",showLabel:!0,labelFontSize:14,labelPadding:5,showTitle:!0,titleFontSize:16,titlePadding:5,showTick:!0,tickLength:5,tickWidth:2,showAxisLine:!0,axisLineWidth:2},yAxis:{$ref:"#/$defs/XYChartAxisConfig",showLabel:!0,labelFontSize:14,labelPadding:5,showTitle:!0,titleFontSize:16,titlePadding:5,showTick:!0,tickLength:5,tickWidth:2,showAxisLine:!0,axisLineWidth:2},chartOrientation:"vertical",plotReservedSpacePercent:50},requirement:{useMaxWidth:!0,rect_fill:"#f9f9f9",text_color:"#333",rect_border_size:"0.5px",rect_border_color:"#bbb",rect_min_width:200,rect_min_height:200,fontSize:14,rect_padding:10,line_height:20},mindmap:{useMaxWidth:!0,padding:10,maxNodeWidth:200},timeline:{useMaxWidth:!0,diagramMarginX:50,diagramMarginY:10,leftMargin:150,width:150,height:50,boxMargin:10,boxTextMargin:5,noteMargin:10,messageMargin:35,messageAlign:"center",bottomMarginAdj:1,rightAngles:!1,taskFontSize:14,taskFontFamily:'"Open Sans", sans-serif',taskMargin:50,activationWidth:10,textPlacement:"fo",actorColours:["#8FBC8F","#7CFC00","#00FFFF","#20B2AA","#B0E0E6","#FFFFE0"],sectionFills:["#191970","#8B008B","#4B0082","#2F4F4F","#800000","#8B4513","#00008B"],sectionColours:["#fff"],disableMulticolor:!1},gitGraph:{useMaxWidth:!0,titleTopMargin:25,diagramPadding:8,nodeLabel:{width:75,height:100,x:-25,y:0},mainBranchName:"main",mainBranchOrder:0,showCommitLabel:!0,showBranches:!0,rotateCommitLabel:!0,arrowMarkerAbsolute:!1},c4:{useMaxWidth:!0,diagramMarginX:50,diagramMarginY:10,c4ShapeMargin:50,c4ShapePadding:20,width:216,height:60,boxMargin:10,c4ShapeInRow:4,nextLinePaddingX:0,c4BoundaryInRow:2,personFontSize:14,personFontFamily:'"Open Sans", sans-serif',personFontWeight:"normal",external_personFontSize:14,external_personFontFamily:'"Open Sans", sans-serif',external_personFontWeight:"normal",systemFontSize:14,systemFontFamily:'"Open Sans", sans-serif',systemFontWeight:"normal",external_systemFontSize:14,external_systemFontFamily:'"Open Sans", sans-serif',external_systemFontWeight:"normal",system_dbFontSize:14,system_dbFontFamily:'"Open Sans", sans-serif',system_dbFontWeight:"normal",external_system_dbFontSize:14,external_system_dbFontFamily:'"Open Sans", sans-serif',external_system_dbFontWeight:"normal",system_queueFontSize:14,system_queueFontFamily:'"Open Sans", sans-serif',system_queueFontWeight:"normal",external_system_queueFontSize:14,external_system_queueFontFamily:'"Open Sans", sans-serif',external_system_queueFontWeight:"normal",boundaryFontSize:14,boundaryFontFamily:'"Open Sans", sans-serif',boundaryFontWeight:"normal",messageFontSize:12,messageFontFamily:'"Open Sans", sans-serif',messageFontWeight:"normal",containerFontSize:14,containerFontFamily:'"Open Sans", sans-serif',containerFontWeight:"normal",external_containerFontSize:14,external_containerFontFamily:'"Open Sans", sans-serif',external_containerFontWeight:"normal",container_dbFontSize:14,container_dbFontFamily:'"Open Sans", sans-serif',container_dbFontWeight:"normal",external_container_dbFontSize:14,external_container_dbFontFamily:'"Open Sans", sans-serif',external_container_dbFontWeight:"normal",container_queueFontSize:14,container_queueFontFamily:'"Open Sans", sans-serif',container_queueFontWeight:"normal",external_container_queueFontSize:14,external_container_queueFontFamily:'"Open Sans", sans-serif',external_container_queueFontWeight:"normal",componentFontSize:14,componentFontFamily:'"Open Sans", sans-serif',componentFontWeight:"normal",external_componentFontSize:14,external_componentFontFamily:'"Open Sans", sans-serif',external_componentFontWeight:"normal",component_dbFontSize:14,component_dbFontFamily:'"Open Sans", sans-serif',component_dbFontWeight:"normal",external_component_dbFontSize:14,external_component_dbFontFamily:'"Open Sans", sans-serif',external_component_dbFontWeight:"normal",component_queueFontSize:14,component_queueFontFamily:'"Open Sans", sans-serif',component_queueFontWeight:"normal",external_component_queueFontSize:14,external_component_queueFontFamily:'"Open Sans", sans-serif',external_component_queueFontWeight:"normal",wrap:!0,wrapPadding:10,person_bg_color:"#08427B",person_border_color:"#073B6F",external_person_bg_color:"#686868",external_person_border_color:"#8A8A8A",system_bg_color:"#1168BD",system_border_color:"#3C7FC0",system_db_bg_color:"#1168BD",system_db_border_color:"#3C7FC0",system_queue_bg_color:"#1168BD",system_queue_border_color:"#3C7FC0",external_system_bg_color:"#999999",external_system_border_color:"#8A8A8A",external_system_db_bg_color:"#999999",external_system_db_border_color:"#8A8A8A",external_system_queue_bg_color:"#999999",external_system_queue_border_color:"#8A8A8A",container_bg_color:"#438DD5",container_border_color:"#3C7FC0",container_db_bg_color:"#438DD5",container_db_border_color:"#3C7FC0",container_queue_bg_color:"#438DD5",container_queue_border_color:"#3C7FC0",external_container_bg_color:"#B3B3B3",external_container_border_color:"#A6A6A6",external_container_db_bg_color:"#B3B3B3",external_container_db_border_color:"#A6A6A6",external_container_queue_bg_color:"#B3B3B3",external_container_queue_border_color:"#A6A6A6",component_bg_color:"#85BBF0",component_border_color:"#78A8D8",component_db_bg_color:"#85BBF0",component_db_border_color:"#78A8D8",component_queue_bg_color:"#85BBF0",component_queue_border_color:"#78A8D8",external_component_bg_color:"#CCCCCC",external_component_border_color:"#BFBFBF",external_component_db_bg_color:"#CCCCCC",external_component_db_border_color:"#BFBFBF",external_component_queue_bg_color:"#CCCCCC",external_component_queue_border_color:"#BFBFBF"},sankey:{useMaxWidth:!0,width:600,height:400,linkColor:"gradient",nodeAlignment:"justify",showValues:!0,prefix:"",suffix:""},theme:"default",maxTextSize:5e4,darkMode:!1,fontFamily:'"trebuchet ms", verdana, arial, sans-serif;',logLevel:5,securityLevel:"strict",startOnLoad:!0,arrowMarkerAbsolute:!1,secure:["secure","securityLevel","startOnLoad","maxTextSize"],deterministicIds:!1,fontSize:16},iIt={...C5,deterministicIDSeed:void 0,themeCSS:void 0,themeVariables:T5.default.getThemeVariables(),sequence:{...C5.sequence,messageFont:function(){return{fontFamily:this.messageFontFamily,fontSize:this.messageFontSize,fontWeight:this.messageFontWeight}},noteFont:function(){return{fontFamily:this.noteFontFamily,fontSize:this.noteFontSize,fontWeight:this.noteFontWeight}},actorFont:function(){return{fontFamily:this.actorFontFamily,fontSize:this.actorFontSize,fontWeight:this.actorFontWeight}}},gantt:{...C5.gantt,tickInterval:void 0,useWidth:void 0},c4:{...C5.c4,useWidth:void 0,personFont:function(){return{fontFamily:this.personFontFamily,fontSize:this.personFontSize,fontWeight:this.personFontWeight}},external_personFont:function(){return{fontFamily:this.external_personFontFamily,fontSize:this.external_personFontSize,fontWeight:this.external_personFontWeight}},systemFont:function(){return{fontFamily:this.systemFontFamily,fontSize:this.systemFontSize,fontWeight:this.systemFontWeight}},external_systemFont:function(){return{fontFamily:this.external_systemFontFamily,fontSize:this.external_systemFontSize,fontWeight:this.external_systemFontWeight}},system_dbFont:function(){return{fontFamily:this.system_dbFontFamily,fontSize:this.system_dbFontSize,fontWeight:this.system_dbFontWeight}},external_system_dbFont:function(){return{fontFamily:this.external_system_dbFontFamily,fontSize:this.external_system_dbFontSize,fontWeight:this.external_system_dbFontWeight}},system_queueFont:function(){return{fontFamily:this.system_queueFontFamily,fontSize:this.system_queueFontSize,fontWeight:this.system_queueFontWeight}},external_system_queueFont:function(){return{fontFamily:this.external_system_queueFontFamily,fontSize:this.external_system_queueFontSize,fontWeight:this.external_system_queueFontWeight}},containerFont:function(){return{fontFamily:this.containerFontFamily,fontSize:this.containerFontSize,fontWeight:this.containerFontWeight}},external_containerFont:function(){return{fontFamily:this.external_containerFontFamily,fontSize:this.external_containerFontSize,fontWeight:this.external_containerFontWeight}},container_dbFont:function(){return{fontFamily:this.container_dbFontFamily,fontSize:this.container_dbFontSize,fontWeight:this.container_dbFontWeight}},external_container_dbFont:function(){return{fontFamily:this.external_container_dbFontFamily,fontSize:this.external_container_dbFontSize,fontWeight:this.external_container_dbFontWeight}},container_queueFont:function(){return{fontFamily:this.container_queueFontFamily,fontSize:this.container_queueFontSize,fontWeight:this.container_queueFontWeight}},external_container_queueFont:function(){return{fontFamily:this.external_container_queueFontFamily,fontSize:this.external_container_queueFontSize,fontWeight:this.external_container_queueFontWeight}},componentFont:function(){return{fontFamily:this.componentFontFamily,fontSize:this.componentFontSize,fontWeight:this.componentFontWeight}},external_componentFont:function(){return{fontFamily:this.external_componentFontFamily,fontSize:this.external_componentFontSize,fontWeight:this.external_componentFontWeight}},component_dbFont:function(){return{fontFamily:this.component_dbFontFamily,fontSize:this.component_dbFontSize,fontWeight:this.component_dbFontWeight}},external_component_dbFont:function(){return{fontFamily:this.external_component_dbFontFamily,fontSize:this.external_component_dbFontSize,fontWeight:this.external_component_dbFontWeight}},component_queueFont:function(){return{fontFamily:this.component_queueFontFamily,fontSize:this.component_queueFontSize,fontWeight:this.component_queueFontWeight}},external_component_queueFont:function(){return{fontFamily:this.external_component_queueFontFamily,fontSize:this.external_component_queueFontSize,fontWeight:this.external_component_queueFontWeight}},boundaryFont:function(){return{fontFamily:this.boundaryFontFamily,fontSize:this.boundaryFontSize,fontWeight:this.boundaryFontWeight}},messageFont:function(){return{fontFamily:this.messageFontFamily,fontSize:this.messageFontSize,fontWeight:this.messageFontWeight}}},pie:{...C5.pie,useWidth:984},xyChart:{...C5.xyChart,useWidth:void 0},requirement:{...C5.requirement,useWidth:void 0},gitGraph:{...C5.gitGraph,useMaxWidth:!1},sankey:{...C5.sankey,useMaxWidth:!1}},sIt=(i,a="")=>Object.keys(i).reduce((f,p)=>Array.isArray(i[p])?f:typeof i[p]=="object"&&i[p]!==null?[...f,a+p,...sIt(i[p],"")]:[...f,a+p],[]),yCe=new Set(sIt(iIt,"")),Zh=iIt,mW=i=>{if(Ut.debug("sanitizeDirective called with",i),!(typeof i!="object"||i==null)){if(Array.isArray(i)){i.forEach(a=>mW(a));return}for(const a of Object.keys(i)){if(Ut.debug("Checking key",a),a.startsWith("__")||a.includes("proto")||a.includes("constr")||!yCe.has(a)||i[a]==null){Ut.debug("sanitize deleting key: ",a),delete i[a];continue}if(typeof i[a]=="object"){Ut.debug("sanitizing object",a),mW(i[a]);continue}const f=["themeCSS","fontFamily","altFontFamily"];for(const p of f)a.includes(p)&&(Ut.debug("sanitizing css option",a),i[a]=xCe(i[a]))}if(i.themeVariables)for(const a of Object.keys(i.themeVariables)){const f=i.themeVariables[a];f!=null&&f.match&&!f.match(/^[\d "#%(),.;A-Za-z]+$/)&&(i.themeVariables[a]="")}Ut.debug("After sanitization",i)}},xCe=i=>{let a=0,f=0;for(const p of i){if(a{for(const{id:a,detector:f,loader:p}of i)uIt(a,f,p)},uIt=(i,a,f)=>{NA[i]?Ut.error(`Detector with key ${i} already exists`):NA[i]={detector:a,loader:f},Ut.debug(`Detector with key ${i} added${f?" with loader":""}`)},ECe=i=>NA[i].loader,Q1t=(i,a,{depth:f=2,clobber:p=!1}={})=>{const w={depth:f,clobber:p};return Array.isArray(a)&&!Array.isArray(i)?(a.forEach(m=>Q1t(i,m,w)),i):Array.isArray(a)&&Array.isArray(i)?(a.forEach(m=>{i.includes(m)||i.push(m)}),i):i===void 0||f<=0?i!=null&&typeof i=="object"&&typeof a=="object"?Object.assign(i,a):a:(a!==void 0&&typeof i=="object"&&typeof a=="object"&&Object.keys(a).forEach(m=>{typeof a[m]=="object"&&(i[m]===void 0||typeof i[m]=="object")?(i[m]===void 0&&(i[m]=Array.isArray(a[m])?[]:{}),i[m]=Q1t(i[m],a[m],{depth:f-1,clobber:p})):(p||typeof i[m]!="object"&&typeof a[m]!="object")&&(i[m]=a[m])}),i)},Z1=Q1t;var TCe=typeof global=="object"&&global&&global.Object===Object&&global;const lIt=TCe;var CCe=typeof self=="object"&&self&&self.Object===Object&&self,_Ce=lIt||CCe||Function("return this")();const nm=_Ce;var SCe=nm.Symbol;const tw=SCe;var hIt=Object.prototype,ACe=hIt.hasOwnProperty,LCe=hIt.toString,QP=tw?tw.toStringTag:void 0;function MCe(i){var a=ACe.call(i,QP),f=i[QP];try{i[QP]=void 0;var p=!0}catch{}var w=LCe.call(i);return p&&(a?i[QP]=f:delete i[QP]),w}var DCe=Object.prototype,ICe=DCe.toString;function OCe(i){return ICe.call(i)}var PCe="[object Null]",FCe="[object Undefined]",fIt=tw?tw.toStringTag:void 0;function sT(i){return i==null?i===void 0?FCe:PCe:fIt&&fIt in Object(i)?MCe(i):OCe(i)}function Fb(i){var a=typeof i;return i!=null&&(a=="object"||a=="function")}var NCe="[object AsyncFunction]",BCe="[object Function]",RCe="[object GeneratorFunction]",jCe="[object Proxy]";function BA(i){if(!Fb(i))return!1;var a=sT(i);return a==BCe||a==RCe||a==NCe||a==jCe}var $Ce=nm["__core-js_shared__"];const Z1t=$Ce;var dIt=function(){var i=/[^.]+$/.exec(Z1t&&Z1t.keys&&Z1t.keys.IE_PROTO||"");return i?"Symbol(src)_1."+i:""}();function zCe(i){return!!dIt&&dIt in i}var qCe=Function.prototype,HCe=qCe.toString;function aT(i){if(i!=null){try{return HCe.call(i)}catch{}try{return i+""}catch{}}return""}var VCe=/[\\^$.*+?()[\]{}|]/g,GCe=/^\[object .+?Constructor\]$/,UCe=Function.prototype,WCe=Object.prototype,YCe=UCe.toString,KCe=WCe.hasOwnProperty,XCe=RegExp("^"+YCe.call(KCe).replace(VCe,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$");function QCe(i){if(!Fb(i)||zCe(i))return!1;var a=BA(i)?XCe:GCe;return a.test(aT(i))}function ZCe(i,a){return i==null?void 0:i[a]}function oT(i,a){var f=ZCe(i,a);return QCe(f)?f:void 0}var JCe=oT(Object,"create");const ZP=JCe;function t9e(){this.__data__=ZP?ZP(null):{},this.size=0}function e9e(i){var a=this.has(i)&&delete this.__data__[i];return this.size-=a?1:0,a}var n9e="__lodash_hash_undefined__",r9e=Object.prototype,i9e=r9e.hasOwnProperty;function s9e(i){var a=this.__data__;if(ZP){var f=a[i];return f===n9e?void 0:f}return i9e.call(a,i)?a[i]:void 0}var a9e=Object.prototype,o9e=a9e.hasOwnProperty;function c9e(i){var a=this.__data__;return ZP?a[i]!==void 0:o9e.call(a,i)}var u9e="__lodash_hash_undefined__";function l9e(i,a){var f=this.__data__;return this.size+=this.has(i)?0:1,f[i]=ZP&&a===void 0?u9e:a,this}function cT(i){var a=-1,f=i==null?0:i.length;for(this.clear();++a-1}function w9e(i,a){var f=this.__data__,p=xW(f,i);return p<0?(++this.size,f.push([i,a])):f[p][1]=a,this}function _5(i){var a=-1,f=i==null?0:i.length;for(this.clear();++a-1&&i%1==0&&i<=U9e}function ck(i){return i!=null&&rdt(i.length)&&!BA(i)}function _It(i){return f3(i)&&ck(i)}function W9e(){return!1}var SIt=typeof exports=="object"&&exports&&!exports.nodeType&&exports,AIt=SIt&&typeof module=="object"&&module&&!module.nodeType&&module,Y9e=AIt&&AIt.exports===SIt,LIt=Y9e?nm.Buffer:void 0,K9e=LIt?LIt.isBuffer:void 0,X9e=K9e||W9e;const zA=X9e;var Q9e="[object Object]",Z9e=Function.prototype,J9e=Object.prototype,MIt=Z9e.toString,t_e=J9e.hasOwnProperty,e_e=MIt.call(Object);function DIt(i){if(!f3(i)||sT(i)!=Q9e)return!1;var a=ndt(i);if(a===null)return!0;var f=t_e.call(a,"constructor")&&a.constructor;return typeof f=="function"&&f instanceof f&&MIt.call(f)==e_e}var n_e="[object Arguments]",r_e="[object Array]",i_e="[object Boolean]",s_e="[object Date]",a_e="[object Error]",o_e="[object Function]",c_e="[object Map]",u_e="[object Number]",l_e="[object Object]",h_e="[object RegExp]",f_e="[object Set]",d_e="[object String]",g_e="[object WeakMap]",p_e="[object ArrayBuffer]",b_e="[object DataView]",w_e="[object Float32Array]",v_e="[object Float64Array]",m_e="[object Int8Array]",y_e="[object Int16Array]",x_e="[object Int32Array]",k_e="[object Uint8Array]",E_e="[object Uint8ClampedArray]",T_e="[object Uint16Array]",C_e="[object Uint32Array]",bl={};bl[w_e]=bl[v_e]=bl[m_e]=bl[y_e]=bl[x_e]=bl[k_e]=bl[E_e]=bl[T_e]=bl[C_e]=!0,bl[n_e]=bl[r_e]=bl[p_e]=bl[i_e]=bl[b_e]=bl[s_e]=bl[a_e]=bl[o_e]=bl[c_e]=bl[u_e]=bl[l_e]=bl[h_e]=bl[f_e]=bl[d_e]=bl[g_e]=!1;function __e(i){return f3(i)&&rdt(i.length)&&!!bl[sT(i)]}function SW(i){return function(a){return i(a)}}var IIt=typeof exports=="object"&&exports&&!exports.nodeType&&exports,tF=IIt&&typeof module=="object"&&module&&!module.nodeType&&module,S_e=tF&&tF.exports===IIt,idt=S_e&&lIt.process,A_e=function(){try{var i=tF&&tF.require&&tF.require("util").types;return i||idt&&idt.binding&&idt.binding("util")}catch{}}();const qA=A_e;var OIt=qA&&qA.isTypedArray,L_e=OIt?SW(OIt):__e;const AW=L_e;function sdt(i,a){if(!(a==="constructor"&&typeof i[a]=="function")&&a!="__proto__")return i[a]}var M_e=Object.prototype,D_e=M_e.hasOwnProperty;function LW(i,a,f){var p=i[a];(!(D_e.call(i,a)&&RA(p,f))||f===void 0&&!(a in i))&&TW(i,a,f)}function eF(i,a,f,p){var w=!f;f||(f={});for(var m=-1,b=a.length;++m-1&&i%1==0&&i0){if(++a>=U_e)return arguments[0]}else a=0;return i.apply(void 0,arguments)}}var X_e=K_e(G_e);const RIt=X_e;function DW(i,a){return RIt(BIt(i,a,lT),i+"")}function nF(i,a,f){if(!Fb(f))return!1;var p=typeof a;return(p=="number"?ck(f)&&MW(a,f.length):p=="string"&&a in f)?RA(f[a],i):!1}function Q_e(i){return DW(function(a,f){var p=-1,w=f.length,m=w>1?f[w-1]:void 0,b=w>2?f[2]:void 0;for(m=i.length>3&&typeof m=="function"?(w--,m):void 0,b&&nF(f[0],f[1],b)&&(m=w<3?void 0:m,w=1),a=Object(a);++pE.args);mW(b),p=Z1(p,[...b])}else p=f.args;if(!p)return;let w=yW(i,a);const m="config";return p[m]!==void 0&&(w==="flowchart-v2"&&(w="flowchart"),p[w]=p[m],delete p[m]),p},$It=function(i,a=null){try{const f=new RegExp(`[%]{2}(?![{]${tSe.source})(?=[}][%]{2}).* +`,"ig");i=i.trim().replace(f,"").replace(/'/gm,'"'),Ut.debug(`Detecting diagram directive${a!==null?" type:"+a:""} based on the text:${i}`);let p;const w=[];for(;(p=XP.exec(i))!==null;)if(p.index===XP.lastIndex&&XP.lastIndex++,p&&!a||a&&p[1]&&p[1].match(a)||a&&p[2]&&p[2].match(a)){const m=p[1]?p[1]:p[2],b=p[3]?p[3].trim():p[4]?JSON.parse(p[4].trim()):null;w.push({type:m,args:b})}return w.length===0?{type:i,args:null}:w.length===1?w[0]:w}catch(f){return Ut.error(`ERROR: ${f.message} - Unable to parse directive type: '${a}' based on the text: '${i}'`),{type:void 0,args:null}}},nSe=function(i){return i.replace(XP,"")},rSe=function(i,a){for(const[f,p]of a.entries())if(p.match(i))return f;return-1};function ew(i,a){if(!i)return a;const f=`curve${i.charAt(0).toUpperCase()+i.slice(1)}`;return J_e[f]??a}function iSe(i,a){const f=i.trim();if(f)return a.securityLevel!=="loose"?ik(f):f}const sSe=(i,...a)=>{const f=i.split("."),p=f.length-1,w=f[p];let m=window;for(let b=0;b{f+=zIt(w,a),a=w});const p=f/2;return adt(i,p)}function oSe(i){return i.length===1?i[0]:aSe(i)}const qIt=(i,a=2)=>{const f=Math.pow(10,a);return Math.round(i*f)/f},adt=(i,a)=>{let f,p=a;for(const w of i){if(f){const m=zIt(w,f);if(m=1)return{x:w.x,y:w.y};if(b>0&&b<1)return{x:qIt((1-b)*f.x+b*w.x,5),y:qIt((1-b)*f.y+b*w.y,5)}}}f=w}throw new Error("Could not find a suitable point for the given distance")},cSe=(i,a,f)=>{Ut.info(`our points ${JSON.stringify(a)}`),a[0]!==f&&(a=a.reverse());const w=adt(a,25),m=i?10:5,b=Math.atan2(a[0].y-w.y,a[0].x-w.x),E={x:0,y:0};return E.x=Math.sin(b)*m+(a[0].x+w.x)/2,E.y=-Math.cos(b)*m+(a[0].y+w.y)/2,E};function uSe(i,a,f){const p=structuredClone(f);Ut.info("our points",p),a!=="start_left"&&a!=="start_right"&&p.reverse();const w=25+i,m=adt(p,w),b=10+i*.5,E=Math.atan2(p[0].y-m.y,p[0].x-m.x),_={x:0,y:0};return a==="start_left"?(_.x=Math.sin(E+Math.PI)*b+(p[0].x+m.x)/2,_.y=-Math.cos(E+Math.PI)*b+(p[0].y+m.y)/2):a==="end_right"?(_.x=Math.sin(E-Math.PI)*b+(p[0].x+m.x)/2-5,_.y=-Math.cos(E-Math.PI)*b+(p[0].y+m.y)/2-5):a==="end_left"?(_.x=Math.sin(E)*b+(p[0].x+m.x)/2-5,_.y=-Math.cos(E)*b+(p[0].y+m.y)/2-5):(_.x=Math.sin(E)*b+(p[0].x+m.x)/2,_.y=-Math.cos(E)*b+(p[0].y+m.y)/2),_}function im(i){let a="",f="";for(const p of i)p!==void 0&&(p.startsWith("color:")||p.startsWith("text-align:")?f=f+p+";":a=a+p+";");return{style:a,labelStyle:f}}let HIt=0;const VIt=()=>(HIt++,"id-"+Math.random().toString(36).substr(2,12)+"-"+HIt);function lSe(i){let a="";const f="0123456789abcdef",p=f.length;for(let w=0;wlSe(i.length),hSe=function(){return{x:0,y:0,fill:void 0,anchor:"start",style:"#666",width:100,height:100,textMargin:0,rx:0,ry:0,valign:void 0,text:""}},fSe=function(i,a){const f=a.text.replace(Kr.lineBreakRegex," "),[,p]=VA(a.fontSize),w=i.append("text");w.attr("x",a.x),w.attr("y",a.y),w.style("text-anchor",a.anchor),w.style("font-family",a.fontFamily),w.style("font-size",p),w.style("font-weight",a.fontWeight),w.attr("fill",a.fill),a.class!==void 0&&w.attr("class",a.class);const m=w.append("tspan");return m.attr("x",a.x+a.textMargin*2),m.attr("fill",a.fill),m.text(f),w},UIt=jA((i,a,f)=>{if(!i||(f=Object.assign({fontSize:12,fontWeight:400,fontFamily:"Arial",joinWith:"
            "},f),Kr.lineBreakRegex.test(i)))return i;const p=i.split(" "),w=[];let m="";return p.forEach((b,E)=>{const _=d3(`${b} `,f),A=d3(m,f);if(_>a){const{hyphenatedStrings:N,remainingWord:R}=dSe(b,a,"-",f);w.push(m,...N),m=R}else A+_>=a?(w.push(m),m=b):m=[m,b].filter(Boolean).join(" ");E+1===p.length&&w.push(m)}),w.filter(b=>b!=="").join(f.joinWith)},(i,a,f)=>`${i}${a}${f.fontSize}${f.fontWeight}${f.fontFamily}${f.joinWith}`),dSe=jA((i,a,f="-",p)=>{p=Object.assign({fontSize:12,fontWeight:400,fontFamily:"Arial",margin:0},p);const w=[...i],m=[];let b="";return w.forEach((E,_)=>{const A=`${b}${E}`;if(d3(A,p)>=a){const B=_+1,N=w.length===B,R=`${A}${f}`;m.push(N?A:R),b=""}else b=A}),{hyphenatedStrings:m,remainingWord:b}},(i,a,f="-",p)=>`${i}${a}${f}${p.fontSize}${p.fontWeight}${p.fontFamily}`);function odt(i,a){return cdt(i,a).height}function d3(i,a){return cdt(i,a).width}const cdt=jA((i,a)=>{const{fontSize:f=12,fontFamily:p="Arial",fontWeight:w=400}=a;if(!i)return{width:0,height:0};const[,m]=VA(f),b=["sans-serif",p],E=i.split(Kr.lineBreakRegex),_=[],A=yr("body");if(!A.remove)return{width:0,height:0,lineHeight:0};const I=A.append("svg");for(const N of b){let R=0;const z={width:0,height:0,lineHeight:0};for(const W of E){const et=hSe();et.text=W||jIt;const st=fSe(I,et).style("font-size",m).style("font-weight",w).style("font-family",N),at=(st._groups||st)[0][0].getBBox();if(at.width===0&&at.height===0)throw new Error("svg element not in render tree");z.width=Math.round(Math.max(z.width,at.width)),R=Math.round(at.height),z.height+=R,z.lineHeight=Math.round(Math.max(z.lineHeight,R))}_.push(z)}I.remove();const B=isNaN(_[1].height)||isNaN(_[1].width)||isNaN(_[1].lineHeight)||_[0].height>_[1].height&&_[0].width>_[1].width&&_[0].lineHeight>_[1].lineHeight?0:1;return _[B]},(i,a)=>`${i}${a.fontSize}${a.fontWeight}${a.fontFamily}`);class gSe{constructor(a=!1,f){this.count=0,this.count=f?f.length:0,this.next=a?()=>this.count++:()=>Date.now()}}let OW;const pSe=function(i){return OW=OW||document.createElement("div"),i=escape(i).replace(/%26/g,"&").replace(/%23/g,"#").replace(/%3B/g,";"),OW.innerHTML=i,unescape(OW.textContent)};function WIt(i){return"str"in i}const bSe=(i,a,f,p)=>{var m;if(!p)return;const w=(m=i.node())==null?void 0:m.getBBox();w&&i.append("text").text(p).attr("x",w.x+w.width/2).attr("y",-f).attr("class",a)},VA=i=>{if(typeof i=="number")return[i,i+"px"];const a=parseInt(i??"",10);return Number.isNaN(a)?[void 0,void 0]:i===String(a)?[a,i+"px"]:[a,i]};function rF(i,a){return IW({},i,a)}const $a={assignWithDepth:Z1,wrapLabel:UIt,calculateTextHeight:odt,calculateTextWidth:d3,calculateTextDimensions:cdt,cleanAndMerge:rF,detectInit:eSe,detectDirective:$It,isSubstringInArray:rSe,interpolateToCurve:ew,calcLabelPosition:oSe,calcCardinalityPosition:cSe,calcTerminalLabelPosition:uSe,formatUrl:iSe,getStylesFromArray:im,generateId:VIt,random:GIt,runFunc:sSe,entityDecode:pSe,insertTitle:bSe,parseFontSize:VA,InitIDGenerator:gSe};var YIt="comm",KIt="rule",XIt="decl",wSe="@import",vSe="@keyframes",mSe=Math.abs,udt=String.fromCharCode;function QIt(i){return i.trim()}function ldt(i,a,f){return i.replace(a,f)}function ySe(i,a){return i.indexOf(a)}function iF(i,a){return i.charCodeAt(a)|0}function sF(i,a,f){return i.slice(a,f)}function uk(i){return i.length}function ZIt(i){return i.length}function PW(i,a){return a.push(i),i}var FW=1,GA=1,JIt=0,nw=0,Of=0,UA="";function hdt(i,a,f,p,w,m,b){return{value:i,root:a,parent:f,type:p,props:w,children:m,line:FW,column:GA,length:b,return:""}}function xSe(){return Of}function kSe(){return Of=nw>0?iF(UA,--nw):0,GA--,Of===10&&(GA=1,FW--),Of}function sm(){return Of=nw2||fdt(Of)>3?"":" "}function _Se(i,a){for(;--a&&sm()&&!(Of<48||Of>102||Of>57&&Of<65||Of>70&&Of<97););return BW(i,NW()+(a<6&&hT()==32&&sm()==32))}function gdt(i){for(;sm();)switch(Of){case i:return nw;case 34:case 39:i!==34&&i!==39&&gdt(Of);break;case 40:i===41&&gdt(i);break;case 92:sm();break}return nw}function SSe(i,a){for(;sm()&&i+Of!==47+10;)if(i+Of===42+42&&hT()===47)break;return"/*"+BW(a,nw-1)+"*"+udt(i===47?i:sm())}function ASe(i){for(;!fdt(hT());)sm();return BW(i,nw)}function LSe(i){return TSe(RW("",null,null,null,[""],i=ESe(i),0,[0],i))}function RW(i,a,f,p,w,m,b,E,_){for(var A=0,I=0,B=b,N=0,R=0,z=0,W=1,et=1,st=1,at=0,bt="",mt=w,yt=m,ft=p,ut=bt;et;)switch(z=at,at=sm()){case 40:if(z!=108&&iF(ut,B-1)==58){ySe(ut+=ldt(ddt(at),"&","&\f"),"&\f")!=-1&&(st=-1);break}case 34:case 39:case 91:ut+=ddt(at);break;case 9:case 10:case 13:case 32:ut+=CSe(z);break;case 92:ut+=_Se(NW()-1,7);continue;case 47:switch(hT()){case 42:case 47:PW(MSe(SSe(sm(),NW()),a,f),_);break;default:ut+="/"}break;case 123*W:E[A++]=uk(ut)*st;case 125*W:case 59:case 0:switch(at){case 0:case 125:et=0;case 59+I:R>0&&uk(ut)-B&&PW(R>32?eOt(ut+";",p,f,B-1):eOt(ldt(ut," ","")+";",p,f,B-2),_);break;case 59:ut+=";";default:if(PW(ft=tOt(ut,a,f,A,I,w,E,bt,mt=[],yt=[],B),m),at===123)if(I===0)RW(ut,a,ft,ft,mt,m,B,E,yt);else switch(N===99&&iF(ut,3)===110?100:N){case 100:case 109:case 115:RW(i,ft,ft,p&&PW(tOt(i,ft,ft,0,0,w,E,bt,w,mt=[],B),yt),w,yt,B,E,p?mt:yt);break;default:RW(ut,ft,ft,ft,[""],yt,0,E,yt)}}A=I=R=0,W=st=1,bt=ut="",B=b;break;case 58:B=1+uk(ut),R=z;default:if(W<1){if(at==123)--W;else if(at==125&&W++==0&&kSe()==125)continue}switch(ut+=udt(at),at*W){case 38:st=I>0?1:(ut+="\f",-1);break;case 44:E[A++]=(uk(ut)-1)*st,st=1;break;case 64:hT()===45&&(ut+=ddt(sm())),N=hT(),I=B=uk(bt=ut+=ASe(NW())),at++;break;case 45:z===45&&uk(ut)==2&&(W=0)}}return m}function tOt(i,a,f,p,w,m,b,E,_,A,I){for(var B=w-1,N=w===0?m:[""],R=ZIt(N),z=0,W=0,et=0;z0?N[st]+" "+at:ldt(at,/&\f/g,N[st])))&&(_[et++]=bt);return hdt(i,a,f,w===0?KIt:E,_,A,I)}function MSe(i,a,f){return hdt(i,a,f,YIt,udt(xSe()),sF(i,2,-2),0)}function eOt(i,a,f,p){return hdt(i,a,f,XIt,sF(i,0,p),sF(i,p+1,-1),p)}function pdt(i,a){for(var f="",p=ZIt(i),w=0;w{let f=Z1({},i),p={};for(const w of a)aOt(w),p=Z1(p,w);if(f=Z1(f,p),p.theme&&p.theme in T5){const w=Z1({},rOt),m=Z1(w.themeVariables||{},p.themeVariables);f.theme&&f.theme in T5&&(f.themeVariables=T5[f.theme].getThemeVariables(m))}return aF=f,cOt(aF),aF},ISe=i=>(fp=Z1({},WA),fp=Z1(fp,i),i.theme&&T5[i.theme]&&(fp.themeVariables=T5[i.theme].getThemeVariables(i.themeVariables)),jW(fp,YA),fp),OSe=i=>{rOt=Z1({},i)},PSe=i=>(fp=Z1(fp,i),jW(fp,YA),fp),iOt=()=>Z1({},fp),sOt=i=>(cOt(i),Z1(aF,i),Fd()),Fd=()=>Z1({},aF),aOt=i=>{i&&(["secure",...fp.secure??[]].forEach(a=>{Object.hasOwn(i,a)&&(Ut.debug(`Denied attempt to modify a secure key ${a}`,i[a]),delete i[a])}),Object.keys(i).forEach(a=>{a.startsWith("__")&&delete i[a]}),Object.keys(i).forEach(a=>{typeof i[a]=="string"&&(i[a].includes("<")||i[a].includes(">")||i[a].includes("url(data:"))&&delete i[a],typeof i[a]=="object"&&aOt(i[a])}))},FSe=i=>{mW(i),i.fontFamily&&(!i.themeVariables||!i.themeVariables.fontFamily)&&(i.themeVariables={fontFamily:i.fontFamily}),YA.push(i),jW(fp,YA)},$W=(i=fp)=>{YA=[],jW(i,YA)},NSe={LAZY_LOAD_DEPRECATED:"The configuration options lazyLoadedDiagrams and loadExternalDiagramsAtStartup are deprecated. Please use registerExternalDiagrams instead."},oOt={},BSe=i=>{oOt[i]||(Ut.warn(NSe[i]),oOt[i]=!0)},cOt=i=>{i&&(i.lazyLoadedDiagrams||i.loadExternalDiagramsAtStartup)&&BSe("LAZY_LOAD_DEPRECATED")},uOt="c4",RSe={id:uOt,detector:i=>/^\s*C4Context|C4Container|C4Component|C4Dynamic|C4Deployment/.test(i),loader:async()=>{const{diagram:i}=await Promise.resolve().then(()=>nIe);return{id:uOt,diagram:i}}},lOt="flowchart",jSe={id:lOt,detector:(i,a)=>{var f,p;return((f=a==null?void 0:a.flowchart)==null?void 0:f.defaultRenderer)==="dagre-wrapper"||((p=a==null?void 0:a.flowchart)==null?void 0:p.defaultRenderer)==="elk"?!1:/^\s*graph/.test(i)},loader:async()=>{const{diagram:i}=await Promise.resolve().then(()=>cze);return{id:lOt,diagram:i}}},hOt="flowchart-v2",$Se={id:hOt,detector:(i,a)=>{var f,p,w;return((f=a==null?void 0:a.flowchart)==null?void 0:f.defaultRenderer)==="dagre-d3"||((p=a==null?void 0:a.flowchart)==null?void 0:p.defaultRenderer)==="elk"?!1:/^\s*graph/.test(i)&&((w=a==null?void 0:a.flowchart)==null?void 0:w.defaultRenderer)==="dagre-wrapper"?!0:/^\s*flowchart/.test(i)},loader:async()=>{const{diagram:i}=await Promise.resolve().then(()=>uze);return{id:hOt,diagram:i}}},fOt="er",zSe={id:fOt,detector:i=>/^\s*erDiagram/.test(i),loader:async()=>{const{diagram:i}=await Promise.resolve().then(()=>Fze);return{id:fOt,diagram:i}}},dOt="gitGraph",qSe={id:dOt,detector:i=>/^\s*gitGraph/.test(i),loader:async()=>{const{diagram:i}=await Promise.resolve().then(()=>aqe);return{id:dOt,diagram:i}}},gOt="gantt",HSe={id:gOt,detector:i=>/^\s*gantt/.test(i),loader:async()=>{const{diagram:i}=await Promise.resolve().then(()=>Kqe);return{id:gOt,diagram:i}}},pOt="info",VSe={id:pOt,detector:i=>/^\s*info/.test(i),loader:async()=>{const{diagram:i}=await Promise.resolve().then(()=>Qqe);return{id:pOt,diagram:i}}},bOt="pie",GSe={id:bOt,detector:i=>/^\s*pie/.test(i),loader:async()=>{const{diagram:i}=await Promise.resolve().then(()=>rHe);return{id:bOt,diagram:i}}},wOt="quadrantChart",USe={id:wOt,detector:i=>/^\s*quadrantChart/.test(i),loader:async()=>{const{diagram:i}=await Promise.resolve().then(()=>mHe);return{id:wOt,diagram:i}}},vOt="xychart",WSe={id:vOt,detector:i=>/^\s*xychart-beta/.test(i),loader:async()=>{const{diagram:i}=await Promise.resolve().then(()=>HHe);return{id:vOt,diagram:i}}},mOt="requirement",YSe={id:mOt,detector:i=>/^\s*requirement(Diagram)?/.test(i),loader:async()=>{const{diagram:i}=await Promise.resolve().then(()=>JHe);return{id:mOt,diagram:i}}},yOt="sequence",KSe={id:yOt,detector:i=>/^\s*sequenceDiagram/.test(i),loader:async()=>{const{diagram:i}=await Promise.resolve().then(()=>iGe);return{id:yOt,diagram:i}}},xOt="class",XSe={id:xOt,detector:(i,a)=>{var f;return((f=a==null?void 0:a.class)==null?void 0:f.defaultRenderer)==="dagre-wrapper"?!1:/^\s*classDiagram/.test(i)},loader:async()=>{const{diagram:i}=await Promise.resolve().then(()=>AGe);return{id:xOt,diagram:i}}},kOt="classDiagram",QSe={id:kOt,detector:(i,a)=>{var f;return/^\s*classDiagram/.test(i)&&((f=a==null?void 0:a.class)==null?void 0:f.defaultRenderer)==="dagre-wrapper"?!0:/^\s*classDiagram-v2/.test(i)},loader:async()=>{const{diagram:i}=await Promise.resolve().then(()=>PGe);return{id:kOt,diagram:i}}},EOt="state",ZSe={id:EOt,detector:(i,a)=>{var f;return((f=a==null?void 0:a.state)==null?void 0:f.defaultRenderer)==="dagre-wrapper"?!1:/^\s*stateDiagram/.test(i)},loader:async()=>{const{diagram:i}=await Promise.resolve().then(()=>xUe);return{id:EOt,diagram:i}}},TOt="stateDiagram",JSe={id:TOt,detector:(i,a)=>{var f;return!!(/^\s*stateDiagram-v2/.test(i)||/^\s*stateDiagram/.test(i)&&((f=a==null?void 0:a.state)==null?void 0:f.defaultRenderer)==="dagre-wrapper")},loader:async()=>{const{diagram:i}=await Promise.resolve().then(()=>$Ue);return{id:TOt,diagram:i}}},COt="journey",tAe={id:COt,detector:i=>/^\s*journey/.test(i),loader:async()=>{const{diagram:i}=await Promise.resolve().then(()=>sWe);return{id:COt,diagram:i}}},eAe=function(i,a){for(let f of a)i.attr(f[0],f[1])},nAe=function(i,a,f){let p=new Map;return f?(p.set("width","100%"),p.set("style",`max-width: ${a}px;`)):(p.set("height",i),p.set("width",a)),p},k0=function(i,a,f,p){const w=nAe(a,f,p);eAe(i,w)},fT=function(i,a,f,p){const w=a.node().getBBox(),m=w.width,b=w.height;Ut.info(`SVG bounds: ${m}x${b}`,w);let E=0,_=0;Ut.info(`Graph bounds: ${E}x${_}`,i),E=m+f*2,_=b+f*2,Ut.info(`Calculated bounds: ${E}x${_}`),k0(a,_,E,p);const A=`${w.x-f} ${w.y-f} ${w.width+2*f} ${w.height+2*f}`;a.attr("viewBox",A)},zW={},rAe=(i,a,f)=>{let p="";return i in zW&&zW[i]?p=zW[i](f):Ut.warn(`No theme found for ${i}`),` & { + font-family: ${f.fontFamily}; + font-size: ${f.fontSize}; + fill: ${f.textColor} + } + + /* Classes common for multiple diagrams */ + + & .error-icon { + fill: ${f.errorBkgColor}; + } + & .error-text { + fill: ${f.errorTextColor}; + stroke: ${f.errorTextColor}; + } + + & .edge-thickness-normal { + stroke-width: 2px; + } + & .edge-thickness-thick { + stroke-width: 3.5px + } + & .edge-pattern-solid { + stroke-dasharray: 0; + } + + & .edge-pattern-dashed{ + stroke-dasharray: 3; + } + .edge-pattern-dotted { + stroke-dasharray: 2; + } + + & .marker { + fill: ${f.lineColor}; + stroke: ${f.lineColor}; + } + & .marker.cross { + stroke: ${f.lineColor}; + } + + & svg { + font-family: ${f.fontFamily}; + font-size: ${f.fontSize}; + } + + ${p} + + ${a} +`},iAe=(i,a)=>{a!==void 0&&(zW[i]=a)},sAe=rAe;let bdt="",wdt="",vdt="";const mdt=i=>Q1(i,Fd()),hg=()=>{bdt="",vdt="",wdt=""},E0=i=>{bdt=mdt(i).replace(/^\s+/g,"")},fg=()=>bdt,dg=i=>{vdt=mdt(i).replace(/\n\s+/g,` +`)},gg=()=>vdt,Nb=i=>{wdt=mdt(i)},pg=()=>wdt,_Ot=Object.freeze(Object.defineProperty({__proto__:null,clear:hg,getAccDescription:gg,getAccTitle:fg,getDiagramTitle:pg,setAccDescription:dg,setAccTitle:E0,setDiagramTitle:Nb},Symbol.toStringTag,{value:"Module"})),aAe=Ut,oAe=Xft,Oe=Fd,cAe=sOt,SOt=WA,uAe=i=>Q1(i,Oe()),AOt=fT,lAe=()=>_Ot,qW={},HW=(i,a,f)=>{var p;if(qW[i])throw new Error(`Diagram ${i} already registered.`);qW[i]=a,f&&uIt(i,f),iAe(i,a.styles),(p=a.injectUtils)==null||p.call(a,aAe,oAe,Oe,uAe,AOt,lAe(),()=>{})},ydt=i=>{if(i in qW)return qW[i];throw new hAe(i)};class hAe extends Error{constructor(a){super(`Diagram ${a} not found.`)}}const VW=i=>{var w;const{securityLevel:a}=Oe();let f=yr("body");if(a==="sandbox"){const b=((w=yr(`#i${i}`).node())==null?void 0:w.contentDocument)??document;f=yr(b.body)}return f.select(`#${i}`)},LOt={draw:(i,a,f)=>{Ut.debug(`renering svg for syntax error +`);const p=VW(a);p.attr("viewBox","0 0 2412 512"),k0(p,100,512,!0);const w=p.append("g");w.append("path").attr("class","error-icon").attr("d","m411.313,123.313c6.25-6.25 6.25-16.375 0-22.625s-16.375-6.25-22.625,0l-32,32-9.375,9.375-20.688-20.688c-12.484-12.5-32.766-12.5-45.25,0l-16,16c-1.261,1.261-2.304,2.648-3.31,4.051-21.739-8.561-45.324-13.426-70.065-13.426-105.867,0-192,86.133-192,192s86.133,192 192,192 192-86.133 192-192c0-24.741-4.864-48.327-13.426-70.065 1.402-1.007 2.79-2.049 4.051-3.31l16-16c12.5-12.492 12.5-32.758 0-45.25l-20.688-20.688 9.375-9.375 32.001-31.999zm-219.313,100.687c-52.938,0-96,43.063-96,96 0,8.836-7.164,16-16,16s-16-7.164-16-16c0-70.578 57.422-128 128-128 8.836,0 16,7.164 16,16s-7.164,16-16,16z"),w.append("path").attr("class","error-icon").attr("d","m459.02,148.98c-6.25-6.25-16.375-6.25-22.625,0s-6.25,16.375 0,22.625l16,16c3.125,3.125 7.219,4.688 11.313,4.688 4.094,0 8.188-1.563 11.313-4.688 6.25-6.25 6.25-16.375 0-22.625l-16.001-16z"),w.append("path").attr("class","error-icon").attr("d","m340.395,75.605c3.125,3.125 7.219,4.688 11.313,4.688 4.094,0 8.188-1.563 11.313-4.688 6.25-6.25 6.25-16.375 0-22.625l-16-16c-6.25-6.25-16.375-6.25-22.625,0s-6.25,16.375 0,22.625l15.999,16z"),w.append("path").attr("class","error-icon").attr("d","m400,64c8.844,0 16-7.164 16-16v-32c0-8.836-7.156-16-16-16-8.844,0-16,7.164-16,16v32c0,8.836 7.156,16 16,16z"),w.append("path").attr("class","error-icon").attr("d","m496,96.586h-32c-8.844,0-16,7.164-16,16 0,8.836 7.156,16 16,16h32c8.844,0 16-7.164 16-16 0-8.836-7.156-16-16-16z"),w.append("path").attr("class","error-icon").attr("d","m436.98,75.605c3.125,3.125 7.219,4.688 11.313,4.688 4.094,0 8.188-1.563 11.313-4.688l32-32c6.25-6.25 6.25-16.375 0-22.625s-16.375-6.25-22.625,0l-32,32c-6.251,6.25-6.251,16.375-0.001,22.625z"),w.append("text").attr("class","error-text").attr("x",1440).attr("y",250).attr("font-size","150px").style("text-anchor","middle").text("Syntax error in text"),w.append("text").attr("class","error-text").attr("x",1250).attr("y",400).attr("font-size","100px").style("text-anchor","middle").text(`mermaid version ${f}`)}},fAe=LOt,dAe={db:{},renderer:LOt,parser:{parser:{yy:{}},parse:()=>{}}},MOt="flowchart-elk",gAe={id:MOt,detector:(i,a)=>{var f;return!!(/^\s*flowchart-elk/.test(i)||/^\s*flowchart|graph/.test(i)&&((f=a==null?void 0:a.flowchart)==null?void 0:f.defaultRenderer)==="elk")},loader:async()=>{const{diagram:i}=await Promise.resolve().then(()=>xWe);return{id:MOt,diagram:i}}},DOt="timeline",pAe={id:DOt,detector:i=>/^\s*timeline/.test(i),loader:async()=>{const{diagram:i}=await Promise.resolve().then(()=>$We);return{id:DOt,diagram:i}}},IOt="mindmap",bAe={id:IOt,detector:i=>/^\s*mindmap/.test(i),loader:async()=>{const{diagram:i}=await Promise.resolve().then(()=>bYe);return{id:IOt,diagram:i}}},OOt="sankey",wAe={id:OOt,detector:i=>/^\s*sankey-beta/.test(i),loader:async()=>{const{diagram:i}=await Promise.resolve().then(()=>UYe);return{id:OOt,diagram:i}}};let POt=!1;const xdt=()=>{POt||(POt=!0,HW("error",dAe,i=>i.toLowerCase().trim()==="error"),HW("---",{db:{clear:()=>{}},styles:{},renderer:{draw:()=>{}},parser:{parser:{yy:{}},parse:()=>{throw new Error("Diagrams beginning with --- are not valid. If you were trying to use a YAML front-matter, please ensure that you've correctly opened and closed the YAML front-matter with un-indented `---` blocks")}},init:()=>null},i=>i.toLowerCase().trimStart().startsWith("---")),cIt(RSe,QSe,XSe,zSe,HSe,VSe,GSe,YSe,KSe,gAe,$Se,jSe,bAe,pAe,qSe,JSe,ZSe,tAe,USe,wAe,WSe))};class FOt{constructor(a,f={}){this.text=a,this.metadata=f,this.type="graph",this.text+=` +`;const p=Fd();try{this.type=yW(a,p)}catch(m){this.type="error",this.detectError=m}const w=ydt(this.type);Ut.debug("Type "+this.type),this.db=w.db,this.renderer=w.renderer,this.parser=w.parser,this.parser.parser.yy=this.db,this.init=w.init,this.parse()}parse(){var f,p,w,m,b;if(this.detectError)throw this.detectError;(p=(f=this.db).clear)==null||p.call(f);const a=Fd();(w=this.init)==null||w.call(this,a),this.metadata.title&&((b=(m=this.db).setDiagramTitle)==null||b.call(m,this.metadata.title)),this.parser.parse(this.text)}async render(a,f){await this.renderer.draw(this.text,a,f,this)}getParser(){return this.parser}getType(){return this.type}}const kdt=async(i,a={})=>{const f=yW(i,Fd());try{ydt(f)}catch{const w=ECe(f);if(!w)throw new oIt(`Diagram ${f} not found.`);const{id:m,diagram:b}=await w();HW(m,b)}return new FOt(i,a)};let Edt=[];const vAe=i=>{Edt.push(i)},mAe=()=>{Edt.forEach(i=>{i()}),Edt=[]};var yAe=kIt(Object.keys,Object);const xAe=yAe;var kAe=Object.prototype,EAe=kAe.hasOwnProperty;function NOt(i){if(!_W(i))return xAe(i);var a=[];for(var f in Object(i))EAe.call(i,f)&&f!="constructor"&&a.push(f);return a}var TAe=oT(nm,"DataView");const Tdt=TAe;var CAe=oT(nm,"Promise");const Cdt=CAe;var _Ae=oT(nm,"Set");const KA=_Ae;var SAe=oT(nm,"WeakMap");const _dt=SAe;var BOt="[object Map]",AAe="[object Object]",ROt="[object Promise]",jOt="[object Set]",$Ot="[object WeakMap]",zOt="[object DataView]",LAe=aT(Tdt),MAe=aT(JP),DAe=aT(Cdt),IAe=aT(KA),OAe=aT(_dt),dT=sT;(Tdt&&dT(new Tdt(new ArrayBuffer(1)))!=zOt||JP&&dT(new JP)!=BOt||Cdt&&dT(Cdt.resolve())!=ROt||KA&&dT(new KA)!=jOt||_dt&&dT(new _dt)!=$Ot)&&(dT=function(i){var a=sT(i),f=a==AAe?i.constructor:void 0,p=f?aT(f):"";if(p)switch(p){case LAe:return zOt;case MAe:return BOt;case DAe:return ROt;case IAe:return jOt;case OAe:return $Ot}return a});const XA=dT;var PAe="[object Map]",FAe="[object Set]",NAe=Object.prototype,BAe=NAe.hasOwnProperty;function oF(i){if(i==null)return!0;if(ck(i)&&(If(i)||typeof i=="string"||typeof i.splice=="function"||zA(i)||AW(i)||$A(i)))return!i.length;var a=XA(i);if(a==PAe||a==FAe)return!i.size;if(_W(i))return!NOt(i).length;for(var f in i)if(BAe.call(i,f))return!1;return!0}const RAe="graphics-document document";function jAe(i,a){i.attr("role",RAe),a!==""&&i.attr("aria-roledescription",a)}function $Ae(i,a,f,p){if(i.insert!==void 0){if(f){const w=`chart-desc-${p}`;i.attr("aria-describedby",w),i.insert("desc",":first-child").attr("id",w).text(f)}if(a){const w=`chart-title-${p}`;i.attr("aria-labelledby",w),i.insert("title",":first-child").attr("id",w).text(a)}}}const zAe=i=>i.replace(/^\s*%%(?!{)[^\n]+\n?/gm,"").trimStart();/*! js-yaml 4.1.0 https://github.com/nodeca/js-yaml @license MIT */function qOt(i){return typeof i>"u"||i===null}function qAe(i){return typeof i=="object"&&i!==null}function HAe(i){return Array.isArray(i)?i:qOt(i)?[]:[i]}function VAe(i,a){var f,p,w,m;if(a)for(m=Object.keys(a),f=0,p=m.length;fE&&(m=" ... ",a=p-E+m.length),f-p>E&&(b=" ...",f=p+E-b.length),{str:m+i.slice(a,f).replace(/\t/g,"→")+b,pos:p-a+m.length}}function Adt(i,a){return bg.repeat(" ",a-i.length)+i}function JAe(i,a){if(a=Object.create(a||null),!i.buffer)return null;a.maxLength||(a.maxLength=79),typeof a.indent!="number"&&(a.indent=1),typeof a.linesBefore!="number"&&(a.linesBefore=3),typeof a.linesAfter!="number"&&(a.linesAfter=2);for(var f=/\r?\n|\r|\0/g,p=[0],w=[],m,b=-1;m=f.exec(i.buffer);)w.push(m.index),p.push(m.index+m[0].length),i.position<=m.index&&b<0&&(b=p.length-2);b<0&&(b=p.length-1);var E="",_,A,I=Math.min(i.line+a.linesAfter,w.length).toString().length,B=a.maxLength-(a.indent+I+3);for(_=1;_<=a.linesBefore&&!(b-_<0);_++)A=Sdt(i.buffer,p[b-_],w[b-_],i.position-(p[b]-p[b-_]),B),E=bg.repeat(" ",a.indent)+Adt((i.line-_+1).toString(),I)+" | "+A.str+` +`+E;for(A=Sdt(i.buffer,p[b],w[b],i.position,B),E+=bg.repeat(" ",a.indent)+Adt((i.line+1).toString(),I)+" | "+A.str+` +`,E+=bg.repeat("-",a.indent+I+3+A.pos)+`^ +`,_=1;_<=a.linesAfter&&!(b+_>=w.length);_++)A=Sdt(i.buffer,p[b+_],w[b+_],i.position-(p[b]-p[b+_]),B),E+=bg.repeat(" ",a.indent)+Adt((i.line+_+1).toString(),I)+" | "+A.str+` +`;return E.replace(/\n$/,"")}var tLe=JAe,eLe=["kind","multi","resolve","construct","instanceOf","predicate","represent","representName","defaultStyle","styleAliases"],nLe=["scalar","sequence","mapping"];function rLe(i){var a={};return i!==null&&Object.keys(i).forEach(function(f){i[f].forEach(function(p){a[String(p)]=f})}),a}function iLe(i,a){if(a=a||{},Object.keys(a).forEach(function(f){if(eLe.indexOf(f)===-1)throw new A5('Unknown option "'+f+'" is met in definition of "'+i+'" YAML type.')}),this.options=a,this.tag=i,this.kind=a.kind||null,this.resolve=a.resolve||function(){return!0},this.construct=a.construct||function(f){return f},this.instanceOf=a.instanceOf||null,this.predicate=a.predicate||null,this.represent=a.represent||null,this.representName=a.representName||null,this.defaultStyle=a.defaultStyle||null,this.multi=a.multi||!1,this.styleAliases=rLe(a.styleAliases||null),nLe.indexOf(this.kind)===-1)throw new A5('Unknown kind "'+this.kind+'" is specified for "'+i+'" YAML type.')}var T0=iLe;function VOt(i,a){var f=[];return i[a].forEach(function(p){var w=f.length;f.forEach(function(m,b){m.tag===p.tag&&m.kind===p.kind&&m.multi===p.multi&&(w=b)}),f[w]=p}),f}function sLe(){var i={scalar:{},sequence:{},mapping:{},fallback:{},multi:{scalar:[],sequence:[],mapping:[],fallback:[]}},a,f;function p(w){w.multi?(i.multi[w.kind].push(w),i.multi.fallback.push(w)):i[w.kind][w.tag]=i.fallback[w.tag]=w}for(a=0,f=arguments.length;a=0?"0b"+i.toString(2):"-0b"+i.toString(2).slice(1)},octal:function(i){return i>=0?"0o"+i.toString(8):"-0o"+i.toString(8).slice(1)},decimal:function(i){return i.toString(10)},hexadecimal:function(i){return i>=0?"0x"+i.toString(16).toUpperCase():"-0x"+i.toString(16).toUpperCase().slice(1)}},defaultStyle:"decimal",styleAliases:{binary:[2,"bin"],octal:[8,"oct"],decimal:[10,"dec"],hexadecimal:[16,"hex"]}}),_Le=new RegExp("^(?:[-+]?(?:[0-9][0-9_]*)(?:\\.[0-9_]*)?(?:[eE][-+]?[0-9]+)?|\\.[0-9_]+(?:[eE][-+]?[0-9]+)?|[-+]?\\.(?:inf|Inf|INF)|\\.(?:nan|NaN|NAN))$");function SLe(i){return!(i===null||!_Le.test(i)||i[i.length-1]==="_")}function ALe(i){var a,f;return a=i.replace(/_/g,"").toLowerCase(),f=a[0]==="-"?-1:1,"+-".indexOf(a[0])>=0&&(a=a.slice(1)),a===".inf"?f===1?Number.POSITIVE_INFINITY:Number.NEGATIVE_INFINITY:a===".nan"?NaN:f*parseFloat(a,10)}var LLe=/^[-+]?[0-9]+e/;function MLe(i,a){var f;if(isNaN(i))switch(a){case"lowercase":return".nan";case"uppercase":return".NAN";case"camelcase":return".NaN"}else if(Number.POSITIVE_INFINITY===i)switch(a){case"lowercase":return".inf";case"uppercase":return".INF";case"camelcase":return".Inf"}else if(Number.NEGATIVE_INFINITY===i)switch(a){case"lowercase":return"-.inf";case"uppercase":return"-.INF";case"camelcase":return"-.Inf"}else if(bg.isNegativeZero(i))return"-0.0";return f=i.toString(10),LLe.test(f)?f.replace("e",".e"):f}function DLe(i){return Object.prototype.toString.call(i)==="[object Number]"&&(i%1!==0||bg.isNegativeZero(i))}var ILe=new T0("tag:yaml.org,2002:float",{kind:"scalar",resolve:SLe,construct:ALe,predicate:DLe,represent:MLe,defaultStyle:"lowercase"}),GOt=lLe.extend({implicit:[gLe,vLe,CLe,ILe]}),OLe=GOt,UOt=new RegExp("^([0-9][0-9][0-9][0-9])-([0-9][0-9])-([0-9][0-9])$"),WOt=new RegExp("^([0-9][0-9][0-9][0-9])-([0-9][0-9]?)-([0-9][0-9]?)(?:[Tt]|[ \\t]+)([0-9][0-9]?):([0-9][0-9]):([0-9][0-9])(?:\\.([0-9]*))?(?:[ \\t]*(Z|([-+])([0-9][0-9]?)(?::([0-9][0-9]))?))?$");function PLe(i){return i===null?!1:UOt.exec(i)!==null||WOt.exec(i)!==null}function FLe(i){var a,f,p,w,m,b,E,_=0,A=null,I,B,N;if(a=UOt.exec(i),a===null&&(a=WOt.exec(i)),a===null)throw new Error("Date resolve error");if(f=+a[1],p=+a[2]-1,w=+a[3],!a[4])return new Date(Date.UTC(f,p,w));if(m=+a[4],b=+a[5],E=+a[6],a[7]){for(_=a[7].slice(0,3);_.length<3;)_+="0";_=+_}return a[9]&&(I=+a[10],B=+(a[11]||0),A=(I*60+B)*6e4,a[9]==="-"&&(A=-A)),N=new Date(Date.UTC(f,p,w,m,b,E,_)),A&&N.setTime(N.getTime()-A),N}function NLe(i){return i.toISOString()}var BLe=new T0("tag:yaml.org,2002:timestamp",{kind:"scalar",resolve:PLe,construct:FLe,instanceOf:Date,represent:NLe});function RLe(i){return i==="<<"||i===null}var jLe=new T0("tag:yaml.org,2002:merge",{kind:"scalar",resolve:RLe}),Mdt=`ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/= +\r`;function $Le(i){if(i===null)return!1;var a,f,p=0,w=i.length,m=Mdt;for(f=0;f64)){if(a<0)return!1;p+=6}return p%8===0}function zLe(i){var a,f,p=i.replace(/[\r\n=]/g,""),w=p.length,m=Mdt,b=0,E=[];for(a=0;a>16&255),E.push(b>>8&255),E.push(b&255)),b=b<<6|m.indexOf(p.charAt(a));return f=w%4*6,f===0?(E.push(b>>16&255),E.push(b>>8&255),E.push(b&255)):f===18?(E.push(b>>10&255),E.push(b>>2&255)):f===12&&E.push(b>>4&255),new Uint8Array(E)}function qLe(i){var a="",f=0,p,w,m=i.length,b=Mdt;for(p=0;p>18&63],a+=b[f>>12&63],a+=b[f>>6&63],a+=b[f&63]),f=(f<<8)+i[p];return w=m%3,w===0?(a+=b[f>>18&63],a+=b[f>>12&63],a+=b[f>>6&63],a+=b[f&63]):w===2?(a+=b[f>>10&63],a+=b[f>>4&63],a+=b[f<<2&63],a+=b[64]):w===1&&(a+=b[f>>2&63],a+=b[f<<4&63],a+=b[64],a+=b[64]),a}function HLe(i){return Object.prototype.toString.call(i)==="[object Uint8Array]"}var VLe=new T0("tag:yaml.org,2002:binary",{kind:"scalar",resolve:$Le,construct:zLe,predicate:HLe,represent:qLe}),GLe=Object.prototype.hasOwnProperty,ULe=Object.prototype.toString;function WLe(i){if(i===null)return!0;var a=[],f,p,w,m,b,E=i;for(f=0,p=E.length;f>10)+55296,(i-65536&1023)+56320)}for(var ePt=new Array(256),nPt=new Array(256),ZA=0;ZA<256;ZA++)ePt[ZA]=tPt(ZA)?1:0,nPt[ZA]=tPt(ZA);function dMe(i,a){this.input=i,this.filename=a.filename||null,this.schema=a.schema||iMe,this.onWarning=a.onWarning||null,this.legacy=a.legacy||!1,this.json=a.json||!1,this.listener=a.listener||null,this.implicitTypes=this.schema.compiledImplicit,this.typeMap=this.schema.compiledTypeMap,this.length=i.length,this.position=0,this.line=0,this.lineStart=0,this.lineIndent=0,this.firstTabInLine=-1,this.documents=[]}function rPt(i,a){var f={name:i.filename,buffer:i.input.slice(0,-1),position:i.position,line:i.line,column:i.position-i.lineStart};return f.snippet=tLe(f),new A5(a,f)}function Ss(i,a){throw rPt(i,a)}function WW(i,a){i.onWarning&&i.onWarning.call(null,rPt(i,a))}var iPt={YAML:function(a,f,p){var w,m,b;a.version!==null&&Ss(a,"duplication of %YAML directive"),p.length!==1&&Ss(a,"YAML directive accepts exactly one argument"),w=/^([0-9]+)\.([0-9]+)$/.exec(p[0]),w===null&&Ss(a,"ill-formed argument of the YAML directive"),m=parseInt(w[1],10),b=parseInt(w[2],10),m!==1&&Ss(a,"unacceptable YAML version of the document"),a.version=p[0],a.checkLineBreaks=b<2,b!==1&&b!==2&&WW(a,"unsupported YAML version of the document")},TAG:function(a,f,p){var w,m;p.length!==2&&Ss(a,"TAG directive accepts exactly two arguments"),w=p[0],m=p[1],QOt.test(w)||Ss(a,"ill-formed tag handle (first argument) of the TAG directive"),lk.call(a.tagMap,w)&&Ss(a,'there is a previously declared suffix for "'+w+'" tag handle'),ZOt.test(m)||Ss(a,"ill-formed tag prefix (second argument) of the TAG directive");try{m=decodeURIComponent(m)}catch{Ss(a,"tag prefix is malformed: "+m)}a.tagMap[w]=m}};function hk(i,a,f,p){var w,m,b,E;if(a1&&(i.result+=bg.repeat(` +`,a-1))}function gMe(i,a,f){var p,w,m,b,E,_,A,I,B=i.kind,N=i.result,R;if(R=i.input.charCodeAt(i.position),dp(R)||QA(R)||R===35||R===38||R===42||R===33||R===124||R===62||R===39||R===34||R===37||R===64||R===96||(R===63||R===45)&&(w=i.input.charCodeAt(i.position+1),dp(w)||f&&QA(w)))return!1;for(i.kind="scalar",i.result="",m=b=i.position,E=!1;R!==0;){if(R===58){if(w=i.input.charCodeAt(i.position+1),dp(w)||f&&QA(w))break}else if(R===35){if(p=i.input.charCodeAt(i.position-1),dp(p))break}else{if(i.position===i.lineStart&&YW(i)||f&&QA(R))break;if(g3(R))if(_=i.line,A=i.lineStart,I=i.lineIndent,Pf(i,!1,-1),i.lineIndent>=a){E=!0,R=i.input.charCodeAt(i.position);continue}else{i.position=b,i.line=_,i.lineStart=A,i.lineIndent=I;break}}E&&(hk(i,m,b,!1),Odt(i,i.line-_),m=b=i.position,E=!1),gT(R)||(b=i.position+1),R=i.input.charCodeAt(++i.position)}return hk(i,m,b,!1),i.result?!0:(i.kind=B,i.result=N,!1)}function pMe(i,a){var f,p,w;if(f=i.input.charCodeAt(i.position),f!==39)return!1;for(i.kind="scalar",i.result="",i.position++,p=w=i.position;(f=i.input.charCodeAt(i.position))!==0;)if(f===39)if(hk(i,p,i.position,!0),f=i.input.charCodeAt(++i.position),f===39)p=i.position,i.position++,w=i.position;else return!0;else g3(f)?(hk(i,p,w,!0),Odt(i,Pf(i,!1,a)),p=w=i.position):i.position===i.lineStart&&YW(i)?Ss(i,"unexpected end of the document within a single quoted scalar"):(i.position++,w=i.position);Ss(i,"unexpected end of the stream within a single quoted scalar")}function bMe(i,a){var f,p,w,m,b,E;if(E=i.input.charCodeAt(i.position),E!==34)return!1;for(i.kind="scalar",i.result="",i.position++,f=p=i.position;(E=i.input.charCodeAt(i.position))!==0;){if(E===34)return hk(i,f,i.position,!0),i.position++,!0;if(E===92){if(hk(i,f,i.position,!0),E=i.input.charCodeAt(++i.position),g3(E))Pf(i,!1,a);else if(E<256&&ePt[E])i.result+=nPt[E],i.position++;else if((b=lMe(E))>0){for(w=b,m=0;w>0;w--)E=i.input.charCodeAt(++i.position),(b=uMe(E))>=0?m=(m<<4)+b:Ss(i,"expected hexadecimal character");i.result+=fMe(m),i.position++}else Ss(i,"unknown escape sequence");f=p=i.position}else g3(E)?(hk(i,f,p,!0),Odt(i,Pf(i,!1,a)),f=p=i.position):i.position===i.lineStart&&YW(i)?Ss(i,"unexpected end of the document within a double quoted scalar"):(i.position++,p=i.position)}Ss(i,"unexpected end of the stream within a double quoted scalar")}function wMe(i,a){var f=!0,p,w,m,b=i.tag,E,_=i.anchor,A,I,B,N,R,z=Object.create(null),W,et,st,at;if(at=i.input.charCodeAt(i.position),at===91)I=93,R=!1,E=[];else if(at===123)I=125,R=!0,E={};else return!1;for(i.anchor!==null&&(i.anchorMap[i.anchor]=E),at=i.input.charCodeAt(++i.position);at!==0;){if(Pf(i,!0,a),at=i.input.charCodeAt(i.position),at===I)return i.position++,i.tag=b,i.anchor=_,i.kind=R?"mapping":"sequence",i.result=E,!0;f?at===44&&Ss(i,"expected the node content, but found ','"):Ss(i,"missed comma between flow collection entries"),et=W=st=null,B=N=!1,at===63&&(A=i.input.charCodeAt(i.position+1),dp(A)&&(B=N=!0,i.position++,Pf(i,!0,a))),p=i.line,w=i.lineStart,m=i.position,tL(i,a,GW,!1,!0),et=i.tag,W=i.result,Pf(i,!0,a),at=i.input.charCodeAt(i.position),(N||i.line===p)&&at===58&&(B=!0,at=i.input.charCodeAt(++i.position),Pf(i,!0,a),tL(i,a,GW,!1,!0),st=i.result),R?JA(i,E,z,et,W,st,p,w,m):B?E.push(JA(i,null,z,et,W,st,p,w,m)):E.push(W),Pf(i,!0,a),at=i.input.charCodeAt(i.position),at===44?(f=!0,at=i.input.charCodeAt(++i.position)):f=!1}Ss(i,"unexpected end of the stream within a flow collection")}function vMe(i,a){var f,p,w=Ddt,m=!1,b=!1,E=a,_=0,A=!1,I,B;if(B=i.input.charCodeAt(i.position),B===124)p=!1;else if(B===62)p=!0;else return!1;for(i.kind="scalar",i.result="";B!==0;)if(B=i.input.charCodeAt(++i.position),B===43||B===45)Ddt===w?w=B===43?XOt:sMe:Ss(i,"repeat of a chomping mode identifier");else if((I=hMe(B))>=0)I===0?Ss(i,"bad explicit indentation width of a block scalar; it cannot be less than one"):b?Ss(i,"repeat of an indentation width identifier"):(E=a+I-1,b=!0);else break;if(gT(B)){do B=i.input.charCodeAt(++i.position);while(gT(B));if(B===35)do B=i.input.charCodeAt(++i.position);while(!g3(B)&&B!==0)}for(;B!==0;){for(Idt(i),i.lineIndent=0,B=i.input.charCodeAt(i.position);(!b||i.lineIndentE&&(E=i.lineIndent),g3(B)){_++;continue}if(i.lineIndenta)&&_!==0)Ss(i,"bad indentation of a sequence entry");else if(i.lineIndenta)&&(et&&(b=i.line,E=i.lineStart,_=i.position),tL(i,a,UW,!0,w)&&(et?z=i.result:W=i.result),et||(JA(i,B,N,R,z,W,b,E,_),R=z=W=null),Pf(i,!0,-1),at=i.input.charCodeAt(i.position)),(i.line===m||i.lineIndent>a)&&at!==0)Ss(i,"bad indentation of a mapping entry");else if(i.lineIndenta?_=1:i.lineIndent===a?_=0:i.lineIndenta?_=1:i.lineIndent===a?_=0:i.lineIndent tag; it should be "scalar", not "'+i.kind+'"'),B=0,N=i.implicitTypes.length;B"),i.result!==null&&z.kind!==i.kind&&Ss(i,"unacceptable node kind for !<"+i.tag+'> tag; it should be "'+z.kind+'", not "'+i.kind+'"'),z.resolve(i.result,i.tag)?(i.result=z.construct(i.result,i.tag),i.anchor!==null&&(i.anchorMap[i.anchor]=i.result)):Ss(i,"cannot resolve a node with !<"+i.tag+"> explicit tag")}return i.listener!==null&&i.listener("close",i),i.tag!==null||i.anchor!==null||I}function EMe(i){var a=i.position,f,p,w,m=!1,b;for(i.version=null,i.checkLineBreaks=i.legacy,i.tagMap=Object.create(null),i.anchorMap=Object.create(null);(b=i.input.charCodeAt(i.position))!==0&&(Pf(i,!0,-1),b=i.input.charCodeAt(i.position),!(i.lineIndent>0||b!==37));){for(m=!0,b=i.input.charCodeAt(++i.position),f=i.position;b!==0&&!dp(b);)b=i.input.charCodeAt(++i.position);for(p=i.input.slice(f,i.position),w=[],p.length<1&&Ss(i,"directive name must not be less than one character in length");b!==0;){for(;gT(b);)b=i.input.charCodeAt(++i.position);if(b===35){do b=i.input.charCodeAt(++i.position);while(b!==0&&!g3(b));break}if(g3(b))break;for(f=i.position;b!==0&&!dp(b);)b=i.input.charCodeAt(++i.position);w.push(i.input.slice(f,i.position))}b!==0&&Idt(i),lk.call(iPt,p)?iPt[p](i,p,w):WW(i,'unknown document directive "'+p+'"')}if(Pf(i,!0,-1),i.lineIndent===0&&i.input.charCodeAt(i.position)===45&&i.input.charCodeAt(i.position+1)===45&&i.input.charCodeAt(i.position+2)===45?(i.position+=3,Pf(i,!0,-1)):m&&Ss(i,"directives end mark is expected"),tL(i,i.lineIndent-1,UW,!1,!0),Pf(i,!0,-1),i.checkLineBreaks&&oMe.test(i.input.slice(a,i.position))&&WW(i,"non-ASCII line breaks are interpreted as content"),i.documents.push(i.result),i.position===i.lineStart&&YW(i)){i.input.charCodeAt(i.position)===46&&(i.position+=3,Pf(i,!0,-1));return}if(i.position"u"&&(f=a,a=null);var p=oPt(i,f);if(typeof a!="function")return p;for(var w=0,m=p.length;wi.replace(/\r\n?/g,` +`).replace(/<(\w+)([^>]*)>/g,(a,f,p)=>"<"+f+p.replace(/="([^"]*)"/g,"='$1'")+">"),OMe=i=>{const{text:a,metadata:f}=DMe(i),{displayMode:p,title:w,config:m={}}=f;return p&&(m.gantt||(m.gantt={}),m.gantt.displayMode=p),{title:w,config:m,text:a}},PMe=i=>{const a=$a.detectInit(i)??{},f=$a.detectDirective(i,"wrap");return Array.isArray(f)?a.wrap=f.some(({type:p})=>{}):(f==null?void 0:f.type)==="wrap"&&(a.wrap=!0),{text:nSe(i),directive:a}};function FMe(i){const a=IMe(i),f=OMe(a),p=PMe(f.text),w=rF(f.config,p.directive);return i=zAe(p.text),{code:i,title:f.title,config:w}}const NMe=5e4,BMe="graph TB;a[Maximum text size in diagram exceeded];style a fill:#faa",RMe="sandbox",jMe="loose",$Me="http://www.w3.org/2000/svg",zMe="http://www.w3.org/1999/xlink",qMe="http://www.w3.org/1999/xhtml",HMe="100%",VMe="100%",GMe="border:0;margin:0;",UMe="margin:0",WMe="allow-top-navigation-by-user-activation allow-popups",YMe='The "iframe" tag is not supported by your browser.',KMe=["foreignobject"],XMe=["dominant-baseline"];function cPt(i){const a=FMe(i);return $W(),FSe(a.config??{}),a}async function QMe(i,a){xdt(),i=cPt(i).code;try{await kdt(i)}catch(f){if(a!=null&&a.suppressErrors)return!1;throw f}return!0}const ZMe=function(i){let a=i;return a=a.replace(/style.*:\S*#.*;/g,function(f){return f.substring(0,f.length-1)}),a=a.replace(/classDef.*:\S*#.*;/g,function(f){return f.substring(0,f.length-1)}),a=a.replace(/#\w+;/g,function(f){const p=f.substring(1,f.length-1);return/^\+?\d+$/.test(p)?"fl°°"+p+"¶ß":"fl°"+p+"¶ß"}),a},uF=function(i){return i.replace(/fl°°/g,"&#").replace(/fl°/g,"&").replace(/¶ß/g,";")},uPt=(i,a,f=[])=>` +.${i} ${a} { ${f.join(" !important; ")} !important; }`,JMe=(i,a={})=>{var p;let f="";if(i.themeCSS!==void 0&&(f+=` +${i.themeCSS}`),i.fontFamily!==void 0&&(f+=` +:root { --mermaid-font-family: ${i.fontFamily}}`),i.altFontFamily!==void 0&&(f+=` +:root { --mermaid-alt-font-family: ${i.altFontFamily}}`),!oF(a)){const E=i.htmlLabels||((p=i.flowchart)==null?void 0:p.htmlLabels)?["> *","span"]:["rect","polygon","ellipse","circle","path"];for(const _ in a){const A=a[_];oF(A.styles)||E.forEach(I=>{f+=uPt(A.id,I,A.styles)}),oF(A.textStyles)||(f+=uPt(A.id,"tspan",A.textStyles))}}return f},tDe=(i,a,f,p)=>{const w=JMe(i,f),m=sAe(a,w,i.themeVariables);return pdt(LSe(`${p}{${m}}`),DSe)},eDe=(i="",a,f)=>{let p=i;return!f&&!a&&(p=p.replace(/marker-end="url\([\d+./:=?A-Za-z-]*?#/g,'marker-end="url(#')),p=uF(p),p=p.replace(/
            /g,"
            "),p},nDe=(i="",a)=>{var w,m;const f=(m=(w=a==null?void 0:a.viewBox)==null?void 0:w.baseVal)!=null&&m.height?a.viewBox.baseVal.height+"px":VMe,p=btoa(''+i+"");return``},lPt=(i,a,f,p,w)=>{const m=i.append("div");m.attr("id",f),p&&m.attr("style",p);const b=m.append("svg").attr("id",a).attr("width","100%").attr("xmlns",$Me);return w&&b.attr("xmlns:xlink",w),b.append("g"),i};function hPt(i,a){return i.append("iframe").attr("id",a).attr("style","width: 100%; height: 100%;").attr("sandbox","")}const rDe=(i,a,f,p)=>{var w,m,b;(w=i.getElementById(a))==null||w.remove(),(m=i.getElementById(f))==null||m.remove(),(b=i.getElementById(p))==null||b.remove()},iDe=async function(i,a,f){var nt,It,Ot,Bt,Et,Z;xdt();const p=cPt(a);a=p.code;const w=Fd();Ut.debug(w),a.length>((w==null?void 0:w.maxTextSize)??NMe)&&(a=BMe);const m="#"+i,b="i"+i,E="#"+b,_="d"+i,A="#"+_;let I=yr("body");const B=w.securityLevel===RMe,N=w.securityLevel===jMe,R=w.fontFamily;if(f!==void 0){if(f&&(f.innerHTML=""),B){const Ct=hPt(yr(f),b);I=yr(Ct.nodes()[0].contentDocument.body),I.node().style.margin=0}else I=yr(f);lPt(I,i,_,`font-family: ${R}`,zMe)}else{if(rDe(document,i,_,b),B){const Ct=hPt(yr("body"),b);I=yr(Ct.nodes()[0].contentDocument.body),I.node().style.margin=0}else I=yr("body");lPt(I,i,_)}a=ZMe(a);let z,W;try{z=await kdt(a,{title:p.title})}catch(Ct){z=new FOt("error"),W=Ct}const et=I.select(A).node(),st=z.type,at=et.firstChild,bt=at.firstChild,mt=(It=(nt=z.renderer).getClasses)==null?void 0:It.call(nt,a,z),yt=tDe(w,st,mt,m),ft=document.createElement("style");ft.innerHTML=yt,at.insertBefore(ft,bt);try{await z.renderer.draw(a,i,nOt,z)}catch(Ct){throw fAe.draw(a,i,nOt),Ct}const ut=I.select(`${A} svg`),vt=(Bt=(Ot=z.db).getAccTitle)==null?void 0:Bt.call(Ot),X=(Z=(Et=z.db).getAccDescription)==null?void 0:Z.call(Et);aDe(st,ut,vt,X),I.select(`[id="${i}"]`).selectAll("foreignobject > *").attr("xmlns",qMe);let pt=I.select(A).node().innerHTML;if(Ut.debug("config.arrowMarkerAbsolute",w.arrowMarkerAbsolute),pt=eDe(pt,B,o1(w.arrowMarkerAbsolute)),B){const Ct=I.select(A+" svg").node();pt=nDe(pt,Ct)}else N||(pt=lW.sanitize(pt,{ADD_TAGS:KMe,ADD_ATTR:XMe}));if(mAe(),W)throw W;const Tt=yr(B?E:A).node();return Tt&&"remove"in Tt&&Tt.remove(),{svg:pt,bindFunctions:z.db.bindFunctions}};function sDe(i={}){var f;i!=null&&i.fontFamily&&!((f=i.themeVariables)!=null&&f.fontFamily)&&(i.themeVariables||(i.themeVariables={}),i.themeVariables.fontFamily=i.fontFamily),OSe(i),i!=null&&i.theme&&i.theme in T5?i.themeVariables=T5[i.theme].getThemeVariables(i.themeVariables):i&&(i.themeVariables=T5.default.getThemeVariables(i.themeVariables));const a=typeof i=="object"?ISe(i):iOt();Xft(a.logLevel),xdt()}function aDe(i,a,f,p){jAe(a,i),$Ae(a,f,p,a.attr("id"))}const pT=Object.freeze({render:iDe,parse:QMe,getDiagramFromText:kdt,initialize:sDe,getConfig:Fd,setConfig:sOt,getSiteConfig:iOt,updateSiteConfig:PSe,reset:()=>{$W()},globalReset:()=>{$W(WA)},defaultConfig:WA});Xft(Fd().logLevel),$W(Fd());const oDe=async()=>{Ut.debug("Loading registered diagrams");const a=(await Promise.allSettled(Object.entries(NA).map(async([f,{detector:p,loader:w}])=>{if(w)try{ydt(f)}catch{try{const{diagram:b,id:E}=await w();HW(E,b,p)}catch(b){throw Ut.error(`Failed to load external diagram with key ${f}. Removing from detectors.`),delete NA[f],b}}}))).filter(f=>f.status==="rejected");if(a.length>0){Ut.error(`Failed to load ${a.length} external diagrams`);for(const f of a)Ut.error(f);throw new Error(`Failed to load ${a.length} external diagrams`)}},cDe=(i,a,f)=>{Ut.warn(i),WIt(i)?(f&&f(i.str,i.hash),a.push({...i,message:i.str,error:i})):(f&&f(i),i instanceof Error&&a.push({str:i.message,message:i.message,hash:i.name,error:i}))},fPt=async function(i={querySelector:".mermaid"}){try{await uDe(i)}catch(a){if(WIt(a)&&Ut.error(a.str),Bb.parseError&&Bb.parseError(a),!i.suppressErrors)throw Ut.error("Use the suppressErrors option to suppress these errors"),a}},uDe=async function({postRenderCallback:i,querySelector:a,nodes:f}={querySelector:".mermaid"}){const p=pT.getConfig();Ut.debug(`${i?"":"No "}Callback function found`);let w;if(f)w=f;else if(a)w=document.querySelectorAll(a);else throw new Error("Nodes and querySelector are both undefined");Ut.debug(`Found ${w.length} diagrams`),(p==null?void 0:p.startOnLoad)!==void 0&&(Ut.debug("Start On Load: "+(p==null?void 0:p.startOnLoad)),pT.updateSiteConfig({startOnLoad:p==null?void 0:p.startOnLoad}));const m=new $a.InitIDGenerator(p.deterministicIds,p.deterministicIDSeed);let b;const E=[];for(const _ of Array.from(w)){Ut.info("Rendering diagram: "+_.id);/*! Check if previously processed */if(_.getAttribute("data-processed"))continue;_.setAttribute("data-processed","true");const A=`mermaid-${m.next()}`;b=_.innerHTML,b=xA($a.entityDecode(b)).trim().replace(//gi,"
            ");const I=$a.detectInit(b);I&&Ut.debug("Detected early reinit: ",I);try{const{svg:B,bindFunctions:N}=await bPt(A,b,_);_.innerHTML=B,i&&await i(A),N&&N(_)}catch(B){cDe(B,E,Bb.parseError)}}if(E.length>0)throw E[0]},dPt=function(i){pT.initialize(i)},lDe=async function(i,a,f){Ut.warn("mermaid.init is deprecated. Please use run instead."),i&&dPt(i);const p={postRenderCallback:f,querySelector:".mermaid"};typeof a=="string"?p.querySelector=a:a&&(a instanceof HTMLElement?p.nodes=[a]:p.nodes=a),await fPt(p)},hDe=async(i,{lazyLoad:a=!0}={})=>{cIt(...i),a===!1&&await oDe()},gPt=function(){if(Bb.startOnLoad){const{startOnLoad:i}=pT.getConfig();i&&Bb.run().catch(a=>Ut.error("Mermaid failed to initialize",a))}};if(typeof document<"u"){/*! + * Wait for document loaded before starting the execution + */window.addEventListener("load",gPt,!1)}const fDe=function(i){Bb.parseError=i},KW=[];let Pdt=!1;const pPt=async()=>{if(!Pdt){for(Pdt=!0;KW.length>0;){const i=KW.shift();if(i)try{await i()}catch(a){Ut.error("Error executing queue",a)}}Pdt=!1}},dDe=async(i,a)=>new Promise((f,p)=>{const w=()=>new Promise((m,b)=>{pT.parse(i,a).then(E=>{m(E),f(E)},E=>{var _;Ut.error("Error parsing",E),(_=Bb.parseError)==null||_.call(Bb,E),b(E),p(E)})});KW.push(w),pPt().catch(p)}),bPt=(i,a,f)=>new Promise((p,w)=>{const m=()=>new Promise((b,E)=>{pT.render(i,a,f).then(_=>{b(_),p(_)},_=>{var A;Ut.error("Error parsing",_),(A=Bb.parseError)==null||A.call(Bb,_),E(_),w(_)})});KW.push(m),pPt().catch(w)}),Bb={startOnLoad:!0,mermaidAPI:pT,parse:dDe,render:bPt,init:lDe,run:fPt,registerExternalDiagrams:hDe,initialize:dPt,parseError:void 0,contentLoaded:gPt,setParseErrorHandler:fDe,detectType:yW};var XW=function(){var i=function(Xi,Er,Xn,di){for(Xn=Xn||{},di=Xi.length;di--;Xn[Xi[di]]=Er);return Xn},a=[1,24],f=[1,25],p=[1,26],w=[1,27],m=[1,28],b=[1,63],E=[1,64],_=[1,65],A=[1,66],I=[1,67],B=[1,68],N=[1,69],R=[1,29],z=[1,30],W=[1,31],et=[1,32],st=[1,33],at=[1,34],bt=[1,35],mt=[1,36],yt=[1,37],ft=[1,38],ut=[1,39],vt=[1,40],X=[1,41],pt=[1,42],U=[1,43],Tt=[1,44],nt=[1,45],It=[1,46],Ot=[1,47],Bt=[1,48],Et=[1,50],Z=[1,51],Ct=[1,52],xt=[1,53],Ht=[1,54],Le=[1,55],Ft=[1,56],gn=[1,57],Se=[1,58],me=[1,59],Ve=[1,60],Ye=[14,42],ce=[14,34,36,37,38,39,40,41,42,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74],ke=[12,14,34,36,37,38,39,40,41,42,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74],zt=[1,82],re=[1,83],se=[1,84],Pe=[1,85],te=[12,14,42],Me=[12,14,33,42],de=[12,14,33,42,76,77,79,80],on=[12,33],ni=[34,36,37,38,39,40,41,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74],Ks={trace:function(){},yy:{},symbols_:{error:2,start:3,mermaidDoc:4,direction:5,direction_tb:6,direction_bt:7,direction_rl:8,direction_lr:9,graphConfig:10,C4_CONTEXT:11,NEWLINE:12,statements:13,EOF:14,C4_CONTAINER:15,C4_COMPONENT:16,C4_DYNAMIC:17,C4_DEPLOYMENT:18,otherStatements:19,diagramStatements:20,otherStatement:21,title:22,accDescription:23,acc_title:24,acc_title_value:25,acc_descr:26,acc_descr_value:27,acc_descr_multiline_value:28,boundaryStatement:29,boundaryStartStatement:30,boundaryStopStatement:31,boundaryStart:32,LBRACE:33,ENTERPRISE_BOUNDARY:34,attributes:35,SYSTEM_BOUNDARY:36,BOUNDARY:37,CONTAINER_BOUNDARY:38,NODE:39,NODE_L:40,NODE_R:41,RBRACE:42,diagramStatement:43,PERSON:44,PERSON_EXT:45,SYSTEM:46,SYSTEM_DB:47,SYSTEM_QUEUE:48,SYSTEM_EXT:49,SYSTEM_EXT_DB:50,SYSTEM_EXT_QUEUE:51,CONTAINER:52,CONTAINER_DB:53,CONTAINER_QUEUE:54,CONTAINER_EXT:55,CONTAINER_EXT_DB:56,CONTAINER_EXT_QUEUE:57,COMPONENT:58,COMPONENT_DB:59,COMPONENT_QUEUE:60,COMPONENT_EXT:61,COMPONENT_EXT_DB:62,COMPONENT_EXT_QUEUE:63,REL:64,BIREL:65,REL_U:66,REL_D:67,REL_L:68,REL_R:69,REL_B:70,REL_INDEX:71,UPDATE_EL_STYLE:72,UPDATE_REL_STYLE:73,UPDATE_LAYOUT_CONFIG:74,attribute:75,STR:76,STR_KEY:77,STR_VALUE:78,ATTRIBUTE:79,ATTRIBUTE_EMPTY:80,$accept:0,$end:1},terminals_:{2:"error",6:"direction_tb",7:"direction_bt",8:"direction_rl",9:"direction_lr",11:"C4_CONTEXT",12:"NEWLINE",14:"EOF",15:"C4_CONTAINER",16:"C4_COMPONENT",17:"C4_DYNAMIC",18:"C4_DEPLOYMENT",22:"title",23:"accDescription",24:"acc_title",25:"acc_title_value",26:"acc_descr",27:"acc_descr_value",28:"acc_descr_multiline_value",33:"LBRACE",34:"ENTERPRISE_BOUNDARY",36:"SYSTEM_BOUNDARY",37:"BOUNDARY",38:"CONTAINER_BOUNDARY",39:"NODE",40:"NODE_L",41:"NODE_R",42:"RBRACE",44:"PERSON",45:"PERSON_EXT",46:"SYSTEM",47:"SYSTEM_DB",48:"SYSTEM_QUEUE",49:"SYSTEM_EXT",50:"SYSTEM_EXT_DB",51:"SYSTEM_EXT_QUEUE",52:"CONTAINER",53:"CONTAINER_DB",54:"CONTAINER_QUEUE",55:"CONTAINER_EXT",56:"CONTAINER_EXT_DB",57:"CONTAINER_EXT_QUEUE",58:"COMPONENT",59:"COMPONENT_DB",60:"COMPONENT_QUEUE",61:"COMPONENT_EXT",62:"COMPONENT_EXT_DB",63:"COMPONENT_EXT_QUEUE",64:"REL",65:"BIREL",66:"REL_U",67:"REL_D",68:"REL_L",69:"REL_R",70:"REL_B",71:"REL_INDEX",72:"UPDATE_EL_STYLE",73:"UPDATE_REL_STYLE",74:"UPDATE_LAYOUT_CONFIG",76:"STR",77:"STR_KEY",78:"STR_VALUE",79:"ATTRIBUTE",80:"ATTRIBUTE_EMPTY"},productions_:[0,[3,1],[3,1],[5,1],[5,1],[5,1],[5,1],[4,1],[10,4],[10,4],[10,4],[10,4],[10,4],[13,1],[13,1],[13,2],[19,1],[19,2],[19,3],[21,1],[21,1],[21,2],[21,2],[21,1],[29,3],[30,3],[30,3],[30,4],[32,2],[32,2],[32,2],[32,2],[32,2],[32,2],[32,2],[31,1],[20,1],[20,2],[20,3],[43,2],[43,2],[43,2],[43,2],[43,2],[43,2],[43,2],[43,2],[43,2],[43,2],[43,2],[43,2],[43,2],[43,2],[43,2],[43,2],[43,2],[43,2],[43,2],[43,2],[43,1],[43,2],[43,2],[43,2],[43,2],[43,2],[43,2],[43,2],[43,2],[43,2],[43,2],[43,2],[35,1],[35,2],[75,1],[75,2],[75,1],[75,1]],performAction:function(Er,Xn,di,Ee,Kn,He,Ti){var pn=He.length-1;switch(Kn){case 3:Ee.setDirection("TB");break;case 4:Ee.setDirection("BT");break;case 5:Ee.setDirection("RL");break;case 6:Ee.setDirection("LR");break;case 8:case 9:case 10:case 11:case 12:Ee.setC4Type(He[pn-3]);break;case 19:Ee.setTitle(He[pn].substring(6)),this.$=He[pn].substring(6);break;case 20:Ee.setAccDescription(He[pn].substring(15)),this.$=He[pn].substring(15);break;case 21:this.$=He[pn].trim(),Ee.setTitle(this.$);break;case 22:case 23:this.$=He[pn].trim(),Ee.setAccDescription(this.$);break;case 28:case 29:He[pn].splice(2,0,"ENTERPRISE"),Ee.addPersonOrSystemBoundary(...He[pn]),this.$=He[pn];break;case 30:Ee.addPersonOrSystemBoundary(...He[pn]),this.$=He[pn];break;case 31:He[pn].splice(2,0,"CONTAINER"),Ee.addContainerBoundary(...He[pn]),this.$=He[pn];break;case 32:Ee.addDeploymentNode("node",...He[pn]),this.$=He[pn];break;case 33:Ee.addDeploymentNode("nodeL",...He[pn]),this.$=He[pn];break;case 34:Ee.addDeploymentNode("nodeR",...He[pn]),this.$=He[pn];break;case 35:Ee.popBoundaryParseStack();break;case 39:Ee.addPersonOrSystem("person",...He[pn]),this.$=He[pn];break;case 40:Ee.addPersonOrSystem("external_person",...He[pn]),this.$=He[pn];break;case 41:Ee.addPersonOrSystem("system",...He[pn]),this.$=He[pn];break;case 42:Ee.addPersonOrSystem("system_db",...He[pn]),this.$=He[pn];break;case 43:Ee.addPersonOrSystem("system_queue",...He[pn]),this.$=He[pn];break;case 44:Ee.addPersonOrSystem("external_system",...He[pn]),this.$=He[pn];break;case 45:Ee.addPersonOrSystem("external_system_db",...He[pn]),this.$=He[pn];break;case 46:Ee.addPersonOrSystem("external_system_queue",...He[pn]),this.$=He[pn];break;case 47:Ee.addContainer("container",...He[pn]),this.$=He[pn];break;case 48:Ee.addContainer("container_db",...He[pn]),this.$=He[pn];break;case 49:Ee.addContainer("container_queue",...He[pn]),this.$=He[pn];break;case 50:Ee.addContainer("external_container",...He[pn]),this.$=He[pn];break;case 51:Ee.addContainer("external_container_db",...He[pn]),this.$=He[pn];break;case 52:Ee.addContainer("external_container_queue",...He[pn]),this.$=He[pn];break;case 53:Ee.addComponent("component",...He[pn]),this.$=He[pn];break;case 54:Ee.addComponent("component_db",...He[pn]),this.$=He[pn];break;case 55:Ee.addComponent("component_queue",...He[pn]),this.$=He[pn];break;case 56:Ee.addComponent("external_component",...He[pn]),this.$=He[pn];break;case 57:Ee.addComponent("external_component_db",...He[pn]),this.$=He[pn];break;case 58:Ee.addComponent("external_component_queue",...He[pn]),this.$=He[pn];break;case 60:Ee.addRel("rel",...He[pn]),this.$=He[pn];break;case 61:Ee.addRel("birel",...He[pn]),this.$=He[pn];break;case 62:Ee.addRel("rel_u",...He[pn]),this.$=He[pn];break;case 63:Ee.addRel("rel_d",...He[pn]),this.$=He[pn];break;case 64:Ee.addRel("rel_l",...He[pn]),this.$=He[pn];break;case 65:Ee.addRel("rel_r",...He[pn]),this.$=He[pn];break;case 66:Ee.addRel("rel_b",...He[pn]),this.$=He[pn];break;case 67:He[pn].splice(0,1),Ee.addRel("rel",...He[pn]),this.$=He[pn];break;case 68:Ee.updateElStyle("update_el_style",...He[pn]),this.$=He[pn];break;case 69:Ee.updateRelStyle("update_rel_style",...He[pn]),this.$=He[pn];break;case 70:Ee.updateLayoutConfig("update_layout_config",...He[pn]),this.$=He[pn];break;case 71:this.$=[He[pn]];break;case 72:He[pn].unshift(He[pn-1]),this.$=He[pn];break;case 73:case 75:this.$=He[pn].trim();break;case 74:let Es={};Es[He[pn-1].trim()]=He[pn].trim(),this.$=Es;break;case 76:this.$="";break}},table:[{3:1,4:2,5:3,6:[1,5],7:[1,6],8:[1,7],9:[1,8],10:4,11:[1,9],15:[1,10],16:[1,11],17:[1,12],18:[1,13]},{1:[3]},{1:[2,1]},{1:[2,2]},{1:[2,7]},{1:[2,3]},{1:[2,4]},{1:[2,5]},{1:[2,6]},{12:[1,14]},{12:[1,15]},{12:[1,16]},{12:[1,17]},{12:[1,18]},{13:19,19:20,20:21,21:22,22:a,23:f,24:p,26:w,28:m,29:49,30:61,32:62,34:b,36:E,37:_,38:A,39:I,40:B,41:N,43:23,44:R,45:z,46:W,47:et,48:st,49:at,50:bt,51:mt,52:yt,53:ft,54:ut,55:vt,56:X,57:pt,58:U,59:Tt,60:nt,61:It,62:Ot,63:Bt,64:Et,65:Z,66:Ct,67:xt,68:Ht,69:Le,70:Ft,71:gn,72:Se,73:me,74:Ve},{13:70,19:20,20:21,21:22,22:a,23:f,24:p,26:w,28:m,29:49,30:61,32:62,34:b,36:E,37:_,38:A,39:I,40:B,41:N,43:23,44:R,45:z,46:W,47:et,48:st,49:at,50:bt,51:mt,52:yt,53:ft,54:ut,55:vt,56:X,57:pt,58:U,59:Tt,60:nt,61:It,62:Ot,63:Bt,64:Et,65:Z,66:Ct,67:xt,68:Ht,69:Le,70:Ft,71:gn,72:Se,73:me,74:Ve},{13:71,19:20,20:21,21:22,22:a,23:f,24:p,26:w,28:m,29:49,30:61,32:62,34:b,36:E,37:_,38:A,39:I,40:B,41:N,43:23,44:R,45:z,46:W,47:et,48:st,49:at,50:bt,51:mt,52:yt,53:ft,54:ut,55:vt,56:X,57:pt,58:U,59:Tt,60:nt,61:It,62:Ot,63:Bt,64:Et,65:Z,66:Ct,67:xt,68:Ht,69:Le,70:Ft,71:gn,72:Se,73:me,74:Ve},{13:72,19:20,20:21,21:22,22:a,23:f,24:p,26:w,28:m,29:49,30:61,32:62,34:b,36:E,37:_,38:A,39:I,40:B,41:N,43:23,44:R,45:z,46:W,47:et,48:st,49:at,50:bt,51:mt,52:yt,53:ft,54:ut,55:vt,56:X,57:pt,58:U,59:Tt,60:nt,61:It,62:Ot,63:Bt,64:Et,65:Z,66:Ct,67:xt,68:Ht,69:Le,70:Ft,71:gn,72:Se,73:me,74:Ve},{13:73,19:20,20:21,21:22,22:a,23:f,24:p,26:w,28:m,29:49,30:61,32:62,34:b,36:E,37:_,38:A,39:I,40:B,41:N,43:23,44:R,45:z,46:W,47:et,48:st,49:at,50:bt,51:mt,52:yt,53:ft,54:ut,55:vt,56:X,57:pt,58:U,59:Tt,60:nt,61:It,62:Ot,63:Bt,64:Et,65:Z,66:Ct,67:xt,68:Ht,69:Le,70:Ft,71:gn,72:Se,73:me,74:Ve},{14:[1,74]},i(Ye,[2,13],{43:23,29:49,30:61,32:62,20:75,34:b,36:E,37:_,38:A,39:I,40:B,41:N,44:R,45:z,46:W,47:et,48:st,49:at,50:bt,51:mt,52:yt,53:ft,54:ut,55:vt,56:X,57:pt,58:U,59:Tt,60:nt,61:It,62:Ot,63:Bt,64:Et,65:Z,66:Ct,67:xt,68:Ht,69:Le,70:Ft,71:gn,72:Se,73:me,74:Ve}),i(Ye,[2,14]),i(ce,[2,16],{12:[1,76]}),i(Ye,[2,36],{12:[1,77]}),i(ke,[2,19]),i(ke,[2,20]),{25:[1,78]},{27:[1,79]},i(ke,[2,23]),{35:80,75:81,76:zt,77:re,79:se,80:Pe},{35:86,75:81,76:zt,77:re,79:se,80:Pe},{35:87,75:81,76:zt,77:re,79:se,80:Pe},{35:88,75:81,76:zt,77:re,79:se,80:Pe},{35:89,75:81,76:zt,77:re,79:se,80:Pe},{35:90,75:81,76:zt,77:re,79:se,80:Pe},{35:91,75:81,76:zt,77:re,79:se,80:Pe},{35:92,75:81,76:zt,77:re,79:se,80:Pe},{35:93,75:81,76:zt,77:re,79:se,80:Pe},{35:94,75:81,76:zt,77:re,79:se,80:Pe},{35:95,75:81,76:zt,77:re,79:se,80:Pe},{35:96,75:81,76:zt,77:re,79:se,80:Pe},{35:97,75:81,76:zt,77:re,79:se,80:Pe},{35:98,75:81,76:zt,77:re,79:se,80:Pe},{35:99,75:81,76:zt,77:re,79:se,80:Pe},{35:100,75:81,76:zt,77:re,79:se,80:Pe},{35:101,75:81,76:zt,77:re,79:se,80:Pe},{35:102,75:81,76:zt,77:re,79:se,80:Pe},{35:103,75:81,76:zt,77:re,79:se,80:Pe},{35:104,75:81,76:zt,77:re,79:se,80:Pe},i(te,[2,59]),{35:105,75:81,76:zt,77:re,79:se,80:Pe},{35:106,75:81,76:zt,77:re,79:se,80:Pe},{35:107,75:81,76:zt,77:re,79:se,80:Pe},{35:108,75:81,76:zt,77:re,79:se,80:Pe},{35:109,75:81,76:zt,77:re,79:se,80:Pe},{35:110,75:81,76:zt,77:re,79:se,80:Pe},{35:111,75:81,76:zt,77:re,79:se,80:Pe},{35:112,75:81,76:zt,77:re,79:se,80:Pe},{35:113,75:81,76:zt,77:re,79:se,80:Pe},{35:114,75:81,76:zt,77:re,79:se,80:Pe},{35:115,75:81,76:zt,77:re,79:se,80:Pe},{20:116,29:49,30:61,32:62,34:b,36:E,37:_,38:A,39:I,40:B,41:N,43:23,44:R,45:z,46:W,47:et,48:st,49:at,50:bt,51:mt,52:yt,53:ft,54:ut,55:vt,56:X,57:pt,58:U,59:Tt,60:nt,61:It,62:Ot,63:Bt,64:Et,65:Z,66:Ct,67:xt,68:Ht,69:Le,70:Ft,71:gn,72:Se,73:me,74:Ve},{12:[1,118],33:[1,117]},{35:119,75:81,76:zt,77:re,79:se,80:Pe},{35:120,75:81,76:zt,77:re,79:se,80:Pe},{35:121,75:81,76:zt,77:re,79:se,80:Pe},{35:122,75:81,76:zt,77:re,79:se,80:Pe},{35:123,75:81,76:zt,77:re,79:se,80:Pe},{35:124,75:81,76:zt,77:re,79:se,80:Pe},{35:125,75:81,76:zt,77:re,79:se,80:Pe},{14:[1,126]},{14:[1,127]},{14:[1,128]},{14:[1,129]},{1:[2,8]},i(Ye,[2,15]),i(ce,[2,17],{21:22,19:130,22:a,23:f,24:p,26:w,28:m}),i(Ye,[2,37],{19:20,20:21,21:22,43:23,29:49,30:61,32:62,13:131,22:a,23:f,24:p,26:w,28:m,34:b,36:E,37:_,38:A,39:I,40:B,41:N,44:R,45:z,46:W,47:et,48:st,49:at,50:bt,51:mt,52:yt,53:ft,54:ut,55:vt,56:X,57:pt,58:U,59:Tt,60:nt,61:It,62:Ot,63:Bt,64:Et,65:Z,66:Ct,67:xt,68:Ht,69:Le,70:Ft,71:gn,72:Se,73:me,74:Ve}),i(ke,[2,21]),i(ke,[2,22]),i(te,[2,39]),i(Me,[2,71],{75:81,35:132,76:zt,77:re,79:se,80:Pe}),i(de,[2,73]),{78:[1,133]},i(de,[2,75]),i(de,[2,76]),i(te,[2,40]),i(te,[2,41]),i(te,[2,42]),i(te,[2,43]),i(te,[2,44]),i(te,[2,45]),i(te,[2,46]),i(te,[2,47]),i(te,[2,48]),i(te,[2,49]),i(te,[2,50]),i(te,[2,51]),i(te,[2,52]),i(te,[2,53]),i(te,[2,54]),i(te,[2,55]),i(te,[2,56]),i(te,[2,57]),i(te,[2,58]),i(te,[2,60]),i(te,[2,61]),i(te,[2,62]),i(te,[2,63]),i(te,[2,64]),i(te,[2,65]),i(te,[2,66]),i(te,[2,67]),i(te,[2,68]),i(te,[2,69]),i(te,[2,70]),{31:134,42:[1,135]},{12:[1,136]},{33:[1,137]},i(on,[2,28]),i(on,[2,29]),i(on,[2,30]),i(on,[2,31]),i(on,[2,32]),i(on,[2,33]),i(on,[2,34]),{1:[2,9]},{1:[2,10]},{1:[2,11]},{1:[2,12]},i(ce,[2,18]),i(Ye,[2,38]),i(Me,[2,72]),i(de,[2,74]),i(te,[2,24]),i(te,[2,35]),i(ni,[2,25]),i(ni,[2,26],{12:[1,138]}),i(ni,[2,27])],defaultActions:{2:[2,1],3:[2,2],4:[2,7],5:[2,3],6:[2,4],7:[2,5],8:[2,6],74:[2,8],126:[2,9],127:[2,10],128:[2,11],129:[2,12]},parseError:function(Er,Xn){if(Xn.recoverable)this.trace(Er);else{var di=new Error(Er);throw di.hash=Xn,di}},parse:function(Er){var Xn=this,di=[0],Ee=[],Kn=[null],He=[],Ti=this.table,pn="",Es=0,qa=0,Ma=2,Gs=1,Po=He.slice.call(arguments,1),vs=Object.create(this.lexer),ru={yy:{}};for(var zs in this.yy)Object.prototype.hasOwnProperty.call(this.yy,zs)&&(ru.yy[zs]=this.yy[zs]);vs.setInput(Er,ru.yy),ru.yy.lexer=vs,ru.yy.parser=this,typeof vs.yylloc>"u"&&(vs.yylloc={});var Du=vs.yylloc;He.push(Du);var pm=vs.options&&vs.options.ranges;typeof ru.yy.parseError=="function"?this.parseError=ru.yy.parseError:this.parseError=Object.getPrototypeOf(this).parseError;function uw(){var Dl;return Dl=Ee.pop()||vs.lex()||Gs,typeof Dl!="number"&&(Dl instanceof Array&&(Ee=Dl,Dl=Ee.pop()),Dl=Xn.symbols_[Dl]||Dl),Dl}for(var Wu,th,Fa,Ml,ha={},bc,Cc,pa,Da;;){if(th=di[di.length-1],this.defaultActions[th]?Fa=this.defaultActions[th]:((Wu===null||typeof Wu>"u")&&(Wu=uw()),Fa=Ti[th]&&Ti[th][Wu]),typeof Fa>"u"||!Fa.length||!Fa[0]){var Ha="";Da=[];for(bc in Ti[th])this.terminals_[bc]&&bc>Ma&&Da.push("'"+this.terminals_[bc]+"'");vs.showPosition?Ha="Parse error on line "+(Es+1)+`: +`+vs.showPosition()+` +Expecting `+Da.join(", ")+", got '"+(this.terminals_[Wu]||Wu)+"'":Ha="Parse error on line "+(Es+1)+": Unexpected "+(Wu==Gs?"end of input":"'"+(this.terminals_[Wu]||Wu)+"'"),this.parseError(Ha,{text:vs.match,token:this.terminals_[Wu]||Wu,line:vs.yylineno,loc:Du,expected:Da})}if(Fa[0]instanceof Array&&Fa.length>1)throw new Error("Parse Error: multiple actions possible at state: "+th+", token: "+Wu);switch(Fa[0]){case 1:di.push(Wu),Kn.push(vs.yytext),He.push(vs.yylloc),di.push(Fa[1]),Wu=null,qa=vs.yyleng,pn=vs.yytext,Es=vs.yylineno,Du=vs.yylloc;break;case 2:if(Cc=this.productions_[Fa[1]][1],ha.$=Kn[Kn.length-Cc],ha._$={first_line:He[He.length-(Cc||1)].first_line,last_line:He[He.length-1].last_line,first_column:He[He.length-(Cc||1)].first_column,last_column:He[He.length-1].last_column},pm&&(ha._$.range=[He[He.length-(Cc||1)].range[0],He[He.length-1].range[1]]),Ml=this.performAction.apply(ha,[pn,qa,Es,ru.yy,Fa[1],Kn,He].concat(Po)),typeof Ml<"u")return Ml;Cc&&(di=di.slice(0,-1*Cc*2),Kn=Kn.slice(0,-1*Cc),He=He.slice(0,-1*Cc)),di.push(this.productions_[Fa[1]][0]),Kn.push(ha.$),He.push(ha._$),pa=Ti[di[di.length-2]][di[di.length-1]],di.push(pa);break;case 3:return!0}}return!0}},ws=function(){var Xi={EOF:1,parseError:function(Xn,di){if(this.yy.parser)this.yy.parser.parseError(Xn,di);else throw new Error(Xn)},setInput:function(Er,Xn){return this.yy=Xn||this.yy||{},this._input=Er,this._more=this._backtrack=this.done=!1,this.yylineno=this.yyleng=0,this.yytext=this.matched=this.match="",this.conditionStack=["INITIAL"],this.yylloc={first_line:1,first_column:0,last_line:1,last_column:0},this.options.ranges&&(this.yylloc.range=[0,0]),this.offset=0,this},input:function(){var Er=this._input[0];this.yytext+=Er,this.yyleng++,this.offset++,this.match+=Er,this.matched+=Er;var Xn=Er.match(/(?:\r\n?|\n).*/g);return Xn?(this.yylineno++,this.yylloc.last_line++):this.yylloc.last_column++,this.options.ranges&&this.yylloc.range[1]++,this._input=this._input.slice(1),Er},unput:function(Er){var Xn=Er.length,di=Er.split(/(?:\r\n?|\n)/g);this._input=Er+this._input,this.yytext=this.yytext.substr(0,this.yytext.length-Xn),this.offset-=Xn;var Ee=this.match.split(/(?:\r\n?|\n)/g);this.match=this.match.substr(0,this.match.length-1),this.matched=this.matched.substr(0,this.matched.length-1),di.length-1&&(this.yylineno-=di.length-1);var Kn=this.yylloc.range;return this.yylloc={first_line:this.yylloc.first_line,last_line:this.yylineno+1,first_column:this.yylloc.first_column,last_column:di?(di.length===Ee.length?this.yylloc.first_column:0)+Ee[Ee.length-di.length].length-di[0].length:this.yylloc.first_column-Xn},this.options.ranges&&(this.yylloc.range=[Kn[0],Kn[0]+this.yyleng-Xn]),this.yyleng=this.yytext.length,this},more:function(){return this._more=!0,this},reject:function(){if(this.options.backtrack_lexer)this._backtrack=!0;else return this.parseError("Lexical error on line "+(this.yylineno+1)+`. You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true). +`+this.showPosition(),{text:"",token:null,line:this.yylineno});return this},less:function(Er){this.unput(this.match.slice(Er))},pastInput:function(){var Er=this.matched.substr(0,this.matched.length-this.match.length);return(Er.length>20?"...":"")+Er.substr(-20).replace(/\n/g,"")},upcomingInput:function(){var Er=this.match;return Er.length<20&&(Er+=this._input.substr(0,20-Er.length)),(Er.substr(0,20)+(Er.length>20?"...":"")).replace(/\n/g,"")},showPosition:function(){var Er=this.pastInput(),Xn=new Array(Er.length+1).join("-");return Er+this.upcomingInput()+` +`+Xn+"^"},test_match:function(Er,Xn){var di,Ee,Kn;if(this.options.backtrack_lexer&&(Kn={yylineno:this.yylineno,yylloc:{first_line:this.yylloc.first_line,last_line:this.last_line,first_column:this.yylloc.first_column,last_column:this.yylloc.last_column},yytext:this.yytext,match:this.match,matches:this.matches,matched:this.matched,yyleng:this.yyleng,offset:this.offset,_more:this._more,_input:this._input,yy:this.yy,conditionStack:this.conditionStack.slice(0),done:this.done},this.options.ranges&&(Kn.yylloc.range=this.yylloc.range.slice(0))),Ee=Er[0].match(/(?:\r\n?|\n).*/g),Ee&&(this.yylineno+=Ee.length),this.yylloc={first_line:this.yylloc.last_line,last_line:this.yylineno+1,first_column:this.yylloc.last_column,last_column:Ee?Ee[Ee.length-1].length-Ee[Ee.length-1].match(/\r?\n?/)[0].length:this.yylloc.last_column+Er[0].length},this.yytext+=Er[0],this.match+=Er[0],this.matches=Er,this.yyleng=this.yytext.length,this.options.ranges&&(this.yylloc.range=[this.offset,this.offset+=this.yyleng]),this._more=!1,this._backtrack=!1,this._input=this._input.slice(Er[0].length),this.matched+=Er[0],di=this.performAction.call(this,this.yy,this,Xn,this.conditionStack[this.conditionStack.length-1]),this.done&&this._input&&(this.done=!1),di)return di;if(this._backtrack){for(var He in Kn)this[He]=Kn[He];return!1}return!1},next:function(){if(this.done)return this.EOF;this._input||(this.done=!0);var Er,Xn,di,Ee;this._more||(this.yytext="",this.match="");for(var Kn=this._currentRules(),He=0;HeXn[0].length)){if(Xn=di,Ee=He,this.options.backtrack_lexer){if(Er=this.test_match(di,Kn[He]),Er!==!1)return Er;if(this._backtrack){Xn=!1;continue}else return!1}else if(!this.options.flex)break}return Xn?(Er=this.test_match(Xn,Kn[Ee]),Er!==!1?Er:!1):this._input===""?this.EOF:this.parseError("Lexical error on line "+(this.yylineno+1)+`. Unrecognized text. +`+this.showPosition(),{text:"",token:null,line:this.yylineno})},lex:function(){var Xn=this.next();return Xn||this.lex()},begin:function(Xn){this.conditionStack.push(Xn)},popState:function(){var Xn=this.conditionStack.length-1;return Xn>0?this.conditionStack.pop():this.conditionStack[0]},_currentRules:function(){return this.conditionStack.length&&this.conditionStack[this.conditionStack.length-1]?this.conditions[this.conditionStack[this.conditionStack.length-1]].rules:this.conditions.INITIAL.rules},topState:function(Xn){return Xn=this.conditionStack.length-1-Math.abs(Xn||0),Xn>=0?this.conditionStack[Xn]:"INITIAL"},pushState:function(Xn){this.begin(Xn)},stateStackSize:function(){return this.conditionStack.length},options:{},performAction:function(Xn,di,Ee,Kn){switch(Ee){case 0:return 6;case 1:return 7;case 2:return 8;case 3:return 9;case 4:return 22;case 5:return 23;case 6:return this.begin("acc_title"),24;case 7:return this.popState(),"acc_title_value";case 8:return this.begin("acc_descr"),26;case 9:return this.popState(),"acc_descr_value";case 10:this.begin("acc_descr_multiline");break;case 11:this.popState();break;case 12:return"acc_descr_multiline_value";case 13:break;case 14:c;break;case 15:return 12;case 16:break;case 17:return 11;case 18:return 15;case 19:return 16;case 20:return 17;case 21:return 18;case 22:return this.begin("person_ext"),45;case 23:return this.begin("person"),44;case 24:return this.begin("system_ext_queue"),51;case 25:return this.begin("system_ext_db"),50;case 26:return this.begin("system_ext"),49;case 27:return this.begin("system_queue"),48;case 28:return this.begin("system_db"),47;case 29:return this.begin("system"),46;case 30:return this.begin("boundary"),37;case 31:return this.begin("enterprise_boundary"),34;case 32:return this.begin("system_boundary"),36;case 33:return this.begin("container_ext_queue"),57;case 34:return this.begin("container_ext_db"),56;case 35:return this.begin("container_ext"),55;case 36:return this.begin("container_queue"),54;case 37:return this.begin("container_db"),53;case 38:return this.begin("container"),52;case 39:return this.begin("container_boundary"),38;case 40:return this.begin("component_ext_queue"),63;case 41:return this.begin("component_ext_db"),62;case 42:return this.begin("component_ext"),61;case 43:return this.begin("component_queue"),60;case 44:return this.begin("component_db"),59;case 45:return this.begin("component"),58;case 46:return this.begin("node"),39;case 47:return this.begin("node"),39;case 48:return this.begin("node_l"),40;case 49:return this.begin("node_r"),41;case 50:return this.begin("rel"),64;case 51:return this.begin("birel"),65;case 52:return this.begin("rel_u"),66;case 53:return this.begin("rel_u"),66;case 54:return this.begin("rel_d"),67;case 55:return this.begin("rel_d"),67;case 56:return this.begin("rel_l"),68;case 57:return this.begin("rel_l"),68;case 58:return this.begin("rel_r"),69;case 59:return this.begin("rel_r"),69;case 60:return this.begin("rel_b"),70;case 61:return this.begin("rel_index"),71;case 62:return this.begin("update_el_style"),72;case 63:return this.begin("update_rel_style"),73;case 64:return this.begin("update_layout_config"),74;case 65:return"EOF_IN_STRUCT";case 66:return this.begin("attribute"),"ATTRIBUTE_EMPTY";case 67:this.begin("attribute");break;case 68:this.popState(),this.popState();break;case 69:return 80;case 70:break;case 71:return 80;case 72:this.begin("string");break;case 73:this.popState();break;case 74:return"STR";case 75:this.begin("string_kv");break;case 76:return this.begin("string_kv_key"),"STR_KEY";case 77:this.popState(),this.begin("string_kv_value");break;case 78:return"STR_VALUE";case 79:this.popState(),this.popState();break;case 80:return"STR";case 81:return"LBRACE";case 82:return"RBRACE";case 83:return"SPACE";case 84:return"EOL";case 85:return 14}},rules:[/^(?:.*direction\s+TB[^\n]*)/,/^(?:.*direction\s+BT[^\n]*)/,/^(?:.*direction\s+RL[^\n]*)/,/^(?:.*direction\s+LR[^\n]*)/,/^(?:title\s[^#\n;]+)/,/^(?:accDescription\s[^#\n;]+)/,/^(?:accTitle\s*:\s*)/,/^(?:(?!\n||)*[^\n]*)/,/^(?:accDescr\s*:\s*)/,/^(?:(?!\n||)*[^\n]*)/,/^(?:accDescr\s*\{\s*)/,/^(?:[\}])/,/^(?:[^\}]*)/,/^(?:%%(?!\{)*[^\n]*(\r?\n?)+)/,/^(?:%%[^\n]*(\r?\n)*)/,/^(?:\s*(\r?\n)+)/,/^(?:\s+)/,/^(?:C4Context\b)/,/^(?:C4Container\b)/,/^(?:C4Component\b)/,/^(?:C4Dynamic\b)/,/^(?:C4Deployment\b)/,/^(?:Person_Ext\b)/,/^(?:Person\b)/,/^(?:SystemQueue_Ext\b)/,/^(?:SystemDb_Ext\b)/,/^(?:System_Ext\b)/,/^(?:SystemQueue\b)/,/^(?:SystemDb\b)/,/^(?:System\b)/,/^(?:Boundary\b)/,/^(?:Enterprise_Boundary\b)/,/^(?:System_Boundary\b)/,/^(?:ContainerQueue_Ext\b)/,/^(?:ContainerDb_Ext\b)/,/^(?:Container_Ext\b)/,/^(?:ContainerQueue\b)/,/^(?:ContainerDb\b)/,/^(?:Container\b)/,/^(?:Container_Boundary\b)/,/^(?:ComponentQueue_Ext\b)/,/^(?:ComponentDb_Ext\b)/,/^(?:Component_Ext\b)/,/^(?:ComponentQueue\b)/,/^(?:ComponentDb\b)/,/^(?:Component\b)/,/^(?:Deployment_Node\b)/,/^(?:Node\b)/,/^(?:Node_L\b)/,/^(?:Node_R\b)/,/^(?:Rel\b)/,/^(?:BiRel\b)/,/^(?:Rel_Up\b)/,/^(?:Rel_U\b)/,/^(?:Rel_Down\b)/,/^(?:Rel_D\b)/,/^(?:Rel_Left\b)/,/^(?:Rel_L\b)/,/^(?:Rel_Right\b)/,/^(?:Rel_R\b)/,/^(?:Rel_Back\b)/,/^(?:RelIndex\b)/,/^(?:UpdateElementStyle\b)/,/^(?:UpdateRelStyle\b)/,/^(?:UpdateLayoutConfig\b)/,/^(?:$)/,/^(?:[(][ ]*[,])/,/^(?:[(])/,/^(?:[)])/,/^(?:,,)/,/^(?:,)/,/^(?:[ ]*["]["])/,/^(?:[ ]*["])/,/^(?:["])/,/^(?:[^"]*)/,/^(?:[ ]*[\$])/,/^(?:[^=]*)/,/^(?:[=][ ]*["])/,/^(?:[^"]+)/,/^(?:["])/,/^(?:[^,]+)/,/^(?:\{)/,/^(?:\})/,/^(?:[\s]+)/,/^(?:[\n\r]+)/,/^(?:$)/],conditions:{acc_descr_multiline:{rules:[11,12],inclusive:!1},acc_descr:{rules:[9],inclusive:!1},acc_title:{rules:[7],inclusive:!1},string_kv_value:{rules:[78,79],inclusive:!1},string_kv_key:{rules:[77],inclusive:!1},string_kv:{rules:[76],inclusive:!1},string:{rules:[73,74],inclusive:!1},attribute:{rules:[68,69,70,71,72,75,80],inclusive:!1},update_layout_config:{rules:[65,66,67,68],inclusive:!1},update_rel_style:{rules:[65,66,67,68],inclusive:!1},update_el_style:{rules:[65,66,67,68],inclusive:!1},rel_b:{rules:[65,66,67,68],inclusive:!1},rel_r:{rules:[65,66,67,68],inclusive:!1},rel_l:{rules:[65,66,67,68],inclusive:!1},rel_d:{rules:[65,66,67,68],inclusive:!1},rel_u:{rules:[65,66,67,68],inclusive:!1},rel_bi:{rules:[],inclusive:!1},rel:{rules:[65,66,67,68],inclusive:!1},node_r:{rules:[65,66,67,68],inclusive:!1},node_l:{rules:[65,66,67,68],inclusive:!1},node:{rules:[65,66,67,68],inclusive:!1},index:{rules:[],inclusive:!1},rel_index:{rules:[65,66,67,68],inclusive:!1},component_ext_queue:{rules:[],inclusive:!1},component_ext_db:{rules:[65,66,67,68],inclusive:!1},component_ext:{rules:[65,66,67,68],inclusive:!1},component_queue:{rules:[65,66,67,68],inclusive:!1},component_db:{rules:[65,66,67,68],inclusive:!1},component:{rules:[65,66,67,68],inclusive:!1},container_boundary:{rules:[65,66,67,68],inclusive:!1},container_ext_queue:{rules:[65,66,67,68],inclusive:!1},container_ext_db:{rules:[65,66,67,68],inclusive:!1},container_ext:{rules:[65,66,67,68],inclusive:!1},container_queue:{rules:[65,66,67,68],inclusive:!1},container_db:{rules:[65,66,67,68],inclusive:!1},container:{rules:[65,66,67,68],inclusive:!1},birel:{rules:[65,66,67,68],inclusive:!1},system_boundary:{rules:[65,66,67,68],inclusive:!1},enterprise_boundary:{rules:[65,66,67,68],inclusive:!1},boundary:{rules:[65,66,67,68],inclusive:!1},system_ext_queue:{rules:[65,66,67,68],inclusive:!1},system_ext_db:{rules:[65,66,67,68],inclusive:!1},system_ext:{rules:[65,66,67,68],inclusive:!1},system_queue:{rules:[65,66,67,68],inclusive:!1},system_db:{rules:[65,66,67,68],inclusive:!1},system:{rules:[65,66,67,68],inclusive:!1},person_ext:{rules:[65,66,67,68],inclusive:!1},person:{rules:[65,66,67,68],inclusive:!1},INITIAL:{rules:[0,1,2,3,4,5,6,8,10,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,81,82,83,84,85],inclusive:!0}}};return Xi}();Ks.lexer=ws;function fo(){this.yy={}}return fo.prototype=Ks,Ks.Parser=fo,new fo}();XW.parser=XW;const gDe=XW;let am=[],fk=[""],wg="global",om="",p3=[{alias:"global",label:{text:"global"},type:{text:"global"},tags:null,link:null,parentBoundary:""}],lF=[],Fdt="",Ndt=!1,QW=4,ZW=2;var wPt;const pDe=function(){return wPt},bDe=function(i){wPt=Q1(i,Oe())},wDe=function(i,a,f,p,w,m,b,E,_){if(i==null||a===void 0||a===null||f===void 0||f===null||p===void 0||p===null)return;let A={};const I=lF.find(B=>B.from===a&&B.to===f);if(I?A=I:lF.push(A),A.type=i,A.from=a,A.to=f,A.label={text:p},w==null)A.techn={text:""};else if(typeof w=="object"){let[B,N]=Object.entries(w)[0];A[B]={text:N}}else A.techn={text:w};if(m==null)A.descr={text:""};else if(typeof m=="object"){let[B,N]=Object.entries(m)[0];A[B]={text:N}}else A.descr={text:m};if(typeof b=="object"){let[B,N]=Object.entries(b)[0];A[B]=N}else A.sprite=b;if(typeof E=="object"){let[B,N]=Object.entries(E)[0];A[B]=N}else A.tags=E;if(typeof _=="object"){let[B,N]=Object.entries(_)[0];A[B]=N}else A.link=_;A.wrap=dk()},vDe=function(i,a,f,p,w,m,b){if(a===null||f===null)return;let E={};const _=am.find(A=>A.alias===a);if(_&&a===_.alias?E=_:(E.alias=a,am.push(E)),f==null?E.label={text:""}:E.label={text:f},p==null)E.descr={text:""};else if(typeof p=="object"){let[A,I]=Object.entries(p)[0];E[A]={text:I}}else E.descr={text:p};if(typeof w=="object"){let[A,I]=Object.entries(w)[0];E[A]=I}else E.sprite=w;if(typeof m=="object"){let[A,I]=Object.entries(m)[0];E[A]=I}else E.tags=m;if(typeof b=="object"){let[A,I]=Object.entries(b)[0];E[A]=I}else E.link=b;E.typeC4Shape={text:i},E.parentBoundary=wg,E.wrap=dk()},mDe=function(i,a,f,p,w,m,b,E){if(a===null||f===null)return;let _={};const A=am.find(I=>I.alias===a);if(A&&a===A.alias?_=A:(_.alias=a,am.push(_)),f==null?_.label={text:""}:_.label={text:f},p==null)_.techn={text:""};else if(typeof p=="object"){let[I,B]=Object.entries(p)[0];_[I]={text:B}}else _.techn={text:p};if(w==null)_.descr={text:""};else if(typeof w=="object"){let[I,B]=Object.entries(w)[0];_[I]={text:B}}else _.descr={text:w};if(typeof m=="object"){let[I,B]=Object.entries(m)[0];_[I]=B}else _.sprite=m;if(typeof b=="object"){let[I,B]=Object.entries(b)[0];_[I]=B}else _.tags=b;if(typeof E=="object"){let[I,B]=Object.entries(E)[0];_[I]=B}else _.link=E;_.wrap=dk(),_.typeC4Shape={text:i},_.parentBoundary=wg},yDe=function(i,a,f,p,w,m,b,E){if(a===null||f===null)return;let _={};const A=am.find(I=>I.alias===a);if(A&&a===A.alias?_=A:(_.alias=a,am.push(_)),f==null?_.label={text:""}:_.label={text:f},p==null)_.techn={text:""};else if(typeof p=="object"){let[I,B]=Object.entries(p)[0];_[I]={text:B}}else _.techn={text:p};if(w==null)_.descr={text:""};else if(typeof w=="object"){let[I,B]=Object.entries(w)[0];_[I]={text:B}}else _.descr={text:w};if(typeof m=="object"){let[I,B]=Object.entries(m)[0];_[I]=B}else _.sprite=m;if(typeof b=="object"){let[I,B]=Object.entries(b)[0];_[I]=B}else _.tags=b;if(typeof E=="object"){let[I,B]=Object.entries(E)[0];_[I]=B}else _.link=E;_.wrap=dk(),_.typeC4Shape={text:i},_.parentBoundary=wg},xDe=function(i,a,f,p,w){if(i===null||a===null)return;let m={};const b=p3.find(E=>E.alias===i);if(b&&i===b.alias?m=b:(m.alias=i,p3.push(m)),a==null?m.label={text:""}:m.label={text:a},f==null)m.type={text:"system"};else if(typeof f=="object"){let[E,_]=Object.entries(f)[0];m[E]={text:_}}else m.type={text:f};if(typeof p=="object"){let[E,_]=Object.entries(p)[0];m[E]=_}else m.tags=p;if(typeof w=="object"){let[E,_]=Object.entries(w)[0];m[E]=_}else m.link=w;m.parentBoundary=wg,m.wrap=dk(),om=wg,wg=i,fk.push(om)},kDe=function(i,a,f,p,w){if(i===null||a===null)return;let m={};const b=p3.find(E=>E.alias===i);if(b&&i===b.alias?m=b:(m.alias=i,p3.push(m)),a==null?m.label={text:""}:m.label={text:a},f==null)m.type={text:"container"};else if(typeof f=="object"){let[E,_]=Object.entries(f)[0];m[E]={text:_}}else m.type={text:f};if(typeof p=="object"){let[E,_]=Object.entries(p)[0];m[E]=_}else m.tags=p;if(typeof w=="object"){let[E,_]=Object.entries(w)[0];m[E]=_}else m.link=w;m.parentBoundary=wg,m.wrap=dk(),om=wg,wg=i,fk.push(om)},EDe=function(i,a,f,p,w,m,b,E){if(a===null||f===null)return;let _={};const A=p3.find(I=>I.alias===a);if(A&&a===A.alias?_=A:(_.alias=a,p3.push(_)),f==null?_.label={text:""}:_.label={text:f},p==null)_.type={text:"node"};else if(typeof p=="object"){let[I,B]=Object.entries(p)[0];_[I]={text:B}}else _.type={text:p};if(w==null)_.descr={text:""};else if(typeof w=="object"){let[I,B]=Object.entries(w)[0];_[I]={text:B}}else _.descr={text:w};if(typeof b=="object"){let[I,B]=Object.entries(b)[0];_[I]=B}else _.tags=b;if(typeof E=="object"){let[I,B]=Object.entries(E)[0];_[I]=B}else _.link=E;_.nodeType=i,_.parentBoundary=wg,_.wrap=dk(),om=wg,wg=a,fk.push(om)},TDe=function(){wg=om,fk.pop(),om=fk.pop(),fk.push(om)},CDe=function(i,a,f,p,w,m,b,E,_,A,I){let B=am.find(N=>N.alias===a);if(!(B===void 0&&(B=p3.find(N=>N.alias===a),B===void 0))){if(f!=null)if(typeof f=="object"){let[N,R]=Object.entries(f)[0];B[N]=R}else B.bgColor=f;if(p!=null)if(typeof p=="object"){let[N,R]=Object.entries(p)[0];B[N]=R}else B.fontColor=p;if(w!=null)if(typeof w=="object"){let[N,R]=Object.entries(w)[0];B[N]=R}else B.borderColor=w;if(m!=null)if(typeof m=="object"){let[N,R]=Object.entries(m)[0];B[N]=R}else B.shadowing=m;if(b!=null)if(typeof b=="object"){let[N,R]=Object.entries(b)[0];B[N]=R}else B.shape=b;if(E!=null)if(typeof E=="object"){let[N,R]=Object.entries(E)[0];B[N]=R}else B.sprite=E;if(_!=null)if(typeof _=="object"){let[N,R]=Object.entries(_)[0];B[N]=R}else B.techn=_;if(A!=null)if(typeof A=="object"){let[N,R]=Object.entries(A)[0];B[N]=R}else B.legendText=A;if(I!=null)if(typeof I=="object"){let[N,R]=Object.entries(I)[0];B[N]=R}else B.legendSprite=I}},_De=function(i,a,f,p,w,m,b){const E=lF.find(_=>_.from===a&&_.to===f);if(E!==void 0){if(p!=null)if(typeof p=="object"){let[_,A]=Object.entries(p)[0];E[_]=A}else E.textColor=p;if(w!=null)if(typeof w=="object"){let[_,A]=Object.entries(w)[0];E[_]=A}else E.lineColor=w;if(m!=null)if(typeof m=="object"){let[_,A]=Object.entries(m)[0];E[_]=parseInt(A)}else E.offsetX=parseInt(m);if(b!=null)if(typeof b=="object"){let[_,A]=Object.entries(b)[0];E[_]=parseInt(A)}else E.offsetY=parseInt(b)}},SDe=function(i,a,f){let p=QW,w=ZW;if(typeof a=="object"){const m=Object.values(a)[0];p=parseInt(m)}else p=parseInt(a);if(typeof f=="object"){const m=Object.values(f)[0];w=parseInt(m)}else w=parseInt(f);p>=1&&(QW=p),w>=1&&(ZW=w)},ADe=function(){return QW},LDe=function(){return ZW},MDe=function(){return wg},DDe=function(){return om},vPt=function(i){return i==null?am:am.filter(a=>a.parentBoundary===i)},IDe=function(i){return am.find(a=>a.alias===i)},ODe=function(i){return Object.keys(vPt(i))},PDe=function(i){return i==null?p3:p3.filter(a=>a.parentBoundary===i)},FDe=function(){return lF},NDe=function(){return Fdt},BDe=function(i){Ndt=i},dk=function(){return Ndt},Bdt={addPersonOrSystem:vDe,addPersonOrSystemBoundary:xDe,addContainer:mDe,addContainerBoundary:kDe,addComponent:yDe,addDeploymentNode:EDe,popBoundaryParseStack:TDe,addRel:wDe,updateElStyle:CDe,updateRelStyle:_De,updateLayoutConfig:SDe,autoWrap:dk,setWrap:BDe,getC4ShapeArray:vPt,getC4Shape:IDe,getC4ShapeKeys:ODe,getBoundarys:PDe,getCurrentBoundaryParse:MDe,getParentBoundaryParse:DDe,getRels:FDe,getTitle:NDe,getC4Type:pDe,getC4ShapeInRow:ADe,getC4BoundaryInRow:LDe,setAccTitle:E0,getAccTitle:fg,getAccDescription:gg,setAccDescription:dg,getConfig:()=>Oe().c4,clear:function(){am=[],p3=[{alias:"global",label:{text:"global"},type:{text:"global"},tags:null,link:null,parentBoundary:""}],om="",wg="global",fk=[""],lF=[],fk=[""],Fdt="",Ndt=!1,QW=4,ZW=2},LINETYPE:{SOLID:0,DOTTED:1,NOTE:2,SOLID_CROSS:3,DOTTED_CROSS:4,SOLID_OPEN:5,DOTTED_OPEN:6,LOOP_START:10,LOOP_END:11,ALT_START:12,ALT_ELSE:13,ALT_END:14,OPT_START:15,OPT_END:16,ACTIVE_START:17,ACTIVE_END:18,PAR_START:19,PAR_AND:20,PAR_END:21,RECT_START:22,RECT_END:23,SOLID_POINT:24,DOTTED_POINT:25},ARROWTYPE:{FILLED:0,OPEN:1},PLACEMENT:{LEFTOF:0,RIGHTOF:1,OVER:2},setTitle:function(i){Fdt=Q1(i,Oe())},setC4Type:bDe},JW=(i,a)=>{const f=i.append("rect");if(f.attr("x",a.x),f.attr("y",a.y),f.attr("fill",a.fill),f.attr("stroke",a.stroke),f.attr("width",a.width),f.attr("height",a.height),a.rx!==void 0&&f.attr("rx",a.rx),a.ry!==void 0&&f.attr("ry",a.ry),a.attrs!==void 0)for(const p in a.attrs)f.attr(p,a.attrs[p]);return a.class!==void 0&&f.attr("class",a.class),f},mPt=(i,a)=>{const f={x:a.startx,y:a.starty,width:a.stopx-a.startx,height:a.stopy-a.starty,fill:a.fill,stroke:a.stroke,class:"rect"};JW(i,f).lower()},RDe=(i,a)=>{const f=a.text.replace(WP," "),p=i.append("text");p.attr("x",a.x),p.attr("y",a.y),p.attr("class","legend"),p.style("text-anchor",a.anchor),a.class!==void 0&&p.attr("class",a.class);const w=p.append("tspan");return w.attr("x",a.x+a.textMargin*2),w.text(f),p},jDe=(i,a,f,p)=>{const w=i.append("image");w.attr("x",a),w.attr("y",f);const m=ik(p);w.attr("xlink:href",m)},$De=(i,a,f,p)=>{const w=i.append("use");w.attr("x",a),w.attr("y",f);const m=ik(p);w.attr("xlink:href",`#${m}`)},bT=()=>({x:0,y:0,width:100,height:100,fill:"#EDF2AE",stroke:"#666",anchor:"start",rx:0,ry:0}),Rdt=()=>({x:0,y:0,width:100,height:100,"text-anchor":"start",style:"#666",textMargin:0,rx:0,ry:0,tspan:!0}),jdt=function(i,a){return JW(i,a)},yPt=function(i,a,f,p,w,m){const b=i.append("image");b.attr("width",a),b.attr("height",f),b.attr("x",p),b.attr("y",w);let E=m.startsWith("data:image/png;base64")?m:ik(m);b.attr("xlink:href",E)},zDe=(i,a,f)=>{const p=i.append("g");let w=0;for(let m of a){let b=m.textColor?m.textColor:"#444444",E=m.lineColor?m.lineColor:"#444444",_=m.offsetX?parseInt(m.offsetX):0,A=m.offsetY?parseInt(m.offsetY):0,I="";if(w===0){let N=p.append("line");N.attr("x1",m.startPoint.x),N.attr("y1",m.startPoint.y),N.attr("x2",m.endPoint.x),N.attr("y2",m.endPoint.y),N.attr("stroke-width","1"),N.attr("stroke",E),N.style("fill","none"),m.type!=="rel_b"&&N.attr("marker-end","url("+I+"#arrowhead)"),(m.type==="birel"||m.type==="rel_b")&&N.attr("marker-start","url("+I+"#arrowend)"),w=-1}else{let N=p.append("path");N.attr("fill","none").attr("stroke-width","1").attr("stroke",E).attr("d","Mstartx,starty Qcontrolx,controly stopx,stopy ".replaceAll("startx",m.startPoint.x).replaceAll("starty",m.startPoint.y).replaceAll("controlx",m.startPoint.x+(m.endPoint.x-m.startPoint.x)/2-(m.endPoint.x-m.startPoint.x)/4).replaceAll("controly",m.startPoint.y+(m.endPoint.y-m.startPoint.y)/2).replaceAll("stopx",m.endPoint.x).replaceAll("stopy",m.endPoint.y)),m.type!=="rel_b"&&N.attr("marker-end","url("+I+"#arrowhead)"),(m.type==="birel"||m.type==="rel_b")&&N.attr("marker-start","url("+I+"#arrowend)")}let B=f.messageFont();L5(f)(m.label.text,p,Math.min(m.startPoint.x,m.endPoint.x)+Math.abs(m.endPoint.x-m.startPoint.x)/2+_,Math.min(m.startPoint.y,m.endPoint.y)+Math.abs(m.endPoint.y-m.startPoint.y)/2+A,m.label.width,m.label.height,{fill:b},B),m.techn&&m.techn.text!==""&&(B=f.messageFont(),L5(f)("["+m.techn.text+"]",p,Math.min(m.startPoint.x,m.endPoint.x)+Math.abs(m.endPoint.x-m.startPoint.x)/2+_,Math.min(m.startPoint.y,m.endPoint.y)+Math.abs(m.endPoint.y-m.startPoint.y)/2+f.messageFontSize+5+A,Math.max(m.label.width,m.techn.width),m.techn.height,{fill:b,"font-style":"italic"},B))}},qDe=function(i,a,f){const p=i.append("g");let w=a.bgColor?a.bgColor:"none",m=a.borderColor?a.borderColor:"#444444",b=a.fontColor?a.fontColor:"black",E={"stroke-width":1,"stroke-dasharray":"7.0,7.0"};a.nodeType&&(E={"stroke-width":1});let _={x:a.x,y:a.y,fill:w,stroke:m,width:a.width,height:a.height,rx:2.5,ry:2.5,attrs:E};jdt(p,_);let A=f.boundaryFont();A.fontWeight="bold",A.fontSize=A.fontSize+2,A.fontColor=b,L5(f)(a.label.text,p,a.x,a.y+a.label.Y,a.width,a.height,{fill:"#444444"},A),a.type&&a.type.text!==""&&(A=f.boundaryFont(),A.fontColor=b,L5(f)(a.type.text,p,a.x,a.y+a.type.Y,a.width,a.height,{fill:"#444444"},A)),a.descr&&a.descr.text!==""&&(A=f.boundaryFont(),A.fontSize=A.fontSize-2,A.fontColor=b,L5(f)(a.descr.text,p,a.x,a.y+a.descr.Y,a.width,a.height,{fill:"#444444"},A))},HDe=function(i,a,f){var B;let p=a.bgColor?a.bgColor:f[a.typeC4Shape.text+"_bg_color"],w=a.borderColor?a.borderColor:f[a.typeC4Shape.text+"_border_color"],m=a.fontColor?a.fontColor:"#FFFFFF",b="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAIAAADYYG7QAAACD0lEQVR4Xu2YoU4EMRCGT+4j8Ai8AhaH4QHgAUjQuFMECUgMIUgwJAgMhgQsAYUiJCiQIBBY+EITsjfTdme6V24v4c8vyGbb+ZjOtN0bNcvjQXmkH83WvYBWto6PLm6v7p7uH1/w2fXD+PBycX1Pv2l3IdDm/vn7x+dXQiAubRzoURa7gRZWd0iGRIiJbOnhnfYBQZNJjNbuyY2eJG8fkDE3bbG4ep6MHUAsgYxmE3nVs6VsBWJSGccsOlFPmLIViMzLOB7pCVO2AtHJMohH7Fh6zqitQK7m0rJvAVYgGcEpe//PLdDz65sM4pF9N7ICcXDKIB5Nv6j7tD0NoSdM2QrU9Gg0ewE1LqBhHR3BBdvj2vapnidjHxD/q6vd7Pvhr31AwcY8eXMTXAKECZZJFXuEq27aLgQK5uLMohCenGGuGewOxSjBvYBqeG6B+Nqiblggdjnc+ZXDy+FNFpFzw76O3UBAROuXh6FoiAcf5g9eTvUgzy0nWg6I8cXHRUpg5bOVBCo+KDpFajOf23GgPme7RSQ+lacIENUgJ6gg1k6HjgOlqnLqip4tEuhv0hNEMXUD0clyXE3p6pZA0S2nnvTlXwLJEZWlb7cTQH1+USgTN4VhAenm/wea1OCAOmqo6fE1WCb9WSKBah+rbUWPWAmE2Rvk0ApiB45eOyNAzU8xcTvj8KvkKEoOaIYeHNA3ZuygAvFMUO0AAAAASUVORK5CYII=";switch(a.typeC4Shape.text){case"person":b="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAIAAADYYG7QAAACD0lEQVR4Xu2YoU4EMRCGT+4j8Ai8AhaH4QHgAUjQuFMECUgMIUgwJAgMhgQsAYUiJCiQIBBY+EITsjfTdme6V24v4c8vyGbb+ZjOtN0bNcvjQXmkH83WvYBWto6PLm6v7p7uH1/w2fXD+PBycX1Pv2l3IdDm/vn7x+dXQiAubRzoURa7gRZWd0iGRIiJbOnhnfYBQZNJjNbuyY2eJG8fkDE3bbG4ep6MHUAsgYxmE3nVs6VsBWJSGccsOlFPmLIViMzLOB7pCVO2AtHJMohH7Fh6zqitQK7m0rJvAVYgGcEpe//PLdDz65sM4pF9N7ICcXDKIB5Nv6j7tD0NoSdM2QrU9Gg0ewE1LqBhHR3BBdvj2vapnidjHxD/q6vd7Pvhr31AwcY8eXMTXAKECZZJFXuEq27aLgQK5uLMohCenGGuGewOxSjBvYBqeG6B+Nqiblggdjnc+ZXDy+FNFpFzw76O3UBAROuXh6FoiAcf5g9eTvUgzy0nWg6I8cXHRUpg5bOVBCo+KDpFajOf23GgPme7RSQ+lacIENUgJ6gg1k6HjgOlqnLqip4tEuhv0hNEMXUD0clyXE3p6pZA0S2nnvTlXwLJEZWlb7cTQH1+USgTN4VhAenm/wea1OCAOmqo6fE1WCb9WSKBah+rbUWPWAmE2Rvk0ApiB45eOyNAzU8xcTvj8KvkKEoOaIYeHNA3ZuygAvFMUO0AAAAASUVORK5CYII=";break;case"external_person":b="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAIAAADYYG7QAAAB6ElEQVR4Xu2YLY+EMBCG9+dWr0aj0Wg0Go1Go0+j8Xdv2uTCvv1gpt0ebHKPuhDaeW4605Z9mJvx4AdXUyTUdd08z+u6flmWZRnHsWkafk9DptAwDPu+f0eAYtu2PEaGWuj5fCIZrBAC2eLBAnRCsEkkxmeaJp7iDJ2QMDdHsLg8SxKFEJaAo8lAXnmuOFIhTMpxxKATebo4UiFknuNo4OniSIXQyRxEA3YsnjGCVEjVXD7yLUAqxBGUyPv/Y4W2beMgGuS7kVQIBycH0fD+oi5pezQETxdHKmQKGk1eQEYldK+jw5GxPfZ9z7Mk0Qnhf1W1m3w//EUn5BDmSZsbR44QQLBEqrBHqOrmSKaQAxdnLArCrxZcM7A7ZKs4ioRq8LFC+NpC3WCBJsvpVw5edm9iEXFuyNfxXAgSwfrFQ1c0iNda8AdejvUgnktOtJQQxmcfFzGglc5WVCj7oDgFqU18boeFSs52CUh8LE8BIVQDT1ABrB0HtgSEYlX5doJnCwv9TXocKCaKbnwhdDKPq4lf3SwU3HLq4V/+WYhHVMa/3b4IlfyikAduCkcBc7mQ3/z/Qq/cTuikhkzB12Ae/mcJC9U+Vo8Ej1gWAtgbeGgFsAMHr50BIWOLCbezvhpBFUdY6EJuJ/QDW0XoMX60zZ0AAAAASUVORK5CYII=";break}const E=i.append("g");E.attr("class","person-man");const _=bT();switch(a.typeC4Shape.text){case"person":case"external_person":case"system":case"external_system":case"container":case"external_container":case"component":case"external_component":_.x=a.x,_.y=a.y,_.fill=p,_.width=a.width,_.height=a.height,_.stroke=w,_.rx=2.5,_.ry=2.5,_.attrs={"stroke-width":.5},jdt(E,_);break;case"system_db":case"external_system_db":case"container_db":case"external_container_db":case"component_db":case"external_component_db":E.append("path").attr("fill",p).attr("stroke-width","0.5").attr("stroke",w).attr("d","Mstartx,startyc0,-10 half,-10 half,-10c0,0 half,0 half,10l0,heightc0,10 -half,10 -half,10c0,0 -half,0 -half,-10l0,-height".replaceAll("startx",a.x).replaceAll("starty",a.y).replaceAll("half",a.width/2).replaceAll("height",a.height)),E.append("path").attr("fill","none").attr("stroke-width","0.5").attr("stroke",w).attr("d","Mstartx,startyc0,10 half,10 half,10c0,0 half,0 half,-10".replaceAll("startx",a.x).replaceAll("starty",a.y).replaceAll("half",a.width/2));break;case"system_queue":case"external_system_queue":case"container_queue":case"external_container_queue":case"component_queue":case"external_component_queue":E.append("path").attr("fill",p).attr("stroke-width","0.5").attr("stroke",w).attr("d","Mstartx,startylwidth,0c5,0 5,half 5,halfc0,0 0,half -5,halfl-width,0c-5,0 -5,-half -5,-halfc0,0 0,-half 5,-half".replaceAll("startx",a.x).replaceAll("starty",a.y).replaceAll("width",a.width).replaceAll("half",a.height/2)),E.append("path").attr("fill","none").attr("stroke-width","0.5").attr("stroke",w).attr("d","Mstartx,startyc-5,0 -5,half -5,halfc0,half 5,half 5,half".replaceAll("startx",a.x+a.width).replaceAll("starty",a.y).replaceAll("half",a.height/2));break}let A=ZDe(f,a.typeC4Shape.text);switch(E.append("text").attr("fill",m).attr("font-family",A.fontFamily).attr("font-size",A.fontSize-2).attr("font-style","italic").attr("lengthAdjust","spacing").attr("textLength",a.typeC4Shape.width).attr("x",a.x+a.width/2-a.typeC4Shape.width/2).attr("y",a.y+a.typeC4Shape.Y).text("<<"+a.typeC4Shape.text+">>"),a.typeC4Shape.text){case"person":case"external_person":yPt(E,48,48,a.x+a.width/2-24,a.y+a.image.Y,b);break}let I=f[a.typeC4Shape.text+"Font"]();return I.fontWeight="bold",I.fontSize=I.fontSize+2,I.fontColor=m,L5(f)(a.label.text,E,a.x,a.y+a.label.Y,a.width,a.height,{fill:m},I),I=f[a.typeC4Shape.text+"Font"](),I.fontColor=m,a.techn&&((B=a.techn)==null?void 0:B.text)!==""?L5(f)(a.techn.text,E,a.x,a.y+a.techn.Y,a.width,a.height,{fill:m,"font-style":"italic"},I):a.type&&a.type.text!==""&&L5(f)(a.type.text,E,a.x,a.y+a.type.Y,a.width,a.height,{fill:m,"font-style":"italic"},I),a.descr&&a.descr.text!==""&&(I=f.personFont(),I.fontColor=m,L5(f)(a.descr.text,E,a.x,a.y+a.descr.Y,a.width,a.height,{fill:m},I)),a.height},VDe=function(i){i.append("defs").append("symbol").attr("id","database").attr("fill-rule","evenodd").attr("clip-rule","evenodd").append("path").attr("transform","scale(.5)").attr("d","M12.258.001l.256.004.255.005.253.008.251.01.249.012.247.015.246.016.242.019.241.02.239.023.236.024.233.027.231.028.229.031.225.032.223.034.22.036.217.038.214.04.211.041.208.043.205.045.201.046.198.048.194.05.191.051.187.053.183.054.18.056.175.057.172.059.168.06.163.061.16.063.155.064.15.066.074.033.073.033.071.034.07.034.069.035.068.035.067.035.066.035.064.036.064.036.062.036.06.036.06.037.058.037.058.037.055.038.055.038.053.038.052.038.051.039.05.039.048.039.047.039.045.04.044.04.043.04.041.04.04.041.039.041.037.041.036.041.034.041.033.042.032.042.03.042.029.042.027.042.026.043.024.043.023.043.021.043.02.043.018.044.017.043.015.044.013.044.012.044.011.045.009.044.007.045.006.045.004.045.002.045.001.045v17l-.001.045-.002.045-.004.045-.006.045-.007.045-.009.044-.011.045-.012.044-.013.044-.015.044-.017.043-.018.044-.02.043-.021.043-.023.043-.024.043-.026.043-.027.042-.029.042-.03.042-.032.042-.033.042-.034.041-.036.041-.037.041-.039.041-.04.041-.041.04-.043.04-.044.04-.045.04-.047.039-.048.039-.05.039-.051.039-.052.038-.053.038-.055.038-.055.038-.058.037-.058.037-.06.037-.06.036-.062.036-.064.036-.064.036-.066.035-.067.035-.068.035-.069.035-.07.034-.071.034-.073.033-.074.033-.15.066-.155.064-.16.063-.163.061-.168.06-.172.059-.175.057-.18.056-.183.054-.187.053-.191.051-.194.05-.198.048-.201.046-.205.045-.208.043-.211.041-.214.04-.217.038-.22.036-.223.034-.225.032-.229.031-.231.028-.233.027-.236.024-.239.023-.241.02-.242.019-.246.016-.247.015-.249.012-.251.01-.253.008-.255.005-.256.004-.258.001-.258-.001-.256-.004-.255-.005-.253-.008-.251-.01-.249-.012-.247-.015-.245-.016-.243-.019-.241-.02-.238-.023-.236-.024-.234-.027-.231-.028-.228-.031-.226-.032-.223-.034-.22-.036-.217-.038-.214-.04-.211-.041-.208-.043-.204-.045-.201-.046-.198-.048-.195-.05-.19-.051-.187-.053-.184-.054-.179-.056-.176-.057-.172-.059-.167-.06-.164-.061-.159-.063-.155-.064-.151-.066-.074-.033-.072-.033-.072-.034-.07-.034-.069-.035-.068-.035-.067-.035-.066-.035-.064-.036-.063-.036-.062-.036-.061-.036-.06-.037-.058-.037-.057-.037-.056-.038-.055-.038-.053-.038-.052-.038-.051-.039-.049-.039-.049-.039-.046-.039-.046-.04-.044-.04-.043-.04-.041-.04-.04-.041-.039-.041-.037-.041-.036-.041-.034-.041-.033-.042-.032-.042-.03-.042-.029-.042-.027-.042-.026-.043-.024-.043-.023-.043-.021-.043-.02-.043-.018-.044-.017-.043-.015-.044-.013-.044-.012-.044-.011-.045-.009-.044-.007-.045-.006-.045-.004-.045-.002-.045-.001-.045v-17l.001-.045.002-.045.004-.045.006-.045.007-.045.009-.044.011-.045.012-.044.013-.044.015-.044.017-.043.018-.044.02-.043.021-.043.023-.043.024-.043.026-.043.027-.042.029-.042.03-.042.032-.042.033-.042.034-.041.036-.041.037-.041.039-.041.04-.041.041-.04.043-.04.044-.04.046-.04.046-.039.049-.039.049-.039.051-.039.052-.038.053-.038.055-.038.056-.038.057-.037.058-.037.06-.037.061-.036.062-.036.063-.036.064-.036.066-.035.067-.035.068-.035.069-.035.07-.034.072-.034.072-.033.074-.033.151-.066.155-.064.159-.063.164-.061.167-.06.172-.059.176-.057.179-.056.184-.054.187-.053.19-.051.195-.05.198-.048.201-.046.204-.045.208-.043.211-.041.214-.04.217-.038.22-.036.223-.034.226-.032.228-.031.231-.028.234-.027.236-.024.238-.023.241-.02.243-.019.245-.016.247-.015.249-.012.251-.01.253-.008.255-.005.256-.004.258-.001.258.001zm-9.258 20.499v.01l.001.021.003.021.004.022.005.021.006.022.007.022.009.023.01.022.011.023.012.023.013.023.015.023.016.024.017.023.018.024.019.024.021.024.022.025.023.024.024.025.052.049.056.05.061.051.066.051.07.051.075.051.079.052.084.052.088.052.092.052.097.052.102.051.105.052.11.052.114.051.119.051.123.051.127.05.131.05.135.05.139.048.144.049.147.047.152.047.155.047.16.045.163.045.167.043.171.043.176.041.178.041.183.039.187.039.19.037.194.035.197.035.202.033.204.031.209.03.212.029.216.027.219.025.222.024.226.021.23.02.233.018.236.016.24.015.243.012.246.01.249.008.253.005.256.004.259.001.26-.001.257-.004.254-.005.25-.008.247-.011.244-.012.241-.014.237-.016.233-.018.231-.021.226-.021.224-.024.22-.026.216-.027.212-.028.21-.031.205-.031.202-.034.198-.034.194-.036.191-.037.187-.039.183-.04.179-.04.175-.042.172-.043.168-.044.163-.045.16-.046.155-.046.152-.047.148-.048.143-.049.139-.049.136-.05.131-.05.126-.05.123-.051.118-.052.114-.051.11-.052.106-.052.101-.052.096-.052.092-.052.088-.053.083-.051.079-.052.074-.052.07-.051.065-.051.06-.051.056-.05.051-.05.023-.024.023-.025.021-.024.02-.024.019-.024.018-.024.017-.024.015-.023.014-.024.013-.023.012-.023.01-.023.01-.022.008-.022.006-.022.006-.022.004-.022.004-.021.001-.021.001-.021v-4.127l-.077.055-.08.053-.083.054-.085.053-.087.052-.09.052-.093.051-.095.05-.097.05-.1.049-.102.049-.105.048-.106.047-.109.047-.111.046-.114.045-.115.045-.118.044-.12.043-.122.042-.124.042-.126.041-.128.04-.13.04-.132.038-.134.038-.135.037-.138.037-.139.035-.142.035-.143.034-.144.033-.147.032-.148.031-.15.03-.151.03-.153.029-.154.027-.156.027-.158.026-.159.025-.161.024-.162.023-.163.022-.165.021-.166.02-.167.019-.169.018-.169.017-.171.016-.173.015-.173.014-.175.013-.175.012-.177.011-.178.01-.179.008-.179.008-.181.006-.182.005-.182.004-.184.003-.184.002h-.37l-.184-.002-.184-.003-.182-.004-.182-.005-.181-.006-.179-.008-.179-.008-.178-.01-.176-.011-.176-.012-.175-.013-.173-.014-.172-.015-.171-.016-.17-.017-.169-.018-.167-.019-.166-.02-.165-.021-.163-.022-.162-.023-.161-.024-.159-.025-.157-.026-.156-.027-.155-.027-.153-.029-.151-.03-.15-.03-.148-.031-.146-.032-.145-.033-.143-.034-.141-.035-.14-.035-.137-.037-.136-.037-.134-.038-.132-.038-.13-.04-.128-.04-.126-.041-.124-.042-.122-.042-.12-.044-.117-.043-.116-.045-.113-.045-.112-.046-.109-.047-.106-.047-.105-.048-.102-.049-.1-.049-.097-.05-.095-.05-.093-.052-.09-.051-.087-.052-.085-.053-.083-.054-.08-.054-.077-.054v4.127zm0-5.654v.011l.001.021.003.021.004.021.005.022.006.022.007.022.009.022.01.022.011.023.012.023.013.023.015.024.016.023.017.024.018.024.019.024.021.024.022.024.023.025.024.024.052.05.056.05.061.05.066.051.07.051.075.052.079.051.084.052.088.052.092.052.097.052.102.052.105.052.11.051.114.051.119.052.123.05.127.051.131.05.135.049.139.049.144.048.147.048.152.047.155.046.16.045.163.045.167.044.171.042.176.042.178.04.183.04.187.038.19.037.194.036.197.034.202.033.204.032.209.03.212.028.216.027.219.025.222.024.226.022.23.02.233.018.236.016.24.014.243.012.246.01.249.008.253.006.256.003.259.001.26-.001.257-.003.254-.006.25-.008.247-.01.244-.012.241-.015.237-.016.233-.018.231-.02.226-.022.224-.024.22-.025.216-.027.212-.029.21-.03.205-.032.202-.033.198-.035.194-.036.191-.037.187-.039.183-.039.179-.041.175-.042.172-.043.168-.044.163-.045.16-.045.155-.047.152-.047.148-.048.143-.048.139-.05.136-.049.131-.05.126-.051.123-.051.118-.051.114-.052.11-.052.106-.052.101-.052.096-.052.092-.052.088-.052.083-.052.079-.052.074-.051.07-.052.065-.051.06-.05.056-.051.051-.049.023-.025.023-.024.021-.025.02-.024.019-.024.018-.024.017-.024.015-.023.014-.023.013-.024.012-.022.01-.023.01-.023.008-.022.006-.022.006-.022.004-.021.004-.022.001-.021.001-.021v-4.139l-.077.054-.08.054-.083.054-.085.052-.087.053-.09.051-.093.051-.095.051-.097.05-.1.049-.102.049-.105.048-.106.047-.109.047-.111.046-.114.045-.115.044-.118.044-.12.044-.122.042-.124.042-.126.041-.128.04-.13.039-.132.039-.134.038-.135.037-.138.036-.139.036-.142.035-.143.033-.144.033-.147.033-.148.031-.15.03-.151.03-.153.028-.154.028-.156.027-.158.026-.159.025-.161.024-.162.023-.163.022-.165.021-.166.02-.167.019-.169.018-.169.017-.171.016-.173.015-.173.014-.175.013-.175.012-.177.011-.178.009-.179.009-.179.007-.181.007-.182.005-.182.004-.184.003-.184.002h-.37l-.184-.002-.184-.003-.182-.004-.182-.005-.181-.007-.179-.007-.179-.009-.178-.009-.176-.011-.176-.012-.175-.013-.173-.014-.172-.015-.171-.016-.17-.017-.169-.018-.167-.019-.166-.02-.165-.021-.163-.022-.162-.023-.161-.024-.159-.025-.157-.026-.156-.027-.155-.028-.153-.028-.151-.03-.15-.03-.148-.031-.146-.033-.145-.033-.143-.033-.141-.035-.14-.036-.137-.036-.136-.037-.134-.038-.132-.039-.13-.039-.128-.04-.126-.041-.124-.042-.122-.043-.12-.043-.117-.044-.116-.044-.113-.046-.112-.046-.109-.046-.106-.047-.105-.048-.102-.049-.1-.049-.097-.05-.095-.051-.093-.051-.09-.051-.087-.053-.085-.052-.083-.054-.08-.054-.077-.054v4.139zm0-5.666v.011l.001.02.003.022.004.021.005.022.006.021.007.022.009.023.01.022.011.023.012.023.013.023.015.023.016.024.017.024.018.023.019.024.021.025.022.024.023.024.024.025.052.05.056.05.061.05.066.051.07.051.075.052.079.051.084.052.088.052.092.052.097.052.102.052.105.051.11.052.114.051.119.051.123.051.127.05.131.05.135.05.139.049.144.048.147.048.152.047.155.046.16.045.163.045.167.043.171.043.176.042.178.04.183.04.187.038.19.037.194.036.197.034.202.033.204.032.209.03.212.028.216.027.219.025.222.024.226.021.23.02.233.018.236.017.24.014.243.012.246.01.249.008.253.006.256.003.259.001.26-.001.257-.003.254-.006.25-.008.247-.01.244-.013.241-.014.237-.016.233-.018.231-.02.226-.022.224-.024.22-.025.216-.027.212-.029.21-.03.205-.032.202-.033.198-.035.194-.036.191-.037.187-.039.183-.039.179-.041.175-.042.172-.043.168-.044.163-.045.16-.045.155-.047.152-.047.148-.048.143-.049.139-.049.136-.049.131-.051.126-.05.123-.051.118-.052.114-.051.11-.052.106-.052.101-.052.096-.052.092-.052.088-.052.083-.052.079-.052.074-.052.07-.051.065-.051.06-.051.056-.05.051-.049.023-.025.023-.025.021-.024.02-.024.019-.024.018-.024.017-.024.015-.023.014-.024.013-.023.012-.023.01-.022.01-.023.008-.022.006-.022.006-.022.004-.022.004-.021.001-.021.001-.021v-4.153l-.077.054-.08.054-.083.053-.085.053-.087.053-.09.051-.093.051-.095.051-.097.05-.1.049-.102.048-.105.048-.106.048-.109.046-.111.046-.114.046-.115.044-.118.044-.12.043-.122.043-.124.042-.126.041-.128.04-.13.039-.132.039-.134.038-.135.037-.138.036-.139.036-.142.034-.143.034-.144.033-.147.032-.148.032-.15.03-.151.03-.153.028-.154.028-.156.027-.158.026-.159.024-.161.024-.162.023-.163.023-.165.021-.166.02-.167.019-.169.018-.169.017-.171.016-.173.015-.173.014-.175.013-.175.012-.177.01-.178.01-.179.009-.179.007-.181.006-.182.006-.182.004-.184.003-.184.001-.185.001-.185-.001-.184-.001-.184-.003-.182-.004-.182-.006-.181-.006-.179-.007-.179-.009-.178-.01-.176-.01-.176-.012-.175-.013-.173-.014-.172-.015-.171-.016-.17-.017-.169-.018-.167-.019-.166-.02-.165-.021-.163-.023-.162-.023-.161-.024-.159-.024-.157-.026-.156-.027-.155-.028-.153-.028-.151-.03-.15-.03-.148-.032-.146-.032-.145-.033-.143-.034-.141-.034-.14-.036-.137-.036-.136-.037-.134-.038-.132-.039-.13-.039-.128-.041-.126-.041-.124-.041-.122-.043-.12-.043-.117-.044-.116-.044-.113-.046-.112-.046-.109-.046-.106-.048-.105-.048-.102-.048-.1-.05-.097-.049-.095-.051-.093-.051-.09-.052-.087-.052-.085-.053-.083-.053-.08-.054-.077-.054v4.153zm8.74-8.179l-.257.004-.254.005-.25.008-.247.011-.244.012-.241.014-.237.016-.233.018-.231.021-.226.022-.224.023-.22.026-.216.027-.212.028-.21.031-.205.032-.202.033-.198.034-.194.036-.191.038-.187.038-.183.04-.179.041-.175.042-.172.043-.168.043-.163.045-.16.046-.155.046-.152.048-.148.048-.143.048-.139.049-.136.05-.131.05-.126.051-.123.051-.118.051-.114.052-.11.052-.106.052-.101.052-.096.052-.092.052-.088.052-.083.052-.079.052-.074.051-.07.052-.065.051-.06.05-.056.05-.051.05-.023.025-.023.024-.021.024-.02.025-.019.024-.018.024-.017.023-.015.024-.014.023-.013.023-.012.023-.01.023-.01.022-.008.022-.006.023-.006.021-.004.022-.004.021-.001.021-.001.021.001.021.001.021.004.021.004.022.006.021.006.023.008.022.01.022.01.023.012.023.013.023.014.023.015.024.017.023.018.024.019.024.02.025.021.024.023.024.023.025.051.05.056.05.06.05.065.051.07.052.074.051.079.052.083.052.088.052.092.052.096.052.101.052.106.052.11.052.114.052.118.051.123.051.126.051.131.05.136.05.139.049.143.048.148.048.152.048.155.046.16.046.163.045.168.043.172.043.175.042.179.041.183.04.187.038.191.038.194.036.198.034.202.033.205.032.21.031.212.028.216.027.22.026.224.023.226.022.231.021.233.018.237.016.241.014.244.012.247.011.25.008.254.005.257.004.26.001.26-.001.257-.004.254-.005.25-.008.247-.011.244-.012.241-.014.237-.016.233-.018.231-.021.226-.022.224-.023.22-.026.216-.027.212-.028.21-.031.205-.032.202-.033.198-.034.194-.036.191-.038.187-.038.183-.04.179-.041.175-.042.172-.043.168-.043.163-.045.16-.046.155-.046.152-.048.148-.048.143-.048.139-.049.136-.05.131-.05.126-.051.123-.051.118-.051.114-.052.11-.052.106-.052.101-.052.096-.052.092-.052.088-.052.083-.052.079-.052.074-.051.07-.052.065-.051.06-.05.056-.05.051-.05.023-.025.023-.024.021-.024.02-.025.019-.024.018-.024.017-.023.015-.024.014-.023.013-.023.012-.023.01-.023.01-.022.008-.022.006-.023.006-.021.004-.022.004-.021.001-.021.001-.021-.001-.021-.001-.021-.004-.021-.004-.022-.006-.021-.006-.023-.008-.022-.01-.022-.01-.023-.012-.023-.013-.023-.014-.023-.015-.024-.017-.023-.018-.024-.019-.024-.02-.025-.021-.024-.023-.024-.023-.025-.051-.05-.056-.05-.06-.05-.065-.051-.07-.052-.074-.051-.079-.052-.083-.052-.088-.052-.092-.052-.096-.052-.101-.052-.106-.052-.11-.052-.114-.052-.118-.051-.123-.051-.126-.051-.131-.05-.136-.05-.139-.049-.143-.048-.148-.048-.152-.048-.155-.046-.16-.046-.163-.045-.168-.043-.172-.043-.175-.042-.179-.041-.183-.04-.187-.038-.191-.038-.194-.036-.198-.034-.202-.033-.205-.032-.21-.031-.212-.028-.216-.027-.22-.026-.224-.023-.226-.022-.231-.021-.233-.018-.237-.016-.241-.014-.244-.012-.247-.011-.25-.008-.254-.005-.257-.004-.26-.001-.26.001z")},GDe=function(i){i.append("defs").append("symbol").attr("id","computer").attr("width","24").attr("height","24").append("path").attr("transform","scale(.5)").attr("d","M2 2v13h20v-13h-20zm18 11h-16v-9h16v9zm-10.228 6l.466-1h3.524l.467 1h-4.457zm14.228 3h-24l2-6h2.104l-1.33 4h18.45l-1.297-4h2.073l2 6zm-5-10h-14v-7h14v7z")},UDe=function(i){i.append("defs").append("symbol").attr("id","clock").attr("width","24").attr("height","24").append("path").attr("transform","scale(.5)").attr("d","M12 2c5.514 0 10 4.486 10 10s-4.486 10-10 10-10-4.486-10-10 4.486-10 10-10zm0-2c-6.627 0-12 5.373-12 12s5.373 12 12 12 12-5.373 12-12-5.373-12-12-12zm5.848 12.459c.202.038.202.333.001.372-1.907.361-6.045 1.111-6.547 1.111-.719 0-1.301-.582-1.301-1.301 0-.512.77-5.447 1.125-7.445.034-.192.312-.181.343.014l.985 6.238 5.394 1.011z")},WDe=function(i){i.append("defs").append("marker").attr("id","arrowhead").attr("refX",9).attr("refY",5).attr("markerUnits","userSpaceOnUse").attr("markerWidth",12).attr("markerHeight",12).attr("orient","auto").append("path").attr("d","M 0 0 L 10 5 L 0 10 z")},YDe=function(i){i.append("defs").append("marker").attr("id","arrowend").attr("refX",1).attr("refY",5).attr("markerUnits","userSpaceOnUse").attr("markerWidth",12).attr("markerHeight",12).attr("orient","auto").append("path").attr("d","M 10 0 L 0 5 L 10 10 z")},KDe=function(i){i.append("defs").append("marker").attr("id","filled-head").attr("refX",18).attr("refY",7).attr("markerWidth",20).attr("markerHeight",28).attr("orient","auto").append("path").attr("d","M 18,7 L9,13 L14,7 L9,1 Z")},XDe=function(i){i.append("defs").append("marker").attr("id","sequencenumber").attr("refX",15).attr("refY",15).attr("markerWidth",60).attr("markerHeight",40).attr("orient","auto").append("circle").attr("cx",15).attr("cy",15).attr("r",6)},QDe=function(i){const f=i.append("defs").append("marker").attr("id","crosshead").attr("markerWidth",15).attr("markerHeight",8).attr("orient","auto").attr("refX",16).attr("refY",4);f.append("path").attr("fill","black").attr("stroke","#000000").style("stroke-dasharray","0, 0").attr("stroke-width","1px").attr("d","M 9,2 V 6 L16,4 Z"),f.append("path").attr("fill","none").attr("stroke","#000000").style("stroke-dasharray","0, 0").attr("stroke-width","1px").attr("d","M 0,1 L 6,7 M 6,1 L 0,7")},ZDe=(i,a)=>({fontFamily:i[a+"FontFamily"],fontSize:i[a+"FontSize"],fontWeight:i[a+"FontWeight"]}),L5=function(){function i(w,m,b,E,_,A,I){const B=m.append("text").attr("x",b+_/2).attr("y",E+A/2+5).style("text-anchor","middle").text(w);p(B,I)}function a(w,m,b,E,_,A,I,B){const{fontSize:N,fontFamily:R,fontWeight:z}=B,W=w.split(Kr.lineBreakRegex);for(let et=0;et=this.data.widthLimit||p>=this.data.widthLimit||this.nextData.cnt>xPt)&&(f=this.nextData.startx+a.margin+ds.nextLinePaddingX,w=this.nextData.stopy+a.margin*2,this.nextData.stopx=p=f+a.width,this.nextData.starty=this.nextData.stopy,this.nextData.stopy=m=w+a.height,this.nextData.cnt=1),a.x=f,a.y=w,this.updateVal(this.data,"startx",f,Math.min),this.updateVal(this.data,"starty",w,Math.min),this.updateVal(this.data,"stopx",p,Math.max),this.updateVal(this.data,"stopy",m,Math.max),this.updateVal(this.nextData,"startx",f,Math.min),this.updateVal(this.nextData,"starty",w,Math.min),this.updateVal(this.nextData,"stopx",p,Math.max),this.updateVal(this.nextData,"stopy",m,Math.max)}init(a){this.name="",this.data={startx:void 0,stopx:void 0,starty:void 0,stopy:void 0,widthLimit:void 0},this.nextData={startx:void 0,stopx:void 0,starty:void 0,stopy:void 0,cnt:0},zdt(a.db.getConfig())}bumpLastMargin(a){this.data.stopx+=a,this.data.stopy+=a}}const zdt=function(i){Z1(ds,i),i.fontFamily&&(ds.personFontFamily=ds.systemFontFamily=ds.messageFontFamily=i.fontFamily),i.fontSize&&(ds.personFontSize=ds.systemFontSize=ds.messageFontSize=i.fontSize),i.fontWeight&&(ds.personFontWeight=ds.systemFontWeight=ds.messageFontWeight=i.fontWeight)},hF=(i,a)=>({fontFamily:i[a+"FontFamily"],fontSize:i[a+"FontSize"],fontWeight:i[a+"FontWeight"]}),nY=i=>({fontFamily:i.boundaryFontFamily,fontSize:i.boundaryFontSize,fontWeight:i.boundaryFontWeight}),JDe=i=>({fontFamily:i.messageFontFamily,fontSize:i.messageFontSize,fontWeight:i.messageFontWeight});function cm(i,a,f,p,w){if(!a[i].width)if(f)a[i].text=UIt(a[i].text,w,p),a[i].textLines=a[i].text.split(Kr.lineBreakRegex).length,a[i].width=w,a[i].height=odt(a[i].text,p);else{let m=a[i].text.split(Kr.lineBreakRegex);a[i].textLines=m.length;let b=0;a[i].height=0,a[i].width=0;for(const E of m)a[i].width=Math.max(d3(E,p),a[i].width),b=odt(E,p),a[i].height=a[i].height+b}}const EPt=function(i,a,f){a.x=f.data.startx,a.y=f.data.starty,a.width=f.data.stopx-f.data.startx,a.height=f.data.stopy-f.data.starty,a.label.y=ds.c4ShapeMargin-35;let p=a.wrap&&ds.wrap,w=nY(ds);w.fontSize=w.fontSize+2,w.fontWeight="bold";let m=d3(a.label.text,w);cm("label",a,p,w,m),b3.drawBoundary(i,a,ds)},TPt=function(i,a,f,p){let w=0;for(const m of p){w=0;const b=f[m];let E=hF(ds,b.typeC4Shape.text);switch(E.fontSize=E.fontSize-2,b.typeC4Shape.width=d3("«"+b.typeC4Shape.text+"»",E),b.typeC4Shape.height=E.fontSize+2,b.typeC4Shape.Y=ds.c4ShapePadding,w=b.typeC4Shape.Y+b.typeC4Shape.height-4,b.image={width:0,height:0,Y:0},b.typeC4Shape.text){case"person":case"external_person":b.image.width=48,b.image.height=48,b.image.Y=w,w=b.image.Y+b.image.height;break}b.sprite&&(b.image.width=48,b.image.height=48,b.image.Y=w,w=b.image.Y+b.image.height);let _=b.wrap&&ds.wrap,A=ds.width-ds.c4ShapePadding*2,I=hF(ds,b.typeC4Shape.text);if(I.fontSize=I.fontSize+2,I.fontWeight="bold",cm("label",b,_,I,A),b.label.Y=w+8,w=b.label.Y+b.label.height,b.type&&b.type.text!==""){b.type.text="["+b.type.text+"]";let R=hF(ds,b.typeC4Shape.text);cm("type",b,_,R,A),b.type.Y=w+5,w=b.type.Y+b.type.height}else if(b.techn&&b.techn.text!==""){b.techn.text="["+b.techn.text+"]";let R=hF(ds,b.techn.text);cm("techn",b,_,R,A),b.techn.Y=w+5,w=b.techn.Y+b.techn.height}let B=w,N=b.label.width;if(b.descr&&b.descr.text!==""){let R=hF(ds,b.typeC4Shape.text);cm("descr",b,_,R,A),b.descr.Y=w+20,w=b.descr.Y+b.descr.height,N=Math.max(b.label.width,b.descr.width),B=w-b.descr.textLines*5}N=N+ds.c4ShapePadding,b.width=Math.max(b.width||ds.width,N,ds.width),b.height=Math.max(b.height||ds.height,B,ds.height),b.margin=b.margin||ds.c4ShapeMargin,i.insert(b),b3.drawC4Shape(a,b,ds)}i.bumpLastMargin(ds.c4ShapeMargin)};let rw=class{constructor(a,f){this.x=a,this.y=f}},CPt=function(i,a){let f=i.x,p=i.y,w=a.x,m=a.y,b=f+i.width/2,E=p+i.height/2,_=Math.abs(f-w),A=Math.abs(p-m),I=A/_,B=i.height/i.width,N=null;return p==m&&fw?N=new rw(f,E):f==w&&pm&&(N=new rw(b,p)),f>w&&p=I?N=new rw(f,E+I*i.width/2):N=new rw(b-_/A*i.height/2,p+i.height):f=I?N=new rw(f+i.width,E+I*i.width/2):N=new rw(b+_/A*i.height/2,p+i.height):fm?B>=I?N=new rw(f+i.width,E-I*i.width/2):N=new rw(b+i.height/2*_/A,p):f>w&&p>m&&(B>=I?N=new rw(f,E-i.width/2*I):N=new rw(b-i.height/2*_/A,p)),N},tIe=function(i,a){let f={x:0,y:0};f.x=a.x+a.width/2,f.y=a.y+a.height/2;let p=CPt(i,f);f.x=i.x+i.width/2,f.y=i.y+i.height/2;let w=CPt(a,f);return{startPoint:p,endPoint:w}};const eIe=function(i,a,f,p){let w=0;for(let m of a){w=w+1;let b=m.wrap&&ds.wrap,E=JDe(ds);p.db.getC4Type()==="C4Dynamic"&&(m.label.text=w+": "+m.label.text);let A=d3(m.label.text,E);cm("label",m,b,E,A),m.techn&&m.techn.text!==""&&(A=d3(m.techn.text,E),cm("techn",m,b,E,A)),m.descr&&m.descr.text!==""&&(A=d3(m.descr.text,E),cm("descr",m,b,E,A));let I=f(m.from),B=f(m.to),N=tIe(I,B);m.startPoint=N.startPoint,m.endPoint=N.endPoint}b3.drawRels(i,a,ds)};function _Pt(i,a,f,p,w){let m=new kPt(w);m.data.widthLimit=f.data.widthLimit/Math.min($dt,p.length);for(let[b,E]of p.entries()){let _=0;E.image={width:0,height:0,Y:0},E.sprite&&(E.image.width=48,E.image.height=48,E.image.Y=_,_=E.image.Y+E.image.height);let A=E.wrap&&ds.wrap,I=nY(ds);if(I.fontSize=I.fontSize+2,I.fontWeight="bold",cm("label",E,A,I,m.data.widthLimit),E.label.Y=_+8,_=E.label.Y+E.label.height,E.type&&E.type.text!==""){E.type.text="["+E.type.text+"]";let z=nY(ds);cm("type",E,A,z,m.data.widthLimit),E.type.Y=_+5,_=E.type.Y+E.type.height}if(E.descr&&E.descr.text!==""){let z=nY(ds);z.fontSize=z.fontSize-2,cm("descr",E,A,z,m.data.widthLimit),E.descr.Y=_+20,_=E.descr.Y+E.descr.height}if(b==0||b%$dt===0){let z=f.data.startx+ds.diagramMarginX,W=f.data.stopy+ds.diagramMarginY+_;m.setData(z,z,W,W)}else{let z=m.data.stopx!==m.data.startx?m.data.stopx+ds.diagramMarginX:m.data.startx,W=m.data.starty;m.setData(z,z,W,W)}m.name=E.alias;let B=w.db.getC4ShapeArray(E.alias),N=w.db.getC4ShapeKeys(E.alias);N.length>0&&TPt(m,i,B,N),a=E.alias;let R=w.db.getBoundarys(a);R.length>0&&_Pt(i,a,m,R,w),E.alias!=="global"&&EPt(i,E,m),f.data.stopy=Math.max(m.data.stopy+ds.c4ShapeMargin,f.data.stopy),f.data.stopx=Math.max(m.data.stopx+ds.c4ShapeMargin,f.data.stopx),tY=Math.max(tY,f.data.stopx),eY=Math.max(eY,f.data.stopy)}}const SPt={drawPersonOrSystemArray:TPt,drawBoundary:EPt,setConf:zdt,draw:function(i,a,f,p){ds=Oe().c4;const w=Oe().securityLevel;let m;w==="sandbox"&&(m=yr("#i"+a));const b=yr(w==="sandbox"?m.nodes()[0].contentDocument.body:"body");let E=p.db;p.db.setWrap(ds.wrap),xPt=E.getC4ShapeInRow(),$dt=E.getC4BoundaryInRow(),Ut.debug(`C:${JSON.stringify(ds,null,2)}`);const _=w==="sandbox"?b.select(`[id="${a}"]`):yr(`[id="${a}"]`);b3.insertComputerIcon(_),b3.insertDatabaseIcon(_),b3.insertClockIcon(_);let A=new kPt(p);A.setData(ds.diagramMarginX,ds.diagramMarginX,ds.diagramMarginY,ds.diagramMarginY),A.data.widthLimit=screen.availWidth,tY=ds.diagramMarginX,eY=ds.diagramMarginY;const I=p.db.getTitle();let B=p.db.getBoundarys("");_Pt(_,"",A,B,p),b3.insertArrowHead(_),b3.insertArrowEnd(_),b3.insertArrowCrossHead(_),b3.insertArrowFilledHead(_),eIe(_,p.db.getRels(),p.db.getC4Shape,p),A.data.stopx=tY,A.data.stopy=eY;const N=A.data;let z=N.stopy-N.starty+2*ds.diagramMarginY;const et=N.stopx-N.startx+2*ds.diagramMarginX;I&&_.append("text").text(I).attr("x",(N.stopx-N.startx)/2-4*ds.diagramMarginX).attr("y",N.starty+ds.diagramMarginY),k0(_,z,et,ds.useMaxWidth);const st=I?60:0;_.attr("viewBox",N.startx-ds.diagramMarginX+" -"+(ds.diagramMarginY+st)+" "+et+" "+(z+st)),Ut.debug("models:",N)}},nIe=Object.freeze(Object.defineProperty({__proto__:null,diagram:{parser:gDe,db:Bdt,renderer:SPt,styles:i=>`.person { + stroke: ${i.personBorder}; + fill: ${i.personBkg}; + } +`,init:({c4:i,wrap:a})=>{SPt.setConf(i),Bdt.setWrap(a)}}},Symbol.toStringTag,{value:"Module"}));var qdt=function(){var i=function(af,Qi,Ts,ka){for(Ts=Ts||{},ka=af.length;ka--;Ts[af[ka]]=Qi);return Ts},a=[1,4],f=[1,3],p=[1,5],w=[1,8,9,10,11,27,34,36,38,42,58,81,82,83,84,85,86,99,102,103,106,108,111,112,113,118,119,120,121],m=[2,2],b=[1,13],E=[1,14],_=[1,15],A=[1,16],I=[1,23],B=[1,25],N=[1,26],R=[1,27],z=[1,49],W=[1,48],et=[1,29],st=[1,30],at=[1,31],bt=[1,32],mt=[1,33],yt=[1,44],ft=[1,46],ut=[1,42],vt=[1,47],X=[1,43],pt=[1,50],U=[1,45],Tt=[1,51],nt=[1,52],It=[1,34],Ot=[1,35],Bt=[1,36],Et=[1,37],Z=[1,57],Ct=[1,8,9,10,11,27,32,34,36,38,42,58,81,82,83,84,85,86,99,102,103,106,108,111,112,113,118,119,120,121],xt=[1,61],Ht=[1,60],Le=[1,62],Ft=[8,9,11,73,75],gn=[1,88],Se=[1,93],me=[1,92],Ve=[1,89],Ye=[1,85],ce=[1,91],ke=[1,87],zt=[1,94],re=[1,90],se=[1,95],Pe=[1,86],te=[8,9,10,11,73,75],Me=[8,9,10,11,44,73,75],de=[8,9,10,11,29,42,44,46,48,50,52,54,56,58,61,63,65,66,68,73,75,86,99,102,103,106,108,111,112,113],on=[8,9,11,42,58,73,75,86,99,102,103,106,108,111,112,113],ni=[42,58,86,99,102,103,106,108,111,112,113],Ks=[1,121],ws=[1,120],fo=[1,128],Xi=[1,142],Er=[1,143],Xn=[1,144],di=[1,145],Ee=[1,130],Kn=[1,132],He=[1,136],Ti=[1,137],pn=[1,138],Es=[1,139],qa=[1,140],Ma=[1,141],Gs=[1,146],Po=[1,147],vs=[1,126],ru=[1,127],zs=[1,134],Du=[1,129],pm=[1,133],uw=[1,131],Wu=[8,9,10,11,27,32,34,36,38,42,58,81,82,83,84,85,86,99,102,103,106,108,111,112,113,118,119,120,121],th=[1,149],Fa=[8,9,11],Ml=[8,9,10,11,14,42,58,86,102,103,106,108,111,112,113],ha=[1,169],bc=[1,165],Cc=[1,166],pa=[1,170],Da=[1,167],Ha=[1,168],Dl=[75,113,116],_c=[8,9,10,11,12,14,27,29,32,42,58,73,81,82,83,84,85,86,87,102,106,108,111,112,113],lw=[10,103],eh=[31,47,49,51,53,55,60,62,64,65,67,69,113,114,115],ed=[1,235],jd=[1,233],nd=[1,237],$d=[1,231],A0=[1,232],Bi=[1,234],cn=[1,236],kr=[1,238],Ei=[1,255],Jo=[8,9,11,103],wc=[8,9,10,11,58,81,102,103,106,107,108,109],rf={trace:function(){},yy:{},symbols_:{error:2,start:3,graphConfig:4,document:5,line:6,statement:7,SEMI:8,NEWLINE:9,SPACE:10,EOF:11,GRAPH:12,NODIR:13,DIR:14,FirstStmtSeperator:15,ending:16,endToken:17,spaceList:18,spaceListNewline:19,verticeStatement:20,separator:21,styleStatement:22,linkStyleStatement:23,classDefStatement:24,classStatement:25,clickStatement:26,subgraph:27,textNoTags:28,SQS:29,text:30,SQE:31,end:32,direction:33,acc_title:34,acc_title_value:35,acc_descr:36,acc_descr_value:37,acc_descr_multiline_value:38,link:39,node:40,styledVertex:41,AMP:42,vertex:43,STYLE_SEPARATOR:44,idString:45,DOUBLECIRCLESTART:46,DOUBLECIRCLEEND:47,PS:48,PE:49,"(-":50,"-)":51,STADIUMSTART:52,STADIUMEND:53,SUBROUTINESTART:54,SUBROUTINEEND:55,VERTEX_WITH_PROPS_START:56,"NODE_STRING[field]":57,COLON:58,"NODE_STRING[value]":59,PIPE:60,CYLINDERSTART:61,CYLINDEREND:62,DIAMOND_START:63,DIAMOND_STOP:64,TAGEND:65,TRAPSTART:66,TRAPEND:67,INVTRAPSTART:68,INVTRAPEND:69,linkStatement:70,arrowText:71,TESTSTR:72,START_LINK:73,edgeText:74,LINK:75,edgeTextToken:76,STR:77,MD_STR:78,textToken:79,keywords:80,STYLE:81,LINKSTYLE:82,CLASSDEF:83,CLASS:84,CLICK:85,DOWN:86,UP:87,textNoTagsToken:88,stylesOpt:89,"idString[vertex]":90,"idString[class]":91,CALLBACKNAME:92,CALLBACKARGS:93,HREF:94,LINK_TARGET:95,"STR[link]":96,"STR[tooltip]":97,alphaNum:98,DEFAULT:99,numList:100,INTERPOLATE:101,NUM:102,COMMA:103,style:104,styleComponent:105,NODE_STRING:106,UNIT:107,BRKT:108,PCT:109,idStringToken:110,MINUS:111,MULT:112,UNICODE_TEXT:113,TEXT:114,TAGSTART:115,EDGE_TEXT:116,alphaNumToken:117,direction_tb:118,direction_bt:119,direction_rl:120,direction_lr:121,$accept:0,$end:1},terminals_:{2:"error",8:"SEMI",9:"NEWLINE",10:"SPACE",11:"EOF",12:"GRAPH",13:"NODIR",14:"DIR",27:"subgraph",29:"SQS",31:"SQE",32:"end",34:"acc_title",35:"acc_title_value",36:"acc_descr",37:"acc_descr_value",38:"acc_descr_multiline_value",42:"AMP",44:"STYLE_SEPARATOR",46:"DOUBLECIRCLESTART",47:"DOUBLECIRCLEEND",48:"PS",49:"PE",50:"(-",51:"-)",52:"STADIUMSTART",53:"STADIUMEND",54:"SUBROUTINESTART",55:"SUBROUTINEEND",56:"VERTEX_WITH_PROPS_START",57:"NODE_STRING[field]",58:"COLON",59:"NODE_STRING[value]",60:"PIPE",61:"CYLINDERSTART",62:"CYLINDEREND",63:"DIAMOND_START",64:"DIAMOND_STOP",65:"TAGEND",66:"TRAPSTART",67:"TRAPEND",68:"INVTRAPSTART",69:"INVTRAPEND",72:"TESTSTR",73:"START_LINK",75:"LINK",77:"STR",78:"MD_STR",81:"STYLE",82:"LINKSTYLE",83:"CLASSDEF",84:"CLASS",85:"CLICK",86:"DOWN",87:"UP",90:"idString[vertex]",91:"idString[class]",92:"CALLBACKNAME",93:"CALLBACKARGS",94:"HREF",95:"LINK_TARGET",96:"STR[link]",97:"STR[tooltip]",99:"DEFAULT",101:"INTERPOLATE",102:"NUM",103:"COMMA",106:"NODE_STRING",107:"UNIT",108:"BRKT",109:"PCT",111:"MINUS",112:"MULT",113:"UNICODE_TEXT",114:"TEXT",115:"TAGSTART",116:"EDGE_TEXT",118:"direction_tb",119:"direction_bt",120:"direction_rl",121:"direction_lr"},productions_:[0,[3,2],[5,0],[5,2],[6,1],[6,1],[6,1],[6,1],[6,1],[4,2],[4,2],[4,2],[4,3],[16,2],[16,1],[17,1],[17,1],[17,1],[15,1],[15,1],[15,2],[19,2],[19,2],[19,1],[19,1],[18,2],[18,1],[7,2],[7,2],[7,2],[7,2],[7,2],[7,2],[7,9],[7,6],[7,4],[7,1],[7,2],[7,2],[7,1],[21,1],[21,1],[21,1],[20,3],[20,4],[20,2],[20,1],[40,1],[40,5],[41,1],[41,3],[43,4],[43,4],[43,6],[43,4],[43,4],[43,4],[43,8],[43,4],[43,4],[43,4],[43,6],[43,4],[43,4],[43,4],[43,4],[43,4],[43,1],[39,2],[39,3],[39,3],[39,1],[39,3],[74,1],[74,2],[74,1],[74,1],[70,1],[71,3],[30,1],[30,2],[30,1],[30,1],[80,1],[80,1],[80,1],[80,1],[80,1],[80,1],[80,1],[80,1],[80,1],[80,1],[80,1],[28,1],[28,2],[28,1],[28,1],[24,5],[25,5],[26,2],[26,4],[26,3],[26,5],[26,3],[26,5],[26,5],[26,7],[26,2],[26,4],[26,2],[26,4],[26,4],[26,6],[22,5],[23,5],[23,5],[23,9],[23,9],[23,7],[23,7],[100,1],[100,3],[89,1],[89,3],[104,1],[104,2],[105,1],[105,1],[105,1],[105,1],[105,1],[105,1],[105,1],[105,1],[110,1],[110,1],[110,1],[110,1],[110,1],[110,1],[110,1],[110,1],[110,1],[110,1],[110,1],[79,1],[79,1],[79,1],[79,1],[88,1],[88,1],[88,1],[88,1],[88,1],[88,1],[88,1],[88,1],[88,1],[88,1],[88,1],[76,1],[76,1],[117,1],[117,1],[117,1],[117,1],[117,1],[117,1],[117,1],[117,1],[117,1],[117,1],[117,1],[45,1],[45,2],[98,1],[98,2],[33,1],[33,1],[33,1],[33,1]],performAction:function(Qi,Ts,ka,xi,Yc,Ce,vp){var Be=Ce.length-1;switch(Yc){case 2:this.$=[];break;case 3:(!Array.isArray(Ce[Be])||Ce[Be].length>0)&&Ce[Be-1].push(Ce[Be]),this.$=Ce[Be-1];break;case 4:case 176:this.$=Ce[Be];break;case 11:xi.setDirection("TB"),this.$="TB";break;case 12:xi.setDirection(Ce[Be-1]),this.$=Ce[Be-1];break;case 27:this.$=Ce[Be-1].nodes;break;case 28:case 29:case 30:case 31:case 32:this.$=[];break;case 33:this.$=xi.addSubGraph(Ce[Be-6],Ce[Be-1],Ce[Be-4]);break;case 34:this.$=xi.addSubGraph(Ce[Be-3],Ce[Be-1],Ce[Be-3]);break;case 35:this.$=xi.addSubGraph(void 0,Ce[Be-1],void 0);break;case 37:this.$=Ce[Be].trim(),xi.setAccTitle(this.$);break;case 38:case 39:this.$=Ce[Be].trim(),xi.setAccDescription(this.$);break;case 43:xi.addLink(Ce[Be-2].stmt,Ce[Be],Ce[Be-1]),this.$={stmt:Ce[Be],nodes:Ce[Be].concat(Ce[Be-2].nodes)};break;case 44:xi.addLink(Ce[Be-3].stmt,Ce[Be-1],Ce[Be-2]),this.$={stmt:Ce[Be-1],nodes:Ce[Be-1].concat(Ce[Be-3].nodes)};break;case 45:this.$={stmt:Ce[Be-1],nodes:Ce[Be-1]};break;case 46:this.$={stmt:Ce[Be],nodes:Ce[Be]};break;case 47:this.$=[Ce[Be]];break;case 48:this.$=Ce[Be-4].concat(Ce[Be]);break;case 49:this.$=Ce[Be];break;case 50:this.$=Ce[Be-2],xi.setClass(Ce[Be-2],Ce[Be]);break;case 51:this.$=Ce[Be-3],xi.addVertex(Ce[Be-3],Ce[Be-1],"square");break;case 52:this.$=Ce[Be-3],xi.addVertex(Ce[Be-3],Ce[Be-1],"doublecircle");break;case 53:this.$=Ce[Be-5],xi.addVertex(Ce[Be-5],Ce[Be-2],"circle");break;case 54:this.$=Ce[Be-3],xi.addVertex(Ce[Be-3],Ce[Be-1],"ellipse");break;case 55:this.$=Ce[Be-3],xi.addVertex(Ce[Be-3],Ce[Be-1],"stadium");break;case 56:this.$=Ce[Be-3],xi.addVertex(Ce[Be-3],Ce[Be-1],"subroutine");break;case 57:this.$=Ce[Be-7],xi.addVertex(Ce[Be-7],Ce[Be-1],"rect",void 0,void 0,void 0,Object.fromEntries([[Ce[Be-5],Ce[Be-3]]]));break;case 58:this.$=Ce[Be-3],xi.addVertex(Ce[Be-3],Ce[Be-1],"cylinder");break;case 59:this.$=Ce[Be-3],xi.addVertex(Ce[Be-3],Ce[Be-1],"round");break;case 60:this.$=Ce[Be-3],xi.addVertex(Ce[Be-3],Ce[Be-1],"diamond");break;case 61:this.$=Ce[Be-5],xi.addVertex(Ce[Be-5],Ce[Be-2],"hexagon");break;case 62:this.$=Ce[Be-3],xi.addVertex(Ce[Be-3],Ce[Be-1],"odd");break;case 63:this.$=Ce[Be-3],xi.addVertex(Ce[Be-3],Ce[Be-1],"trapezoid");break;case 64:this.$=Ce[Be-3],xi.addVertex(Ce[Be-3],Ce[Be-1],"inv_trapezoid");break;case 65:this.$=Ce[Be-3],xi.addVertex(Ce[Be-3],Ce[Be-1],"lean_right");break;case 66:this.$=Ce[Be-3],xi.addVertex(Ce[Be-3],Ce[Be-1],"lean_left");break;case 67:this.$=Ce[Be],xi.addVertex(Ce[Be]);break;case 68:Ce[Be-1].text=Ce[Be],this.$=Ce[Be-1];break;case 69:case 70:Ce[Be-2].text=Ce[Be-1],this.$=Ce[Be-2];break;case 71:this.$=Ce[Be];break;case 72:var Bf=xi.destructLink(Ce[Be],Ce[Be-2]);this.$={type:Bf.type,stroke:Bf.stroke,length:Bf.length,text:Ce[Be-1]};break;case 73:this.$={text:Ce[Be],type:"text"};break;case 74:this.$={text:Ce[Be-1].text+""+Ce[Be],type:Ce[Be-1].type};break;case 75:this.$={text:Ce[Be],type:"string"};break;case 76:this.$={text:Ce[Be],type:"markdown"};break;case 77:var Bf=xi.destructLink(Ce[Be]);this.$={type:Bf.type,stroke:Bf.stroke,length:Bf.length};break;case 78:this.$=Ce[Be-1];break;case 79:this.$={text:Ce[Be],type:"text"};break;case 80:this.$={text:Ce[Be-1].text+""+Ce[Be],type:Ce[Be-1].type};break;case 81:this.$={text:Ce[Be],type:"string"};break;case 82:case 97:this.$={text:Ce[Be],type:"markdown"};break;case 94:this.$={text:Ce[Be],type:"text"};break;case 95:this.$={text:Ce[Be-1].text+""+Ce[Be],type:Ce[Be-1].type};break;case 96:this.$={text:Ce[Be],type:"text"};break;case 98:this.$=Ce[Be-4],xi.addClass(Ce[Be-2],Ce[Be]);break;case 99:this.$=Ce[Be-4],xi.setClass(Ce[Be-2],Ce[Be]);break;case 100:case 108:this.$=Ce[Be-1],xi.setClickEvent(Ce[Be-1],Ce[Be]);break;case 101:case 109:this.$=Ce[Be-3],xi.setClickEvent(Ce[Be-3],Ce[Be-2]),xi.setTooltip(Ce[Be-3],Ce[Be]);break;case 102:this.$=Ce[Be-2],xi.setClickEvent(Ce[Be-2],Ce[Be-1],Ce[Be]);break;case 103:this.$=Ce[Be-4],xi.setClickEvent(Ce[Be-4],Ce[Be-3],Ce[Be-2]),xi.setTooltip(Ce[Be-4],Ce[Be]);break;case 104:this.$=Ce[Be-2],xi.setLink(Ce[Be-2],Ce[Be]);break;case 105:this.$=Ce[Be-4],xi.setLink(Ce[Be-4],Ce[Be-2]),xi.setTooltip(Ce[Be-4],Ce[Be]);break;case 106:this.$=Ce[Be-4],xi.setLink(Ce[Be-4],Ce[Be-2],Ce[Be]);break;case 107:this.$=Ce[Be-6],xi.setLink(Ce[Be-6],Ce[Be-4],Ce[Be]),xi.setTooltip(Ce[Be-6],Ce[Be-2]);break;case 110:this.$=Ce[Be-1],xi.setLink(Ce[Be-1],Ce[Be]);break;case 111:this.$=Ce[Be-3],xi.setLink(Ce[Be-3],Ce[Be-2]),xi.setTooltip(Ce[Be-3],Ce[Be]);break;case 112:this.$=Ce[Be-3],xi.setLink(Ce[Be-3],Ce[Be-2],Ce[Be]);break;case 113:this.$=Ce[Be-5],xi.setLink(Ce[Be-5],Ce[Be-4],Ce[Be]),xi.setTooltip(Ce[Be-5],Ce[Be-2]);break;case 114:this.$=Ce[Be-4],xi.addVertex(Ce[Be-2],void 0,void 0,Ce[Be]);break;case 115:this.$=Ce[Be-4],xi.updateLink([Ce[Be-2]],Ce[Be]);break;case 116:this.$=Ce[Be-4],xi.updateLink(Ce[Be-2],Ce[Be]);break;case 117:this.$=Ce[Be-8],xi.updateLinkInterpolate([Ce[Be-6]],Ce[Be-2]),xi.updateLink([Ce[Be-6]],Ce[Be]);break;case 118:this.$=Ce[Be-8],xi.updateLinkInterpolate(Ce[Be-6],Ce[Be-2]),xi.updateLink(Ce[Be-6],Ce[Be]);break;case 119:this.$=Ce[Be-6],xi.updateLinkInterpolate([Ce[Be-4]],Ce[Be]);break;case 120:this.$=Ce[Be-6],xi.updateLinkInterpolate(Ce[Be-4],Ce[Be]);break;case 121:case 123:this.$=[Ce[Be]];break;case 122:case 124:Ce[Be-2].push(Ce[Be]),this.$=Ce[Be-2];break;case 126:this.$=Ce[Be-1]+Ce[Be];break;case 174:this.$=Ce[Be];break;case 175:this.$=Ce[Be-1]+""+Ce[Be];break;case 177:this.$=Ce[Be-1]+""+Ce[Be];break;case 178:this.$={stmt:"dir",value:"TB"};break;case 179:this.$={stmt:"dir",value:"BT"};break;case 180:this.$={stmt:"dir",value:"RL"};break;case 181:this.$={stmt:"dir",value:"LR"};break}},table:[{3:1,4:2,9:a,10:f,12:p},{1:[3]},i(w,m,{5:6}),{4:7,9:a,10:f,12:p},{4:8,9:a,10:f,12:p},{13:[1,9],14:[1,10]},{1:[2,1],6:11,7:12,8:b,9:E,10:_,11:A,20:17,22:18,23:19,24:20,25:21,26:22,27:I,33:24,34:B,36:N,38:R,40:28,41:38,42:z,43:39,45:40,58:W,81:et,82:st,83:at,84:bt,85:mt,86:yt,99:ft,102:ut,103:vt,106:X,108:pt,110:41,111:U,112:Tt,113:nt,118:It,119:Ot,120:Bt,121:Et},i(w,[2,9]),i(w,[2,10]),i(w,[2,11]),{8:[1,54],9:[1,55],10:Z,15:53,18:56},i(Ct,[2,3]),i(Ct,[2,4]),i(Ct,[2,5]),i(Ct,[2,6]),i(Ct,[2,7]),i(Ct,[2,8]),{8:xt,9:Ht,11:Le,21:58,39:59,70:63,73:[1,64],75:[1,65]},{8:xt,9:Ht,11:Le,21:66},{8:xt,9:Ht,11:Le,21:67},{8:xt,9:Ht,11:Le,21:68},{8:xt,9:Ht,11:Le,21:69},{8:xt,9:Ht,11:Le,21:70},{8:xt,9:Ht,10:[1,71],11:Le,21:72},i(Ct,[2,36]),{35:[1,73]},{37:[1,74]},i(Ct,[2,39]),i(Ft,[2,46],{18:75,10:Z}),{10:[1,76]},{10:[1,77]},{10:[1,78]},{10:[1,79]},{14:gn,42:Se,58:me,77:[1,83],86:Ve,92:[1,80],94:[1,81],98:82,102:Ye,103:ce,106:ke,108:zt,111:re,112:se,113:Pe,117:84},i(Ct,[2,178]),i(Ct,[2,179]),i(Ct,[2,180]),i(Ct,[2,181]),i(te,[2,47]),i(te,[2,49],{44:[1,96]}),i(Me,[2,67],{110:109,29:[1,97],42:z,46:[1,98],48:[1,99],50:[1,100],52:[1,101],54:[1,102],56:[1,103],58:W,61:[1,104],63:[1,105],65:[1,106],66:[1,107],68:[1,108],86:yt,99:ft,102:ut,103:vt,106:X,108:pt,111:U,112:Tt,113:nt}),i(de,[2,174]),i(de,[2,135]),i(de,[2,136]),i(de,[2,137]),i(de,[2,138]),i(de,[2,139]),i(de,[2,140]),i(de,[2,141]),i(de,[2,142]),i(de,[2,143]),i(de,[2,144]),i(de,[2,145]),i(w,[2,12]),i(w,[2,18]),i(w,[2,19]),{9:[1,110]},i(on,[2,26],{18:111,10:Z}),i(Ct,[2,27]),{40:112,41:38,42:z,43:39,45:40,58:W,86:yt,99:ft,102:ut,103:vt,106:X,108:pt,110:41,111:U,112:Tt,113:nt},i(Ct,[2,40]),i(Ct,[2,41]),i(Ct,[2,42]),i(ni,[2,71],{71:113,60:[1,115],72:[1,114]}),{74:116,76:117,77:[1,118],78:[1,119],113:Ks,116:ws},i([42,58,60,72,86,99,102,103,106,108,111,112,113],[2,77]),i(Ct,[2,28]),i(Ct,[2,29]),i(Ct,[2,30]),i(Ct,[2,31]),i(Ct,[2,32]),{10:fo,12:Xi,14:Er,27:Xn,28:122,32:di,42:Ee,58:Kn,73:He,77:[1,124],78:[1,125],80:135,81:Ti,82:pn,83:Es,84:qa,85:Ma,86:Gs,87:Po,88:123,102:vs,106:ru,108:zs,111:Du,112:pm,113:uw},i(Wu,m,{5:148}),i(Ct,[2,37]),i(Ct,[2,38]),i(Ft,[2,45],{42:th}),{42:z,45:150,58:W,86:yt,99:ft,102:ut,103:vt,106:X,108:pt,110:41,111:U,112:Tt,113:nt},{99:[1,151],100:152,102:[1,153]},{42:z,45:154,58:W,86:yt,99:ft,102:ut,103:vt,106:X,108:pt,110:41,111:U,112:Tt,113:nt},{42:z,45:155,58:W,86:yt,99:ft,102:ut,103:vt,106:X,108:pt,110:41,111:U,112:Tt,113:nt},i(Fa,[2,100],{10:[1,156],93:[1,157]}),{77:[1,158]},i(Fa,[2,108],{117:160,10:[1,159],14:gn,42:Se,58:me,86:Ve,102:Ye,103:ce,106:ke,108:zt,111:re,112:se,113:Pe}),i(Fa,[2,110],{10:[1,161]}),i(Ml,[2,176]),i(Ml,[2,163]),i(Ml,[2,164]),i(Ml,[2,165]),i(Ml,[2,166]),i(Ml,[2,167]),i(Ml,[2,168]),i(Ml,[2,169]),i(Ml,[2,170]),i(Ml,[2,171]),i(Ml,[2,172]),i(Ml,[2,173]),{42:z,45:162,58:W,86:yt,99:ft,102:ut,103:vt,106:X,108:pt,110:41,111:U,112:Tt,113:nt},{30:163,65:ha,77:bc,78:Cc,79:164,113:pa,114:Da,115:Ha},{30:171,65:ha,77:bc,78:Cc,79:164,113:pa,114:Da,115:Ha},{30:173,48:[1,172],65:ha,77:bc,78:Cc,79:164,113:pa,114:Da,115:Ha},{30:174,65:ha,77:bc,78:Cc,79:164,113:pa,114:Da,115:Ha},{30:175,65:ha,77:bc,78:Cc,79:164,113:pa,114:Da,115:Ha},{30:176,65:ha,77:bc,78:Cc,79:164,113:pa,114:Da,115:Ha},{106:[1,177]},{30:178,65:ha,77:bc,78:Cc,79:164,113:pa,114:Da,115:Ha},{30:179,63:[1,180],65:ha,77:bc,78:Cc,79:164,113:pa,114:Da,115:Ha},{30:181,65:ha,77:bc,78:Cc,79:164,113:pa,114:Da,115:Ha},{30:182,65:ha,77:bc,78:Cc,79:164,113:pa,114:Da,115:Ha},{30:183,65:ha,77:bc,78:Cc,79:164,113:pa,114:Da,115:Ha},i(de,[2,175]),i(w,[2,20]),i(on,[2,25]),i(Ft,[2,43],{18:184,10:Z}),i(ni,[2,68],{10:[1,185]}),{10:[1,186]},{30:187,65:ha,77:bc,78:Cc,79:164,113:pa,114:Da,115:Ha},{75:[1,188],76:189,113:Ks,116:ws},i(Dl,[2,73]),i(Dl,[2,75]),i(Dl,[2,76]),i(Dl,[2,161]),i(Dl,[2,162]),{8:xt,9:Ht,10:fo,11:Le,12:Xi,14:Er,21:191,27:Xn,29:[1,190],32:di,42:Ee,58:Kn,73:He,80:135,81:Ti,82:pn,83:Es,84:qa,85:Ma,86:Gs,87:Po,88:192,102:vs,106:ru,108:zs,111:Du,112:pm,113:uw},i(_c,[2,94]),i(_c,[2,96]),i(_c,[2,97]),i(_c,[2,150]),i(_c,[2,151]),i(_c,[2,152]),i(_c,[2,153]),i(_c,[2,154]),i(_c,[2,155]),i(_c,[2,156]),i(_c,[2,157]),i(_c,[2,158]),i(_c,[2,159]),i(_c,[2,160]),i(_c,[2,83]),i(_c,[2,84]),i(_c,[2,85]),i(_c,[2,86]),i(_c,[2,87]),i(_c,[2,88]),i(_c,[2,89]),i(_c,[2,90]),i(_c,[2,91]),i(_c,[2,92]),i(_c,[2,93]),{6:11,7:12,8:b,9:E,10:_,11:A,20:17,22:18,23:19,24:20,25:21,26:22,27:I,32:[1,193],33:24,34:B,36:N,38:R,40:28,41:38,42:z,43:39,45:40,58:W,81:et,82:st,83:at,84:bt,85:mt,86:yt,99:ft,102:ut,103:vt,106:X,108:pt,110:41,111:U,112:Tt,113:nt,118:It,119:Ot,120:Bt,121:Et},{10:Z,18:194},{10:[1,195],42:z,58:W,86:yt,99:ft,102:ut,103:vt,106:X,108:pt,110:109,111:U,112:Tt,113:nt},{10:[1,196]},{10:[1,197],103:[1,198]},i(lw,[2,121]),{10:[1,199],42:z,58:W,86:yt,99:ft,102:ut,103:vt,106:X,108:pt,110:109,111:U,112:Tt,113:nt},{10:[1,200],42:z,58:W,86:yt,99:ft,102:ut,103:vt,106:X,108:pt,110:109,111:U,112:Tt,113:nt},{77:[1,201]},i(Fa,[2,102],{10:[1,202]}),i(Fa,[2,104],{10:[1,203]}),{77:[1,204]},i(Ml,[2,177]),{77:[1,205],95:[1,206]},i(te,[2,50],{110:109,42:z,58:W,86:yt,99:ft,102:ut,103:vt,106:X,108:pt,111:U,112:Tt,113:nt}),{31:[1,207],65:ha,79:208,113:pa,114:Da,115:Ha},i(eh,[2,79]),i(eh,[2,81]),i(eh,[2,82]),i(eh,[2,146]),i(eh,[2,147]),i(eh,[2,148]),i(eh,[2,149]),{47:[1,209],65:ha,79:208,113:pa,114:Da,115:Ha},{30:210,65:ha,77:bc,78:Cc,79:164,113:pa,114:Da,115:Ha},{49:[1,211],65:ha,79:208,113:pa,114:Da,115:Ha},{51:[1,212],65:ha,79:208,113:pa,114:Da,115:Ha},{53:[1,213],65:ha,79:208,113:pa,114:Da,115:Ha},{55:[1,214],65:ha,79:208,113:pa,114:Da,115:Ha},{58:[1,215]},{62:[1,216],65:ha,79:208,113:pa,114:Da,115:Ha},{64:[1,217],65:ha,79:208,113:pa,114:Da,115:Ha},{30:218,65:ha,77:bc,78:Cc,79:164,113:pa,114:Da,115:Ha},{31:[1,219],65:ha,79:208,113:pa,114:Da,115:Ha},{65:ha,67:[1,220],69:[1,221],79:208,113:pa,114:Da,115:Ha},{65:ha,67:[1,223],69:[1,222],79:208,113:pa,114:Da,115:Ha},i(Ft,[2,44],{42:th}),i(ni,[2,70]),i(ni,[2,69]),{60:[1,224],65:ha,79:208,113:pa,114:Da,115:Ha},i(ni,[2,72]),i(Dl,[2,74]),{30:225,65:ha,77:bc,78:Cc,79:164,113:pa,114:Da,115:Ha},i(Wu,m,{5:226}),i(_c,[2,95]),i(Ct,[2,35]),{41:227,42:z,43:39,45:40,58:W,86:yt,99:ft,102:ut,103:vt,106:X,108:pt,110:41,111:U,112:Tt,113:nt},{10:ed,58:jd,81:nd,89:228,102:$d,104:229,105:230,106:A0,107:Bi,108:cn,109:kr},{10:ed,58:jd,81:nd,89:239,101:[1,240],102:$d,104:229,105:230,106:A0,107:Bi,108:cn,109:kr},{10:ed,58:jd,81:nd,89:241,101:[1,242],102:$d,104:229,105:230,106:A0,107:Bi,108:cn,109:kr},{102:[1,243]},{10:ed,58:jd,81:nd,89:244,102:$d,104:229,105:230,106:A0,107:Bi,108:cn,109:kr},{42:z,45:245,58:W,86:yt,99:ft,102:ut,103:vt,106:X,108:pt,110:41,111:U,112:Tt,113:nt},i(Fa,[2,101]),{77:[1,246]},{77:[1,247],95:[1,248]},i(Fa,[2,109]),i(Fa,[2,111],{10:[1,249]}),i(Fa,[2,112]),i(Me,[2,51]),i(eh,[2,80]),i(Me,[2,52]),{49:[1,250],65:ha,79:208,113:pa,114:Da,115:Ha},i(Me,[2,59]),i(Me,[2,54]),i(Me,[2,55]),i(Me,[2,56]),{106:[1,251]},i(Me,[2,58]),i(Me,[2,60]),{64:[1,252],65:ha,79:208,113:pa,114:Da,115:Ha},i(Me,[2,62]),i(Me,[2,63]),i(Me,[2,65]),i(Me,[2,64]),i(Me,[2,66]),i([10,42,58,86,99,102,103,106,108,111,112,113],[2,78]),{31:[1,253],65:ha,79:208,113:pa,114:Da,115:Ha},{6:11,7:12,8:b,9:E,10:_,11:A,20:17,22:18,23:19,24:20,25:21,26:22,27:I,32:[1,254],33:24,34:B,36:N,38:R,40:28,41:38,42:z,43:39,45:40,58:W,81:et,82:st,83:at,84:bt,85:mt,86:yt,99:ft,102:ut,103:vt,106:X,108:pt,110:41,111:U,112:Tt,113:nt,118:It,119:Ot,120:Bt,121:Et},i(te,[2,48]),i(Fa,[2,114],{103:Ei}),i(Jo,[2,123],{105:256,10:ed,58:jd,81:nd,102:$d,106:A0,107:Bi,108:cn,109:kr}),i(wc,[2,125]),i(wc,[2,127]),i(wc,[2,128]),i(wc,[2,129]),i(wc,[2,130]),i(wc,[2,131]),i(wc,[2,132]),i(wc,[2,133]),i(wc,[2,134]),i(Fa,[2,115],{103:Ei}),{10:[1,257]},i(Fa,[2,116],{103:Ei}),{10:[1,258]},i(lw,[2,122]),i(Fa,[2,98],{103:Ei}),i(Fa,[2,99],{110:109,42:z,58:W,86:yt,99:ft,102:ut,103:vt,106:X,108:pt,111:U,112:Tt,113:nt}),i(Fa,[2,103]),i(Fa,[2,105],{10:[1,259]}),i(Fa,[2,106]),{95:[1,260]},{49:[1,261]},{60:[1,262]},{64:[1,263]},{8:xt,9:Ht,11:Le,21:264},i(Ct,[2,34]),{10:ed,58:jd,81:nd,102:$d,104:265,105:230,106:A0,107:Bi,108:cn,109:kr},i(wc,[2,126]),{14:gn,42:Se,58:me,86:Ve,98:266,102:Ye,103:ce,106:ke,108:zt,111:re,112:se,113:Pe,117:84},{14:gn,42:Se,58:me,86:Ve,98:267,102:Ye,103:ce,106:ke,108:zt,111:re,112:se,113:Pe,117:84},{95:[1,268]},i(Fa,[2,113]),i(Me,[2,53]),{30:269,65:ha,77:bc,78:Cc,79:164,113:pa,114:Da,115:Ha},i(Me,[2,61]),i(Wu,m,{5:270}),i(Jo,[2,124],{105:256,10:ed,58:jd,81:nd,102:$d,106:A0,107:Bi,108:cn,109:kr}),i(Fa,[2,119],{117:160,10:[1,271],14:gn,42:Se,58:me,86:Ve,102:Ye,103:ce,106:ke,108:zt,111:re,112:se,113:Pe}),i(Fa,[2,120],{117:160,10:[1,272],14:gn,42:Se,58:me,86:Ve,102:Ye,103:ce,106:ke,108:zt,111:re,112:se,113:Pe}),i(Fa,[2,107]),{31:[1,273],65:ha,79:208,113:pa,114:Da,115:Ha},{6:11,7:12,8:b,9:E,10:_,11:A,20:17,22:18,23:19,24:20,25:21,26:22,27:I,32:[1,274],33:24,34:B,36:N,38:R,40:28,41:38,42:z,43:39,45:40,58:W,81:et,82:st,83:at,84:bt,85:mt,86:yt,99:ft,102:ut,103:vt,106:X,108:pt,110:41,111:U,112:Tt,113:nt,118:It,119:Ot,120:Bt,121:Et},{10:ed,58:jd,81:nd,89:275,102:$d,104:229,105:230,106:A0,107:Bi,108:cn,109:kr},{10:ed,58:jd,81:nd,89:276,102:$d,104:229,105:230,106:A0,107:Bi,108:cn,109:kr},i(Me,[2,57]),i(Ct,[2,33]),i(Fa,[2,117],{103:Ei}),i(Fa,[2,118],{103:Ei})],defaultActions:{},parseError:function(Qi,Ts){if(Ts.recoverable)this.trace(Qi);else{var ka=new Error(Qi);throw ka.hash=Ts,ka}},parse:function(Qi){var Ts=this,ka=[0],xi=[],Yc=[null],Ce=[],vp=this.table,Be="",Bf=0,yg=0,bm=2,Ek=1,E3=Ce.slice.call(arguments,1),Il=Object.create(this.lexer),L0={yy:{}};for(var hw in this.yy)Object.prototype.hasOwnProperty.call(this.yy,hw)&&(L0.yy[hw]=this.yy[hw]);Il.setInput(Qi,L0.yy),L0.yy.lexer=Il,L0.yy.parser=this,typeof Il.yylloc>"u"&&(Il.yylloc={});var H5=Il.yylloc;Ce.push(H5);var Hb=Il.options&&Il.options.ranges;typeof L0.yy.parseError=="function"?this.parseError=L0.yy.parseError:this.parseError=Object.getPrototypeOf(this).parseError;function V5(){var xg;return xg=xi.pop()||Il.lex()||Ek,typeof xg!="number"&&(xg instanceof Array&&(xi=xg,xg=xi.pop()),xg=Ts.symbols_[xg]||xg),xg}for(var f1,rd,id,G5,fw={},U5,mp,W5,T3;;){if(rd=ka[ka.length-1],this.defaultActions[rd]?id=this.defaultActions[rd]:((f1===null||typeof f1>"u")&&(f1=V5()),id=vp[rd]&&vp[rd][f1]),typeof id>"u"||!id.length||!id[0]){var wm="";T3=[];for(U5 in vp[rd])this.terminals_[U5]&&U5>bm&&T3.push("'"+this.terminals_[U5]+"'");Il.showPosition?wm="Parse error on line "+(Bf+1)+`: +`+Il.showPosition()+` +Expecting `+T3.join(", ")+", got '"+(this.terminals_[f1]||f1)+"'":wm="Parse error on line "+(Bf+1)+": Unexpected "+(f1==Ek?"end of input":"'"+(this.terminals_[f1]||f1)+"'"),this.parseError(wm,{text:Il.match,token:this.terminals_[f1]||f1,line:Il.yylineno,loc:H5,expected:T3})}if(id[0]instanceof Array&&id.length>1)throw new Error("Parse Error: multiple actions possible at state: "+rd+", token: "+f1);switch(id[0]){case 1:ka.push(f1),Yc.push(Il.yytext),Ce.push(Il.yylloc),ka.push(id[1]),f1=null,yg=Il.yyleng,Be=Il.yytext,Bf=Il.yylineno,H5=Il.yylloc;break;case 2:if(mp=this.productions_[id[1]][1],fw.$=Yc[Yc.length-mp],fw._$={first_line:Ce[Ce.length-(mp||1)].first_line,last_line:Ce[Ce.length-1].last_line,first_column:Ce[Ce.length-(mp||1)].first_column,last_column:Ce[Ce.length-1].last_column},Hb&&(fw._$.range=[Ce[Ce.length-(mp||1)].range[0],Ce[Ce.length-1].range[1]]),G5=this.performAction.apply(fw,[Be,yg,Bf,L0.yy,id[1],Yc,Ce].concat(E3)),typeof G5<"u")return G5;mp&&(ka=ka.slice(0,-1*mp*2),Yc=Yc.slice(0,-1*mp),Ce=Ce.slice(0,-1*mp)),ka.push(this.productions_[id[1]][0]),Yc.push(fw.$),Ce.push(fw._$),W5=vp[ka[ka.length-2]][ka[ka.length-1]],ka.push(W5);break;case 3:return!0}}return!0}},Oc=function(){var af={EOF:1,parseError:function(Ts,ka){if(this.yy.parser)this.yy.parser.parseError(Ts,ka);else throw new Error(Ts)},setInput:function(Qi,Ts){return this.yy=Ts||this.yy||{},this._input=Qi,this._more=this._backtrack=this.done=!1,this.yylineno=this.yyleng=0,this.yytext=this.matched=this.match="",this.conditionStack=["INITIAL"],this.yylloc={first_line:1,first_column:0,last_line:1,last_column:0},this.options.ranges&&(this.yylloc.range=[0,0]),this.offset=0,this},input:function(){var Qi=this._input[0];this.yytext+=Qi,this.yyleng++,this.offset++,this.match+=Qi,this.matched+=Qi;var Ts=Qi.match(/(?:\r\n?|\n).*/g);return Ts?(this.yylineno++,this.yylloc.last_line++):this.yylloc.last_column++,this.options.ranges&&this.yylloc.range[1]++,this._input=this._input.slice(1),Qi},unput:function(Qi){var Ts=Qi.length,ka=Qi.split(/(?:\r\n?|\n)/g);this._input=Qi+this._input,this.yytext=this.yytext.substr(0,this.yytext.length-Ts),this.offset-=Ts;var xi=this.match.split(/(?:\r\n?|\n)/g);this.match=this.match.substr(0,this.match.length-1),this.matched=this.matched.substr(0,this.matched.length-1),ka.length-1&&(this.yylineno-=ka.length-1);var Yc=this.yylloc.range;return this.yylloc={first_line:this.yylloc.first_line,last_line:this.yylineno+1,first_column:this.yylloc.first_column,last_column:ka?(ka.length===xi.length?this.yylloc.first_column:0)+xi[xi.length-ka.length].length-ka[0].length:this.yylloc.first_column-Ts},this.options.ranges&&(this.yylloc.range=[Yc[0],Yc[0]+this.yyleng-Ts]),this.yyleng=this.yytext.length,this},more:function(){return this._more=!0,this},reject:function(){if(this.options.backtrack_lexer)this._backtrack=!0;else return this.parseError("Lexical error on line "+(this.yylineno+1)+`. You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true). +`+this.showPosition(),{text:"",token:null,line:this.yylineno});return this},less:function(Qi){this.unput(this.match.slice(Qi))},pastInput:function(){var Qi=this.matched.substr(0,this.matched.length-this.match.length);return(Qi.length>20?"...":"")+Qi.substr(-20).replace(/\n/g,"")},upcomingInput:function(){var Qi=this.match;return Qi.length<20&&(Qi+=this._input.substr(0,20-Qi.length)),(Qi.substr(0,20)+(Qi.length>20?"...":"")).replace(/\n/g,"")},showPosition:function(){var Qi=this.pastInput(),Ts=new Array(Qi.length+1).join("-");return Qi+this.upcomingInput()+` +`+Ts+"^"},test_match:function(Qi,Ts){var ka,xi,Yc;if(this.options.backtrack_lexer&&(Yc={yylineno:this.yylineno,yylloc:{first_line:this.yylloc.first_line,last_line:this.last_line,first_column:this.yylloc.first_column,last_column:this.yylloc.last_column},yytext:this.yytext,match:this.match,matches:this.matches,matched:this.matched,yyleng:this.yyleng,offset:this.offset,_more:this._more,_input:this._input,yy:this.yy,conditionStack:this.conditionStack.slice(0),done:this.done},this.options.ranges&&(Yc.yylloc.range=this.yylloc.range.slice(0))),xi=Qi[0].match(/(?:\r\n?|\n).*/g),xi&&(this.yylineno+=xi.length),this.yylloc={first_line:this.yylloc.last_line,last_line:this.yylineno+1,first_column:this.yylloc.last_column,last_column:xi?xi[xi.length-1].length-xi[xi.length-1].match(/\r?\n?/)[0].length:this.yylloc.last_column+Qi[0].length},this.yytext+=Qi[0],this.match+=Qi[0],this.matches=Qi,this.yyleng=this.yytext.length,this.options.ranges&&(this.yylloc.range=[this.offset,this.offset+=this.yyleng]),this._more=!1,this._backtrack=!1,this._input=this._input.slice(Qi[0].length),this.matched+=Qi[0],ka=this.performAction.call(this,this.yy,this,Ts,this.conditionStack[this.conditionStack.length-1]),this.done&&this._input&&(this.done=!1),ka)return ka;if(this._backtrack){for(var Ce in Yc)this[Ce]=Yc[Ce];return!1}return!1},next:function(){if(this.done)return this.EOF;this._input||(this.done=!0);var Qi,Ts,ka,xi;this._more||(this.yytext="",this.match="");for(var Yc=this._currentRules(),Ce=0;CeTs[0].length)){if(Ts=ka,xi=Ce,this.options.backtrack_lexer){if(Qi=this.test_match(ka,Yc[Ce]),Qi!==!1)return Qi;if(this._backtrack){Ts=!1;continue}else return!1}else if(!this.options.flex)break}return Ts?(Qi=this.test_match(Ts,Yc[xi]),Qi!==!1?Qi:!1):this._input===""?this.EOF:this.parseError("Lexical error on line "+(this.yylineno+1)+`. Unrecognized text. +`+this.showPosition(),{text:"",token:null,line:this.yylineno})},lex:function(){var Ts=this.next();return Ts||this.lex()},begin:function(Ts){this.conditionStack.push(Ts)},popState:function(){var Ts=this.conditionStack.length-1;return Ts>0?this.conditionStack.pop():this.conditionStack[0]},_currentRules:function(){return this.conditionStack.length&&this.conditionStack[this.conditionStack.length-1]?this.conditions[this.conditionStack[this.conditionStack.length-1]].rules:this.conditions.INITIAL.rules},topState:function(Ts){return Ts=this.conditionStack.length-1-Math.abs(Ts||0),Ts>=0?this.conditionStack[Ts]:"INITIAL"},pushState:function(Ts){this.begin(Ts)},stateStackSize:function(){return this.conditionStack.length},options:{},performAction:function(Ts,ka,xi,Yc){switch(xi){case 0:return this.begin("acc_title"),34;case 1:return this.popState(),"acc_title_value";case 2:return this.begin("acc_descr"),36;case 3:return this.popState(),"acc_descr_value";case 4:this.begin("acc_descr_multiline");break;case 5:this.popState();break;case 6:return"acc_descr_multiline_value";case 7:this.begin("callbackname");break;case 8:this.popState();break;case 9:this.popState(),this.begin("callbackargs");break;case 10:return 92;case 11:this.popState();break;case 12:return 93;case 13:return"MD_STR";case 14:this.popState();break;case 15:this.begin("md_string");break;case 16:return"STR";case 17:this.popState();break;case 18:this.pushState("string");break;case 19:return 81;case 20:return 99;case 21:return 82;case 22:return 101;case 23:return 83;case 24:return 84;case 25:return 94;case 26:this.begin("click");break;case 27:this.popState();break;case 28:return 85;case 29:return Ts.lex.firstGraph()&&this.begin("dir"),12;case 30:return Ts.lex.firstGraph()&&this.begin("dir"),12;case 31:return Ts.lex.firstGraph()&&this.begin("dir"),12;case 32:return 27;case 33:return 32;case 34:return 95;case 35:return 95;case 36:return 95;case 37:return 95;case 38:return this.popState(),13;case 39:return this.popState(),14;case 40:return this.popState(),14;case 41:return this.popState(),14;case 42:return this.popState(),14;case 43:return this.popState(),14;case 44:return this.popState(),14;case 45:return this.popState(),14;case 46:return this.popState(),14;case 47:return this.popState(),14;case 48:return this.popState(),14;case 49:return 118;case 50:return 119;case 51:return 120;case 52:return 121;case 53:return 102;case 54:return 108;case 55:return 44;case 56:return 58;case 57:return 42;case 58:return 8;case 59:return 103;case 60:return 112;case 61:return this.popState(),75;case 62:return this.pushState("edgeText"),73;case 63:return 116;case 64:return this.popState(),75;case 65:return this.pushState("thickEdgeText"),73;case 66:return 116;case 67:return this.popState(),75;case 68:return this.pushState("dottedEdgeText"),73;case 69:return 116;case 70:return 75;case 71:return this.popState(),51;case 72:return"TEXT";case 73:return this.pushState("ellipseText"),50;case 74:return this.popState(),53;case 75:return this.pushState("text"),52;case 76:return this.popState(),55;case 77:return this.pushState("text"),54;case 78:return 56;case 79:return this.pushState("text"),65;case 80:return this.popState(),62;case 81:return this.pushState("text"),61;case 82:return this.popState(),47;case 83:return this.pushState("text"),46;case 84:return this.popState(),67;case 85:return this.popState(),69;case 86:return 114;case 87:return this.pushState("trapText"),66;case 88:return this.pushState("trapText"),68;case 89:return 115;case 90:return 65;case 91:return 87;case 92:return"SEP";case 93:return 86;case 94:return 112;case 95:return 108;case 96:return 42;case 97:return 106;case 98:return 111;case 99:return 113;case 100:return this.popState(),60;case 101:return this.pushState("text"),60;case 102:return this.popState(),49;case 103:return this.pushState("text"),48;case 104:return this.popState(),31;case 105:return this.pushState("text"),29;case 106:return this.popState(),64;case 107:return this.pushState("text"),63;case 108:return"TEXT";case 109:return"QUOTE";case 110:return 9;case 111:return 10;case 112:return 11}},rules:[/^(?:accTitle\s*:\s*)/,/^(?:(?!\n||)*[^\n]*)/,/^(?:accDescr\s*:\s*)/,/^(?:(?!\n||)*[^\n]*)/,/^(?:accDescr\s*\{\s*)/,/^(?:[\}])/,/^(?:[^\}]*)/,/^(?:call[\s]+)/,/^(?:\([\s]*\))/,/^(?:\()/,/^(?:[^(]*)/,/^(?:\))/,/^(?:[^)]*)/,/^(?:[^`"]+)/,/^(?:[`]["])/,/^(?:["][`])/,/^(?:[^"]+)/,/^(?:["])/,/^(?:["])/,/^(?:style\b)/,/^(?:default\b)/,/^(?:linkStyle\b)/,/^(?:interpolate\b)/,/^(?:classDef\b)/,/^(?:class\b)/,/^(?:href[\s])/,/^(?:click[\s]+)/,/^(?:[\s\n])/,/^(?:[^\s\n]*)/,/^(?:flowchart-elk\b)/,/^(?:graph\b)/,/^(?:flowchart\b)/,/^(?:subgraph\b)/,/^(?:end\b\s*)/,/^(?:_self\b)/,/^(?:_blank\b)/,/^(?:_parent\b)/,/^(?:_top\b)/,/^(?:(\r?\n)*\s*\n)/,/^(?:\s*LR\b)/,/^(?:\s*RL\b)/,/^(?:\s*TB\b)/,/^(?:\s*BT\b)/,/^(?:\s*TD\b)/,/^(?:\s*BR\b)/,/^(?:\s*<)/,/^(?:\s*>)/,/^(?:\s*\^)/,/^(?:\s*v\b)/,/^(?:.*direction\s+TB[^\n]*)/,/^(?:.*direction\s+BT[^\n]*)/,/^(?:.*direction\s+RL[^\n]*)/,/^(?:.*direction\s+LR[^\n]*)/,/^(?:[0-9]+)/,/^(?:#)/,/^(?::::)/,/^(?::)/,/^(?:&)/,/^(?:;)/,/^(?:,)/,/^(?:\*)/,/^(?:\s*[xo<]?--+[-xo>]\s*)/,/^(?:\s*[xo<]?--\s*)/,/^(?:[^-]|-(?!-)+)/,/^(?:\s*[xo<]?==+[=xo>]\s*)/,/^(?:\s*[xo<]?==\s*)/,/^(?:[^=]|=(?!))/,/^(?:\s*[xo<]?-?\.+-[xo>]?\s*)/,/^(?:\s*[xo<]?-\.\s*)/,/^(?:[^\.]|\.(?!))/,/^(?:\s*~~[\~]+\s*)/,/^(?:[-/\)][\)])/,/^(?:[^\(\)\[\]\{\}]|!\)+)/,/^(?:\(-)/,/^(?:\]\))/,/^(?:\(\[)/,/^(?:\]\])/,/^(?:\[\[)/,/^(?:\[\|)/,/^(?:>)/,/^(?:\)\])/,/^(?:\[\()/,/^(?:\)\)\))/,/^(?:\(\(\()/,/^(?:[\\(?=\])][\]])/,/^(?:\/(?=\])\])/,/^(?:\/(?!\])|\\(?!\])|[^\\\[\]\(\)\{\}\/]+)/,/^(?:\[\/)/,/^(?:\[\\)/,/^(?:<)/,/^(?:>)/,/^(?:\^)/,/^(?:\\\|)/,/^(?:v\b)/,/^(?:\*)/,/^(?:#)/,/^(?:&)/,/^(?:([A-Za-z0-9!"\#$%&'*+\.`?\\_\/]|-(?=[^\>\-\.])|(?!))+)/,/^(?:-)/,/^(?:[\u00AA\u00B5\u00BA\u00C0-\u00D6\u00D8-\u00F6]|[\u00F8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377]|[\u037A-\u037D\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5]|[\u03F7-\u0481\u048A-\u0527\u0531-\u0556\u0559\u0561-\u0587\u05D0-\u05EA]|[\u05F0-\u05F2\u0620-\u064A\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE]|[\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA]|[\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u08A0]|[\u08A2-\u08AC\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0977]|[\u0979-\u097F\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2]|[\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09F0\u09F1\u0A05-\u0A0A]|[\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39]|[\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8]|[\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0B05-\u0B0C]|[\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C]|[\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99]|[\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0]|[\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C33\u0C35-\u0C39\u0C3D]|[\u0C58\u0C59\u0C60\u0C61\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3]|[\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D05-\u0D0C\u0D0E-\u0D10]|[\u0D12-\u0D3A\u0D3D\u0D4E\u0D60\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1]|[\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E81]|[\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3]|[\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6]|[\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A]|[\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081]|[\u108E\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D]|[\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0]|[\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310]|[\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F4\u1401-\u166C]|[\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u1700-\u170C\u170E-\u1711]|[\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7]|[\u17DC\u1820-\u1877\u1880-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191C]|[\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19C1-\u19C7\u1A00-\u1A16]|[\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-\u1B4B\u1B83-\u1BA0\u1BAE\u1BAF]|[\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\u1CE9-\u1CEC]|[\u1CEE-\u1CF1\u1CF5\u1CF6\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D]|[\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D]|[\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3]|[\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F]|[\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128]|[\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2183\u2184]|[\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3]|[\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6]|[\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE]|[\u2DD0-\u2DD6\u2DD8-\u2DDE\u2E2F\u3005\u3006\u3031-\u3035\u303B\u303C]|[\u3041-\u3096\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D]|[\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FCC]|[\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B]|[\uA640-\uA66E\uA67F-\uA697\uA6A0-\uA6E5\uA717-\uA71F\uA722-\uA788]|[\uA78B-\uA78E\uA790-\uA793\uA7A0-\uA7AA\uA7F8-\uA801\uA803-\uA805]|[\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB]|[\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF\uAA00-\uAA28]|[\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA80-\uAAAF\uAAB1\uAAB5]|[\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4]|[\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E]|[\uABC0-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D]|[\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36]|[\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D]|[\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC]|[\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF]|[\uFFD2-\uFFD7\uFFDA-\uFFDC])/,/^(?:\|)/,/^(?:\|)/,/^(?:\))/,/^(?:\()/,/^(?:\])/,/^(?:\[)/,/^(?:(\}))/,/^(?:\{)/,/^(?:[^\[\]\(\)\{\}\|\"]+)/,/^(?:")/,/^(?:(\r?\n)+)/,/^(?:\s)/,/^(?:$)/],conditions:{callbackargs:{rules:[11,12,15,18,70,73,75,77,81,83,87,88,101,103,105,107],inclusive:!1},callbackname:{rules:[8,9,10,15,18,70,73,75,77,81,83,87,88,101,103,105,107],inclusive:!1},href:{rules:[15,18,70,73,75,77,81,83,87,88,101,103,105,107],inclusive:!1},click:{rules:[15,18,27,28,70,73,75,77,81,83,87,88,101,103,105,107],inclusive:!1},dottedEdgeText:{rules:[15,18,67,69,70,73,75,77,81,83,87,88,101,103,105,107],inclusive:!1},thickEdgeText:{rules:[15,18,64,66,70,73,75,77,81,83,87,88,101,103,105,107],inclusive:!1},edgeText:{rules:[15,18,61,63,70,73,75,77,81,83,87,88,101,103,105,107],inclusive:!1},trapText:{rules:[15,18,70,73,75,77,81,83,84,85,86,87,88,101,103,105,107],inclusive:!1},ellipseText:{rules:[15,18,70,71,72,73,75,77,81,83,87,88,101,103,105,107],inclusive:!1},text:{rules:[15,18,70,73,74,75,76,77,80,81,82,83,87,88,100,101,102,103,104,105,106,107,108],inclusive:!1},vertex:{rules:[15,18,70,73,75,77,81,83,87,88,101,103,105,107],inclusive:!1},dir:{rules:[15,18,38,39,40,41,42,43,44,45,46,47,48,70,73,75,77,81,83,87,88,101,103,105,107],inclusive:!1},acc_descr_multiline:{rules:[5,6,15,18,70,73,75,77,81,83,87,88,101,103,105,107],inclusive:!1},acc_descr:{rules:[3,15,18,70,73,75,77,81,83,87,88,101,103,105,107],inclusive:!1},acc_title:{rules:[1,15,18,70,73,75,77,81,83,87,88,101,103,105,107],inclusive:!1},md_string:{rules:[13,14,15,18,70,73,75,77,81,83,87,88,101,103,105,107],inclusive:!1},string:{rules:[15,16,17,18,70,73,75,77,81,83,87,88,101,103,105,107],inclusive:!1},INITIAL:{rules:[0,2,4,7,15,18,19,20,21,22,23,24,25,26,29,30,31,32,33,34,35,36,37,49,50,51,52,53,54,55,56,57,58,59,60,61,62,64,65,67,68,70,73,75,77,78,79,81,83,87,88,89,90,91,92,93,94,95,96,97,98,99,101,103,105,107,109,110,111,112],inclusive:!0}}};return af}();rf.lexer=Oc;function sf(){this.yy={}}return sf.prototype=rf,rf.Parser=sf,new sf}();qdt.parser=qdt;const Hdt=qdt,rIe="flowchart-";let APt=0,Vdt=Oe(),wl={},gk=[],eL={},M5=[],rY={},iY={},sY=0,Gdt=!0,iw,aY,oY=[];const cY=i=>Kr.sanitizeText(i,Vdt),fF=function(i){const a=Object.keys(wl);for(const f of a)if(wl[f].id===i)return wl[f].domId;return i},LPt=function(i,a,f,p,w,m,b={}){let E,_=i;_!==void 0&&_.trim().length!==0&&(wl[_]===void 0&&(wl[_]={id:_,labelType:"text",domId:rIe+_+"-"+APt,styles:[],classes:[]}),APt++,a!==void 0?(Vdt=Oe(),E=cY(a.text.trim()),wl[_].labelType=a.type,E[0]==='"'&&E[E.length-1]==='"'&&(E=E.substring(1,E.length-1)),wl[_].text=E):wl[_].text===void 0&&(wl[_].text=i),f!==void 0&&(wl[_].type=f),p!=null&&p.forEach(function(A){wl[_].styles.push(A)}),w!=null&&w.forEach(function(A){wl[_].classes.push(A)}),m!==void 0&&(wl[_].dir=m),wl[_].props===void 0?wl[_].props=b:b!==void 0&&Object.assign(wl[_].props,b))},MPt=function(i,a,f){const m={start:i,end:a,type:void 0,text:"",labelType:"text"};Ut.info("abc78 Got edge...",m);const b=f.text;if(b!==void 0&&(m.text=cY(b.text.trim()),m.text[0]==='"'&&m.text[m.text.length-1]==='"'&&(m.text=m.text.substring(1,m.text.length-1)),m.labelType=b.type),f!==void 0&&(m.type=f.type,m.stroke=f.stroke,m.length=f.length),(m==null?void 0:m.length)>10&&(m.length=10),gk.length<280)Ut.info("abc78 pushing edge..."),gk.push(m);else throw new Error("Too many edges")},DPt=function(i,a,f){Ut.info("addLink (abc78)",i,a,f);let p,w;for(p=0;p/)&&(iw="LR"),iw.match(/.*v/)&&(iw="TB"),iw==="TD"&&(iw="TB")},uY=function(i,a){i.split(",").forEach(function(f){let p=f;wl[p]!==void 0&&wl[p].classes.push(a),rY[p]!==void 0&&rY[p].classes.push(a)})},iIe=function(i,a){i.split(",").forEach(function(f){a!==void 0&&(iY[aY==="gen-1"?fF(f):f]=cY(a))})},sIe=function(i,a,f){let p=fF(i);if(Oe().securityLevel!=="loose"||a===void 0)return;let w=[];if(typeof f=="string"){w=f.split(/,(?=(?:(?:[^"]*"){2})*[^"]*$)/);for(let m=0;m")),w.classed("hover",!0)}).on("mouseout",function(){a.transition().duration(500).style("opacity",0),yr(this).classed("hover",!1)})};oY.push(VPt);const GPt=function(i="gen-1"){wl={},eL={},gk=[],oY=[VPt],M5=[],rY={},sY=0,iY={},Gdt=!0,aY=i,hg()},UPt=i=>{aY=i||"gen-2"},WPt=function(){return"fill:#ffa;stroke: #f66; stroke-width: 3px; stroke-dasharray: 5, 5;fill:#ffa;stroke: #666;"},YPt=function(i,a,f){let p=i.text.trim(),w=f.text;i===f&&f.text.match(/\s/)&&(p=void 0);function m(I){const B={boolean:{},number:{},string:{}},N=[];let R;return{nodeList:I.filter(function(W){const et=typeof W;return W.stmt&&W.stmt==="dir"?(R=W.value,!1):W.trim()===""?!1:et in B?B[et].hasOwnProperty(W)?!1:B[et][W]=!0:N.includes(W)?!1:N.push(W)}),dir:R}}let b=[];const{nodeList:E,dir:_}=m(b.concat.apply(b,a));if(b=E,aY==="gen-1")for(let I=0;I2e3)return;if(KPt[dF]=a,M5[a].id===i)return{result:!0,count:0};let p=0,w=1;for(;p=0){const b=XPt(i,m);if(b.result)return{result:!0,count:w+b.count};w=w+b.count}p=p+1}return{result:!1,count:w}},QPt=function(i){return KPt[i]},ZPt=function(){dF=-1,M5.length>0&&XPt("none",M5.length-1)},JPt=function(){return M5},tFt=()=>Gdt?(Gdt=!1,!0):!1,oIe=i=>{let a=i.trim(),f="arrow_open";switch(a[0]){case"<":f="arrow_point",a=a.slice(1);break;case"x":f="arrow_cross",a=a.slice(1);break;case"o":f="arrow_circle",a=a.slice(1);break}let p="normal";return a.includes("=")&&(p="thick"),a.includes(".")&&(p="dotted"),{type:f,stroke:p}},cIe=(i,a)=>{const f=a.length;let p=0;for(let w=0;w{const a=i.trim();let f=a.slice(0,-1),p="arrow_open";switch(a.slice(-1)){case"x":p="arrow_cross",a[0]==="x"&&(p="double_"+p,f=f.slice(1));break;case">":p="arrow_point",a[0]==="<"&&(p="double_"+p,f=f.slice(1));break;case"o":p="arrow_circle",a[0]==="o"&&(p="double_"+p,f=f.slice(1));break}let w="normal",m=f.length-1;f[0]==="="&&(w="thick"),f[0]==="~"&&(w="invisible");let b=cIe(".",f);return b&&(w="dotted",m=b),{type:p,stroke:w,length:m}},eFt=(i,a)=>{const f=uIe(i);let p;if(a){if(p=oIe(a),p.stroke!==f.stroke)return{type:"INVALID",stroke:"INVALID"};if(p.type==="arrow_open")p.type=f.type;else{if(p.type!==f.type)return{type:"INVALID",stroke:"INVALID"};p.type="double_"+p.type}return p.type==="double_arrow"&&(p.type="double_arrow_point"),p.length=f.length,p}return f},nFt=(i,a)=>{let f=!1;return i.forEach(p=>{p.nodes.indexOf(a)>=0&&(f=!0)}),f},rFt=(i,a)=>{const f=[];return i.nodes.forEach((p,w)=>{nFt(a,p)||f.push(i.nodes[w])}),{nodes:f}},iFt={firstGraph:tFt},wT={defaultConfig:()=>SOt.flowchart,setAccTitle:E0,getAccTitle:fg,getAccDescription:gg,setAccDescription:dg,addVertex:LPt,lookUpDomId:fF,addLink:DPt,updateLinkInterpolate:IPt,updateLink:OPt,addClass:PPt,setDirection:FPt,setClass:uY,setTooltip:iIe,getTooltip:BPt,setClickEvent:RPt,setLink:NPt,bindFunctions:jPt,getDirection:$Pt,getVertices:zPt,getEdges:qPt,getClasses:HPt,clear:GPt,setGen:UPt,defaultStyle:WPt,addSubGraph:YPt,getDepthFirstPos:QPt,indexNodes:ZPt,getSubGraphs:JPt,destructLink:eFt,lex:iFt,exists:nFt,makeUniq:rFt,setDiagramTitle:Nb,getDiagramTitle:pg},lIe=Object.freeze(Object.defineProperty({__proto__:null,addClass:PPt,addLink:DPt,addSingleLink:MPt,addSubGraph:YPt,addVertex:LPt,bindFunctions:jPt,clear:GPt,default:wT,defaultStyle:WPt,destructLink:eFt,firstGraph:tFt,getClasses:HPt,getDepthFirstPos:QPt,getDirection:$Pt,getEdges:qPt,getSubGraphs:JPt,getTooltip:BPt,getVertices:zPt,indexNodes:ZPt,lex:iFt,lookUpDomId:fF,setClass:uY,setClickEvent:RPt,setDirection:FPt,setGen:UPt,setLink:NPt,updateLink:OPt,updateLinkInterpolate:IPt},Symbol.toStringTag,{value:"Module"}));var hIe="[object Symbol]";function vT(i){return typeof i=="symbol"||f3(i)&&sT(i)==hIe}function nL(i,a){for(var f=-1,p=i==null?0:i.length,w=Array(p);++f-1}function Rb(i){return ck(i)?PIt(i):NOt(i)}var LIe=/\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,MIe=/^\w*$/;function Udt(i,a){if(If(i))return!1;var f=typeof i;return f=="number"||f=="symbol"||f=="boolean"||i==null||vT(i)?!0:MIe.test(i)||!LIe.test(i)||a!=null&&i in Object(a)}var DIe=500;function IIe(i){var a=jA(i,function(p){return f.size===DIe&&f.clear(),p}),f=a.cache;return a}var OIe=/[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g,PIe=/\\(\\)?/g,FIe=IIe(function(i){var a=[];return i.charCodeAt(0)===46&&a.push(""),i.replace(OIe,function(f,p,w,m){a.push(w?m.replace(PIe,"$1"):p||f)}),a});const NIe=FIe;function fFt(i){return i==null?"":oFt(i)}function hY(i,a){return If(i)?i:Udt(i,a)?[i]:NIe(fFt(i))}var BIe=1/0;function gF(i){if(typeof i=="string"||vT(i))return i;var a=i+"";return a=="0"&&1/i==-BIe?"-0":a}function fY(i,a){a=hY(a,i);for(var f=0,p=a.length;i!=null&&f0&&f(E)?a>1?dY(E,a-1,f,p,w):Wdt(w,E):p||(w[w.length]=E)}return w}function rL(i){var a=i==null?0:i.length;return a?dY(i,1):[]}function $Ie(i){return RIt(BIt(i,void 0,rL),i+"")}function zIe(i,a,f,p){var w=-1,m=i==null?0:i.length;for(p&&m&&(f=i[++w]);++wE))return!1;var A=m.get(i),I=m.get(a);if(A&&I)return A==a&&I==i;var B=-1,N=!0,R=f&pPe?new bF:void 0;for(m.set(i,a),m.set(a,i);++B2?a[2]:void 0;for(w&&nF(a[0],a[1],w)&&(p=1);++f-1?w[m?a[b]:b]:void 0}}var iFe=Math.max;function sFe(i,a,f){var p=i==null?0:i.length;if(!p)return-1;var w=f==null?0:EIe(f);return w<0&&(w=iFe(p+w,0)),hFt(i,pk(a),w)}var aFe=rFe(sFe);const e0t=aFe;function RFt(i,a){var f=-1,p=ck(i)?Array(i.length):[];return pY(i,function(w,m,b){p[++f]=a(w,m,b)}),p}function Ff(i,a){var f=If(i)?nL:RFt;return f(i,pk(a))}function oFe(i,a){return i==null?i:tdt(i,t0t(a),uT)}function cFe(i,a){return i&&Jdt(i,t0t(a))}function uFe(i,a){return i>a}var lFe=Object.prototype,hFe=lFe.hasOwnProperty;function fFe(i,a){return i!=null&&hFe.call(i,a)}function za(i,a){return i!=null&&PFt(i,a,fFe)}function dFe(i,a){return nL(a,function(f){return i[f]})}function I5(i){return i==null?[]:dFe(i,Rb(i))}function Jh(i){return i===void 0}function jFt(i,a){return ia||m&&b&&_&&!E&&!A||p&&b&&_||!f&&_||!w)return 1;if(!p&&!m&&!A&&i=E)return _;var A=f[p];return _*(A=="desc"?-1:1)}}return i.index-a.index}function mFe(i,a,f){a.length?a=nL(a,function(m){return If(m)?function(b){return fY(b,m.length===1?m[0]:m)}:m}):a=[lT];var p=-1;a=nL(a,SW(pk));var w=RFt(i,function(m,b,E){var _=nL(a,function(A){return A(m)});return{criteria:_,index:++p,value:m}});return bFe(w,function(m,b){return vFe(m,b,f)})}function yFe(i,a){return pFe(i,a,function(f,p){return FFt(i,p)})}var xFe=$Ie(function(i,a){return i==null?{}:yFe(i,a)});const vF=xFe;var kFe=Math.ceil,EFe=Math.max;function TFe(i,a,f,p){for(var w=-1,m=EFe(kFe((a-i)/(f||1)),0),b=Array(m);m--;)b[p?m:++w]=i,i+=f;return b}function CFe(i){return function(a,f,p){return p&&typeof p!="number"&&nF(a,f,p)&&(f=p=void 0),a=lY(a),f===void 0?(f=a,a=0):f=lY(f),p=p===void 0?a1&&nF(i,a[0],a[1])?a=[]:f>2&&nF(a[0],a[1],a[2])&&(a=[a[0]]),mFe(i,dY(a,1),[])});const yF=AFe;var LFe=1/0,MFe=KA&&1/Xdt(new KA([,-0]))[1]==LFe?function(i){return new KA(i)}:TIe;const DFe=MFe;var IFe=200;function OFe(i,a,f){var p=-1,w=AIe,m=i.length,b=!0,E=[],_=E;if(f)b=!1,w=eFe;else if(m>=IFe){var A=a?null:DFe(i);if(A)return Xdt(A);b=!1,w=_Ft,_=new bF}else _=a?[]:E;t:for(;++p1?w.setNode(m,f):w.setNode(m)}),this}setNode(a,f){return za(this._nodes,a)?(arguments.length>1&&(this._nodes[a]=f),this):(this._nodes[a]=arguments.length>1?f:this._defaultNodeLabelFn(a),this._isCompound&&(this._parent[a]=xT,this._children[a]={},this._children[xT][a]=!0),this._in[a]={},this._preds[a]={},this._out[a]={},this._sucs[a]={},++this._nodeCount,this)}node(a){return this._nodes[a]}hasNode(a){return za(this._nodes,a)}removeNode(a){var f=this;if(za(this._nodes,a)){var p=function(w){f.removeEdge(f._edgeObjs[w])};delete this._nodes[a],this._isCompound&&(this._removeFromParentsChildList(a),delete this._parent[a],cr(this.children(a),function(w){f.setParent(w)}),delete this._children[a]),cr(Rb(this._in[a]),p),delete this._in[a],delete this._preds[a],cr(Rb(this._out[a]),p),delete this._out[a],delete this._sucs[a],--this._nodeCount}return this}setParent(a,f){if(!this._isCompound)throw new Error("Cannot set parent in a non-compound graph");if(Jh(f))f=xT;else{f+="";for(var p=f;!Jh(p);p=this.parent(p))if(p===a)throw new Error("Setting "+f+" as parent of "+a+" would create a cycle");this.setNode(f)}return this.setNode(a),this._removeFromParentsChildList(a),this._parent[a]=f,this._children[f][a]=!0,this}_removeFromParentsChildList(a){delete this._children[this._parent[a]][a]}parent(a){if(this._isCompound){var f=this._parent[a];if(f!==xT)return f}}children(a){if(Jh(a)&&(a=xT),this._isCompound){var f=this._children[a];if(f)return Rb(f)}else{if(a===xT)return this.nodes();if(this.hasNode(a))return[]}}predecessors(a){var f=this._preds[a];if(f)return Rb(f)}successors(a){var f=this._sucs[a];if(f)return Rb(f)}neighbors(a){var f=this.predecessors(a);if(f)return FFe(f,this.successors(a))}isLeaf(a){var f;return this.isDirected()?f=this.successors(a):f=this.neighbors(a),f.length===0}filterNodes(a){var f=new this.constructor({directed:this._isDirected,multigraph:this._isMultigraph,compound:this._isCompound});f.setGraph(this.graph());var p=this;cr(this._nodes,function(b,E){a(E)&&f.setNode(E,b)}),cr(this._edgeObjs,function(b){f.hasNode(b.v)&&f.hasNode(b.w)&&f.setEdge(b,p.edge(b))});var w={};function m(b){var E=p.parent(b);return E===void 0||f.hasNode(E)?(w[b]=E,E):E in w?w[E]:m(E)}return this._isCompound&&cr(f.nodes(),function(b){f.setParent(b,m(b))}),f}setDefaultEdgeLabel(a){return BA(a)||(a=HA(a)),this._defaultEdgeLabelFn=a,this}edgeCount(){return this._edgeCount}edges(){return I5(this._edgeObjs)}setPath(a,f){var p=this,w=arguments;return mF(a,function(m,b){return w.length>1?p.setEdge(m,b,f):p.setEdge(m,b),b}),this}setEdge(){var a,f,p,w,m=!1,b=arguments[0];typeof b=="object"&&b!==null&&"v"in b?(a=b.v,f=b.w,p=b.name,arguments.length===2&&(w=arguments[1],m=!0)):(a=b,f=arguments[1],p=arguments[3],arguments.length>2&&(w=arguments[2],m=!0)),a=""+a,f=""+f,Jh(p)||(p=""+p);var E=xF(this._isDirected,a,f,p);if(za(this._edgeLabels,E))return m&&(this._edgeLabels[E]=w),this;if(!Jh(p)&&!this._isMultigraph)throw new Error("Cannot set a named edge when isMultigraph = false");this.setNode(a),this.setNode(f),this._edgeLabels[E]=m?w:this._defaultEdgeLabelFn(a,f,p);var _=$Fe(this._isDirected,a,f,p);return a=_.v,f=_.w,Object.freeze(_),this._edgeObjs[E]=_,zFt(this._preds[f],a),zFt(this._sucs[a],f),this._in[f][E]=_,this._out[a][E]=_,this._edgeCount++,this}edge(a,f,p){var w=arguments.length===1?i0t(this._isDirected,arguments[0]):xF(this._isDirected,a,f,p);return this._edgeLabels[w]}hasEdge(a,f,p){var w=arguments.length===1?i0t(this._isDirected,arguments[0]):xF(this._isDirected,a,f,p);return za(this._edgeLabels,w)}removeEdge(a,f,p){var w=arguments.length===1?i0t(this._isDirected,arguments[0]):xF(this._isDirected,a,f,p),m=this._edgeObjs[w];return m&&(a=m.v,f=m.w,delete this._edgeLabels[w],delete this._edgeObjs[w],qFt(this._preds[f],a),qFt(this._sucs[a],f),delete this._in[f][w],delete this._out[a][w],this._edgeCount--),this}inEdges(a,f){var p=this._in[a];if(p){var w=I5(p);return f?D5(w,function(m){return m.v===f}):w}}outEdges(a,f){var p=this._out[a];if(p){var w=I5(p);return f?D5(w,function(m){return m.w===f}):w}}nodeEdges(a,f){var p=this.inEdges(a,f);if(p)return p.concat(this.outEdges(a,f))}}c1.prototype._nodeCount=0,c1.prototype._edgeCount=0;function zFt(i,a){i[a]?i[a]++:i[a]=1}function qFt(i,a){--i[a]||delete i[a]}function xF(i,a,f,p){var w=""+a,m=""+f;if(!i&&w>m){var b=w;w=m,m=b}return w+$Ft+m+$Ft+(Jh(p)?jFe:p)}function $Fe(i,a,f,p){var w=""+a,m=""+f;if(!i&&w>m){var b=w;w=m,m=b}var E={v:w,w:m};return p&&(E.name=p),E}function i0t(i,a){return xF(i,a.v,a.w,a.name)}class zFe{constructor(){var a={};a._next=a._prev=a,this._sentinel=a}dequeue(){var a=this._sentinel,f=a._prev;if(f!==a)return HFt(f),f}enqueue(a){var f=this._sentinel;a._prev&&a._next&&HFt(a),a._next=f._next,f._next._prev=a,f._next=a,a._prev=f}toString(){for(var a=[],f=this._sentinel,p=f._prev;p!==f;)a.push(JSON.stringify(p,qFe)),p=p._prev;return"["+a.join(", ")+"]"}}function HFt(i){i._prev._next=i._next,i._next._prev=i._prev,delete i._next,delete i._prev}function qFe(i,a){if(i!=="_next"&&i!=="_prev")return a}var HFe=HA(1);function VFe(i,a){if(i.nodeCount()<=1)return[];var f=UFe(i,a||HFe),p=GFe(f.graph,f.buckets,f.zeroIdx);return rL(Ff(p,function(w){return i.outEdges(w.v,w.w)}))}function GFe(i,a,f){for(var p=[],w=a[a.length-1],m=a[0],b;i.nodeCount();){for(;b=m.dequeue();)s0t(i,a,f,b);for(;b=w.dequeue();)s0t(i,a,f,b);if(i.nodeCount()){for(var E=a.length-2;E>0;--E)if(b=a[E].dequeue(),b){p=p.concat(s0t(i,a,f,b,!0));break}}}return p}function s0t(i,a,f,p,w){var m=w?[]:void 0;return cr(i.inEdges(p.v),function(b){var E=i.edge(b),_=i.node(b.v);w&&m.push({v:b.v,w:b.w}),_.out-=E,a0t(a,f,_)}),cr(i.outEdges(p.v),function(b){var E=i.edge(b),_=b.w,A=i.node(_);A.in-=E,a0t(a,f,A)}),i.removeNode(p.v),m}function UFe(i,a){var f=new c1,p=0,w=0;cr(i.nodes(),function(E){f.setNode(E,{v:E,in:0,out:0})}),cr(i.edges(),function(E){var _=f.edge(E.v,E.w)||0,A=a(E),I=_+A;f.setEdge(E.v,E.w,I),w=Math.max(w,f.node(E.v).out+=A),p=Math.max(p,f.node(E.w).in+=A)});var m=yT(w+p+3).map(function(){return new zFe}),b=p+1;return cr(f.nodes(),function(E){a0t(m,b,f.node(E))}),{graph:f,buckets:m,zeroIdx:b}}function a0t(i,a,f){f.out?f.in?i[f.out-f.in+a].enqueue(f):i[i.length-1].enqueue(f):i[0].enqueue(f)}function WFe(i){var a=i.graph().acyclicer==="greedy"?VFe(i,f(i)):YFe(i);cr(a,function(p){var w=i.edge(p);i.removeEdge(p),w.forwardName=p.name,w.reversed=!0,i.setEdge(p.w,p.v,w,vY("rev"))});function f(p){return function(w){return p.edge(w).weight}}}function YFe(i){var a=[],f={},p={};function w(m){za(p,m)||(p[m]=!0,f[m]=!0,cr(i.outEdges(m),function(b){za(f,b.w)?a.push(b):w(b.w)}),delete f[m])}return cr(i.nodes(),w),a}function KFe(i){cr(i.edges(),function(a){var f=i.edge(a);if(f.reversed){i.removeEdge(a);var p=f.forwardName;delete f.reversed,delete f.forwardName,i.setEdge(a.w,a.v,f,p)}})}function sL(i,a,f,p){var w;do w=vY(p);while(i.hasNode(w));return f.dummy=a,i.setNode(w,f),w}function XFe(i){var a=new c1().setGraph(i.graph());return cr(i.nodes(),function(f){a.setNode(f,i.node(f))}),cr(i.edges(),function(f){var p=a.edge(f.v,f.w)||{weight:0,minlen:1},w=i.edge(f);a.setEdge(f.v,f.w,{weight:p.weight+w.weight,minlen:Math.max(p.minlen,w.minlen)})}),a}function VFt(i){var a=new c1({multigraph:i.isMultigraph()}).setGraph(i.graph());return cr(i.nodes(),function(f){i.children(f).length||a.setNode(f,i.node(f))}),cr(i.edges(),function(f){a.setEdge(f,i.edge(f))}),a}function GFt(i,a){var f=i.x,p=i.y,w=a.x-f,m=a.y-p,b=i.width/2,E=i.height/2;if(!w&&!m)throw new Error("Not possible to find intersection inside of the rectangle");var _,A;return Math.abs(m)*b>Math.abs(w)*E?(m<0&&(E=-E),_=E*w/m,A=E):(w<0&&(b=-b),_=b,A=b*m/w),{x:f+_,y:p+A}}function mY(i){var a=Ff(yT(WFt(i)+1),function(){return[]});return cr(i.nodes(),function(f){var p=i.node(f),w=p.rank;Jh(w)||(a[w][p.order]=f)}),a}function QFe(i){var a=wF(Ff(i.nodes(),function(f){return i.node(f).rank}));cr(i.nodes(),function(f){var p=i.node(f);za(p,"rank")&&(p.rank-=a)})}function ZFe(i){var a=wF(Ff(i.nodes(),function(m){return i.node(m).rank})),f=[];cr(i.nodes(),function(m){var b=i.node(m).rank-a;f[b]||(f[b]=[]),f[b].push(m)});var p=0,w=i.graph().nodeRankFactor;cr(f,function(m,b){Jh(m)&&b%w!==0?--p:p&&cr(m,function(E){i.node(E).rank+=p})})}function UFt(i,a,f,p){var w={width:0,height:0};return arguments.length>=4&&(w.rank=f,w.order=p),sL(i,"border",w,a)}function WFt(i){return mT(Ff(i.nodes(),function(a){var f=i.node(a).rank;if(!Jh(f))return f}))}function JFe(i,a){var f={lhs:[],rhs:[]};return cr(i,function(p){a(p)?f.lhs.push(p):f.rhs.push(p)}),f}function tNe(i,a){var f=NFt();try{return a()}finally{console.log(i+" time: "+(NFt()-f)+"ms")}}function eNe(i,a){return a()}function nNe(i){function a(f){var p=i.children(f),w=i.node(f);if(p.length&&cr(p,a),za(w,"minRank")){w.borderLeft=[],w.borderRight=[];for(var m=w.minRank,b=w.maxRank+1;mb.lim&&(E=b,_=!0);var A=D5(a.edges(),function(I){return _===sNt(i,i.node(I.v),E)&&_!==sNt(i,i.node(I.w),E)});return r0t(A,function(I){return kF(a,I)})}function iNt(i,a,f,p){var w=f.v,m=f.w;i.removeEdge(w,m),i.setEdge(p.v,p.w,{}),h0t(i),l0t(i,a),wNe(i,a)}function wNe(i,a){var f=e0t(i.nodes(),function(w){return!a.node(w).parent}),p=pNe(i,f);p=p.slice(1),cr(p,function(w){var m=i.node(w).parent,b=a.edge(w,m),E=!1;b||(b=a.edge(m,w),E=!0),a.node(w).rank=a.node(m).rank+(E?b.minlen:-b.minlen)})}function vNe(i,a,f){return i.hasEdge(a,f)}function sNt(i,a,f){return f.low<=a.lim&&a.lim<=f.lim}function mNe(i){switch(i.graph().ranker){case"network-simplex":aNt(i);break;case"tight-tree":xNe(i);break;case"longest-path":yNe(i);break;default:aNt(i)}}var yNe=u0t;function xNe(i){u0t(i),QFt(i)}function aNt(i){kT(i)}function kNe(i){var a=sL(i,"root",{},"_root"),f=ENe(i),p=mT(I5(f))-1,w=2*p+1;i.graph().nestingRoot=a,cr(i.edges(),function(b){i.edge(b).minlen*=w});var m=TNe(i)+1;cr(i.children(),function(b){oNt(i,a,w,m,p,f,b)}),i.graph().nodeRankFactor=w}function oNt(i,a,f,p,w,m,b){var E=i.children(b);if(!E.length){b!==a&&i.setEdge(a,b,{weight:0,minlen:f});return}var _=UFt(i,"_bt"),A=UFt(i,"_bb"),I=i.node(b);i.setParent(_,b),I.borderTop=_,i.setParent(A,b),I.borderBottom=A,cr(E,function(B){oNt(i,a,f,p,w,m,B);var N=i.node(B),R=N.borderTop?N.borderTop:B,z=N.borderBottom?N.borderBottom:B,W=N.borderTop?p:2*p,et=R!==z?1:w-m[b]+1;i.setEdge(_,R,{weight:W,minlen:et,nestingEdge:!0}),i.setEdge(z,A,{weight:W,minlen:et,nestingEdge:!0})}),i.parent(b)||i.setEdge(a,_,{weight:0,minlen:w+m[b]})}function ENe(i){var a={};function f(p,w){var m=i.children(p);m&&m.length&&cr(m,function(b){f(b,w+1)}),a[p]=w}return cr(i.children(),function(p){f(p,1)}),a}function TNe(i){return mF(i.edges(),function(a,f){return a+i.edge(f).weight},0)}function CNe(i){var a=i.graph();i.removeNode(a.nestingRoot),delete a.nestingRoot,cr(i.edges(),function(f){var p=i.edge(f);p.nestingEdge&&i.removeEdge(f)})}function _Ne(i,a,f){var p={},w;cr(f,function(m){for(var b=i.parent(m),E,_;b;){if(E=i.parent(b),E?(_=p[E],p[E]=b):(_=w,w=b),_&&_!==b){a.setEdge(_,b);return}b=E}})}function SNe(i,a,f){var p=ANe(i),w=new c1({compound:!0}).setGraph({root:p}).setDefaultNodeLabel(function(m){return i.node(m)});return cr(i.nodes(),function(m){var b=i.node(m),E=i.parent(m);(b.rank===a||b.minRank<=a&&a<=b.maxRank)&&(w.setNode(m),w.setParent(m,E||p),cr(i[f](m),function(_){var A=_.v===m?_.w:_.v,I=w.edge(A,m),B=Jh(I)?0:I.weight;w.setEdge(A,m,{weight:i.edge(_).weight+B})}),za(b,"minRank")&&w.setNode(m,{borderLeft:b.borderLeft[a],borderRight:b.borderRight[a]}))}),w}function ANe(i){for(var a;i.hasNode(a=vY("_root")););return a}function LNe(i,a){for(var f=0,p=1;p0;)I%2&&(B+=E[I+1]),I=I-1>>1,E[I]+=A.weight;_+=A.weight*B})),_}function DNe(i){var a={},f=D5(i.nodes(),function(E){return!i.children(E).length}),p=mT(Ff(f,function(E){return i.node(E).rank})),w=Ff(yT(p+1),function(){return[]});function m(E){if(!za(a,E)){a[E]=!0;var _=i.node(E);w[_.rank].push(E),cr(i.successors(E),m)}}var b=yF(f,function(E){return i.node(E).rank});return cr(b,m),w}function INe(i,a){return Ff(a,function(f){var p=i.inEdges(f);if(p.length){var w=mF(p,function(m,b){var E=i.edge(b),_=i.node(b.v);return{sum:m.sum+E.weight*_.order,weight:m.weight+E.weight}},{sum:0,weight:0});return{v:f,barycenter:w.sum/w.weight,weight:w.weight}}else return{v:f}})}function ONe(i,a){var f={};cr(i,function(w,m){var b=f[w.v]={indegree:0,in:[],out:[],vs:[w.v],i:m};Jh(w.barycenter)||(b.barycenter=w.barycenter,b.weight=w.weight)}),cr(a.edges(),function(w){var m=f[w.v],b=f[w.w];!Jh(m)&&!Jh(b)&&(b.indegree++,m.out.push(f[w.w]))});var p=D5(f,function(w){return!w.indegree});return PNe(p)}function PNe(i){var a=[];function f(m){return function(b){b.merged||(Jh(b.barycenter)||Jh(m.barycenter)||b.barycenter>=m.barycenter)&&FNe(m,b)}}function p(m){return function(b){b.in.push(m),--b.indegree===0&&i.push(b)}}for(;i.length;){var w=i.pop();a.push(w),cr(w.in.reverse(),f(w)),cr(w.out,p(w))}return Ff(D5(a,function(m){return!m.merged}),function(m){return vF(m,["vs","i","barycenter","weight"])})}function FNe(i,a){var f=0,p=0;i.weight&&(f+=i.barycenter*i.weight,p+=i.weight),a.weight&&(f+=a.barycenter*a.weight,p+=a.weight),i.vs=a.vs.concat(i.vs),i.barycenter=f/p,i.weight=p,i.i=Math.min(a.i,i.i),a.merged=!0}function NNe(i,a){var f=JFe(i,function(I){return za(I,"barycenter")}),p=f.lhs,w=yF(f.rhs,function(I){return-I.i}),m=[],b=0,E=0,_=0;p.sort(BNe(!!a)),_=cNt(m,w,_),cr(p,function(I){_+=I.vs.length,m.push(I.vs),b+=I.barycenter*I.weight,E+=I.weight,_=cNt(m,w,_)});var A={vs:rL(m)};return E&&(A.barycenter=b/E,A.weight=E),A}function cNt(i,a,f){for(var p;a.length&&(p=bY(a)).i<=f;)a.pop(),i.push(p.vs),f++;return f}function BNe(i){return function(a,f){return a.barycenterf.barycenter?1:i?f.i-a.i:a.i-f.i}}function uNt(i,a,f,p){var w=i.children(a),m=i.node(a),b=m?m.borderLeft:void 0,E=m?m.borderRight:void 0,_={};b&&(w=D5(w,function(z){return z!==b&&z!==E}));var A=INe(i,w);cr(A,function(z){if(i.children(z.v).length){var W=uNt(i,z.v,f,p);_[z.v]=W,za(W,"barycenter")&&jNe(z,W)}});var I=ONe(A,f);RNe(I,_);var B=NNe(I,p);if(b&&(B.vs=rL([b,B.vs,E]),i.predecessors(b).length)){var N=i.node(i.predecessors(b)[0]),R=i.node(i.predecessors(E)[0]);za(B,"barycenter")||(B.barycenter=0,B.weight=0),B.barycenter=(B.barycenter*B.weight+N.order+R.order)/(B.weight+2),B.weight+=2}return B}function RNe(i,a){cr(i,function(f){f.vs=rL(f.vs.map(function(p){return a[p]?a[p].vs:p}))})}function jNe(i,a){Jh(i.barycenter)?(i.barycenter=a.barycenter,i.weight=a.weight):(i.barycenter=(i.barycenter*i.weight+a.barycenter*a.weight)/(i.weight+a.weight),i.weight+=a.weight)}function $Ne(i){var a=WFt(i),f=lNt(i,yT(1,a+1),"inEdges"),p=lNt(i,yT(a-1,-1,-1),"outEdges"),w=DNe(i);hNt(i,w);for(var m=Number.POSITIVE_INFINITY,b,E=0,_=0;_<4;++E,++_){zNe(E%2?f:p,E%4>=2),w=mY(i);var A=LNe(i,w);Ab||E>a[_].lim));for(A=_,_=p;(_=i.parent(_))!==A;)m.push(_);return{path:w.concat(m.reverse()),lca:A}}function VNe(i){var a={},f=0;function p(w){var m=f;cr(i.children(w),p),a[w]={low:m,lim:f++}}return cr(i.children(),p),a}function GNe(i,a){var f={};function p(w,m){var b=0,E=0,_=w.length,A=bY(m);return cr(m,function(I,B){var N=WNe(i,I),R=N?i.node(N).order:_;(N||I===A)&&(cr(m.slice(E,B+1),function(z){cr(i.predecessors(z),function(W){var et=i.node(W),st=et.order;(stA)&&fNt(f,N,I)})})}function w(m,b){var E=-1,_,A=0;return cr(b,function(I,B){if(i.node(I).dummy==="border"){var N=i.predecessors(I);N.length&&(_=i.node(N[0]).order,p(b,A,B,E,_),A=B,E=_)}p(b,A,b.length,_,m.length)}),b}return mF(a,w),f}function WNe(i,a){if(i.node(a).dummy)return e0t(i.predecessors(a),function(f){return i.node(f).dummy})}function fNt(i,a,f){if(a>f){var p=a;a=f,f=p}var w=i[a];w||(i[a]=w={}),w[f]=!0}function YNe(i,a,f){if(a>f){var p=a;a=f,f=p}return za(i[a],f)}function KNe(i,a,f,p){var w={},m={},b={};return cr(a,function(E){cr(E,function(_,A){w[_]=_,m[_]=_,b[_]=A})}),cr(a,function(E){var _=-1;cr(E,function(A){var I=p(A);if(I.length){I=yF(I,function(W){return b[W]});for(var B=(I.length-1)/2,N=Math.floor(B),R=Math.ceil(B);N<=R;++N){var z=I[N];m[A]===A&&_0}function v3(i,a,f){var p=i.x,w=i.y,m=[],b=Number.POSITIVE_INFINITY,E=Number.POSITIVE_INFINITY;a.forEach(function(z){b=Math.min(b,z.x),E=Math.min(E,z.y)});for(var _=p-i.width/2-b,A=w-i.height/2-E,I=0;I1&&m.sort(function(z,W){var et=z.x-f.x,st=z.y-f.y,at=Math.sqrt(et*et+st*st),bt=W.x-f.x,mt=W.y-f.y,yt=Math.sqrt(bt*bt+mt*mt);return atMath.abs(w)*E?(m<0&&(E=-E),_=m===0?0:E*w/m,A=E):(w<0&&(b=-b),_=b,A=w===0?0:b*m/w),{x:f+_,y:p+A}}var E0t={rect:ZBe,ellipse:JBe,circle:tRe,diamond:eRe};function QBe(i){E0t=i}function ZBe(i,a,f){var p=i.insert("rect",":first-child").attr("rx",f.rx).attr("ry",f.ry).attr("x",-a.width/2).attr("y",-a.height/2).attr("width",a.width).attr("height",a.height);return f.intersect=function(w){return k0t(f,w)},p}function JBe(i,a,f){var p=a.width/2,w=a.height/2,m=i.insert("ellipse",":first-child").attr("x",-a.width/2).attr("y",-a.height/2).attr("rx",p).attr("ry",w);return f.intersect=function(b){return vNt(f,p,w,b)},m}function tRe(i,a,f){var p=Math.max(a.width,a.height)/2,w=i.insert("circle",":first-child").attr("x",-a.width/2).attr("y",-a.height/2).attr("r",p);return f.intersect=function(m){return KBe(f,p,m)},w}function eRe(i,a,f){var p=a.width*Math.SQRT2/2,w=a.height*Math.SQRT2/2,m=[{x:0,y:-w},{x:-p,y:0},{x:0,y:w},{x:p,y:0}],b=i.insert("polygon",":first-child").attr("points",m.map(function(E){return E.x+","+E.y}).join(" "));return f.intersect=function(E){return v3(f,m,E)},b}function nRe(){var i=function(a,f){sRe(f);var p=EF(a,"output"),w=EF(p,"clusters"),m=EF(p,"edgePaths"),b=m0t(EF(p,"edgeLabels"),f),E=x0t(EF(p,"nodes"),f,E0t);aL(f),YBe(E,f),WBe(b,f),y0t(m,f,p0t);var _=v0t(w,f);UBe(_,f),aRe(f)};return i.createNodes=function(a){return arguments.length?(GBe(a),i):x0t},i.createClusters=function(a){return arguments.length?(BBe(a),i):v0t},i.createEdgeLabels=function(a){return arguments.length?(RBe(a),i):m0t},i.createEdgePaths=function(a){return arguments.length?(jBe(a),i):y0t},i.shapes=function(a){return arguments.length?(QBe(a),i):E0t},i.arrows=function(a){return arguments.length?(MBe(a),i):p0t},i}var rRe={paddingLeft:10,paddingRight:10,paddingTop:10,paddingBottom:10,rx:0,ry:0,shape:"rect"},iRe={arrowhead:"normal",curve:cg};function sRe(i){i.nodes().forEach(function(a){var f=i.node(a);!za(f,"label")&&!i.children(a).length&&(f.label=a),za(f,"paddingX")&&iL(f,{paddingLeft:f.paddingX,paddingRight:f.paddingX}),za(f,"paddingY")&&iL(f,{paddingTop:f.paddingY,paddingBottom:f.paddingY}),za(f,"padding")&&iL(f,{paddingLeft:f.padding,paddingRight:f.padding,paddingTop:f.padding,paddingBottom:f.padding}),iL(f,rRe),cr(["paddingLeft","paddingRight","paddingTop","paddingBottom"],function(p){f[p]=Number(f[p])}),za(f,"width")&&(f._prevWidth=f.width),za(f,"height")&&(f._prevHeight=f.height)}),i.edges().forEach(function(a){var f=i.edge(a);za(f,"label")||(f.label=""),iL(f,iRe)})}function aRe(i){cr(i.nodes(),function(a){var f=i.node(a);za(f,"_prevWidth")?f.width=f._prevWidth:delete f.width,za(f,"_prevHeight")?f.height=f._prevHeight:delete f.height,delete f._prevWidth,delete f._prevHeight})}function EF(i,a){var f=i.select("g."+a);return f.empty()&&(f=i.append("g").attr("class",a)),f}function yNt(i,a,f){const p=a.width,w=a.height,m=(p+w)*.9,b=[{x:m/2,y:0},{x:m,y:-m/2},{x:m/2,y:-m},{x:0,y:-m/2}],E=O5(i,m,m,b);return f.intersect=function(_){return v3(f,b,_)},E}function xNt(i,a,f){const w=a.height,m=w/4,b=a.width+2*m,E=[{x:m,y:0},{x:b-m,y:0},{x:b,y:-w/2},{x:b-m,y:-w},{x:m,y:-w},{x:0,y:-w/2}],_=O5(i,b,w,E);return f.intersect=function(A){return v3(f,E,A)},_}function kNt(i,a,f){const p=a.width,w=a.height,m=[{x:-w/2,y:0},{x:p,y:0},{x:p,y:-w},{x:-w/2,y:-w},{x:0,y:-w/2}],b=O5(i,p,w,m);return f.intersect=function(E){return v3(f,m,E)},b}function ENt(i,a,f){const p=a.width,w=a.height,m=[{x:-2*w/6,y:0},{x:p-w/6,y:0},{x:p+2*w/6,y:-w},{x:w/6,y:-w}],b=O5(i,p,w,m);return f.intersect=function(E){return v3(f,m,E)},b}function TNt(i,a,f){const p=a.width,w=a.height,m=[{x:2*w/6,y:0},{x:p+w/6,y:0},{x:p-2*w/6,y:-w},{x:-w/6,y:-w}],b=O5(i,p,w,m);return f.intersect=function(E){return v3(f,m,E)},b}function CNt(i,a,f){const p=a.width,w=a.height,m=[{x:-2*w/6,y:0},{x:p+2*w/6,y:0},{x:p-w/6,y:-w},{x:w/6,y:-w}],b=O5(i,p,w,m);return f.intersect=function(E){return v3(f,m,E)},b}function _Nt(i,a,f){const p=a.width,w=a.height,m=[{x:w/6,y:0},{x:p-w/6,y:0},{x:p+2*w/6,y:-w},{x:-2*w/6,y:-w}],b=O5(i,p,w,m);return f.intersect=function(E){return v3(f,m,E)},b}function SNt(i,a,f){const p=a.width,w=a.height,m=[{x:0,y:0},{x:p+w/2,y:0},{x:p,y:-w/2},{x:p+w/2,y:-w},{x:0,y:-w}],b=O5(i,p,w,m);return f.intersect=function(E){return v3(f,m,E)},b}function ANt(i,a,f){const p=a.height,w=a.width+p/4,m=i.insert("rect",":first-child").attr("rx",p/2).attr("ry",p/2).attr("x",-w/2).attr("y",-p/2).attr("width",w).attr("height",p);return f.intersect=function(b){return k0t(f,b)},m}function LNt(i,a,f){const p=a.width,w=a.height,m=[{x:0,y:0},{x:p,y:0},{x:p,y:-w},{x:0,y:-w},{x:0,y:0},{x:-8,y:0},{x:p+8,y:0},{x:p+8,y:-w},{x:-8,y:-w},{x:-8,y:0}],b=O5(i,p,w,m);return f.intersect=function(E){return v3(f,m,E)},b}function MNt(i,a,f){const p=a.width,w=p/2,m=w/(2.5+p/50),b=a.height+m,E="M 0,"+m+" a "+w+","+m+" 0,0,0 "+p+" 0 a "+w+","+m+" 0,0,0 "+-p+" 0 l 0,"+b+" a "+w+","+m+" 0,0,0 "+p+" 0 l 0,"+-b,_=i.attr("label-offset-y",m).insert("path",":first-child").attr("d",E).attr("transform","translate("+-p/2+","+-(b/2+m)+")");return f.intersect=function(A){const I=k0t(f,A),B=I.x-f.x;if(w!=0&&(Math.abs(B)f.height/2-m)){let N=m*m*(1-B*B/(w*w));N!=0&&(N=Math.sqrt(N)),N=m-N,A.y-f.y>0&&(N=-N),I.y+=N}return I},_}function oRe(i){i.shapes().question=yNt,i.shapes().hexagon=xNt,i.shapes().stadium=ANt,i.shapes().subroutine=LNt,i.shapes().cylinder=MNt,i.shapes().rect_left_inv_arrow=kNt,i.shapes().lean_right=ENt,i.shapes().lean_left=TNt,i.shapes().trapezoid=CNt,i.shapes().inv_trapezoid=_Nt,i.shapes().rect_right_inv_arrow=SNt}function cRe(i){i({question:yNt}),i({hexagon:xNt}),i({stadium:ANt}),i({subroutine:LNt}),i({cylinder:MNt}),i({rect_left_inv_arrow:kNt}),i({lean_right:ENt}),i({lean_left:TNt}),i({trapezoid:CNt}),i({inv_trapezoid:_Nt}),i({rect_right_inv_arrow:SNt})}function O5(i,a,f,p){return i.insert("polygon",":first-child").attr("points",p.map(function(w){return w.x+","+w.y}).join(" ")).attr("transform","translate("+-a/2+","+f/2+")")}const uRe={addToRender:oRe,addToRenderV2:cRe},DNt={},lRe=function(i){const a=Object.keys(i);for(const f of a)DNt[f]=i[f]},INt=function(i,a,f,p,w,m){const b=p?p.select(`[id="${f}"]`):yr(`[id="${f}"]`),E=w||document;Object.keys(i).forEach(function(A){const I=i[A];let B="default";I.classes.length>0&&(B=I.classes.join(" "));const N=im(I.styles);let R=I.text!==void 0?I.text:I.id,z;if(o1(Oe().flowchart.htmlLabels)){const st={label:R.replace(/fa[blrs]?:fa-[\w-]+/g,at=>``)};z=b0t(b,st).node(),z.parentNode.removeChild(z)}else{const st=E.createElementNS("http://www.w3.org/2000/svg","text");st.setAttribute("style",N.labelStyle.replace("color:","fill:"));const at=R.split(Kr.lineBreakRegex);for(const bt of at){const mt=E.createElementNS("http://www.w3.org/2000/svg","tspan");mt.setAttributeNS("http://www.w3.org/XML/1998/namespace","xml:space","preserve"),mt.setAttribute("dy","1em"),mt.setAttribute("x","1"),mt.textContent=bt,st.appendChild(mt)}z=st}let W=0,et="";switch(I.type){case"round":W=5,et="rect";break;case"square":et="rect";break;case"diamond":et="question";break;case"hexagon":et="hexagon";break;case"odd":et="rect_left_inv_arrow";break;case"lean_right":et="lean_right";break;case"lean_left":et="lean_left";break;case"trapezoid":et="trapezoid";break;case"inv_trapezoid":et="inv_trapezoid";break;case"odd_right":et="rect_left_inv_arrow";break;case"circle":et="circle";break;case"ellipse":et="ellipse";break;case"stadium":et="stadium";break;case"subroutine":et="subroutine";break;case"cylinder":et="cylinder";break;case"group":et="rect";break;default:et="rect"}Ut.warn("Adding node",I.id,I.domId),a.setNode(m.db.lookUpDomId(I.id),{labelType:"svg",labelStyle:N.labelStyle,shape:et,label:z,rx:W,ry:W,class:B,style:N.style,id:m.db.lookUpDomId(I.id)})})},ONt=function(i,a,f){let p=0,w,m;if(i.defaultStyle!==void 0){const b=im(i.defaultStyle);w=b.style,m=b.labelStyle}i.forEach(function(b){p++;const E="L-"+b.start+"-"+b.end,_="LS-"+b.start,A="LE-"+b.end,I={};b.type==="arrow_open"?I.arrowhead="none":I.arrowhead="normal";let B="",N="";if(b.style!==void 0){const R=im(b.style);B=R.style,N=R.labelStyle}else switch(b.stroke){case"normal":B="fill:none",w!==void 0&&(B=w),m!==void 0&&(N=m);break;case"dotted":B="fill:none;stroke-width:2px;stroke-dasharray:3;";break;case"thick":B=" stroke-width: 3.5px;fill:none";break}I.style=B,I.labelStyle=N,b.interpolate!==void 0?I.curve=ew(b.interpolate,cg):i.defaultInterpolate!==void 0?I.curve=ew(i.defaultInterpolate,cg):I.curve=ew(DNt.curve,cg),b.text===void 0?b.style!==void 0&&(I.arrowheadStyle="fill: #333"):(I.arrowheadStyle="fill: #333",I.labelpos="c",o1(Oe().flowchart.htmlLabels)?(I.labelType="html",I.label=`${b.text.replace(/fa[blrs]?:fa-[\w-]+/g,R=>``)}`):(I.labelType="text",I.label=b.text.replace(Kr.lineBreakRegex,` +`),b.style===void 0&&(I.style=I.style||"stroke: #333; stroke-width: 1.5px;fill:none"),I.labelStyle=I.labelStyle.replace("color:","fill:"))),I.id=E,I.class=_+" "+A,I.minlen=b.length||1,a.setEdge(f.db.lookUpDomId(b.start),f.db.lookUpDomId(b.end),I,p)})},hRe={setConf:lRe,addVertices:INt,addEdges:ONt,getClasses:function(i,a){return Ut.info("Extracting classes"),a.db.getClasses()},draw:function(i,a,f,p){Ut.info("Drawing flowchart");const{securityLevel:w,flowchart:m}=Oe();let b;w==="sandbox"&&(b=yr("#i"+a));const E=yr(w==="sandbox"?b.nodes()[0].contentDocument.body:"body"),_=w==="sandbox"?b.nodes()[0].contentDocument:document;let A=p.db.getDirection();A===void 0&&(A="TD");const I=m.nodeSpacing||50,B=m.rankSpacing||50,N=new c1({multigraph:!0,compound:!0}).setGraph({rankdir:A,nodesep:I,ranksep:B,marginx:8,marginy:8}).setDefaultEdgeLabel(function(){return{}});let R;const z=p.db.getSubGraphs();for(let ft=z.length-1;ft>=0;ft--)R=z[ft],p.db.addVertex(R.id,R.title,"group",void 0,R.classes);const W=p.db.getVertices();Ut.warn("Get vertices",W);const et=p.db.getEdges();let st=0;for(st=z.length-1;st>=0;st--){R=z[st],sMt("cluster").append("text");for(let ft=0;ft{a.forEach(w=>{pRe[w](i,f,p)})},pRe={extension:(i,a,f)=>{Ut.trace("Making markers for ",f),i.append("defs").append("marker").attr("id",f+"_"+a+"-extensionStart").attr("class","marker extension "+a).attr("refX",18).attr("refY",7).attr("markerWidth",190).attr("markerHeight",240).attr("orient","auto").append("path").attr("d","M 1,7 L18,13 V 1 Z"),i.append("defs").append("marker").attr("id",f+"_"+a+"-extensionEnd").attr("class","marker extension "+a).attr("refX",1).attr("refY",7).attr("markerWidth",20).attr("markerHeight",28).attr("orient","auto").append("path").attr("d","M 1,1 V 13 L18,7 Z")},composition:(i,a,f)=>{i.append("defs").append("marker").attr("id",f+"_"+a+"-compositionStart").attr("class","marker composition "+a).attr("refX",18).attr("refY",7).attr("markerWidth",190).attr("markerHeight",240).attr("orient","auto").append("path").attr("d","M 18,7 L9,13 L1,7 L9,1 Z"),i.append("defs").append("marker").attr("id",f+"_"+a+"-compositionEnd").attr("class","marker composition "+a).attr("refX",1).attr("refY",7).attr("markerWidth",20).attr("markerHeight",28).attr("orient","auto").append("path").attr("d","M 18,7 L9,13 L1,7 L9,1 Z")},aggregation:(i,a,f)=>{i.append("defs").append("marker").attr("id",f+"_"+a+"-aggregationStart").attr("class","marker aggregation "+a).attr("refX",18).attr("refY",7).attr("markerWidth",190).attr("markerHeight",240).attr("orient","auto").append("path").attr("d","M 18,7 L9,13 L1,7 L9,1 Z"),i.append("defs").append("marker").attr("id",f+"_"+a+"-aggregationEnd").attr("class","marker aggregation "+a).attr("refX",1).attr("refY",7).attr("markerWidth",20).attr("markerHeight",28).attr("orient","auto").append("path").attr("d","M 18,7 L9,13 L1,7 L9,1 Z")},dependency:(i,a,f)=>{i.append("defs").append("marker").attr("id",f+"_"+a+"-dependencyStart").attr("class","marker dependency "+a).attr("refX",6).attr("refY",7).attr("markerWidth",190).attr("markerHeight",240).attr("orient","auto").append("path").attr("d","M 5,7 L9,13 L1,7 L9,1 Z"),i.append("defs").append("marker").attr("id",f+"_"+a+"-dependencyEnd").attr("class","marker dependency "+a).attr("refX",13).attr("refY",7).attr("markerWidth",20).attr("markerHeight",28).attr("orient","auto").append("path").attr("d","M 18,7 L9,13 L14,7 L9,1 Z")},lollipop:(i,a,f)=>{i.append("defs").append("marker").attr("id",f+"_"+a+"-lollipopStart").attr("class","marker lollipop "+a).attr("refX",13).attr("refY",7).attr("markerWidth",190).attr("markerHeight",240).attr("orient","auto").append("circle").attr("stroke","black").attr("fill","transparent").attr("cx",7).attr("cy",7).attr("r",6),i.append("defs").append("marker").attr("id",f+"_"+a+"-lollipopEnd").attr("class","marker lollipop "+a).attr("refX",1).attr("refY",7).attr("markerWidth",190).attr("markerHeight",240).attr("orient","auto").append("circle").attr("stroke","black").attr("fill","transparent").attr("cx",7).attr("cy",7).attr("r",6)},point:(i,a,f)=>{i.append("marker").attr("id",f+"_"+a+"-pointEnd").attr("class","marker "+a).attr("viewBox","0 0 10 10").attr("refX",6).attr("refY",5).attr("markerUnits","userSpaceOnUse").attr("markerWidth",12).attr("markerHeight",12).attr("orient","auto").append("path").attr("d","M 0 0 L 10 5 L 0 10 z").attr("class","arrowMarkerPath").style("stroke-width",1).style("stroke-dasharray","1,0"),i.append("marker").attr("id",f+"_"+a+"-pointStart").attr("class","marker "+a).attr("viewBox","0 0 10 10").attr("refX",4.5).attr("refY",5).attr("markerUnits","userSpaceOnUse").attr("markerWidth",12).attr("markerHeight",12).attr("orient","auto").append("path").attr("d","M 0 5 L 10 10 L 10 0 z").attr("class","arrowMarkerPath").style("stroke-width",1).style("stroke-dasharray","1,0")},circle:(i,a,f)=>{i.append("marker").attr("id",f+"_"+a+"-circleEnd").attr("class","marker "+a).attr("viewBox","0 0 10 10").attr("refX",11).attr("refY",5).attr("markerUnits","userSpaceOnUse").attr("markerWidth",11).attr("markerHeight",11).attr("orient","auto").append("circle").attr("cx","5").attr("cy","5").attr("r","5").attr("class","arrowMarkerPath").style("stroke-width",1).style("stroke-dasharray","1,0"),i.append("marker").attr("id",f+"_"+a+"-circleStart").attr("class","marker "+a).attr("viewBox","0 0 10 10").attr("refX",-1).attr("refY",5).attr("markerUnits","userSpaceOnUse").attr("markerWidth",11).attr("markerHeight",11).attr("orient","auto").append("circle").attr("cx","5").attr("cy","5").attr("r","5").attr("class","arrowMarkerPath").style("stroke-width",1).style("stroke-dasharray","1,0")},cross:(i,a,f)=>{i.append("marker").attr("id",f+"_"+a+"-crossEnd").attr("class","marker cross "+a).attr("viewBox","0 0 11 11").attr("refX",12).attr("refY",5.2).attr("markerUnits","userSpaceOnUse").attr("markerWidth",11).attr("markerHeight",11).attr("orient","auto").append("path").attr("d","M 1,1 l 9,9 M 10,1 l -9,9").attr("class","arrowMarkerPath").style("stroke-width",2).style("stroke-dasharray","1,0"),i.append("marker").attr("id",f+"_"+a+"-crossStart").attr("class","marker cross "+a).attr("viewBox","0 0 11 11").attr("refX",-1).attr("refY",5.2).attr("markerUnits","userSpaceOnUse").attr("markerWidth",11).attr("markerHeight",11).attr("orient","auto").append("path").attr("d","M 1,1 l 9,9 M 10,1 l -9,9").attr("class","arrowMarkerPath").style("stroke-width",2).style("stroke-dasharray","1,0")},barb:(i,a,f)=>{i.append("defs").append("marker").attr("id",f+"_"+a+"-barbEnd").attr("refX",19).attr("refY",7).attr("markerWidth",20).attr("markerHeight",14).attr("markerUnits","strokeWidth").attr("orient","auto").append("path").attr("d","M 19,7 L9,13 L14,7 L9,1 Z")}},PNt=gRe;function bRe(i,a){a&&i.attr("style",a)}function wRe(i){const a=yr(document.createElementNS("http://www.w3.org/2000/svg","foreignObject")),f=a.append("xhtml:div"),p=i.label,w=i.isNode?"nodeLabel":"edgeLabel";return f.html('"+p+""),bRe(f,i.labelStyle),f.style("display","inline-block"),f.style("white-space","nowrap"),f.attr("xmlns","http://www.w3.org/1999/xhtml"),a.node()}const gp=(i,a,f,p)=>{let w=i||"";if(typeof w=="object"&&(w=w[0]),o1(Oe().flowchart.htmlLabels)){w=w.replace(/\\n|\n/g,"
            "),Ut.info("vertexText"+w);const m={isNode:p,label:uF(w).replace(/fa[blrs]?:fa-[\w-]+/g,E=>``),labelStyle:a.replace("fill:","color:")};return wRe(m)}else{const m=document.createElementNS("http://www.w3.org/2000/svg","text");m.setAttribute("style",a.replace("color:","fill:"));let b=[];typeof w=="string"?b=w.split(/\\n|\n|/gi):Array.isArray(w)?b=w:b=[];for(const E of b){const _=document.createElementNS("http://www.w3.org/2000/svg","tspan");_.setAttributeNS("http://www.w3.org/XML/1998/namespace","xml:space","preserve"),_.setAttribute("dy","1em"),_.setAttribute("x","0"),f?_.setAttribute("class","title-row"):_.setAttribute("class","row"),_.textContent=E.trim(),m.appendChild(_)}return m}},vRe={};function mRe(i,a){const f=a||vRe,p=typeof f.includeImageAlt=="boolean"?f.includeImageAlt:!0,w=typeof f.includeHtml=="boolean"?f.includeHtml:!0;return FNt(i,p,w)}function FNt(i,a,f){if(yRe(i)){if("value"in i)return i.type==="html"&&!f?"":i.value;if(a&&"alt"in i&&i.alt)return i.alt;if("children"in i)return NNt(i.children,a,f)}return Array.isArray(i)?NNt(i,a,f):""}function NNt(i,a,f){const p=[];let w=-1;for(;++ww?0:w+a:a=a>w?w:a,f=f>0?f:0,p.length<1e4)b=Array.from(p),b.unshift(a,f),i.splice(...b);else for(f&&i.splice(a,f);m0?(m3(i,i.length,0,a),i):a}const BNt={}.hasOwnProperty;function xRe(i){const a={};let f=-1;for(;++fb))return;const ut=a.events.length;let vt=ut,X,pt;for(;vt--;)if(a.events[vt][0]==="exit"&&a.events[vt][1].type==="chunkFlow"){if(X){pt=a.events[vt][1].end;break}X=!0}for(st(p),ft=ut;ftbt;){const yt=f[mt];a.containerState=yt[1],yt[0].exit.call(a,i)}f.length=bt}function at(){w.write([null]),m=void 0,w=void 0,a.containerState._closeFlow=void 0}}function PRe(i,a,f){return il(i,i.attempt(this.parser.constructs.document,a,f),"linePrefix",this.parser.constructs.disable.null.includes("codeIndented")?void 0:4)}function jNt(i){if(i===null||pp(i)||LRe(i))return 1;if(ARe(i))return 2}function _0t(i,a,f){const p=[];let w=-1;for(;++w1&&i[f][1].end.offset-i[f][1].start.offset>1?2:1;const B=Object.assign({},i[p][1].end),N=Object.assign({},i[f][1].start);$Nt(B,-_),$Nt(N,_),b={type:_>1?"strongSequence":"emphasisSequence",start:B,end:Object.assign({},i[p][1].end)},E={type:_>1?"strongSequence":"emphasisSequence",start:Object.assign({},i[f][1].start),end:N},m={type:_>1?"strongText":"emphasisText",start:Object.assign({},i[p][1].end),end:Object.assign({},i[f][1].start)},w={type:_>1?"strong":"emphasis",start:Object.assign({},b.start),end:Object.assign({},E.end)},i[p][1].end=Object.assign({},b.start),i[f][1].start=Object.assign({},E.end),A=[],i[p][1].end.offset-i[p][1].start.offset&&(A=sw(A,[["enter",i[p][1],a],["exit",i[p][1],a]])),A=sw(A,[["enter",w,a],["enter",b,a],["exit",b,a],["enter",m,a]]),A=sw(A,_0t(a.parser.constructs.insideSpan.null,i.slice(p+1,f),a)),A=sw(A,[["exit",m,a],["enter",E,a],["exit",E,a],["exit",w,a]]),i[f][1].end.offset-i[f][1].start.offset?(I=2,A=sw(A,[["enter",i[f][1],a],["exit",i[f][1],a]])):I=0,m3(i,p-1,f-p+3,A),f=p+A.length-I-2;break}}for(f=-1;++f0&&Wc(ft)?il(i,at,"linePrefix",m+1)(ft):at(ft)}function at(ft){return ft===null||xa(ft)?i.check(GNt,W,mt)(ft):(i.enter("codeFlowValue"),bt(ft))}function bt(ft){return ft===null||xa(ft)?(i.exit("codeFlowValue"),at(ft)):(i.consume(ft),bt)}function mt(ft){return i.exit("codeFenced"),a(ft)}function yt(ft,ut,vt){let X=0;return pt;function pt(Ot){return ft.enter("lineEnding"),ft.consume(Ot),ft.exit("lineEnding"),U}function U(Ot){return ft.enter("codeFencedFence"),Wc(Ot)?il(ft,Tt,"linePrefix",p.parser.constructs.disable.null.includes("codeIndented")?void 0:4)(Ot):Tt(Ot)}function Tt(Ot){return Ot===E?(ft.enter("codeFencedFenceSequence"),nt(Ot)):vt(Ot)}function nt(Ot){return Ot===E?(X++,ft.consume(Ot),nt):X>=b?(ft.exit("codeFencedFenceSequence"),Wc(Ot)?il(ft,It,"whitespace")(Ot):It(Ot)):vt(Ot)}function It(Ot){return Ot===null||xa(Ot)?(ft.exit("codeFencedFence"),ut(Ot)):vt(Ot)}}}function URe(i,a,f){const p=this;return w;function w(b){return b===null?f(b):(i.enter("lineEnding"),i.consume(b),i.exit("lineEnding"),m)}function m(b){return p.parser.lazy[p.now().line]?f(b):a(b)}}const L0t={name:"codeIndented",tokenize:YRe},WRe={tokenize:KRe,partial:!0};function YRe(i,a,f){const p=this;return w;function w(A){return i.enter("codeIndented"),il(i,m,"linePrefix",4+1)(A)}function m(A){const I=p.events[p.events.length-1];return I&&I[1].type==="linePrefix"&&I[2].sliceSerialize(I[1],!0).length>=4?b(A):f(A)}function b(A){return A===null?_(A):xa(A)?i.attempt(WRe,b,_)(A):(i.enter("codeFlowValue"),E(A))}function E(A){return A===null||xa(A)?(i.exit("codeFlowValue"),b(A)):(i.consume(A),E)}function _(A){return i.exit("codeIndented"),a(A)}}function KRe(i,a,f){const p=this;return w;function w(b){return p.parser.lazy[p.now().line]?f(b):xa(b)?(i.enter("lineEnding"),i.consume(b),i.exit("lineEnding"),w):il(i,m,"linePrefix",4+1)(b)}function m(b){const E=p.events[p.events.length-1];return E&&E[1].type==="linePrefix"&&E[2].sliceSerialize(E[1],!0).length>=4?a(b):xa(b)?w(b):f(b)}}const XRe={name:"codeText",tokenize:JRe,resolve:QRe,previous:ZRe};function QRe(i){let a=i.length-4,f=3,p,w;if((i[f][1].type==="lineEnding"||i[f][1].type==="space")&&(i[a][1].type==="lineEnding"||i[a][1].type==="space")){for(p=f;++p=4?a(b):i.interrupt(p.parser.constructs.flow,f,a)(b)}}function YNt(i,a,f,p,w,m,b,E,_){const A=_||Number.POSITIVE_INFINITY;let I=0;return B;function B(st){return st===60?(i.enter(p),i.enter(w),i.enter(m),i.consume(st),i.exit(m),N):st===null||st===32||st===41||T0t(st)?f(st):(i.enter(p),i.enter(b),i.enter(E),i.enter("chunkString",{contentType:"string"}),W(st))}function N(st){return st===62?(i.enter(m),i.consume(st),i.exit(m),i.exit(w),i.exit(p),a):(i.enter(E),i.enter("chunkString",{contentType:"string"}),R(st))}function R(st){return st===62?(i.exit("chunkString"),i.exit(E),N(st)):st===null||st===60||xa(st)?f(st):(i.consume(st),st===92?z:R)}function z(st){return st===60||st===62||st===92?(i.consume(st),R):R(st)}function W(st){return!I&&(st===null||st===41||pp(st))?(i.exit("chunkString"),i.exit(E),i.exit(b),i.exit(p),a(st)):I999||R===null||R===91||R===93&&!_||R===94&&!E&&"_hiddenFootnoteSupport"in b.parser.constructs?f(R):R===93?(i.exit(m),i.enter(w),i.consume(R),i.exit(w),i.exit(p),a):xa(R)?(i.enter("lineEnding"),i.consume(R),i.exit("lineEnding"),I):(i.enter("chunkString",{contentType:"string"}),B(R))}function B(R){return R===null||R===91||R===93||xa(R)||E++>999?(i.exit("chunkString"),I(R)):(i.consume(R),_||(_=!Wc(R)),R===92?N:B)}function N(R){return R===91||R===92||R===93?(i.consume(R),E++,B):B(R)}}function XNt(i,a,f,p,w,m){let b;return E;function E(N){return N===34||N===39||N===40?(i.enter(p),i.enter(w),i.consume(N),i.exit(w),b=N===40?41:N,_):f(N)}function _(N){return N===b?(i.enter(w),i.consume(N),i.exit(w),i.exit(p),a):(i.enter(m),A(N))}function A(N){return N===b?(i.exit(m),_(b)):N===null?f(N):xa(N)?(i.enter("lineEnding"),i.consume(N),i.exit("lineEnding"),il(i,A,"linePrefix")):(i.enter("chunkString",{contentType:"string"}),I(N))}function I(N){return N===b||N===null||xa(N)?(i.exit("chunkString"),A(N)):(i.consume(N),N===92?B:I)}function B(N){return N===b||N===92?(i.consume(N),I):I(N)}}function TF(i,a){let f;return p;function p(w){return xa(w)?(i.enter("lineEnding"),i.consume(w),i.exit("lineEnding"),f=!0,p):Wc(w)?il(i,p,f?"linePrefix":"lineSuffix")(w):a(w)}}function oL(i){return i.replace(/[\t\n\r ]+/g," ").replace(/^ | $/g,"").toLowerCase().toUpperCase()}const aje={name:"definition",tokenize:cje},oje={tokenize:uje,partial:!0};function cje(i,a,f){const p=this;let w;return m;function m(R){return i.enter("definition"),b(R)}function b(R){return KNt.call(p,i,E,f,"definitionLabel","definitionLabelMarker","definitionLabelString")(R)}function E(R){return w=oL(p.sliceSerialize(p.events[p.events.length-1][1]).slice(1,-1)),R===58?(i.enter("definitionMarker"),i.consume(R),i.exit("definitionMarker"),_):f(R)}function _(R){return pp(R)?TF(i,A)(R):A(R)}function A(R){return YNt(i,I,f,"definitionDestination","definitionDestinationLiteral","definitionDestinationLiteralMarker","definitionDestinationRaw","definitionDestinationString")(R)}function I(R){return i.attempt(oje,B,B)(R)}function B(R){return Wc(R)?il(i,N,"whitespace")(R):N(R)}function N(R){return R===null||xa(R)?(i.exit("definition"),p.parser.defined.push(w),a(R)):f(R)}}function uje(i,a,f){return p;function p(E){return pp(E)?TF(i,w)(E):f(E)}function w(E){return XNt(i,m,f,"definitionTitle","definitionTitleMarker","definitionTitleString")(E)}function m(E){return Wc(E)?il(i,b,"whitespace")(E):b(E)}function b(E){return E===null||xa(E)?a(E):f(E)}}const lje={name:"hardBreakEscape",tokenize:hje};function hje(i,a,f){return p;function p(m){return i.enter("hardBreakEscape"),i.consume(m),w}function w(m){return xa(m)?(i.exit("hardBreakEscape"),a(m)):f(m)}}const fje={name:"headingAtx",tokenize:gje,resolve:dje};function dje(i,a){let f=i.length-2,p=3,w,m;return i[p][1].type==="whitespace"&&(p+=2),f-2>p&&i[f][1].type==="whitespace"&&(f-=2),i[f][1].type==="atxHeadingSequence"&&(p===f-1||f-4>p&&i[f-2][1].type==="whitespace")&&(f-=p+1===f?2:4),f>p&&(w={type:"atxHeadingText",start:i[p][1].start,end:i[f][1].end},m={type:"chunkText",start:i[p][1].start,end:i[f][1].end,contentType:"text"},m3(i,p,f-p+1,[["enter",w,a],["enter",m,a],["exit",m,a],["exit",w,a]])),i}function gje(i,a,f){let p=0;return w;function w(I){return i.enter("atxHeading"),m(I)}function m(I){return i.enter("atxHeadingSequence"),b(I)}function b(I){return I===35&&p++<6?(i.consume(I),b):I===null||pp(I)?(i.exit("atxHeadingSequence"),E(I)):f(I)}function E(I){return I===35?(i.enter("atxHeadingSequence"),_(I)):I===null||xa(I)?(i.exit("atxHeading"),a(I)):Wc(I)?il(i,E,"whitespace")(I):(i.enter("atxHeadingText"),A(I))}function _(I){return I===35?(i.consume(I),_):(i.exit("atxHeadingSequence"),E(I))}function A(I){return I===null||I===35||pp(I)?(i.exit("atxHeadingText"),E(I)):(i.consume(I),A)}}const pje=["address","article","aside","base","basefont","blockquote","body","caption","center","col","colgroup","dd","details","dialog","dir","div","dl","dt","fieldset","figcaption","figure","footer","form","frame","frameset","h1","h2","h3","h4","h5","h6","head","header","hr","html","iframe","legend","li","link","main","menu","menuitem","nav","noframes","ol","optgroup","option","p","param","search","section","summary","table","tbody","td","tfoot","th","thead","title","tr","track","ul"],QNt=["pre","script","style","textarea"],bje={name:"htmlFlow",tokenize:yje,resolveTo:mje,concrete:!0},wje={tokenize:kje,partial:!0},vje={tokenize:xje,partial:!0};function mje(i){let a=i.length;for(;a--&&!(i[a][0]==="enter"&&i[a][1].type==="htmlFlow"););return a>1&&i[a-2][1].type==="linePrefix"&&(i[a][1].start=i[a-2][1].start,i[a+1][1].start=i[a-2][1].start,i.splice(a-2,2)),i}function yje(i,a,f){const p=this;let w,m,b,E,_;return A;function A(Ft){return I(Ft)}function I(Ft){return i.enter("htmlFlow"),i.enter("htmlFlowData"),i.consume(Ft),B}function B(Ft){return Ft===33?(i.consume(Ft),N):Ft===47?(i.consume(Ft),m=!0,W):Ft===63?(i.consume(Ft),w=3,p.interrupt?a:xt):y3(Ft)?(i.consume(Ft),b=String.fromCharCode(Ft),et):f(Ft)}function N(Ft){return Ft===45?(i.consume(Ft),w=2,R):Ft===91?(i.consume(Ft),w=5,E=0,z):y3(Ft)?(i.consume(Ft),w=4,p.interrupt?a:xt):f(Ft)}function R(Ft){return Ft===45?(i.consume(Ft),p.interrupt?a:xt):f(Ft)}function z(Ft){const gn="CDATA[";return Ft===gn.charCodeAt(E++)?(i.consume(Ft),E===gn.length?p.interrupt?a:Tt:z):f(Ft)}function W(Ft){return y3(Ft)?(i.consume(Ft),b=String.fromCharCode(Ft),et):f(Ft)}function et(Ft){if(Ft===null||Ft===47||Ft===62||pp(Ft)){const gn=Ft===47,Se=b.toLowerCase();return!gn&&!m&&QNt.includes(Se)?(w=1,p.interrupt?a(Ft):Tt(Ft)):pje.includes(b.toLowerCase())?(w=6,gn?(i.consume(Ft),st):p.interrupt?a(Ft):Tt(Ft)):(w=7,p.interrupt&&!p.parser.lazy[p.now().line]?f(Ft):m?at(Ft):bt(Ft))}return Ft===45||lm(Ft)?(i.consume(Ft),b+=String.fromCharCode(Ft),et):f(Ft)}function st(Ft){return Ft===62?(i.consume(Ft),p.interrupt?a:Tt):f(Ft)}function at(Ft){return Wc(Ft)?(i.consume(Ft),at):pt(Ft)}function bt(Ft){return Ft===47?(i.consume(Ft),pt):Ft===58||Ft===95||y3(Ft)?(i.consume(Ft),mt):Wc(Ft)?(i.consume(Ft),bt):pt(Ft)}function mt(Ft){return Ft===45||Ft===46||Ft===58||Ft===95||lm(Ft)?(i.consume(Ft),mt):yt(Ft)}function yt(Ft){return Ft===61?(i.consume(Ft),ft):Wc(Ft)?(i.consume(Ft),yt):bt(Ft)}function ft(Ft){return Ft===null||Ft===60||Ft===61||Ft===62||Ft===96?f(Ft):Ft===34||Ft===39?(i.consume(Ft),_=Ft,ut):Wc(Ft)?(i.consume(Ft),ft):vt(Ft)}function ut(Ft){return Ft===_?(i.consume(Ft),_=null,X):Ft===null||xa(Ft)?f(Ft):(i.consume(Ft),ut)}function vt(Ft){return Ft===null||Ft===34||Ft===39||Ft===47||Ft===60||Ft===61||Ft===62||Ft===96||pp(Ft)?yt(Ft):(i.consume(Ft),vt)}function X(Ft){return Ft===47||Ft===62||Wc(Ft)?bt(Ft):f(Ft)}function pt(Ft){return Ft===62?(i.consume(Ft),U):f(Ft)}function U(Ft){return Ft===null||xa(Ft)?Tt(Ft):Wc(Ft)?(i.consume(Ft),U):f(Ft)}function Tt(Ft){return Ft===45&&w===2?(i.consume(Ft),Bt):Ft===60&&w===1?(i.consume(Ft),Et):Ft===62&&w===4?(i.consume(Ft),Ht):Ft===63&&w===3?(i.consume(Ft),xt):Ft===93&&w===5?(i.consume(Ft),Ct):xa(Ft)&&(w===6||w===7)?(i.exit("htmlFlowData"),i.check(wje,Le,nt)(Ft)):Ft===null||xa(Ft)?(i.exit("htmlFlowData"),nt(Ft)):(i.consume(Ft),Tt)}function nt(Ft){return i.check(vje,It,Le)(Ft)}function It(Ft){return i.enter("lineEnding"),i.consume(Ft),i.exit("lineEnding"),Ot}function Ot(Ft){return Ft===null||xa(Ft)?nt(Ft):(i.enter("htmlFlowData"),Tt(Ft))}function Bt(Ft){return Ft===45?(i.consume(Ft),xt):Tt(Ft)}function Et(Ft){return Ft===47?(i.consume(Ft),b="",Z):Tt(Ft)}function Z(Ft){if(Ft===62){const gn=b.toLowerCase();return QNt.includes(gn)?(i.consume(Ft),Ht):Tt(Ft)}return y3(Ft)&&b.length<8?(i.consume(Ft),b+=String.fromCharCode(Ft),Z):Tt(Ft)}function Ct(Ft){return Ft===93?(i.consume(Ft),xt):Tt(Ft)}function xt(Ft){return Ft===62?(i.consume(Ft),Ht):Ft===45&&w===2?(i.consume(Ft),xt):Tt(Ft)}function Ht(Ft){return Ft===null||xa(Ft)?(i.exit("htmlFlowData"),Le(Ft)):(i.consume(Ft),Ht)}function Le(Ft){return i.exit("htmlFlow"),a(Ft)}}function xje(i,a,f){const p=this;return w;function w(b){return xa(b)?(i.enter("lineEnding"),i.consume(b),i.exit("lineEnding"),m):f(b)}function m(b){return p.parser.lazy[p.now().line]?f(b):a(b)}}function kje(i,a,f){return p;function p(w){return i.enter("lineEnding"),i.consume(w),i.exit("lineEnding"),i.attempt(yY,a,f)}}const Eje={name:"htmlText",tokenize:Tje};function Tje(i,a,f){const p=this;let w,m,b;return E;function E(xt){return i.enter("htmlText"),i.enter("htmlTextData"),i.consume(xt),_}function _(xt){return xt===33?(i.consume(xt),A):xt===47?(i.consume(xt),yt):xt===63?(i.consume(xt),bt):y3(xt)?(i.consume(xt),vt):f(xt)}function A(xt){return xt===45?(i.consume(xt),I):xt===91?(i.consume(xt),m=0,z):y3(xt)?(i.consume(xt),at):f(xt)}function I(xt){return xt===45?(i.consume(xt),R):f(xt)}function B(xt){return xt===null?f(xt):xt===45?(i.consume(xt),N):xa(xt)?(b=B,Et(xt)):(i.consume(xt),B)}function N(xt){return xt===45?(i.consume(xt),R):B(xt)}function R(xt){return xt===62?Bt(xt):xt===45?N(xt):B(xt)}function z(xt){const Ht="CDATA[";return xt===Ht.charCodeAt(m++)?(i.consume(xt),m===Ht.length?W:z):f(xt)}function W(xt){return xt===null?f(xt):xt===93?(i.consume(xt),et):xa(xt)?(b=W,Et(xt)):(i.consume(xt),W)}function et(xt){return xt===93?(i.consume(xt),st):W(xt)}function st(xt){return xt===62?Bt(xt):xt===93?(i.consume(xt),st):W(xt)}function at(xt){return xt===null||xt===62?Bt(xt):xa(xt)?(b=at,Et(xt)):(i.consume(xt),at)}function bt(xt){return xt===null?f(xt):xt===63?(i.consume(xt),mt):xa(xt)?(b=bt,Et(xt)):(i.consume(xt),bt)}function mt(xt){return xt===62?Bt(xt):bt(xt)}function yt(xt){return y3(xt)?(i.consume(xt),ft):f(xt)}function ft(xt){return xt===45||lm(xt)?(i.consume(xt),ft):ut(xt)}function ut(xt){return xa(xt)?(b=ut,Et(xt)):Wc(xt)?(i.consume(xt),ut):Bt(xt)}function vt(xt){return xt===45||lm(xt)?(i.consume(xt),vt):xt===47||xt===62||pp(xt)?X(xt):f(xt)}function X(xt){return xt===47?(i.consume(xt),Bt):xt===58||xt===95||y3(xt)?(i.consume(xt),pt):xa(xt)?(b=X,Et(xt)):Wc(xt)?(i.consume(xt),X):Bt(xt)}function pt(xt){return xt===45||xt===46||xt===58||xt===95||lm(xt)?(i.consume(xt),pt):U(xt)}function U(xt){return xt===61?(i.consume(xt),Tt):xa(xt)?(b=U,Et(xt)):Wc(xt)?(i.consume(xt),U):X(xt)}function Tt(xt){return xt===null||xt===60||xt===61||xt===62||xt===96?f(xt):xt===34||xt===39?(i.consume(xt),w=xt,nt):xa(xt)?(b=Tt,Et(xt)):Wc(xt)?(i.consume(xt),Tt):(i.consume(xt),It)}function nt(xt){return xt===w?(i.consume(xt),w=void 0,Ot):xt===null?f(xt):xa(xt)?(b=nt,Et(xt)):(i.consume(xt),nt)}function It(xt){return xt===null||xt===34||xt===39||xt===60||xt===61||xt===96?f(xt):xt===47||xt===62||pp(xt)?X(xt):(i.consume(xt),It)}function Ot(xt){return xt===47||xt===62||pp(xt)?X(xt):f(xt)}function Bt(xt){return xt===62?(i.consume(xt),i.exit("htmlTextData"),i.exit("htmlText"),a):f(xt)}function Et(xt){return i.exit("htmlTextData"),i.enter("lineEnding"),i.consume(xt),i.exit("lineEnding"),Z}function Z(xt){return Wc(xt)?il(i,Ct,"linePrefix",p.parser.constructs.disable.null.includes("codeIndented")?void 0:4)(xt):Ct(xt)}function Ct(xt){return i.enter("htmlTextData"),b(xt)}}const M0t={name:"labelEnd",tokenize:Mje,resolveTo:Lje,resolveAll:Aje},Cje={tokenize:Dje},_je={tokenize:Ije},Sje={tokenize:Oje};function Aje(i){let a=-1;for(;++a=3&&(A===null||xa(A))?(i.exit("thematicBreak"),a(A)):f(A)}function _(A){return A===w?(i.consume(A),p++,_):(i.exit("thematicBreakSequence"),Wc(A)?il(i,E,"whitespace")(A):E(A))}}const bp={name:"list",tokenize:qje,continuation:{tokenize:Hje},exit:Gje},$je={tokenize:Uje,partial:!0},zje={tokenize:Vje,partial:!0};function qje(i,a,f){const p=this,w=p.events[p.events.length-1];let m=w&&w[1].type==="linePrefix"?w[2].sliceSerialize(w[1],!0).length:0,b=0;return E;function E(R){const z=p.containerState.type||(R===42||R===43||R===45?"listUnordered":"listOrdered");if(z==="listUnordered"?!p.containerState.marker||R===p.containerState.marker:C0t(R)){if(p.containerState.type||(p.containerState.type=z,i.enter(z,{_container:!0})),z==="listUnordered")return i.enter("listItemPrefix"),R===42||R===45?i.check(xY,f,A)(R):A(R);if(!p.interrupt||R===49)return i.enter("listItemPrefix"),i.enter("listItemValue"),_(R)}return f(R)}function _(R){return C0t(R)&&++b<10?(i.consume(R),_):(!p.interrupt||b<2)&&(p.containerState.marker?R===p.containerState.marker:R===41||R===46)?(i.exit("listItemValue"),A(R)):f(R)}function A(R){return i.enter("listItemMarker"),i.consume(R),i.exit("listItemMarker"),p.containerState.marker=p.containerState.marker||R,i.check(yY,p.interrupt?f:I,i.attempt($je,N,B))}function I(R){return p.containerState.initialBlankLine=!0,m++,N(R)}function B(R){return Wc(R)?(i.enter("listItemPrefixWhitespace"),i.consume(R),i.exit("listItemPrefixWhitespace"),N):f(R)}function N(R){return p.containerState.size=m+p.sliceSerialize(i.exit("listItemPrefix"),!0).length,a(R)}}function Hje(i,a,f){const p=this;return p.containerState._closeFlow=void 0,i.check(yY,w,m);function w(E){return p.containerState.furtherBlankLines=p.containerState.furtherBlankLines||p.containerState.initialBlankLine,il(i,a,"listItemIndent",p.containerState.size+1)(E)}function m(E){return p.containerState.furtherBlankLines||!Wc(E)?(p.containerState.furtherBlankLines=void 0,p.containerState.initialBlankLine=void 0,b(E)):(p.containerState.furtherBlankLines=void 0,p.containerState.initialBlankLine=void 0,i.attempt(zje,a,b)(E))}function b(E){return p.containerState._closeFlow=!0,p.interrupt=void 0,il(i,i.attempt(bp,a,f),"linePrefix",p.parser.constructs.disable.null.includes("codeIndented")?void 0:4)(E)}}function Vje(i,a,f){const p=this;return il(i,w,"listItemIndent",p.containerState.size+1);function w(m){const b=p.events[p.events.length-1];return b&&b[1].type==="listItemIndent"&&b[2].sliceSerialize(b[1],!0).length===p.containerState.size?a(m):f(m)}}function Gje(i){i.exit(this.containerState.type)}function Uje(i,a,f){const p=this;return il(i,w,"listItemPrefixWhitespace",p.parser.constructs.disable.null.includes("codeIndented")?void 0:4+1);function w(m){const b=p.events[p.events.length-1];return!Wc(m)&&b&&b[1].type==="listItemPrefixWhitespace"?a(m):f(m)}}const ZNt={name:"setextUnderline",tokenize:Yje,resolveTo:Wje};function Wje(i,a){let f=i.length,p,w,m;for(;f--;)if(i[f][0]==="enter"){if(i[f][1].type==="content"){p=f;break}i[f][1].type==="paragraph"&&(w=f)}else i[f][1].type==="content"&&i.splice(f,1),!m&&i[f][1].type==="definition"&&(m=f);const b={type:"setextHeading",start:Object.assign({},i[w][1].start),end:Object.assign({},i[i.length-1][1].end)};return i[w][1].type="setextHeadingText",m?(i.splice(w,0,["enter",b,a]),i.splice(m+1,0,["exit",i[p][1],a]),i[p][1].end=Object.assign({},i[m][1].end)):i[p][1]=b,i.push(["exit",b,a]),i}function Yje(i,a,f){const p=this;let w;return m;function m(A){let I=p.events.length,B;for(;I--;)if(p.events[I][1].type!=="lineEnding"&&p.events[I][1].type!=="linePrefix"&&p.events[I][1].type!=="content"){B=p.events[I][1].type==="paragraph";break}return!p.parser.lazy[p.now().line]&&(p.interrupt||B)?(i.enter("setextHeadingLine"),w=A,b(A)):f(A)}function b(A){return i.enter("setextHeadingLineSequence"),E(A)}function E(A){return A===w?(i.consume(A),E):(i.exit("setextHeadingLineSequence"),Wc(A)?il(i,_,"lineSuffix")(A):_(A))}function _(A){return A===null||xa(A)?(i.exit("setextHeadingLine"),a(A)):f(A)}}const Kje={tokenize:Xje};function Xje(i){const a=this,f=i.attempt(yY,p,i.attempt(this.parser.constructs.flowInitial,w,il(i,i.attempt(this.parser.constructs.flow,w,i.attempt(eje,w)),"linePrefix")));return f;function p(m){if(m===null){i.consume(m);return}return i.enter("lineEndingBlank"),i.consume(m),i.exit("lineEndingBlank"),a.currentConstruct=void 0,f}function w(m){if(m===null){i.consume(m);return}return i.enter("lineEnding"),i.consume(m),i.exit("lineEnding"),a.currentConstruct=void 0,f}}const Qje={resolveAll:tBt()},Zje=JNt("string"),Jje=JNt("text");function JNt(i){return{tokenize:a,resolveAll:tBt(i==="text"?t$e:void 0)};function a(f){const p=this,w=this.parser.constructs[i],m=f.attempt(w,b,E);return b;function b(I){return A(I)?m(I):E(I)}function E(I){if(I===null){f.consume(I);return}return f.enter("data"),f.consume(I),_}function _(I){return A(I)?(f.exit("data"),m(I)):(f.consume(I),_)}function A(I){if(I===null)return!0;const B=w[I];let N=-1;if(B)for(;++N-1){const E=b[0];typeof E=="string"?b[0]=E.slice(p):b.shift()}m>0&&b.push(i[w].slice(0,m))}return b}function r$e(i,a){let f=-1;const p=[];let w;for(;++f13&&f<32||f>126&&f<160||f>55295&&f<57344||f>64975&&f<65008||(f&65535)===65535||(f&65535)===65534||f>1114111?"�":String.fromCharCode(f)}const c$e=/\\([!-/:-@[-`{-~])|&(#(?:\d{1,7}|x[\da-f]{1,6})|[\da-z]{1,31});/gi;function u$e(i){return i.replace(c$e,l$e)}function l$e(i,a,f){if(a)return a;if(f.charCodeAt(0)===35){const w=f.charCodeAt(1),m=w===120||w===88;return nBt(f.slice(m?2:1),m?16:10)}return A0t(f)||i}function kY(i){return!i||typeof i!="object"?"":"position"in i||"type"in i?rBt(i.position):"start"in i||"end"in i?rBt(i):"line"in i||"column"in i?I0t(i):""}function I0t(i){return iBt(i&&i.line)+":"+iBt(i&&i.column)}function rBt(i){return I0t(i&&i.start)+"-"+I0t(i&&i.end)}function iBt(i){return i&&typeof i=="number"?i:1}const sBt={}.hasOwnProperty,aBt=function(i,a,f){return typeof a!="string"&&(f=a,a=void 0),h$e(f)(o$e(s$e(f).document().write(a$e()(i,a,!0))))};function h$e(i){const a={transforms:[],canContainEols:["emphasis","fragment","heading","paragraph","strong"],enter:{autolink:E(Ks),autolinkProtocol:U,autolinkEmail:U,atxHeading:E(Me),blockQuote:E(zt),characterEscape:U,characterReference:U,codeFenced:E(re),codeFencedFenceInfo:_,codeFencedFenceMeta:_,codeIndented:E(re,_),codeText:E(se,_),codeTextData:U,data:U,codeFlowValue:U,definition:E(Pe),definitionDestinationString:_,definitionLabelString:_,definitionTitleString:_,emphasis:E(te),hardBreakEscape:E(de),hardBreakTrailing:E(de),htmlFlow:E(on,_),htmlFlowData:U,htmlText:E(on,_),htmlTextData:U,image:E(ni),label:_,link:E(Ks),listItem:E(fo),listItemValue:z,listOrdered:E(ws,R),listUnordered:E(ws),paragraph:E(Xi),reference:Se,referenceString:_,resourceDestinationString:_,resourceTitleString:_,setextHeading:E(Me),strong:E(Er),thematicBreak:E(di)},exit:{atxHeading:I(),atxHeadingSequence:ut,autolink:I(),autolinkEmail:ke,autolinkProtocol:ce,blockQuote:I(),characterEscapeValue:Tt,characterReferenceMarkerHexadecimal:Ve,characterReferenceMarkerNumeric:Ve,characterReferenceValue:Ye,codeFenced:I(at),codeFencedFence:st,codeFencedFenceInfo:W,codeFencedFenceMeta:et,codeFlowValue:Tt,codeIndented:I(bt),codeText:I(Et),codeTextData:Tt,data:Tt,definition:I(),definitionDestinationString:ft,definitionLabelString:mt,definitionTitleString:yt,emphasis:I(),hardBreakEscape:I(It),hardBreakTrailing:I(It),htmlFlow:I(Ot),htmlFlowData:Tt,htmlText:I(Bt),htmlTextData:Tt,image:I(Ct),label:Ht,labelText:xt,lineEnding:nt,link:I(Z),listItem:I(),listOrdered:I(),listUnordered:I(),paragraph:I(),referenceString:me,resourceDestinationString:Le,resourceTitleString:Ft,resource:gn,setextHeading:I(pt),setextHeadingLineSequence:X,setextHeadingText:vt,strong:I(),thematicBreak:I()}};oBt(a,(i||{}).mdastExtensions||[]);const f={};return p;function p(Ee){let Kn={type:"root",children:[]};const He={stack:[Kn],tokenStack:[],config:a,enter:A,exit:B,buffer:_,resume:N,setData:m,getData:b},Ti=[];let pn=-1;for(;++pn0){const Es=He.tokenStack[He.tokenStack.length-1];(Es[1]||cBt).call(He,void 0,Es[0])}for(Kn.position={start:wk(Ee.length>0?Ee[0][1].start:{line:1,column:1,offset:0}),end:wk(Ee.length>0?Ee[Ee.length-2][1].end:{line:1,column:1,offset:0})},pn=-1;++pn{I!==0&&(w++,p.push([])),A.split(" ").forEach(B=>{B&&p[w].push({content:B,type:E})})}):(b.type==="strong"||b.type==="emphasis")&&b.children.forEach(_=>{m(_,b.type)})}return f.forEach(b=>{b.type==="paragraph"&&b.children.forEach(E=>{m(E)})}),p}function p$e(i){const{children:a}=aBt(i);function f(p){return p.type==="text"?p.value.replace(/\n/g,"
            "):p.type==="strong"?`${p.children.map(f).join("")}`:p.type==="emphasis"?`${p.children.map(f).join("")}`:p.type==="paragraph"?`

            ${p.children.map(f).join("")}

            `:`Unsupported markdown: ${p.type}`}return a.map(f).join("")}function b$e(i){return Intl.Segmenter?[...new Intl.Segmenter().segment(i)].map(a=>a.segment):[...i]}function w$e(i,a){const f=b$e(a.content);return uBt(i,[],f,a.type)}function uBt(i,a,f,p){if(f.length===0)return[{content:a.join(""),type:p},{content:"",type:p}];const[w,...m]=f,b=[...a,w];return i([{content:b.join(""),type:p}])?uBt(i,b,m,p):(a.length===0&&w&&(a.push(w),f.shift()),[{content:a.join(""),type:p},{content:f.join(""),type:p}])}function v$e(i,a){if(i.some(({content:f})=>f.includes(` +`)))throw new Error("splitLineToFitWidth does not support newlines in the line");return O0t(i,a)}function O0t(i,a,f=[],p=[]){if(i.length===0)return p.length>0&&f.push(p),f.length>0?f:[];let w="";i[0].content===" "&&(w=" ",i.shift());const m=i.shift()??{content:" ",type:"normal"},b=[...p];if(w!==""&&b.push({content:w,type:"normal"}),b.push(m),a(b))return O0t(i,a,f,b);if(p.length>0)f.push(p),i.unshift(m);else if(m.content){const[E,_]=w$e(a,m);f.push([E]),_.content&&i.unshift(_)}return O0t(i,a,f)}function m$e(i,a){a&&i.attr("style",a)}function y$e(i,a,f,p,w=!1){const m=i.append("foreignObject"),b=m.append("xhtml:div"),E=a.label,_=a.isNode?"nodeLabel":"edgeLabel";b.html(` + "+E+""),m$e(b,a.labelStyle),b.style("display","table-cell"),b.style("white-space","nowrap"),b.style("max-width",f+"px"),b.attr("xmlns","http://www.w3.org/1999/xhtml"),w&&b.attr("class","labelBkg");let A=b.node().getBoundingClientRect();return A.width===f&&(b.style("display","table"),b.style("white-space","break-spaces"),b.style("width",f+"px"),A=b.node().getBoundingClientRect()),m.style("width",A.width),m.style("height",A.height),m.node()}function P0t(i,a,f){return i.append("tspan").attr("class","text-outer-tspan").attr("x",0).attr("y",a*f-.1+"em").attr("dy",f+"em")}function x$e(i,a,f){const p=i.append("text"),w=P0t(p,1,a);F0t(w,f);const m=w.node().getComputedTextLength();return p.remove(),m}function k$e(i,a,f){var b;const p=i.append("text"),w=P0t(p,1,a);F0t(w,[{content:f,type:"normal"}]);const m=(b=w.node())==null?void 0:b.getBoundingClientRect();return m&&p.remove(),m}function E$e(i,a,f,p=!1){const m=a.append("g"),b=m.insert("rect").attr("class","background"),E=m.append("text").attr("y","-10.1");let _=0;for(const A of f){const I=N=>x$e(m,1.1,N)<=i,B=I(A)?[A]:v$e(A,I);for(const N of B){const R=P0t(E,_,1.1);F0t(R,N),_++}}if(p){const A=E.node().getBBox(),I=2;return b.attr("x",-I).attr("y",-I).attr("width",A.width+2*I).attr("height",A.height+2*I),m.node()}else return E.node()}function F0t(i,a){i.text(""),a.forEach((f,p)=>{const w=i.append("tspan").attr("font-style",f.type==="emphasis"?"italic":"normal").attr("class","text-inner-tspan").attr("font-weight",f.type==="strong"?"bold":"normal");p===0?w.text(f.content):w.text(" "+f.content)})}const EY=(i,a="",{style:f="",isTitle:p=!1,classes:w="",useHtmlLabels:m=!0,isNode:b=!0,width:E=200,addSvgBackground:_=!1}={})=>{if(Ut.info("createText",a,f,p,w,m,b,_),m){const A=p$e(a),I={isNode:b,label:uF(A).replace(/fa[blrs]?:fa-[\w-]+/g,N=>``),labelStyle:f.replace("fill:","color:")};return y$e(i,I,E,w,_)}else{const A=g$e(a);return E$e(E,i,A,_)}},Nd=async(i,a,f,p)=>{let w;const m=a.useHtmlLabels||o1(Oe().flowchart.htmlLabels);f?w=f:w="node default";const b=i.insert("g").attr("class",w).attr("id",a.domId||a.id),E=b.insert("g").attr("class","label").attr("style",a.labelStyle);let _;a.labelText===void 0?_="":_=typeof a.labelText=="string"?a.labelText:a.labelText[0];const A=E.node();let I;a.labelType==="markdown"?I=EY(E,Q1(uF(_),Oe()),{useHtmlLabels:m,width:a.width||Oe().flowchart.wrappingWidth,classes:"markdown-node-label"}):I=A.appendChild(gp(Q1(uF(_),Oe()),a.labelStyle,!1,p));let B=I.getBBox();const N=a.padding/2;if(o1(Oe().flowchart.htmlLabels)){const R=I.children[0],z=yr(I),W=R.getElementsByTagName("img");if(W){const et=_.replace(/]*>/g,"").trim()==="";await Promise.all([...W].map(st=>new Promise(at=>{function bt(){if(st.style.display="flex",st.style.flexDirection="column",et){const mt=Oe().fontSize?Oe().fontSize:window.getComputedStyle(document.body).fontSize,yt=5;st.style.width=parseInt(mt,10)*yt+"px"}else st.style.width="100%";at(st)}setTimeout(()=>{st.complete&&bt()}),st.addEventListener("error",bt),st.addEventListener("load",bt)})))}B=R.getBoundingClientRect(),z.attr("width",B.width),z.attr("height",B.height)}return m?E.attr("transform","translate("+-B.width/2+", "+-B.height/2+")"):E.attr("transform","translate(0, "+-B.height/2+")"),a.centerLabel&&E.attr("transform","translate("+-B.width/2+", "+-B.height/2+")"),E.insert("rect",":first-child"),{shapeSvg:b,bbox:B,halfPadding:N,label:E}},tf=(i,a)=>{const f=a.node().getBBox();i.width=f.width,i.height=f.height};function F5(i,a,f,p){return i.insert("polygon",":first-child").attr("points",p.map(function(w){return w.x+","+w.y}).join(" ")).attr("class","label-container").attr("transform","translate("+-a/2+","+f/2+")")}let Ho={},hm={},lBt={};const T$e=()=>{hm={},lBt={},Ho={}},TY=(i,a)=>(Ut.trace("In isDecendant",a," ",i," = ",hm[a].includes(i)),!!hm[a].includes(i)),C$e=(i,a)=>(Ut.info("Decendants of ",a," is ",hm[a]),Ut.info("Edge is ",i),i.v===a||i.w===a?!1:hm[a]?hm[a].includes(i.v)||TY(i.v,a)||TY(i.w,a)||hm[a].includes(i.w):(Ut.debug("Tilt, ",a,",not in decendants"),!1)),hBt=(i,a,f,p)=>{Ut.warn("Copying children of ",i,"root",p,"data",a.node(i),p);const w=a.children(i)||[];i!==p&&w.push(i),Ut.warn("Copying (nodes) clusterId",i,"nodes",w),w.forEach(m=>{if(a.children(m).length>0)hBt(m,a,f,p);else{const b=a.node(m);Ut.info("cp ",m," to ",p," with parent ",i),f.setNode(m,b),p!==a.parent(m)&&(Ut.warn("Setting parent",m,a.parent(m)),f.setParent(m,a.parent(m))),i!==p&&m!==i?(Ut.debug("Setting parent",m,i),f.setParent(m,i)):(Ut.info("In copy ",i,"root",p,"data",a.node(i),p),Ut.debug("Not Setting parent for node=",m,"cluster!==rootId",i!==p,"node!==clusterId",m!==i));const E=a.edges(m);Ut.debug("Copying Edges",E),E.forEach(_=>{Ut.info("Edge",_);const A=a.edge(_.v,_.w,_.name);Ut.info("Edge data",A,p);try{C$e(_,p)?(Ut.info("Copying as ",_.v,_.w,A,_.name),f.setEdge(_.v,_.w,A,_.name),Ut.info("newGraph edges ",f.edges(),f.edge(f.edges()[0]))):Ut.info("Skipping copy of edge ",_.v,"-->",_.w," rootId: ",p," clusterId:",i)}catch(I){Ut.error(I)}})}Ut.debug("Removing node",m),a.removeNode(m)})},fBt=(i,a)=>{const f=a.children(i);let p=[...f];for(const w of f)lBt[w]=i,p=[...p,...fBt(w,a)];return p},CF=(i,a)=>{Ut.trace("Searching",i);const f=a.children(i);if(Ut.trace("Searching children of id ",i,f),f.length<1)return Ut.trace("This is a valid node",i),i;for(const p of f){const w=CF(p,a);if(w)return Ut.trace("Found replacement for",i," => ",w),w}},CY=i=>!Ho[i]||!Ho[i].externalConnections?i:Ho[i]?Ho[i].id:i,_$e=(i,a)=>{if(!i||a>10){Ut.debug("Opting out, no graph ");return}else Ut.debug("Opting in, graph ");i.nodes().forEach(function(f){i.children(f).length>0&&(Ut.warn("Cluster identified",f," Replacement id in edges: ",CF(f,i)),hm[f]=fBt(f,i),Ho[f]={id:CF(f,i),clusterData:i.node(f)})}),i.nodes().forEach(function(f){const p=i.children(f),w=i.edges();p.length>0?(Ut.debug("Cluster identified",f,hm),w.forEach(m=>{if(m.v!==f&&m.w!==f){const b=TY(m.v,f),E=TY(m.w,f);b^E&&(Ut.warn("Edge: ",m," leaves cluster ",f),Ut.warn("Decendants of XXX ",f,": ",hm[f]),Ho[f].externalConnections=!0)}})):Ut.debug("Not a cluster ",f,hm)}),i.edges().forEach(function(f){const p=i.edge(f);Ut.warn("Edge "+f.v+" -> "+f.w+": "+JSON.stringify(f)),Ut.warn("Edge "+f.v+" -> "+f.w+": "+JSON.stringify(i.edge(f)));let w=f.v,m=f.w;if(Ut.warn("Fix XXX",Ho,"ids:",f.v,f.w,"Translating: ",Ho[f.v]," --- ",Ho[f.w]),Ho[f.v]&&Ho[f.w]&&Ho[f.v]===Ho[f.w]){Ut.warn("Fixing and trixing link to self - removing XXX",f.v,f.w,f.name),Ut.warn("Fixing and trixing - removing XXX",f.v,f.w,f.name),w=CY(f.v),m=CY(f.w),i.removeEdge(f.v,f.w,f.name);const b=f.w+"---"+f.v;i.setNode(b,{domId:b,id:b,labelStyle:"",labelText:p.label,padding:0,shape:"labelRect",style:""});const E=structuredClone(p),_=structuredClone(p);E.label="",E.arrowTypeEnd="none",_.label="",E.fromCluster=f.v,_.toCluster=f.v,i.setEdge(w,b,E,f.name+"-cyclic-special"),i.setEdge(b,m,_,f.name+"-cyclic-special")}else(Ho[f.v]||Ho[f.w])&&(Ut.warn("Fixing and trixing - removing XXX",f.v,f.w,f.name),w=CY(f.v),m=CY(f.w),i.removeEdge(f.v,f.w,f.name),w!==f.v&&(p.fromCluster=f.v),m!==f.w&&(p.toCluster=f.w),Ut.warn("Fix Replacing with XXX",w,m,f.name),i.setEdge(w,m,p,f.name))}),Ut.warn("Adjusted Graph",P5(i)),dBt(i,0),Ut.trace(Ho)},dBt=(i,a)=>{if(Ut.warn("extractor - ",a,P5(i),i.children("D")),a>10){Ut.error("Bailing out");return}let f=i.nodes(),p=!1;for(const w of f){const m=i.children(w);p=p||m.length>0}if(!p){Ut.debug("Done, no node has children",i.nodes());return}Ut.debug("Nodes = ",f,a);for(const w of f)if(Ut.debug("Extracting node",w,Ho,Ho[w]&&!Ho[w].externalConnections,!i.parent(w),i.node(w),i.children("D")," Depth ",a),!Ho[w])Ut.debug("Not a cluster",w,a);else if(!Ho[w].externalConnections&&i.children(w)&&i.children(w).length>0){Ut.warn("Cluster without external connections, without a parent and with children",w,a);let b=i.graph().rankdir==="TB"?"LR":"TB";Ho[w]&&Ho[w].clusterData&&Ho[w].clusterData.dir&&(b=Ho[w].clusterData.dir,Ut.warn("Fixing dir",Ho[w].clusterData.dir,b));const E=new c1({multigraph:!0,compound:!0}).setGraph({rankdir:b,nodesep:50,ranksep:50,marginx:8,marginy:8}).setDefaultEdgeLabel(function(){return{}});Ut.warn("Old graph before copy",P5(i)),hBt(w,i,E,w),i.setNode(w,{clusterNode:!0,id:w,clusterData:Ho[w].clusterData,labelText:Ho[w].labelText,graph:E}),Ut.warn("New graph after copy node: (",w,")",P5(E)),Ut.debug("Old graph after copy",P5(i))}else Ut.warn("Cluster ** ",w," **not meeting the criteria !externalConnections:",!Ho[w].externalConnections," no parent: ",!i.parent(w)," children ",i.children(w)&&i.children(w).length>0,i.children("D"),a),Ut.debug(Ho);f=i.nodes(),Ut.warn("New list of nodes",f);for(const w of f){const m=i.node(w);Ut.warn(" Now next level",w,m),m.clusterNode&&dBt(m.graph,a+1)}},gBt=(i,a)=>{if(a.length===0)return[];let f=Object.assign(a);return a.forEach(p=>{const w=i.children(p),m=gBt(i,w);f=[...f,...m]}),f},S$e=i=>gBt(i,i.children());function A$e(i,a){return i.intersect(a)}function pBt(i,a,f,p){var w=i.x,m=i.y,b=w-p.x,E=m-p.y,_=Math.sqrt(a*a*E*E+f*f*b*b),A=Math.abs(a*f*b/_);p.x0}function D$e(i,a,f){var p=i.x,w=i.y,m=[],b=Number.POSITIVE_INFINITY,E=Number.POSITIVE_INFINITY;typeof a.forEach=="function"?a.forEach(function(z){b=Math.min(b,z.x),E=Math.min(E,z.y)}):(b=Math.min(b,a.x),E=Math.min(E,a.y));for(var _=p-i.width/2-b,A=w-i.height/2-E,I=0;I1&&m.sort(function(z,W){var et=z.x-f.x,st=z.y-f.y,at=Math.sqrt(et*et+st*st),bt=W.x-f.x,mt=W.y-f.y,yt=Math.sqrt(bt*bt+mt*mt);return at{var f=i.x,p=i.y,w=a.x-f,m=a.y-p,b=i.width/2,E=i.height/2,_,A;return Math.abs(m)*b>Math.abs(w)*E?(m<0&&(E=-E),_=m===0?0:E*w/m,A=E):(w<0&&(b=-b),_=b,A=w===0?0:b*m/w),{x:f+_,y:p+A}},kh={node:A$e,circle:L$e,ellipse:pBt,polygon:D$e,rect:_F},I$e=async(i,a)=>{a.useHtmlLabels||Oe().flowchart.htmlLabels||(a.centerLabel=!0);const{shapeSvg:p,bbox:w,halfPadding:m}=await Nd(i,a,"node "+a.classes,!0);Ut.info("Classes = ",a.classes);const b=p.insert("rect",":first-child");return b.attr("rx",a.rx).attr("ry",a.ry).attr("x",-w.width/2-m).attr("y",-w.height/2-m).attr("width",w.width+a.padding).attr("height",w.height+a.padding),tf(a,b),a.intersect=function(E){return kh.rect(a,E)},p},wBt=i=>i?" "+i:"",jb=(i,a)=>`${a||"node default"}${wBt(i.classes)} ${wBt(i.class)}`,vBt=async(i,a)=>{const{shapeSvg:f,bbox:p}=await Nd(i,a,jb(a,void 0),!0),w=p.width+a.padding,m=p.height+a.padding,b=w+m,E=[{x:b/2,y:0},{x:b,y:-b/2},{x:b/2,y:-b},{x:0,y:-b/2}];Ut.info("Question main (Circle)");const _=F5(f,b,b,E);return _.attr("style",a.style),tf(a,_),a.intersect=function(A){return Ut.warn("Intersect called"),kh.polygon(a,E,A)},f},O$e=(i,a)=>{const f=i.insert("g").attr("class","node default").attr("id",a.domId||a.id),p=28,w=[{x:0,y:p/2},{x:p/2,y:0},{x:0,y:-p/2},{x:-p/2,y:0}];return f.insert("polygon",":first-child").attr("points",w.map(function(b){return b.x+","+b.y}).join(" ")).attr("class","state-start").attr("r",7).attr("width",28).attr("height",28),a.width=28,a.height=28,a.intersect=function(b){return kh.circle(a,14,b)},f},P$e=async(i,a)=>{const{shapeSvg:f,bbox:p}=await Nd(i,a,jb(a,void 0),!0),w=4,m=p.height+a.padding,b=m/w,E=p.width+2*b+a.padding,_=[{x:b,y:0},{x:E-b,y:0},{x:E,y:-m/2},{x:E-b,y:-m},{x:b,y:-m},{x:0,y:-m/2}],A=F5(f,E,m,_);return A.attr("style",a.style),tf(a,A),a.intersect=function(I){return kh.polygon(a,_,I)},f},F$e=async(i,a)=>{const{shapeSvg:f,bbox:p}=await Nd(i,a,jb(a,void 0),!0),w=p.width+a.padding,m=p.height+a.padding,b=[{x:-m/2,y:0},{x:w,y:0},{x:w,y:-m},{x:-m/2,y:-m},{x:0,y:-m/2}];return F5(f,w,m,b).attr("style",a.style),a.width=w+m,a.height=m,a.intersect=function(_){return kh.polygon(a,b,_)},f},N$e=async(i,a)=>{const{shapeSvg:f,bbox:p}=await Nd(i,a,jb(a),!0),w=p.width+a.padding,m=p.height+a.padding,b=[{x:-2*m/6,y:0},{x:w-m/6,y:0},{x:w+2*m/6,y:-m},{x:m/6,y:-m}],E=F5(f,w,m,b);return E.attr("style",a.style),tf(a,E),a.intersect=function(_){return kh.polygon(a,b,_)},f},B$e=async(i,a)=>{const{shapeSvg:f,bbox:p}=await Nd(i,a,jb(a,void 0),!0),w=p.width+a.padding,m=p.height+a.padding,b=[{x:2*m/6,y:0},{x:w+m/6,y:0},{x:w-2*m/6,y:-m},{x:-m/6,y:-m}],E=F5(f,w,m,b);return E.attr("style",a.style),tf(a,E),a.intersect=function(_){return kh.polygon(a,b,_)},f},R$e=async(i,a)=>{const{shapeSvg:f,bbox:p}=await Nd(i,a,jb(a,void 0),!0),w=p.width+a.padding,m=p.height+a.padding,b=[{x:-2*m/6,y:0},{x:w+2*m/6,y:0},{x:w-m/6,y:-m},{x:m/6,y:-m}],E=F5(f,w,m,b);return E.attr("style",a.style),tf(a,E),a.intersect=function(_){return kh.polygon(a,b,_)},f},j$e=async(i,a)=>{const{shapeSvg:f,bbox:p}=await Nd(i,a,jb(a,void 0),!0),w=p.width+a.padding,m=p.height+a.padding,b=[{x:m/6,y:0},{x:w-m/6,y:0},{x:w+2*m/6,y:-m},{x:-2*m/6,y:-m}],E=F5(f,w,m,b);return E.attr("style",a.style),tf(a,E),a.intersect=function(_){return kh.polygon(a,b,_)},f},$$e=async(i,a)=>{const{shapeSvg:f,bbox:p}=await Nd(i,a,jb(a,void 0),!0),w=p.width+a.padding,m=p.height+a.padding,b=[{x:0,y:0},{x:w+m/2,y:0},{x:w,y:-m/2},{x:w+m/2,y:-m},{x:0,y:-m}],E=F5(f,w,m,b);return E.attr("style",a.style),tf(a,E),a.intersect=function(_){return kh.polygon(a,b,_)},f},z$e=async(i,a)=>{const{shapeSvg:f,bbox:p}=await Nd(i,a,jb(a,void 0),!0),w=p.width+a.padding,m=w/2,b=m/(2.5+w/50),E=p.height+b+a.padding,_="M 0,"+b+" a "+m+","+b+" 0,0,0 "+w+" 0 a "+m+","+b+" 0,0,0 "+-w+" 0 l 0,"+E+" a "+m+","+b+" 0,0,0 "+w+" 0 l 0,"+-E,A=f.attr("label-offset-y",b).insert("path",":first-child").attr("style",a.style).attr("d",_).attr("transform","translate("+-w/2+","+-(E/2+b)+")");return tf(a,A),a.intersect=function(I){const B=kh.rect(a,I),N=B.x-a.x;if(m!=0&&(Math.abs(N)a.height/2-b)){let R=b*b*(1-N*N/(m*m));R!=0&&(R=Math.sqrt(R)),R=b-R,I.y-a.y>0&&(R=-R),B.y+=R}return B},f},q$e=async(i,a)=>{const{shapeSvg:f,bbox:p,halfPadding:w}=await Nd(i,a,"node "+a.classes+" "+a.class,!0),m=f.insert("rect",":first-child"),b=p.width+a.padding,E=p.height+a.padding;if(m.attr("class","basic label-container").attr("style",a.style).attr("rx",a.rx).attr("ry",a.ry).attr("x",-p.width/2-w).attr("y",-p.height/2-w).attr("width",b).attr("height",E),a.props){const _=new Set(Object.keys(a.props));a.props.borders&&(mBt(m,a.props.borders,b,E),_.delete("borders")),_.forEach(A=>{Ut.warn(`Unknown node property ${A}`)})}return tf(a,m),a.intersect=function(_){return kh.rect(a,_)},f},H$e=async(i,a)=>{const{shapeSvg:f}=await Nd(i,a,"label",!0);Ut.trace("Classes = ",a.class);const p=f.insert("rect",":first-child"),w=0,m=0;if(p.attr("width",w).attr("height",m),f.attr("class","label edgeLabel"),a.props){const b=new Set(Object.keys(a.props));a.props.borders&&(mBt(p,a.props.borders,w,m),b.delete("borders")),b.forEach(E=>{Ut.warn(`Unknown node property ${E}`)})}return tf(a,p),a.intersect=function(b){return kh.rect(a,b)},f};function mBt(i,a,f,p){const w=[],m=E=>{w.push(E,0)},b=E=>{w.push(0,E)};a.includes("t")?(Ut.debug("add top border"),m(f)):b(f),a.includes("r")?(Ut.debug("add right border"),m(p)):b(p),a.includes("b")?(Ut.debug("add bottom border"),m(f)):b(f),a.includes("l")?(Ut.debug("add left border"),m(p)):b(p),i.attr("stroke-dasharray",w.join(" "))}const V$e=(i,a)=>{let f;a.classes?f="node "+a.classes:f="node default";const p=i.insert("g").attr("class",f).attr("id",a.domId||a.id),w=p.insert("rect",":first-child"),m=p.insert("line"),b=p.insert("g").attr("class","label"),E=a.labelText.flat?a.labelText.flat():a.labelText;let _="";typeof E=="object"?_=E[0]:_=E,Ut.info("Label text abc79",_,E,typeof E=="object");const A=b.node().appendChild(gp(_,a.labelStyle,!0,!0));let I={width:0,height:0};if(o1(Oe().flowchart.htmlLabels)){const W=A.children[0],et=yr(A);I=W.getBoundingClientRect(),et.attr("width",I.width),et.attr("height",I.height)}Ut.info("Text 2",E);const B=E.slice(1,E.length);let N=A.getBBox();const R=b.node().appendChild(gp(B.join?B.join("
            "):B,a.labelStyle,!0,!0));if(o1(Oe().flowchart.htmlLabels)){const W=R.children[0],et=yr(R);I=W.getBoundingClientRect(),et.attr("width",I.width),et.attr("height",I.height)}const z=a.padding/2;return yr(R).attr("transform","translate( "+(I.width>N.width?0:(N.width-I.width)/2)+", "+(N.height+z+5)+")"),yr(A).attr("transform","translate( "+(I.width{const{shapeSvg:f,bbox:p}=await Nd(i,a,jb(a,void 0),!0),w=p.height+a.padding,m=p.width+w/4+a.padding,b=f.insert("rect",":first-child").attr("style",a.style).attr("rx",w/2).attr("ry",w/2).attr("x",-m/2).attr("y",-w/2).attr("width",m).attr("height",w);return tf(a,b),a.intersect=function(E){return kh.rect(a,E)},f},U$e=async(i,a)=>{const{shapeSvg:f,bbox:p,halfPadding:w}=await Nd(i,a,jb(a,void 0),!0),m=f.insert("circle",":first-child");return m.attr("style",a.style).attr("rx",a.rx).attr("ry",a.ry).attr("r",p.width/2+w).attr("width",p.width+a.padding).attr("height",p.height+a.padding),Ut.info("Circle main"),tf(a,m),a.intersect=function(b){return Ut.info("Circle intersect",a,p.width/2+w,b),kh.circle(a,p.width/2+w,b)},f},W$e=async(i,a)=>{const{shapeSvg:f,bbox:p,halfPadding:w}=await Nd(i,a,jb(a,void 0),!0),m=5,b=f.insert("g",":first-child"),E=b.insert("circle"),_=b.insert("circle");return b.attr("class",a.class),E.attr("style",a.style).attr("rx",a.rx).attr("ry",a.ry).attr("r",p.width/2+w+m).attr("width",p.width+a.padding+m*2).attr("height",p.height+a.padding+m*2),_.attr("style",a.style).attr("rx",a.rx).attr("ry",a.ry).attr("r",p.width/2+w).attr("width",p.width+a.padding).attr("height",p.height+a.padding),Ut.info("DoubleCircle main"),tf(a,E),a.intersect=function(A){return Ut.info("DoubleCircle intersect",a,p.width/2+w+m,A),kh.circle(a,p.width/2+w+m,A)},f},Y$e=async(i,a)=>{const{shapeSvg:f,bbox:p}=await Nd(i,a,jb(a,void 0),!0),w=p.width+a.padding,m=p.height+a.padding,b=[{x:0,y:0},{x:w,y:0},{x:w,y:-m},{x:0,y:-m},{x:0,y:0},{x:-8,y:0},{x:w+8,y:0},{x:w+8,y:-m},{x:-8,y:-m},{x:-8,y:0}],E=F5(f,w,m,b);return E.attr("style",a.style),tf(a,E),a.intersect=function(_){return kh.polygon(a,b,_)},f},K$e=(i,a)=>{const f=i.insert("g").attr("class","node default").attr("id",a.domId||a.id),p=f.insert("circle",":first-child");return p.attr("class","state-start").attr("r",7).attr("width",14).attr("height",14),tf(a,p),a.intersect=function(w){return kh.circle(a,7,w)},f},yBt=(i,a,f)=>{const p=i.insert("g").attr("class","node default").attr("id",a.domId||a.id);let w=70,m=10;f==="LR"&&(w=10,m=70);const b=p.append("rect").attr("x",-1*w/2).attr("y",-1*m/2).attr("width",w).attr("height",m).attr("class","fork-join");return tf(a,b),a.height=a.height+a.padding/2,a.width=a.width+a.padding/2,a.intersect=function(E){return kh.rect(a,E)},p},xBt={rhombus:vBt,question:vBt,rect:q$e,labelRect:H$e,rectWithTitle:V$e,choice:O$e,circle:U$e,doublecircle:W$e,stadium:G$e,hexagon:P$e,rect_left_inv_arrow:F$e,lean_right:N$e,lean_left:B$e,trapezoid:R$e,inv_trapezoid:j$e,rect_right_inv_arrow:$$e,cylinder:z$e,start:K$e,end:(i,a)=>{const f=i.insert("g").attr("class","node default").attr("id",a.domId||a.id),p=f.insert("circle",":first-child"),w=f.insert("circle",":first-child");return w.attr("class","state-start").attr("r",7).attr("width",14).attr("height",14),p.attr("class","state-end").attr("r",5).attr("width",10).attr("height",10),tf(a,w),a.intersect=function(m){return kh.circle(a,7,m)},f},note:I$e,subroutine:Y$e,fork:yBt,join:yBt,class_box:(i,a)=>{const f=a.padding/2,p=4,w=8;let m;a.classes?m="node "+a.classes:m="node default";const b=i.insert("g").attr("class",m).attr("id",a.domId||a.id),E=b.insert("rect",":first-child"),_=b.insert("line"),A=b.insert("line");let I=0,B=p;const N=b.insert("g").attr("class","label");let R=0;const z=a.classData.annotations&&a.classData.annotations[0],W=a.classData.annotations[0]?"«"+a.classData.annotations[0]+"»":"",et=N.node().appendChild(gp(W,a.labelStyle,!0,!0));let st=et.getBBox();if(o1(Oe().flowchart.htmlLabels)){const vt=et.children[0],X=yr(et);st=vt.getBoundingClientRect(),X.attr("width",st.width),X.attr("height",st.height)}a.classData.annotations[0]&&(B+=st.height+p,I+=st.width);let at=a.classData.label;a.classData.type!==void 0&&a.classData.type!==""&&(Oe().flowchart.htmlLabels?at+="<"+a.classData.type+">":at+="<"+a.classData.type+">");const bt=N.node().appendChild(gp(at,a.labelStyle,!0,!0));yr(bt).attr("class","classTitle");let mt=bt.getBBox();if(o1(Oe().flowchart.htmlLabels)){const vt=bt.children[0],X=yr(bt);mt=vt.getBoundingClientRect(),X.attr("width",mt.width),X.attr("height",mt.height)}B+=mt.height+p,mt.width>I&&(I=mt.width);const yt=[];a.classData.members.forEach(vt=>{const X=vt.getDisplayDetails();let pt=X.displayText;Oe().flowchart.htmlLabels&&(pt=pt.replace(//g,">"));const U=N.node().appendChild(gp(pt,X.cssStyle?X.cssStyle:a.labelStyle,!0,!0));let Tt=U.getBBox();if(o1(Oe().flowchart.htmlLabels)){const nt=U.children[0],It=yr(U);Tt=nt.getBoundingClientRect(),It.attr("width",Tt.width),It.attr("height",Tt.height)}Tt.width>I&&(I=Tt.width),B+=Tt.height+p,yt.push(U)}),B+=w;const ft=[];if(a.classData.methods.forEach(vt=>{const X=vt.getDisplayDetails();let pt=X.displayText;Oe().flowchart.htmlLabels&&(pt=pt.replace(//g,">"));const U=N.node().appendChild(gp(pt,X.cssStyle?X.cssStyle:a.labelStyle,!0,!0));let Tt=U.getBBox();if(o1(Oe().flowchart.htmlLabels)){const nt=U.children[0],It=yr(U);Tt=nt.getBoundingClientRect(),It.attr("width",Tt.width),It.attr("height",Tt.height)}Tt.width>I&&(I=Tt.width),B+=Tt.height+p,ft.push(U)}),B+=w,z){let vt=(I-st.width)/2;yr(et).attr("transform","translate( "+(-1*I/2+vt)+", "+-1*B/2+")"),R=st.height+p}let ut=(I-mt.width)/2;return yr(bt).attr("transform","translate( "+(-1*I/2+ut)+", "+(-1*B/2+R)+")"),R+=mt.height+p,_.attr("class","divider").attr("x1",-I/2-f).attr("x2",I/2+f).attr("y1",-B/2-f+w+R).attr("y2",-B/2-f+w+R),R+=w,yt.forEach(vt=>{yr(vt).attr("transform","translate( "+-I/2+", "+(-1*B/2+R+w/2)+")");const X=vt==null?void 0:vt.getBBox();R+=((X==null?void 0:X.height)??0)+p}),R+=w,A.attr("class","divider").attr("x1",-I/2-f).attr("x2",I/2+f).attr("y1",-B/2-f+w+R).attr("y2",-B/2-f+w+R),R+=w,ft.forEach(vt=>{yr(vt).attr("transform","translate( "+-I/2+", "+(-1*B/2+R)+")");const X=vt==null?void 0:vt.getBBox();R+=((X==null?void 0:X.height)??0)+p}),E.attr("class","outer title-state").attr("x",-I/2-f).attr("y",-(B/2)-f).attr("width",I+a.padding).attr("height",B+a.padding),tf(a,E),a.intersect=function(vt){return kh.rect(a,vt)},b}};let cL={};const kBt=async(i,a,f)=>{let p,w;if(a.link){let m;Oe().securityLevel==="sandbox"?m="_top":a.linkTarget&&(m=a.linkTarget||"_blank"),p=i.insert("svg:a").attr("xlink:href",a.link).attr("target",m),w=await xBt[a.shape](p,a,f)}else w=await xBt[a.shape](i,a,f),p=w;return a.tooltip&&w.attr("title",a.tooltip),a.class&&w.attr("class","node default "+a.class),cL[a.id]=p,a.haveCallback&&cL[a.id].attr("class",cL[a.id].attr("class")+" clickable"),p},X$e=(i,a)=>{cL[a.id]=i},Q$e=()=>{cL={}},EBt=i=>{const a=cL[i.id];Ut.trace("Transforming node",i.diff,i,"translate("+(i.x-i.width/2-5)+", "+i.width/2+")");const f=8,p=i.diff||0;return i.clusterNode?a.attr("transform","translate("+(i.x+p-i.width/2)+", "+(i.y-i.height/2-f)+")"):a.attr("transform","translate("+i.x+", "+i.y+")"),p},Z$e={rect:(i,a)=>{Ut.info("Creating subgraph rect for ",a.id,a);const f=i.insert("g").attr("class","cluster"+(a.class?" "+a.class:"")).attr("id",a.id),p=f.insert("rect",":first-child"),w=o1(Oe().flowchart.htmlLabels),m=f.insert("g").attr("class","cluster-label"),b=a.labelType==="markdown"?EY(m,a.labelText,{style:a.labelStyle,useHtmlLabels:w}):m.node().appendChild(gp(a.labelText,a.labelStyle,void 0,!0));let E=b.getBBox();if(o1(Oe().flowchart.htmlLabels)){const N=b.children[0],R=yr(b);E=N.getBoundingClientRect(),R.attr("width",E.width),R.attr("height",E.height)}const _=0*a.padding,A=_/2,I=a.width<=E.width+_?E.width+_:a.width;a.width<=E.width+_?a.diff=(E.width-a.width)/2-a.padding/2:a.diff=-a.padding/2,Ut.trace("Data ",a,JSON.stringify(a)),p.attr("style",a.style).attr("rx",a.rx).attr("ry",a.ry).attr("x",a.x-I/2).attr("y",a.y-a.height/2-A).attr("width",I).attr("height",a.height+_),w?m.attr("transform","translate("+(a.x-E.width/2)+", "+(a.y-a.height/2)+")"):m.attr("transform","translate("+a.x+", "+(a.y-a.height/2)+")");const B=p.node().getBBox();return a.width=B.width,a.height=B.height,a.intersect=function(N){return _F(a,N)},f},roundedWithTitle:(i,a)=>{const f=i.insert("g").attr("class",a.classes).attr("id",a.id),p=f.insert("rect",":first-child"),w=f.insert("g").attr("class","cluster-label"),m=f.append("rect"),b=w.node().appendChild(gp(a.labelText,a.labelStyle,void 0,!0));let E=b.getBBox();if(o1(Oe().flowchart.htmlLabels)){const N=b.children[0],R=yr(b);E=N.getBoundingClientRect(),R.attr("width",E.width),R.attr("height",E.height)}E=b.getBBox();const _=0*a.padding,A=_/2,I=a.width<=E.width+a.padding?E.width+a.padding:a.width;a.width<=E.width+a.padding?a.diff=(E.width+a.padding*0-a.width)/2:a.diff=-a.padding/2,p.attr("class","outer").attr("x",a.x-I/2-A).attr("y",a.y-a.height/2-A).attr("width",I+_).attr("height",a.height+_),m.attr("class","inner").attr("x",a.x-I/2-A).attr("y",a.y-a.height/2-A+E.height-1).attr("width",I+_).attr("height",a.height+_-E.height-3),w.attr("transform","translate("+(a.x-E.width/2)+", "+(a.y-a.height/2-a.padding/3+(o1(Oe().flowchart.htmlLabels)?5:3))+")");const B=p.node().getBBox();return a.height=B.height,a.intersect=function(N){return _F(a,N)},f},noteGroup:(i,a)=>{const f=i.insert("g").attr("class","note-cluster").attr("id",a.id),p=f.insert("rect",":first-child"),w=0*a.padding,m=w/2;p.attr("rx",a.rx).attr("ry",a.ry).attr("x",a.x-a.width/2-m).attr("y",a.y-a.height/2-m).attr("width",a.width+w).attr("height",a.height+w).attr("fill","none");const b=p.node().getBBox();return a.width=b.width,a.height=b.height,a.intersect=function(E){return _F(a,E)},f},divider:(i,a)=>{const f=i.insert("g").attr("class",a.classes).attr("id",a.id),p=f.insert("rect",":first-child"),w=0*a.padding,m=w/2;p.attr("class","divider").attr("x",a.x-a.width/2-m).attr("y",a.y-a.height/2).attr("width",a.width+w).attr("height",a.height+w);const b=p.node().getBBox();return a.width=b.width,a.height=b.height,a.diff=-a.padding/2,a.intersect=function(E){return _F(a,E)},f}};let TBt={};const J$e=(i,a)=>{Ut.trace("Inserting cluster");const f=a.shape||"rect";TBt[a.id]=Z$e[f](i,a)},tze=()=>{TBt={}},vk={aggregation:18,extension:18,composition:18,dependency:6,lollipop:13.5,arrow_point:5.3};function _Y(i,a){i=SY(i),a=SY(a);const[f,p]=[i.x,i.y],[w,m]=[a.x,a.y],b=w-f,E=m-p;return{angle:Math.atan(E/b),deltaX:b,deltaY:E}}const SY=i=>Array.isArray(i)?{x:i[0],y:i[1]}:i,CBt=i=>({x:function(a,f,p){let w=0;if(f===0&&Object.hasOwn(vk,i.arrowTypeStart)){const{angle:m,deltaX:b}=_Y(p[0],p[1]);w=vk[i.arrowTypeStart]*Math.cos(m)*(b>=0?1:-1)}else if(f===p.length-1&&Object.hasOwn(vk,i.arrowTypeEnd)){const{angle:m,deltaX:b}=_Y(p[p.length-1],p[p.length-2]);w=vk[i.arrowTypeEnd]*Math.cos(m)*(b>=0?1:-1)}return SY(a).x+w},y:function(a,f,p){let w=0;if(f===0&&Object.hasOwn(vk,i.arrowTypeStart)){const{angle:m,deltaY:b}=_Y(p[0],p[1]);w=vk[i.arrowTypeStart]*Math.abs(Math.sin(m))*(b>=0?1:-1)}else if(f===p.length-1&&Object.hasOwn(vk,i.arrowTypeEnd)){const{angle:m,deltaY:b}=_Y(p[p.length-1],p[p.length-2]);w=vk[i.arrowTypeEnd]*Math.abs(Math.sin(m))*(b>=0?1:-1)}return SY(a).y+w}});let AY={},Bd={};const eze=()=>{AY={},Bd={}},_Bt=(i,a)=>{const f=o1(Oe().flowchart.htmlLabels),p=a.labelType==="markdown"?EY(i,a.label,{style:a.labelStyle,useHtmlLabels:f,addSvgBackground:!0}):gp(a.label,a.labelStyle);Ut.info("abc82",a,a.labelType);const w=i.insert("g").attr("class","edgeLabel"),m=w.insert("g").attr("class","label");m.node().appendChild(p);let b=p.getBBox();if(f){const _=p.children[0],A=yr(p);b=_.getBoundingClientRect(),A.attr("width",b.width),A.attr("height",b.height)}m.attr("transform","translate("+-b.width/2+", "+-b.height/2+")"),AY[a.id]=w,a.width=b.width,a.height=b.height;let E;if(a.startLabelLeft){const _=gp(a.startLabelLeft,a.labelStyle),A=i.insert("g").attr("class","edgeTerminals"),I=A.insert("g").attr("class","inner");E=I.node().appendChild(_);const B=_.getBBox();I.attr("transform","translate("+-B.width/2+", "+-B.height/2+")"),Bd[a.id]||(Bd[a.id]={}),Bd[a.id].startLeft=A,LY(E,a.startLabelLeft)}if(a.startLabelRight){const _=gp(a.startLabelRight,a.labelStyle),A=i.insert("g").attr("class","edgeTerminals"),I=A.insert("g").attr("class","inner");E=A.node().appendChild(_),I.node().appendChild(_);const B=_.getBBox();I.attr("transform","translate("+-B.width/2+", "+-B.height/2+")"),Bd[a.id]||(Bd[a.id]={}),Bd[a.id].startRight=A,LY(E,a.startLabelRight)}if(a.endLabelLeft){const _=gp(a.endLabelLeft,a.labelStyle),A=i.insert("g").attr("class","edgeTerminals"),I=A.insert("g").attr("class","inner");E=I.node().appendChild(_);const B=_.getBBox();I.attr("transform","translate("+-B.width/2+", "+-B.height/2+")"),A.node().appendChild(_),Bd[a.id]||(Bd[a.id]={}),Bd[a.id].endLeft=A,LY(E,a.endLabelLeft)}if(a.endLabelRight){const _=gp(a.endLabelRight,a.labelStyle),A=i.insert("g").attr("class","edgeTerminals"),I=A.insert("g").attr("class","inner");E=I.node().appendChild(_);const B=_.getBBox();I.attr("transform","translate("+-B.width/2+", "+-B.height/2+")"),A.node().appendChild(_),Bd[a.id]||(Bd[a.id]={}),Bd[a.id].endRight=A,LY(E,a.endLabelRight)}return p};function LY(i,a){Oe().flowchart.htmlLabels&&i&&(i.style.width=a.length*9+"px",i.style.height="12px")}const nze=(i,a)=>{Ut.info("Moving label abc78 ",i.id,i.label,AY[i.id]);let f=a.updatedPath?a.updatedPath:a.originalPath;if(i.label){const p=AY[i.id];let w=i.x,m=i.y;if(f){const b=$a.calcLabelPosition(f);Ut.info("Moving label "+i.label+" from (",w,",",m,") to (",b.x,",",b.y,") abc78"),a.updatedPath&&(w=b.x,m=b.y)}p.attr("transform","translate("+w+", "+m+")")}if(i.startLabelLeft){const p=Bd[i.id].startLeft;let w=i.x,m=i.y;if(f){const b=$a.calcTerminalLabelPosition(i.arrowTypeStart?10:0,"start_left",f);w=b.x,m=b.y}p.attr("transform","translate("+w+", "+m+")")}if(i.startLabelRight){const p=Bd[i.id].startRight;let w=i.x,m=i.y;if(f){const b=$a.calcTerminalLabelPosition(i.arrowTypeStart?10:0,"start_right",f);w=b.x,m=b.y}p.attr("transform","translate("+w+", "+m+")")}if(i.endLabelLeft){const p=Bd[i.id].endLeft;let w=i.x,m=i.y;if(f){const b=$a.calcTerminalLabelPosition(i.arrowTypeEnd?10:0,"end_left",f);w=b.x,m=b.y}p.attr("transform","translate("+w+", "+m+")")}if(i.endLabelRight){const p=Bd[i.id].endRight;let w=i.x,m=i.y;if(f){const b=$a.calcTerminalLabelPosition(i.arrowTypeEnd?10:0,"end_right",f);w=b.x,m=b.y}p.attr("transform","translate("+w+", "+m+")")}},rze=(i,a)=>{const f=i.x,p=i.y,w=Math.abs(a.x-f),m=Math.abs(a.y-p),b=i.width/2,E=i.height/2;return w>=b||m>=E},ize=(i,a,f)=>{Ut.warn(`intersection calc abc89: + outsidePoint: ${JSON.stringify(a)} + insidePoint : ${JSON.stringify(f)} + node : x:${i.x} y:${i.y} w:${i.width} h:${i.height}`);const p=i.x,w=i.y,m=Math.abs(p-f.x),b=i.width/2;let E=f.xMath.abs(p-a.x)*_){let B=f.y{Ut.warn("abc88 cutPathAtIntersect",i,a);let f=[],p=i[0],w=!1;return i.forEach(m=>{if(Ut.info("abc88 checking point",m,a),!rze(a,m)&&!w){const b=ize(a,p,m);Ut.warn("abc88 inside",m,p,b),Ut.warn("abc88 intersection",b);let E=!1;f.forEach(_=>{E=E||_.x===b.x&&_.y===b.y}),f.some(_=>_.x===b.x&&_.y===b.y)?Ut.warn("abc88 no intersect",b,f):f.push(b),w=!0}else Ut.warn("abc88 outside",m,p),p=m,w||f.push(m)}),Ut.warn("abc88 returning points",f),f},sze=function(i,a,f,p,w,m,b){let E=f.points,_=!1;const A=m.node(a.v);var I=m.node(a.w);Ut.info("abc88 InsertEdge: ",f),I.intersect&&A.intersect&&(E=E.slice(1,f.points.length-1),E.unshift(A.intersect(E[0])),Ut.info("Last point",E[E.length-1],I,I.intersect(E[E.length-1])),E.push(I.intersect(E[E.length-1]))),f.toCluster&&(Ut.info("to cluster abc88",p[f.toCluster]),E=SBt(f.points,p[f.toCluster].node),_=!0),f.fromCluster&&(Ut.info("from cluster abc88",p[f.fromCluster]),E=SBt(E.reverse(),p[f.fromCluster].node).reverse(),_=!0);const B=E.filter(mt=>!Number.isNaN(mt.y));let N=HP;f.curve&&(w==="graph"||w==="flowchart")&&(N=f.curve);const{x:R,y:z}=CBt(f),W=E5().x(R).y(z).curve(N);let et;switch(f.thickness){case"normal":et="edge-thickness-normal";break;case"thick":et="edge-thickness-thick";break;case"invisible":et="edge-thickness-thick";break;default:et=""}switch(f.pattern){case"solid":et+=" edge-pattern-solid";break;case"dotted":et+=" edge-pattern-dotted";break;case"dashed":et+=" edge-pattern-dashed";break}const st=i.append("path").attr("d",W(B)).attr("id",f.id).attr("class"," "+et+(f.classes?" "+f.classes:"")).attr("style",f.style);let at="";switch((Oe().flowchart.arrowMarkerAbsolute||Oe().state.arrowMarkerAbsolute)&&(at=window.location.protocol+"//"+window.location.host+window.location.pathname+window.location.search,at=at.replace(/\(/g,"\\("),at=at.replace(/\)/g,"\\)")),Ut.info("arrowTypeStart",f.arrowTypeStart),Ut.info("arrowTypeEnd",f.arrowTypeEnd),f.arrowTypeStart){case"arrow_cross":st.attr("marker-start","url("+at+"#"+b+"_"+w+"-crossStart)");break;case"arrow_point":st.attr("marker-start","url("+at+"#"+b+"_"+w+"-pointStart)");break;case"arrow_barb":st.attr("marker-start","url("+at+"#"+b+"_"+w+"-barbStart)");break;case"arrow_circle":st.attr("marker-start","url("+at+"#"+b+"_"+w+"-circleStart)");break;case"aggregation":st.attr("marker-start","url("+at+"#"+b+"_"+w+"-aggregationStart)");break;case"extension":st.attr("marker-start","url("+at+"#"+b+"_"+w+"-extensionStart)");break;case"composition":st.attr("marker-start","url("+at+"#"+b+"_"+w+"-compositionStart)");break;case"dependency":st.attr("marker-start","url("+at+"#"+b+"_"+w+"-dependencyStart)");break;case"lollipop":st.attr("marker-start","url("+at+"#"+b+"_"+w+"-lollipopStart)");break}switch(f.arrowTypeEnd){case"arrow_cross":st.attr("marker-end","url("+at+"#"+b+"_"+w+"-crossEnd)");break;case"arrow_point":st.attr("marker-end","url("+at+"#"+b+"_"+w+"-pointEnd)");break;case"arrow_barb":st.attr("marker-end","url("+at+"#"+b+"_"+w+"-barbEnd)");break;case"arrow_circle":st.attr("marker-end","url("+at+"#"+b+"_"+w+"-circleEnd)");break;case"aggregation":st.attr("marker-end","url("+at+"#"+b+"_"+w+"-aggregationEnd)");break;case"extension":st.attr("marker-end","url("+at+"#"+b+"_"+w+"-extensionEnd)");break;case"composition":st.attr("marker-end","url("+at+"#"+b+"_"+w+"-compositionEnd)");break;case"dependency":st.attr("marker-end","url("+at+"#"+b+"_"+w+"-dependencyEnd)");break;case"lollipop":st.attr("marker-end","url("+at+"#"+b+"_"+w+"-lollipopEnd)");break}let bt={};return _&&(bt.updatedPath=E),bt.originalPath=f.points,bt},ABt=async(i,a,f,p,w)=>{Ut.info("Graph in recursive render: XXX",P5(a),w);const m=a.graph().rankdir;Ut.trace("Dir in recursive render - dir:",m);const b=i.insert("g").attr("class","root");a.nodes()?Ut.info("Recursive render XXX",a.nodes()):Ut.info("No nodes found for",a),a.edges().length>0&&Ut.trace("Recursive edges",a.edge(a.edges()[0]));const E=b.insert("g").attr("class","clusters"),_=b.insert("g").attr("class","edgePaths"),A=b.insert("g").attr("class","edgeLabels"),I=b.insert("g").attr("class","nodes");await Promise.all(a.nodes().map(async function(N){const R=a.node(N);if(w!==void 0){const z=JSON.parse(JSON.stringify(w.clusterData));Ut.info("Setting data for cluster XXX (",N,") ",z,w),a.setNode(w.id,z),a.parent(N)||(Ut.trace("Setting parent",N,w.id),a.setParent(N,w.id,z))}if(Ut.info("(Insert) Node XXX"+N+": "+JSON.stringify(a.node(N))),R&&R.clusterNode){Ut.info("Cluster identified",N,R.width,a.node(N));const z=await ABt(I,R.graph,f,p,a.node(N)),W=z.elem;tf(R,W),R.diff=z.diff||0,Ut.info("Node bounds (abc123)",N,R,R.width,R.x,R.y),X$e(W,R),Ut.warn("Recursive render complete ",W,R)}else a.children(N).length>0?(Ut.info("Cluster - the non recursive path XXX",N,R.id,R,a),Ut.info(CF(R.id,a)),Ho[R.id]={id:CF(R.id,a),node:R}):(Ut.info("Node - the non recursive path",N,R.id,R),await kBt(I,a.node(N),m))})),a.edges().forEach(function(N){const R=a.edge(N.v,N.w,N.name);Ut.info("Edge "+N.v+" -> "+N.w+": "+JSON.stringify(N)),Ut.info("Edge "+N.v+" -> "+N.w+": ",N," ",JSON.stringify(a.edge(N))),Ut.info("Fix",Ho,"ids:",N.v,N.w,"Translateing: ",Ho[N.v],Ho[N.w]),_Bt(A,R)}),a.edges().forEach(function(N){Ut.info("Edge "+N.v+" -> "+N.w+": "+JSON.stringify(N))}),Ut.info("#############################################"),Ut.info("### Layout ###"),Ut.info("#############################################"),Ut.info(a),aL(a),Ut.info("Graph after layout:",P5(a));let B=0;return S$e(a).forEach(function(N){const R=a.node(N);Ut.info("Position "+N+": "+JSON.stringify(a.node(N))),Ut.info("Position "+N+": ("+R.x,","+R.y,") width: ",R.width," height: ",R.height),R&&R.clusterNode?EBt(R):a.children(N).length>0?(J$e(E,R),Ho[R.id].node=R):EBt(R)}),a.edges().forEach(function(N){const R=a.edge(N);Ut.info("Edge "+N.v+" -> "+N.w+": "+JSON.stringify(R),R);const z=sze(_,N,R,Ho,f,a,p);nze(R,z)}),a.nodes().forEach(function(N){const R=a.node(N);Ut.info(N,R.type,R.diff),R.type==="group"&&(B=R.diff)}),{elem:b,diff:B}},N0t=async(i,a,f,p,w)=>{PNt(i,f,p,w),Q$e(),eze(),tze(),T$e(),Ut.warn("Graph at first:",JSON.stringify(P5(a))),_$e(a),Ut.warn("Graph after:",JSON.stringify(P5(a))),await ABt(i,a,p,w)},LBt={},aze=function(i){const a=Object.keys(i);for(const f of a)LBt[f]=i[f]},MBt=function(i,a,f,p,w,m){const b=p.select(`[id="${f}"]`);Object.keys(i).forEach(function(_){const A=i[_];let I="default";A.classes.length>0&&(I=A.classes.join(" ")),I=I+" flowchart-label";const B=im(A.styles);let N=A.text!==void 0?A.text:A.id,R;if(Ut.info("vertex",A,A.labelType),A.labelType==="markdown")Ut.info("vertex",A,A.labelType);else if(o1(Oe().flowchart.htmlLabels)){const et={label:N.replace(/fa[blrs]?:fa-[\w-]+/g,st=>``)};R=b0t(b,et).node(),R.parentNode.removeChild(R)}else{const et=w.createElementNS("http://www.w3.org/2000/svg","text");et.setAttribute("style",B.labelStyle.replace("color:","fill:"));const st=N.split(Kr.lineBreakRegex);for(const at of st){const bt=w.createElementNS("http://www.w3.org/2000/svg","tspan");bt.setAttributeNS("http://www.w3.org/XML/1998/namespace","xml:space","preserve"),bt.setAttribute("dy","1em"),bt.setAttribute("x","1"),bt.textContent=at,et.appendChild(bt)}R=et}let z=0,W="";switch(A.type){case"round":z=5,W="rect";break;case"square":W="rect";break;case"diamond":W="question";break;case"hexagon":W="hexagon";break;case"odd":W="rect_left_inv_arrow";break;case"lean_right":W="lean_right";break;case"lean_left":W="lean_left";break;case"trapezoid":W="trapezoid";break;case"inv_trapezoid":W="inv_trapezoid";break;case"odd_right":W="rect_left_inv_arrow";break;case"circle":W="circle";break;case"ellipse":W="ellipse";break;case"stadium":W="stadium";break;case"subroutine":W="subroutine";break;case"cylinder":W="cylinder";break;case"group":W="rect";break;case"doublecircle":W="doublecircle";break;default:W="rect"}a.setNode(A.id,{labelStyle:B.labelStyle,shape:W,labelText:N,labelType:A.labelType,rx:z,ry:z,class:I,style:B.style,id:A.id,link:A.link,linkTarget:A.linkTarget,tooltip:m.db.getTooltip(A.id)||"",domId:m.db.lookUpDomId(A.id),haveCallback:A.haveCallback,width:A.type==="group"?500:void 0,dir:A.dir,type:A.type,props:A.props,padding:Oe().flowchart.padding}),Ut.info("setNode",{labelStyle:B.labelStyle,labelType:A.labelType,shape:W,labelText:N,rx:z,ry:z,class:I,style:B.style,id:A.id,domId:m.db.lookUpDomId(A.id),width:A.type==="group"?500:void 0,type:A.type,dir:A.dir,props:A.props,padding:Oe().flowchart.padding})})},DBt=function(i,a,f){Ut.info("abc78 edges = ",i);let p=0,w={},m,b;if(i.defaultStyle!==void 0){const E=im(i.defaultStyle);m=E.style,b=E.labelStyle}i.forEach(function(E){p++;const _="L-"+E.start+"-"+E.end;w[_]===void 0?(w[_]=0,Ut.info("abc78 new entry",_,w[_])):(w[_]++,Ut.info("abc78 new entry",_,w[_]));let A=_+"-"+w[_];Ut.info("abc78 new link id to be used is",_,A,w[_]);const I="LS-"+E.start,B="LE-"+E.end,N={style:"",labelStyle:""};switch(N.minlen=E.length||1,E.type==="arrow_open"?N.arrowhead="none":N.arrowhead="normal",N.arrowTypeStart="arrow_open",N.arrowTypeEnd="arrow_open",E.type){case"double_arrow_cross":N.arrowTypeStart="arrow_cross";case"arrow_cross":N.arrowTypeEnd="arrow_cross";break;case"double_arrow_point":N.arrowTypeStart="arrow_point";case"arrow_point":N.arrowTypeEnd="arrow_point";break;case"double_arrow_circle":N.arrowTypeStart="arrow_circle";case"arrow_circle":N.arrowTypeEnd="arrow_circle";break}let R="",z="";switch(E.stroke){case"normal":R="fill:none;",m!==void 0&&(R=m),b!==void 0&&(z=b),N.thickness="normal",N.pattern="solid";break;case"dotted":N.thickness="normal",N.pattern="dotted",N.style="fill:none;stroke-width:2px;stroke-dasharray:3;";break;case"thick":N.thickness="thick",N.pattern="solid",N.style="stroke-width: 3.5px;fill:none;";break;case"invisible":N.thickness="invisible",N.pattern="solid",N.style="stroke-width: 0;fill:none;";break}if(E.style!==void 0){const W=im(E.style);R=W.style,z=W.labelStyle}N.style=N.style+=R,N.labelStyle=N.labelStyle+=z,E.interpolate!==void 0?N.curve=ew(E.interpolate,cg):i.defaultInterpolate!==void 0?N.curve=ew(i.defaultInterpolate,cg):N.curve=ew(LBt.curve,cg),E.text===void 0?E.style!==void 0&&(N.arrowheadStyle="fill: #333"):(N.arrowheadStyle="fill: #333",N.labelpos="c"),N.labelType=E.labelType,N.label=E.text.replace(Kr.lineBreakRegex,` +`),E.style===void 0&&(N.style=N.style||"stroke: #333; stroke-width: 1.5px;fill:none;"),N.labelStyle=N.labelStyle.replace("color:","fill:"),N.id=A,N.classes="flowchart-link "+I+" "+B,a.setEdge(E.start,E.end,N,p)})},B0t={setConf:aze,addVertices:MBt,addEdges:DBt,getClasses:function(i,a){return a.db.getClasses()},draw:async function(i,a,f,p){Ut.info("Drawing flowchart");let w=p.db.getDirection();w===void 0&&(w="TD");const{securityLevel:m,flowchart:b}=Oe(),E=b.nodeSpacing||50,_=b.rankSpacing||50;let A;m==="sandbox"&&(A=yr("#i"+a));const I=yr(m==="sandbox"?A.nodes()[0].contentDocument.body:"body"),B=m==="sandbox"?A.nodes()[0].contentDocument:document,N=new c1({multigraph:!0,compound:!0}).setGraph({rankdir:w,nodesep:E,ranksep:_,marginx:0,marginy:0}).setDefaultEdgeLabel(function(){return{}});let R;const z=p.db.getSubGraphs();Ut.info("Subgraphs - ",z);for(let yt=z.length-1;yt>=0;yt--)R=z[yt],Ut.info("Subgraph - ",R),p.db.addVertex(R.id,{text:R.title,type:R.labelType},"group",void 0,R.classes,R.dir);const W=p.db.getVertices(),et=p.db.getEdges();Ut.info("Edges",et);let st=0;for(st=z.length-1;st>=0;st--){R=z[st],sMt("cluster").append("text");for(let yt=0;yt{const f=cCe,p=f(i,"r"),w=f(i,"g"),m=f(i,"b");return FA(p,w,m,a)},IBt=i=>`.label { + font-family: ${i.fontFamily}; + color: ${i.nodeTextColor||i.textColor}; + } + .cluster-label text { + fill: ${i.titleColor}; + } + .cluster-label span,p { + color: ${i.titleColor}; + } + + .label text,span,p { + fill: ${i.nodeTextColor||i.textColor}; + color: ${i.nodeTextColor||i.textColor}; + } + + .node rect, + .node circle, + .node ellipse, + .node polygon, + .node path { + fill: ${i.mainBkg}; + stroke: ${i.nodeBorder}; + stroke-width: 1px; + } + .flowchart-label text { + text-anchor: middle; + } + // .flowchart-label .text-outer-tspan { + // text-anchor: middle; + // } + // .flowchart-label .text-inner-tspan { + // text-anchor: start; + // } + + .node .label { + text-align: center; + } + .node.clickable { + cursor: pointer; + } + + .arrowheadPath { + fill: ${i.arrowheadColor}; + } + + .edgePath .path { + stroke: ${i.lineColor}; + stroke-width: 2.0px; + } + + .flowchart-link { + stroke: ${i.lineColor}; + fill: none; + } + + .edgeLabel { + background-color: ${i.edgeLabelBackground}; + rect { + opacity: 0.5; + background-color: ${i.edgeLabelBackground}; + fill: ${i.edgeLabelBackground}; + } + text-align: center; + } + + /* For html labels only */ + .labelBkg { + background-color: ${oze(i.edgeLabelBackground,.5)}; + // background-color: + } + + .cluster rect { + fill: ${i.clusterBkg}; + stroke: ${i.clusterBorder}; + stroke-width: 1px; + } + + .cluster text { + fill: ${i.titleColor}; + } + + .cluster span,p { + color: ${i.titleColor}; + } + /* .cluster div { + color: ${i.titleColor}; + } */ + + div.mermaidTooltip { + position: absolute; + text-align: center; + max-width: 200px; + padding: 2px; + font-family: ${i.fontFamily}; + font-size: 12px; + background: ${i.tertiaryColor}; + border: 1px solid ${i.border2}; + border-radius: 2px; + pointer-events: none; + z-index: 100; + } + + .flowchartTitleText { + text-anchor: middle; + font-size: 18px; + fill: ${i.textColor}; + } +`,cze=Object.freeze(Object.defineProperty({__proto__:null,diagram:{parser:Hdt,db:wT,renderer:B0t,styles:IBt,init:i=>{i.flowchart||(i.flowchart={}),i.flowchart.arrowMarkerAbsolute=i.arrowMarkerAbsolute,hRe.setConf(i.flowchart),wT.clear(),wT.setGen("gen-1")}}},Symbol.toStringTag,{value:"Module"})),uze=Object.freeze(Object.defineProperty({__proto__:null,diagram:{parser:Hdt,db:wT,renderer:B0t,styles:IBt,init:i=>{i.flowchart||(i.flowchart={}),i.flowchart.arrowMarkerAbsolute=i.arrowMarkerAbsolute,cAe({flowchart:{arrowMarkerAbsolute:i.arrowMarkerAbsolute}}),B0t.setConf(i.flowchart),wT.clear(),wT.setGen("gen-2")}}},Symbol.toStringTag,{value:"Module"}));var R0t=function(){var i=function(vt,X,pt,U){for(pt=pt||{},U=vt.length;U--;pt[vt[U]]=X);return pt},a=[6,8,10,20,22,24,26,27,28],f=[1,10],p=[1,11],w=[1,12],m=[1,13],b=[1,14],E=[1,15],_=[1,21],A=[1,22],I=[1,23],B=[1,24],N=[1,25],R=[6,8,10,13,15,18,19,20,22,24,26,27,28,41,42,43,44,45],z=[1,34],W=[27,28,46,47],et=[41,42,43,44,45],st=[17,34],at=[1,54],bt=[1,53],mt=[17,34,36,38],yt={trace:function(){},yy:{},symbols_:{error:2,start:3,ER_DIAGRAM:4,document:5,EOF:6,line:7,SPACE:8,statement:9,NEWLINE:10,entityName:11,relSpec:12,":":13,role:14,BLOCK_START:15,attributes:16,BLOCK_STOP:17,SQS:18,SQE:19,title:20,title_value:21,acc_title:22,acc_title_value:23,acc_descr:24,acc_descr_value:25,acc_descr_multiline_value:26,ALPHANUM:27,ENTITY_NAME:28,attribute:29,attributeType:30,attributeName:31,attributeKeyTypeList:32,attributeComment:33,ATTRIBUTE_WORD:34,attributeKeyType:35,COMMA:36,ATTRIBUTE_KEY:37,COMMENT:38,cardinality:39,relType:40,ZERO_OR_ONE:41,ZERO_OR_MORE:42,ONE_OR_MORE:43,ONLY_ONE:44,MD_PARENT:45,NON_IDENTIFYING:46,IDENTIFYING:47,WORD:48,$accept:0,$end:1},terminals_:{2:"error",4:"ER_DIAGRAM",6:"EOF",8:"SPACE",10:"NEWLINE",13:":",15:"BLOCK_START",17:"BLOCK_STOP",18:"SQS",19:"SQE",20:"title",21:"title_value",22:"acc_title",23:"acc_title_value",24:"acc_descr",25:"acc_descr_value",26:"acc_descr_multiline_value",27:"ALPHANUM",28:"ENTITY_NAME",34:"ATTRIBUTE_WORD",36:"COMMA",37:"ATTRIBUTE_KEY",38:"COMMENT",41:"ZERO_OR_ONE",42:"ZERO_OR_MORE",43:"ONE_OR_MORE",44:"ONLY_ONE",45:"MD_PARENT",46:"NON_IDENTIFYING",47:"IDENTIFYING",48:"WORD"},productions_:[0,[3,3],[5,0],[5,2],[7,2],[7,1],[7,1],[7,1],[9,5],[9,4],[9,3],[9,1],[9,7],[9,6],[9,4],[9,2],[9,2],[9,2],[9,1],[11,1],[11,1],[16,1],[16,2],[29,2],[29,3],[29,3],[29,4],[30,1],[31,1],[32,1],[32,3],[35,1],[33,1],[12,3],[39,1],[39,1],[39,1],[39,1],[39,1],[40,1],[40,1],[14,1],[14,1],[14,1]],performAction:function(X,pt,U,Tt,nt,It,Ot){var Bt=It.length-1;switch(nt){case 1:break;case 2:this.$=[];break;case 3:It[Bt-1].push(It[Bt]),this.$=It[Bt-1];break;case 4:case 5:this.$=It[Bt];break;case 6:case 7:this.$=[];break;case 8:Tt.addEntity(It[Bt-4]),Tt.addEntity(It[Bt-2]),Tt.addRelationship(It[Bt-4],It[Bt],It[Bt-2],It[Bt-3]);break;case 9:Tt.addEntity(It[Bt-3]),Tt.addAttributes(It[Bt-3],It[Bt-1]);break;case 10:Tt.addEntity(It[Bt-2]);break;case 11:Tt.addEntity(It[Bt]);break;case 12:Tt.addEntity(It[Bt-6],It[Bt-4]),Tt.addAttributes(It[Bt-6],It[Bt-1]);break;case 13:Tt.addEntity(It[Bt-5],It[Bt-3]);break;case 14:Tt.addEntity(It[Bt-3],It[Bt-1]);break;case 15:case 16:this.$=It[Bt].trim(),Tt.setAccTitle(this.$);break;case 17:case 18:this.$=It[Bt].trim(),Tt.setAccDescription(this.$);break;case 19:case 43:this.$=It[Bt];break;case 20:case 41:case 42:this.$=It[Bt].replace(/"/g,"");break;case 21:case 29:this.$=[It[Bt]];break;case 22:It[Bt].push(It[Bt-1]),this.$=It[Bt];break;case 23:this.$={attributeType:It[Bt-1],attributeName:It[Bt]};break;case 24:this.$={attributeType:It[Bt-2],attributeName:It[Bt-1],attributeKeyTypeList:It[Bt]};break;case 25:this.$={attributeType:It[Bt-2],attributeName:It[Bt-1],attributeComment:It[Bt]};break;case 26:this.$={attributeType:It[Bt-3],attributeName:It[Bt-2],attributeKeyTypeList:It[Bt-1],attributeComment:It[Bt]};break;case 27:case 28:case 31:this.$=It[Bt];break;case 30:It[Bt-2].push(It[Bt]),this.$=It[Bt-2];break;case 32:this.$=It[Bt].replace(/"/g,"");break;case 33:this.$={cardA:It[Bt],relType:It[Bt-1],cardB:It[Bt-2]};break;case 34:this.$=Tt.Cardinality.ZERO_OR_ONE;break;case 35:this.$=Tt.Cardinality.ZERO_OR_MORE;break;case 36:this.$=Tt.Cardinality.ONE_OR_MORE;break;case 37:this.$=Tt.Cardinality.ONLY_ONE;break;case 38:this.$=Tt.Cardinality.MD_PARENT;break;case 39:this.$=Tt.Identification.NON_IDENTIFYING;break;case 40:this.$=Tt.Identification.IDENTIFYING;break}},table:[{3:1,4:[1,2]},{1:[3]},i(a,[2,2],{5:3}),{6:[1,4],7:5,8:[1,6],9:7,10:[1,8],11:9,20:f,22:p,24:w,26:m,27:b,28:E},i(a,[2,7],{1:[2,1]}),i(a,[2,3]),{9:16,11:9,20:f,22:p,24:w,26:m,27:b,28:E},i(a,[2,5]),i(a,[2,6]),i(a,[2,11],{12:17,39:20,15:[1,18],18:[1,19],41:_,42:A,43:I,44:B,45:N}),{21:[1,26]},{23:[1,27]},{25:[1,28]},i(a,[2,18]),i(R,[2,19]),i(R,[2,20]),i(a,[2,4]),{11:29,27:b,28:E},{16:30,17:[1,31],29:32,30:33,34:z},{11:35,27:b,28:E},{40:36,46:[1,37],47:[1,38]},i(W,[2,34]),i(W,[2,35]),i(W,[2,36]),i(W,[2,37]),i(W,[2,38]),i(a,[2,15]),i(a,[2,16]),i(a,[2,17]),{13:[1,39]},{17:[1,40]},i(a,[2,10]),{16:41,17:[2,21],29:32,30:33,34:z},{31:42,34:[1,43]},{34:[2,27]},{19:[1,44]},{39:45,41:_,42:A,43:I,44:B,45:N},i(et,[2,39]),i(et,[2,40]),{14:46,27:[1,49],28:[1,48],48:[1,47]},i(a,[2,9]),{17:[2,22]},i(st,[2,23],{32:50,33:51,35:52,37:at,38:bt}),i([17,34,37,38],[2,28]),i(a,[2,14],{15:[1,55]}),i([27,28],[2,33]),i(a,[2,8]),i(a,[2,41]),i(a,[2,42]),i(a,[2,43]),i(st,[2,24],{33:56,36:[1,57],38:bt}),i(st,[2,25]),i(mt,[2,29]),i(st,[2,32]),i(mt,[2,31]),{16:58,17:[1,59],29:32,30:33,34:z},i(st,[2,26]),{35:60,37:at},{17:[1,61]},i(a,[2,13]),i(mt,[2,30]),i(a,[2,12])],defaultActions:{34:[2,27],41:[2,22]},parseError:function(X,pt){if(pt.recoverable)this.trace(X);else{var U=new Error(X);throw U.hash=pt,U}},parse:function(X){var pt=this,U=[0],Tt=[],nt=[null],It=[],Ot=this.table,Bt="",Et=0,Z=0,Ct=2,xt=1,Ht=It.slice.call(arguments,1),Le=Object.create(this.lexer),Ft={yy:{}};for(var gn in this.yy)Object.prototype.hasOwnProperty.call(this.yy,gn)&&(Ft.yy[gn]=this.yy[gn]);Le.setInput(X,Ft.yy),Ft.yy.lexer=Le,Ft.yy.parser=this,typeof Le.yylloc>"u"&&(Le.yylloc={});var Se=Le.yylloc;It.push(Se);var me=Le.options&&Le.options.ranges;typeof Ft.yy.parseError=="function"?this.parseError=Ft.yy.parseError:this.parseError=Object.getPrototypeOf(this).parseError;function Ve(){var on;return on=Tt.pop()||Le.lex()||xt,typeof on!="number"&&(on instanceof Array&&(Tt=on,on=Tt.pop()),on=pt.symbols_[on]||on),on}for(var Ye,ce,ke,zt,re={},se,Pe,te,Me;;){if(ce=U[U.length-1],this.defaultActions[ce]?ke=this.defaultActions[ce]:((Ye===null||typeof Ye>"u")&&(Ye=Ve()),ke=Ot[ce]&&Ot[ce][Ye]),typeof ke>"u"||!ke.length||!ke[0]){var de="";Me=[];for(se in Ot[ce])this.terminals_[se]&&se>Ct&&Me.push("'"+this.terminals_[se]+"'");Le.showPosition?de="Parse error on line "+(Et+1)+`: +`+Le.showPosition()+` +Expecting `+Me.join(", ")+", got '"+(this.terminals_[Ye]||Ye)+"'":de="Parse error on line "+(Et+1)+": Unexpected "+(Ye==xt?"end of input":"'"+(this.terminals_[Ye]||Ye)+"'"),this.parseError(de,{text:Le.match,token:this.terminals_[Ye]||Ye,line:Le.yylineno,loc:Se,expected:Me})}if(ke[0]instanceof Array&&ke.length>1)throw new Error("Parse Error: multiple actions possible at state: "+ce+", token: "+Ye);switch(ke[0]){case 1:U.push(Ye),nt.push(Le.yytext),It.push(Le.yylloc),U.push(ke[1]),Ye=null,Z=Le.yyleng,Bt=Le.yytext,Et=Le.yylineno,Se=Le.yylloc;break;case 2:if(Pe=this.productions_[ke[1]][1],re.$=nt[nt.length-Pe],re._$={first_line:It[It.length-(Pe||1)].first_line,last_line:It[It.length-1].last_line,first_column:It[It.length-(Pe||1)].first_column,last_column:It[It.length-1].last_column},me&&(re._$.range=[It[It.length-(Pe||1)].range[0],It[It.length-1].range[1]]),zt=this.performAction.apply(re,[Bt,Z,Et,Ft.yy,ke[1],nt,It].concat(Ht)),typeof zt<"u")return zt;Pe&&(U=U.slice(0,-1*Pe*2),nt=nt.slice(0,-1*Pe),It=It.slice(0,-1*Pe)),U.push(this.productions_[ke[1]][0]),nt.push(re.$),It.push(re._$),te=Ot[U[U.length-2]][U[U.length-1]],U.push(te);break;case 3:return!0}}return!0}},ft=function(){var vt={EOF:1,parseError:function(pt,U){if(this.yy.parser)this.yy.parser.parseError(pt,U);else throw new Error(pt)},setInput:function(X,pt){return this.yy=pt||this.yy||{},this._input=X,this._more=this._backtrack=this.done=!1,this.yylineno=this.yyleng=0,this.yytext=this.matched=this.match="",this.conditionStack=["INITIAL"],this.yylloc={first_line:1,first_column:0,last_line:1,last_column:0},this.options.ranges&&(this.yylloc.range=[0,0]),this.offset=0,this},input:function(){var X=this._input[0];this.yytext+=X,this.yyleng++,this.offset++,this.match+=X,this.matched+=X;var pt=X.match(/(?:\r\n?|\n).*/g);return pt?(this.yylineno++,this.yylloc.last_line++):this.yylloc.last_column++,this.options.ranges&&this.yylloc.range[1]++,this._input=this._input.slice(1),X},unput:function(X){var pt=X.length,U=X.split(/(?:\r\n?|\n)/g);this._input=X+this._input,this.yytext=this.yytext.substr(0,this.yytext.length-pt),this.offset-=pt;var Tt=this.match.split(/(?:\r\n?|\n)/g);this.match=this.match.substr(0,this.match.length-1),this.matched=this.matched.substr(0,this.matched.length-1),U.length-1&&(this.yylineno-=U.length-1);var nt=this.yylloc.range;return this.yylloc={first_line:this.yylloc.first_line,last_line:this.yylineno+1,first_column:this.yylloc.first_column,last_column:U?(U.length===Tt.length?this.yylloc.first_column:0)+Tt[Tt.length-U.length].length-U[0].length:this.yylloc.first_column-pt},this.options.ranges&&(this.yylloc.range=[nt[0],nt[0]+this.yyleng-pt]),this.yyleng=this.yytext.length,this},more:function(){return this._more=!0,this},reject:function(){if(this.options.backtrack_lexer)this._backtrack=!0;else return this.parseError("Lexical error on line "+(this.yylineno+1)+`. You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true). +`+this.showPosition(),{text:"",token:null,line:this.yylineno});return this},less:function(X){this.unput(this.match.slice(X))},pastInput:function(){var X=this.matched.substr(0,this.matched.length-this.match.length);return(X.length>20?"...":"")+X.substr(-20).replace(/\n/g,"")},upcomingInput:function(){var X=this.match;return X.length<20&&(X+=this._input.substr(0,20-X.length)),(X.substr(0,20)+(X.length>20?"...":"")).replace(/\n/g,"")},showPosition:function(){var X=this.pastInput(),pt=new Array(X.length+1).join("-");return X+this.upcomingInput()+` +`+pt+"^"},test_match:function(X,pt){var U,Tt,nt;if(this.options.backtrack_lexer&&(nt={yylineno:this.yylineno,yylloc:{first_line:this.yylloc.first_line,last_line:this.last_line,first_column:this.yylloc.first_column,last_column:this.yylloc.last_column},yytext:this.yytext,match:this.match,matches:this.matches,matched:this.matched,yyleng:this.yyleng,offset:this.offset,_more:this._more,_input:this._input,yy:this.yy,conditionStack:this.conditionStack.slice(0),done:this.done},this.options.ranges&&(nt.yylloc.range=this.yylloc.range.slice(0))),Tt=X[0].match(/(?:\r\n?|\n).*/g),Tt&&(this.yylineno+=Tt.length),this.yylloc={first_line:this.yylloc.last_line,last_line:this.yylineno+1,first_column:this.yylloc.last_column,last_column:Tt?Tt[Tt.length-1].length-Tt[Tt.length-1].match(/\r?\n?/)[0].length:this.yylloc.last_column+X[0].length},this.yytext+=X[0],this.match+=X[0],this.matches=X,this.yyleng=this.yytext.length,this.options.ranges&&(this.yylloc.range=[this.offset,this.offset+=this.yyleng]),this._more=!1,this._backtrack=!1,this._input=this._input.slice(X[0].length),this.matched+=X[0],U=this.performAction.call(this,this.yy,this,pt,this.conditionStack[this.conditionStack.length-1]),this.done&&this._input&&(this.done=!1),U)return U;if(this._backtrack){for(var It in nt)this[It]=nt[It];return!1}return!1},next:function(){if(this.done)return this.EOF;this._input||(this.done=!0);var X,pt,U,Tt;this._more||(this.yytext="",this.match="");for(var nt=this._currentRules(),It=0;Itpt[0].length)){if(pt=U,Tt=It,this.options.backtrack_lexer){if(X=this.test_match(U,nt[It]),X!==!1)return X;if(this._backtrack){pt=!1;continue}else return!1}else if(!this.options.flex)break}return pt?(X=this.test_match(pt,nt[Tt]),X!==!1?X:!1):this._input===""?this.EOF:this.parseError("Lexical error on line "+(this.yylineno+1)+`. Unrecognized text. +`+this.showPosition(),{text:"",token:null,line:this.yylineno})},lex:function(){var pt=this.next();return pt||this.lex()},begin:function(pt){this.conditionStack.push(pt)},popState:function(){var pt=this.conditionStack.length-1;return pt>0?this.conditionStack.pop():this.conditionStack[0]},_currentRules:function(){return this.conditionStack.length&&this.conditionStack[this.conditionStack.length-1]?this.conditions[this.conditionStack[this.conditionStack.length-1]].rules:this.conditions.INITIAL.rules},topState:function(pt){return pt=this.conditionStack.length-1-Math.abs(pt||0),pt>=0?this.conditionStack[pt]:"INITIAL"},pushState:function(pt){this.begin(pt)},stateStackSize:function(){return this.conditionStack.length},options:{"case-insensitive":!0},performAction:function(pt,U,Tt,nt){switch(Tt){case 0:return this.begin("acc_title"),22;case 1:return this.popState(),"acc_title_value";case 2:return this.begin("acc_descr"),24;case 3:return this.popState(),"acc_descr_value";case 4:this.begin("acc_descr_multiline");break;case 5:this.popState();break;case 6:return"acc_descr_multiline_value";case 7:return 10;case 8:break;case 9:return 8;case 10:return 28;case 11:return 48;case 12:return 4;case 13:return this.begin("block"),15;case 14:return 36;case 15:break;case 16:return 37;case 17:return 34;case 18:return 34;case 19:return 38;case 20:break;case 21:return this.popState(),17;case 22:return U.yytext[0];case 23:return 18;case 24:return 19;case 25:return 41;case 26:return 43;case 27:return 43;case 28:return 43;case 29:return 41;case 30:return 41;case 31:return 42;case 32:return 42;case 33:return 42;case 34:return 42;case 35:return 42;case 36:return 43;case 37:return 42;case 38:return 43;case 39:return 44;case 40:return 44;case 41:return 44;case 42:return 44;case 43:return 41;case 44:return 42;case 45:return 43;case 46:return 45;case 47:return 46;case 48:return 47;case 49:return 47;case 50:return 46;case 51:return 46;case 52:return 46;case 53:return 27;case 54:return U.yytext[0];case 55:return 6}},rules:[/^(?:accTitle\s*:\s*)/i,/^(?:(?!\n||)*[^\n]*)/i,/^(?:accDescr\s*:\s*)/i,/^(?:(?!\n||)*[^\n]*)/i,/^(?:accDescr\s*\{\s*)/i,/^(?:[\}])/i,/^(?:[^\}]*)/i,/^(?:[\n]+)/i,/^(?:\s+)/i,/^(?:[\s]+)/i,/^(?:"[^"%\r\n\v\b\\]+")/i,/^(?:"[^"]*")/i,/^(?:erDiagram\b)/i,/^(?:\{)/i,/^(?:,)/i,/^(?:\s+)/i,/^(?:\b((?:PK)|(?:FK)|(?:UK))\b)/i,/^(?:(.*?)[~](.*?)*[~])/i,/^(?:[\*A-Za-z_][A-Za-z0-9\-_\[\]\(\)]*)/i,/^(?:"[^"]*")/i,/^(?:[\n]+)/i,/^(?:\})/i,/^(?:.)/i,/^(?:\[)/i,/^(?:\])/i,/^(?:one or zero\b)/i,/^(?:one or more\b)/i,/^(?:one or many\b)/i,/^(?:1\+)/i,/^(?:\|o\b)/i,/^(?:zero or one\b)/i,/^(?:zero or more\b)/i,/^(?:zero or many\b)/i,/^(?:0\+)/i,/^(?:\}o\b)/i,/^(?:many\(0\))/i,/^(?:many\(1\))/i,/^(?:many\b)/i,/^(?:\}\|)/i,/^(?:one\b)/i,/^(?:only one\b)/i,/^(?:1\b)/i,/^(?:\|\|)/i,/^(?:o\|)/i,/^(?:o\{)/i,/^(?:\|\{)/i,/^(?:\s*u\b)/i,/^(?:\.\.)/i,/^(?:--)/i,/^(?:to\b)/i,/^(?:optionally to\b)/i,/^(?:\.-)/i,/^(?:-\.)/i,/^(?:[A-Za-z_][A-Za-z0-9\-_]*)/i,/^(?:.)/i,/^(?:$)/i],conditions:{acc_descr_multiline:{rules:[5,6],inclusive:!1},acc_descr:{rules:[3],inclusive:!1},acc_title:{rules:[1],inclusive:!1},block:{rules:[14,15,16,17,18,19,20,21,22],inclusive:!1},INITIAL:{rules:[0,2,4,7,8,9,10,11,12,13,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55],inclusive:!0}}};return vt}();yt.lexer=ft;function ut(){this.yy={}}return ut.prototype=yt,yt.Parser=ut,new ut}();R0t.parser=R0t;const lze=R0t;let mk={},j0t=[];const hze={ZERO_OR_ONE:"ZERO_OR_ONE",ZERO_OR_MORE:"ZERO_OR_MORE",ONE_OR_MORE:"ONE_OR_MORE",ONLY_ONE:"ONLY_ONE",MD_PARENT:"MD_PARENT"},fze={NON_IDENTIFYING:"NON_IDENTIFYING",IDENTIFYING:"IDENTIFYING"},OBt=function(i,a=void 0){return mk[i]===void 0?(mk[i]={attributes:[],alias:a},Ut.info("Added new entity :",i)):mk[i]&&!mk[i].alias&&a&&(mk[i].alias=a,Ut.info(`Add alias '${a}' to entity '${i}'`)),mk[i]},dze={Cardinality:hze,Identification:fze,getConfig:()=>Oe().er,addEntity:OBt,addAttributes:function(i,a){let f=OBt(i),p;for(p=a.length-1;p>=0;p--)f.attributes.push(a[p]),Ut.debug("Added attribute ",a[p].attributeName)},getEntities:()=>mk,addRelationship:function(i,a,f,p){let w={entityA:i,roleA:a,entityB:f,relSpec:p};j0t.push(w),Ut.debug("Added new relationship :",w)},getRelationships:()=>j0t,clear:function(){mk={},j0t=[],hg()},setAccTitle:E0,getAccTitle:fg,setAccDescription:dg,getAccDescription:gg,setDiagramTitle:Nb,getDiagramTitle:pg},fm={ONLY_ONE_START:"ONLY_ONE_START",ONLY_ONE_END:"ONLY_ONE_END",ZERO_OR_ONE_START:"ZERO_OR_ONE_START",ZERO_OR_ONE_END:"ZERO_OR_ONE_END",ONE_OR_MORE_START:"ONE_OR_MORE_START",ONE_OR_MORE_END:"ONE_OR_MORE_END",ZERO_OR_MORE_START:"ZERO_OR_MORE_START",ZERO_OR_MORE_END:"ZERO_OR_MORE_END",MD_PARENT_END:"MD_PARENT_END",MD_PARENT_START:"MD_PARENT_START"},dm={ERMarkers:fm,insertMarkers:function(i,a){let f;i.append("defs").append("marker").attr("id",fm.MD_PARENT_START).attr("refX",0).attr("refY",7).attr("markerWidth",190).attr("markerHeight",240).attr("orient","auto").append("path").attr("d","M 18,7 L9,13 L1,7 L9,1 Z"),i.append("defs").append("marker").attr("id",fm.MD_PARENT_END).attr("refX",19).attr("refY",7).attr("markerWidth",20).attr("markerHeight",28).attr("orient","auto").append("path").attr("d","M 18,7 L9,13 L1,7 L9,1 Z"),i.append("defs").append("marker").attr("id",fm.ONLY_ONE_START).attr("refX",0).attr("refY",9).attr("markerWidth",18).attr("markerHeight",18).attr("orient","auto").append("path").attr("stroke",a.stroke).attr("fill","none").attr("d","M9,0 L9,18 M15,0 L15,18"),i.append("defs").append("marker").attr("id",fm.ONLY_ONE_END).attr("refX",18).attr("refY",9).attr("markerWidth",18).attr("markerHeight",18).attr("orient","auto").append("path").attr("stroke",a.stroke).attr("fill","none").attr("d","M3,0 L3,18 M9,0 L9,18"),f=i.append("defs").append("marker").attr("id",fm.ZERO_OR_ONE_START).attr("refX",0).attr("refY",9).attr("markerWidth",30).attr("markerHeight",18).attr("orient","auto"),f.append("circle").attr("stroke",a.stroke).attr("fill","white").attr("cx",21).attr("cy",9).attr("r",6),f.append("path").attr("stroke",a.stroke).attr("fill","none").attr("d","M9,0 L9,18"),f=i.append("defs").append("marker").attr("id",fm.ZERO_OR_ONE_END).attr("refX",30).attr("refY",9).attr("markerWidth",30).attr("markerHeight",18).attr("orient","auto"),f.append("circle").attr("stroke",a.stroke).attr("fill","white").attr("cx",9).attr("cy",9).attr("r",6),f.append("path").attr("stroke",a.stroke).attr("fill","none").attr("d","M21,0 L21,18"),i.append("defs").append("marker").attr("id",fm.ONE_OR_MORE_START).attr("refX",18).attr("refY",18).attr("markerWidth",45).attr("markerHeight",36).attr("orient","auto").append("path").attr("stroke",a.stroke).attr("fill","none").attr("d","M0,18 Q 18,0 36,18 Q 18,36 0,18 M42,9 L42,27"),i.append("defs").append("marker").attr("id",fm.ONE_OR_MORE_END).attr("refX",27).attr("refY",18).attr("markerWidth",45).attr("markerHeight",36).attr("orient","auto").append("path").attr("stroke",a.stroke).attr("fill","none").attr("d","M3,9 L3,27 M9,18 Q27,0 45,18 Q27,36 9,18"),f=i.append("defs").append("marker").attr("id",fm.ZERO_OR_MORE_START).attr("refX",18).attr("refY",18).attr("markerWidth",57).attr("markerHeight",36).attr("orient","auto"),f.append("circle").attr("stroke",a.stroke).attr("fill","white").attr("cx",48).attr("cy",18).attr("r",6),f.append("path").attr("stroke",a.stroke).attr("fill","none").attr("d","M0,18 Q18,0 36,18 Q18,36 0,18"),f=i.append("defs").append("marker").attr("id",fm.ZERO_OR_MORE_END).attr("refX",39).attr("refY",18).attr("markerWidth",57).attr("markerHeight",36).attr("orient","auto"),f.append("circle").attr("stroke",a.stroke).attr("fill","white").attr("cx",9).attr("cy",18).attr("r",6),f.append("path").attr("stroke",a.stroke).attr("fill","none").attr("d","M21,18 Q39,0 57,18 Q39,36 21,18")}},gze=/^(?:[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}|00000000-0000-0000-0000-000000000000)$/i;function pze(i){return typeof i=="string"&&gze.test(i)}const Rd=[];for(let i=0;i<256;++i)Rd.push((i+256).toString(16).slice(1));function bze(i,a=0){return(Rd[i[a+0]]+Rd[i[a+1]]+Rd[i[a+2]]+Rd[i[a+3]]+"-"+Rd[i[a+4]]+Rd[i[a+5]]+"-"+Rd[i[a+6]]+Rd[i[a+7]]+"-"+Rd[i[a+8]]+Rd[i[a+9]]+"-"+Rd[i[a+10]]+Rd[i[a+11]]+Rd[i[a+12]]+Rd[i[a+13]]+Rd[i[a+14]]+Rd[i[a+15]]).toLowerCase()}function wze(i){if(!pze(i))throw TypeError("Invalid UUID");let a;const f=new Uint8Array(16);return f[0]=(a=parseInt(i.slice(0,8),16))>>>24,f[1]=a>>>16&255,f[2]=a>>>8&255,f[3]=a&255,f[4]=(a=parseInt(i.slice(9,13),16))>>>8,f[5]=a&255,f[6]=(a=parseInt(i.slice(14,18),16))>>>8,f[7]=a&255,f[8]=(a=parseInt(i.slice(19,23),16))>>>8,f[9]=a&255,f[10]=(a=parseInt(i.slice(24,36),16))/1099511627776&255,f[11]=a/4294967296&255,f[12]=a>>>24&255,f[13]=a>>>16&255,f[14]=a>>>8&255,f[15]=a&255,f}function vze(i){i=unescape(encodeURIComponent(i));const a=[];for(let f=0;f>>32-a}function Eze(i){const a=[1518500249,1859775393,2400959708,3395469782],f=[1732584193,4023233417,2562383102,271733878,3285377520];if(typeof i=="string"){const b=unescape(encodeURIComponent(i));i=[];for(let E=0;E>>0;N=B,B=I,I=$0t(A,30)>>>0,A=_,_=W}f[0]=f[0]+_>>>0,f[1]=f[1]+A>>>0,f[2]=f[2]+I>>>0,f[3]=f[3]+B>>>0,f[4]=f[4]+N>>>0}return[f[0]>>24&255,f[0]>>16&255,f[0]>>8&255,f[0]&255,f[1]>>24&255,f[1]>>16&255,f[1]>>8&255,f[1]&255,f[2]>>24&255,f[2]>>16&255,f[2]>>8&255,f[2]&255,f[3]>>24&255,f[3]>>16&255,f[3]>>8&255,f[3]&255,f[4]>>24&255,f[4]>>16&255,f[4]>>8&255,f[4]&255]}const Tze=xze("v5",80,Eze),Cze=/[^\dA-Za-z](\W)*/g;let u1={},SF=new Map;const _ze=function(i){const a=Object.keys(i);for(const f of a)u1[f]=i[f]},Sze=(i,a,f)=>{const p=u1.entityPadding/3,w=u1.entityPadding/3,m=u1.fontSize*.85,b=a.node().getBBox(),E=[];let _=!1,A=!1,I=0,B=0,N=0,R=0,z=b.height+p*2,W=1;f.forEach(bt=>{bt.attributeKeyTypeList!==void 0&&bt.attributeKeyTypeList.length>0&&(_=!0),bt.attributeComment!==void 0&&(A=!0)}),f.forEach(bt=>{const mt=`${a.node().id}-attr-${W}`;let yt=0;const ft=YP(bt.attributeType),ut=i.append("text").classed("er entityLabel",!0).attr("id",`${mt}-type`).attr("x",0).attr("y",0).style("dominant-baseline","middle").style("text-anchor","left").style("font-family",Oe().fontFamily).style("font-size",m+"px").text(ft),vt=i.append("text").classed("er entityLabel",!0).attr("id",`${mt}-name`).attr("x",0).attr("y",0).style("dominant-baseline","middle").style("text-anchor","left").style("font-family",Oe().fontFamily).style("font-size",m+"px").text(bt.attributeName),X={};X.tn=ut,X.nn=vt;const pt=ut.node().getBBox(),U=vt.node().getBBox();if(I=Math.max(I,pt.width),B=Math.max(B,U.width),yt=Math.max(pt.height,U.height),_){const Tt=bt.attributeKeyTypeList!==void 0?bt.attributeKeyTypeList.join(","):"",nt=i.append("text").classed("er entityLabel",!0).attr("id",`${mt}-key`).attr("x",0).attr("y",0).style("dominant-baseline","middle").style("text-anchor","left").style("font-family",Oe().fontFamily).style("font-size",m+"px").text(Tt);X.kn=nt;const It=nt.node().getBBox();N=Math.max(N,It.width),yt=Math.max(yt,It.height)}if(A){const Tt=i.append("text").classed("er entityLabel",!0).attr("id",`${mt}-comment`).attr("x",0).attr("y",0).style("dominant-baseline","middle").style("text-anchor","left").style("font-family",Oe().fontFamily).style("font-size",m+"px").text(bt.attributeComment||"");X.cn=Tt;const nt=Tt.node().getBBox();R=Math.max(R,nt.width),yt=Math.max(yt,nt.height)}X.height=yt,E.push(X),z+=yt+p*2,W+=1});let et=4;_&&(et+=2),A&&(et+=2);const st=I+B+N+R,at={width:Math.max(u1.minEntityWidth,Math.max(b.width+u1.entityPadding*2,st+w*et)),height:f.length>0?z:Math.max(u1.minEntityHeight,b.height+u1.entityPadding*2)};if(f.length>0){const bt=Math.max(0,(at.width-st-w*et)/(et/2));a.attr("transform","translate("+at.width/2+","+(p+b.height/2)+")");let mt=b.height+p*2,yt="attributeBoxOdd";E.forEach(ft=>{const ut=mt+p+ft.height/2;ft.tn.attr("transform","translate("+w+","+ut+")");const vt=i.insert("rect","#"+ft.tn.node().id).classed(`er ${yt}`,!0).attr("x",0).attr("y",mt).attr("width",I+w*2+bt).attr("height",ft.height+p*2),X=parseFloat(vt.attr("x"))+parseFloat(vt.attr("width"));ft.nn.attr("transform","translate("+(X+w)+","+ut+")");const pt=i.insert("rect","#"+ft.nn.node().id).classed(`er ${yt}`,!0).attr("x",X).attr("y",mt).attr("width",B+w*2+bt).attr("height",ft.height+p*2);let U=parseFloat(pt.attr("x"))+parseFloat(pt.attr("width"));if(_){ft.kn.attr("transform","translate("+(U+w)+","+ut+")");const Tt=i.insert("rect","#"+ft.kn.node().id).classed(`er ${yt}`,!0).attr("x",U).attr("y",mt).attr("width",N+w*2+bt).attr("height",ft.height+p*2);U=parseFloat(Tt.attr("x"))+parseFloat(Tt.attr("width"))}A&&(ft.cn.attr("transform","translate("+(U+w)+","+ut+")"),i.insert("rect","#"+ft.cn.node().id).classed(`er ${yt}`,"true").attr("x",U).attr("y",mt).attr("width",R+w*2+bt).attr("height",ft.height+p*2)),mt+=ft.height+p*2,yt=yt==="attributeBoxOdd"?"attributeBoxEven":"attributeBoxOdd"})}else at.height=Math.max(u1.minEntityHeight,z),a.attr("transform","translate("+at.width/2+","+at.height/2+")");return at},Aze=function(i,a,f){const p=Object.keys(a);let w;return p.forEach(function(m){const b=Pze(m,"entity");SF.set(m,b);const E=i.append("g").attr("id",b);w=w===void 0?b:w;const _="text-"+b,A=E.append("text").classed("er entityLabel",!0).attr("id",_).attr("x",0).attr("y",0).style("dominant-baseline","middle").style("text-anchor","middle").style("font-family",Oe().fontFamily).style("font-size",u1.fontSize+"px").text(a[m].alias??m),{width:I,height:B}=Sze(E,A,a[m].attributes),R=E.insert("rect","#"+_).classed("er entityBox",!0).attr("x",0).attr("y",0).attr("width",I).attr("height",B).node().getBBox();f.setNode(b,{width:R.width,height:R.height,shape:"rect",id:b})}),w},Lze=function(i,a){a.nodes().forEach(function(f){f!==void 0&&a.node(f)!==void 0&&i.select("#"+f).attr("transform","translate("+(a.node(f).x-a.node(f).width/2)+","+(a.node(f).y-a.node(f).height/2)+" )")})},PBt=function(i){return(i.entityA+i.roleA+i.entityB).replace(/\s/g,"")},Mze=function(i,a){return i.forEach(function(f){a.setEdge(SF.get(f.entityA),SF.get(f.entityB),{relationship:f},PBt(f))}),i};let FBt=0;const Dze=function(i,a,f,p,w){FBt++;const m=f.edge(SF.get(a.entityA),SF.get(a.entityB),PBt(a)),b=E5().x(function(z){return z.x}).y(function(z){return z.y}).curve(HP),E=i.insert("path","#"+p).classed("er relationshipLine",!0).attr("d",b(m.points)).style("stroke",u1.stroke).style("fill","none");a.relSpec.relType===w.db.Identification.NON_IDENTIFYING&&E.attr("stroke-dasharray","8,8");let _="";switch(u1.arrowMarkerAbsolute&&(_=window.location.protocol+"//"+window.location.host+window.location.pathname+window.location.search,_=_.replace(/\(/g,"\\("),_=_.replace(/\)/g,"\\)")),a.relSpec.cardA){case w.db.Cardinality.ZERO_OR_ONE:E.attr("marker-end","url("+_+"#"+dm.ERMarkers.ZERO_OR_ONE_END+")");break;case w.db.Cardinality.ZERO_OR_MORE:E.attr("marker-end","url("+_+"#"+dm.ERMarkers.ZERO_OR_MORE_END+")");break;case w.db.Cardinality.ONE_OR_MORE:E.attr("marker-end","url("+_+"#"+dm.ERMarkers.ONE_OR_MORE_END+")");break;case w.db.Cardinality.ONLY_ONE:E.attr("marker-end","url("+_+"#"+dm.ERMarkers.ONLY_ONE_END+")");break;case w.db.Cardinality.MD_PARENT:E.attr("marker-end","url("+_+"#"+dm.ERMarkers.MD_PARENT_END+")");break}switch(a.relSpec.cardB){case w.db.Cardinality.ZERO_OR_ONE:E.attr("marker-start","url("+_+"#"+dm.ERMarkers.ZERO_OR_ONE_START+")");break;case w.db.Cardinality.ZERO_OR_MORE:E.attr("marker-start","url("+_+"#"+dm.ERMarkers.ZERO_OR_MORE_START+")");break;case w.db.Cardinality.ONE_OR_MORE:E.attr("marker-start","url("+_+"#"+dm.ERMarkers.ONE_OR_MORE_START+")");break;case w.db.Cardinality.ONLY_ONE:E.attr("marker-start","url("+_+"#"+dm.ERMarkers.ONLY_ONE_START+")");break;case w.db.Cardinality.MD_PARENT:E.attr("marker-start","url("+_+"#"+dm.ERMarkers.MD_PARENT_START+")");break}const A=E.node().getTotalLength(),I=E.node().getPointAtLength(A*.5),B="rel"+FBt,R=i.append("text").classed("er relationshipLabel",!0).attr("id",B).attr("x",I.x).attr("y",I.y).style("text-anchor","middle").style("dominant-baseline","middle").style("font-family",Oe().fontFamily).style("font-size",u1.fontSize+"px").text(a.roleA).node().getBBox();i.insert("rect","#"+B).classed("er relationshipLabelBox",!0).attr("x",I.x-R.width/2).attr("y",I.y-R.height/2).attr("width",R.width).attr("height",R.height)},Ize=function(i,a,f,p){u1=Oe().er,Ut.info("Drawing ER diagram");const w=Oe().securityLevel;let m;w==="sandbox"&&(m=yr("#i"+a));const E=yr(w==="sandbox"?m.nodes()[0].contentDocument.body:"body").select(`[id='${a}']`);dm.insertMarkers(E,u1);let _;_=new c1({multigraph:!0,directed:!0,compound:!1}).setGraph({rankdir:u1.layoutDirection,marginx:20,marginy:20,nodesep:100,edgesep:100,ranksep:100}).setDefaultEdgeLabel(function(){return{}});const A=Aze(E,p.db.getEntities(),_),I=Mze(p.db.getRelationships(),_);aL(_),Lze(E,_),I.forEach(function(W){Dze(E,W,_,A,p)});const B=u1.diagramPadding;$a.insertTitle(E,"entityTitleText",u1.titleTopMargin,p.db.getDiagramTitle());const N=E.node().getBBox(),R=N.width+B*2,z=N.height+B*2;k0(E,z,R,u1.useMaxWidth),E.attr("viewBox",`${N.x-B} ${N.y-B} ${R} ${z}`)},Oze="28e9f9db-3c8d-5aa5-9faf-44286ae5937c";function Pze(i="",a=""){const f=i.replace(Cze,"");return`${NBt(a)}${NBt(f)}${Tze(i,Oze)}`}function NBt(i=""){return i.length>0?`${i}-`:""}const Fze=Object.freeze(Object.defineProperty({__proto__:null,diagram:{parser:lze,db:dze,renderer:{setConf:_ze,draw:Ize},styles:i=>` + .entityBox { + fill: ${i.mainBkg}; + stroke: ${i.nodeBorder}; + } + + .attributeBoxOdd { + fill: ${i.attributeBackgroundColorOdd}; + stroke: ${i.nodeBorder}; + } + + .attributeBoxEven { + fill: ${i.attributeBackgroundColorEven}; + stroke: ${i.nodeBorder}; + } + + .relationshipLabelBox { + fill: ${i.tertiaryColor}; + opacity: 0.7; + background-color: ${i.tertiaryColor}; + rect { + opacity: 0.5; + } + } + + .relationshipLine { + stroke: ${i.lineColor}; + } + + .entityTitleText { + text-anchor: middle; + font-size: 18px; + fill: ${i.textColor}; + } + #MD_PARENT_START { + fill: #f5f5f5 !important; + stroke: ${i.lineColor} !important; + stroke-width: 1; + } + #MD_PARENT_END { + fill: #f5f5f5 !important; + stroke: ${i.lineColor} !important; + stroke-width: 1; + } + +`}},Symbol.toStringTag,{value:"Module"}));var z0t=function(){var i=function(yt,ft,ut,vt){for(ut=ut||{},vt=yt.length;vt--;ut[yt[vt]]=ft);return ut},a=[1,3],f=[1,6],p=[1,4],w=[1,5],m=[2,5],b=[1,12],E=[5,7,13,19,21,23,24,26,28,31,36,39,46],_=[7,13,19,21,23,24,26,28,31,36,39],A=[7,12,13,19,21,23,24,26,28,31,36,39],I=[7,13,46],B=[1,42],N=[1,41],R=[7,13,29,32,34,37,46],z=[1,55],W=[1,56],et=[1,57],st=[7,13,32,34,41,46],at={trace:function(){},yy:{},symbols_:{error:2,start:3,eol:4,GG:5,document:6,EOF:7,":":8,DIR:9,options:10,body:11,OPT:12,NL:13,line:14,statement:15,commitStatement:16,mergeStatement:17,cherryPickStatement:18,acc_title:19,acc_title_value:20,acc_descr:21,acc_descr_value:22,acc_descr_multiline_value:23,section:24,branchStatement:25,CHECKOUT:26,ref:27,BRANCH:28,ORDER:29,NUM:30,CHERRY_PICK:31,COMMIT_ID:32,STR:33,COMMIT_TAG:34,EMPTYSTR:35,MERGE:36,COMMIT_TYPE:37,commitType:38,COMMIT:39,commit_arg:40,COMMIT_MSG:41,NORMAL:42,REVERSE:43,HIGHLIGHT:44,ID:45,";":46,$accept:0,$end:1},terminals_:{2:"error",5:"GG",7:"EOF",8:":",9:"DIR",12:"OPT",13:"NL",19:"acc_title",20:"acc_title_value",21:"acc_descr",22:"acc_descr_value",23:"acc_descr_multiline_value",24:"section",26:"CHECKOUT",28:"BRANCH",29:"ORDER",30:"NUM",31:"CHERRY_PICK",32:"COMMIT_ID",33:"STR",34:"COMMIT_TAG",35:"EMPTYSTR",36:"MERGE",37:"COMMIT_TYPE",39:"COMMIT",41:"COMMIT_MSG",42:"NORMAL",43:"REVERSE",44:"HIGHLIGHT",45:"ID",46:";"},productions_:[0,[3,2],[3,3],[3,4],[3,5],[6,0],[6,2],[10,2],[10,1],[11,0],[11,2],[14,2],[14,1],[15,1],[15,1],[15,1],[15,2],[15,2],[15,1],[15,1],[15,1],[15,2],[25,2],[25,4],[18,3],[18,5],[18,5],[18,5],[18,5],[17,2],[17,4],[17,4],[17,4],[17,6],[17,6],[17,6],[17,6],[17,6],[17,6],[17,8],[17,8],[17,8],[17,8],[17,8],[17,8],[16,2],[16,3],[16,3],[16,5],[16,5],[16,3],[16,5],[16,5],[16,5],[16,5],[16,7],[16,7],[16,7],[16,7],[16,7],[16,7],[16,3],[16,5],[16,5],[16,5],[16,5],[16,5],[16,5],[16,7],[16,7],[16,7],[16,7],[16,7],[16,7],[16,7],[16,7],[16,7],[16,7],[16,7],[16,7],[16,7],[16,7],[16,7],[16,7],[16,7],[16,7],[16,9],[16,9],[16,9],[16,9],[16,9],[16,9],[16,9],[16,9],[16,9],[16,9],[16,9],[16,9],[16,9],[16,9],[16,9],[16,9],[16,9],[16,9],[16,9],[16,9],[16,9],[16,9],[16,9],[16,9],[40,0],[40,1],[38,1],[38,1],[38,1],[27,1],[27,1],[4,1],[4,1],[4,1]],performAction:function(ft,ut,vt,X,pt,U,Tt){var nt=U.length-1;switch(pt){case 2:return U[nt];case 3:return U[nt-1];case 4:return X.setDirection(U[nt-3]),U[nt-1];case 6:X.setOptions(U[nt-1]),this.$=U[nt];break;case 7:U[nt-1]+=U[nt],this.$=U[nt-1];break;case 9:this.$=[];break;case 10:U[nt-1].push(U[nt]),this.$=U[nt-1];break;case 11:this.$=U[nt-1];break;case 16:this.$=U[nt].trim(),X.setAccTitle(this.$);break;case 17:case 18:this.$=U[nt].trim(),X.setAccDescription(this.$);break;case 19:X.addSection(U[nt].substr(8)),this.$=U[nt].substr(8);break;case 21:X.checkout(U[nt]);break;case 22:X.branch(U[nt]);break;case 23:X.branch(U[nt-2],U[nt]);break;case 24:X.cherryPick(U[nt],"",void 0);break;case 25:X.cherryPick(U[nt-2],"",U[nt]);break;case 26:case 28:X.cherryPick(U[nt-2],"","");break;case 27:X.cherryPick(U[nt],"",U[nt-2]);break;case 29:X.merge(U[nt],"","","");break;case 30:X.merge(U[nt-2],U[nt],"","");break;case 31:X.merge(U[nt-2],"",U[nt],"");break;case 32:X.merge(U[nt-2],"","",U[nt]);break;case 33:X.merge(U[nt-4],U[nt],"",U[nt-2]);break;case 34:X.merge(U[nt-4],"",U[nt],U[nt-2]);break;case 35:X.merge(U[nt-4],"",U[nt-2],U[nt]);break;case 36:X.merge(U[nt-4],U[nt-2],U[nt],"");break;case 37:X.merge(U[nt-4],U[nt-2],"",U[nt]);break;case 38:X.merge(U[nt-4],U[nt],U[nt-2],"");break;case 39:X.merge(U[nt-6],U[nt-4],U[nt-2],U[nt]);break;case 40:X.merge(U[nt-6],U[nt],U[nt-4],U[nt-2]);break;case 41:X.merge(U[nt-6],U[nt-4],U[nt],U[nt-2]);break;case 42:X.merge(U[nt-6],U[nt-2],U[nt-4],U[nt]);break;case 43:X.merge(U[nt-6],U[nt],U[nt-2],U[nt-4]);break;case 44:X.merge(U[nt-6],U[nt-2],U[nt],U[nt-4]);break;case 45:X.commit(U[nt]);break;case 46:X.commit("","",X.commitType.NORMAL,U[nt]);break;case 47:X.commit("","",U[nt],"");break;case 48:X.commit("","",U[nt],U[nt-2]);break;case 49:X.commit("","",U[nt-2],U[nt]);break;case 50:X.commit("",U[nt],X.commitType.NORMAL,"");break;case 51:X.commit("",U[nt-2],X.commitType.NORMAL,U[nt]);break;case 52:X.commit("",U[nt],X.commitType.NORMAL,U[nt-2]);break;case 53:X.commit("",U[nt-2],U[nt],"");break;case 54:X.commit("",U[nt],U[nt-2],"");break;case 55:X.commit("",U[nt-4],U[nt-2],U[nt]);break;case 56:X.commit("",U[nt-4],U[nt],U[nt-2]);break;case 57:X.commit("",U[nt-2],U[nt-4],U[nt]);break;case 58:X.commit("",U[nt],U[nt-4],U[nt-2]);break;case 59:X.commit("",U[nt],U[nt-2],U[nt-4]);break;case 60:X.commit("",U[nt-2],U[nt],U[nt-4]);break;case 61:X.commit(U[nt],"",X.commitType.NORMAL,"");break;case 62:X.commit(U[nt],"",X.commitType.NORMAL,U[nt-2]);break;case 63:X.commit(U[nt-2],"",X.commitType.NORMAL,U[nt]);break;case 64:X.commit(U[nt-2],"",U[nt],"");break;case 65:X.commit(U[nt],"",U[nt-2],"");break;case 66:X.commit(U[nt],U[nt-2],X.commitType.NORMAL,"");break;case 67:X.commit(U[nt-2],U[nt],X.commitType.NORMAL,"");break;case 68:X.commit(U[nt-4],"",U[nt-2],U[nt]);break;case 69:X.commit(U[nt-4],"",U[nt],U[nt-2]);break;case 70:X.commit(U[nt-2],"",U[nt-4],U[nt]);break;case 71:X.commit(U[nt],"",U[nt-4],U[nt-2]);break;case 72:X.commit(U[nt],"",U[nt-2],U[nt-4]);break;case 73:X.commit(U[nt-2],"",U[nt],U[nt-4]);break;case 74:X.commit(U[nt-4],U[nt],U[nt-2],"");break;case 75:X.commit(U[nt-4],U[nt-2],U[nt],"");break;case 76:X.commit(U[nt-2],U[nt],U[nt-4],"");break;case 77:X.commit(U[nt],U[nt-2],U[nt-4],"");break;case 78:X.commit(U[nt],U[nt-4],U[nt-2],"");break;case 79:X.commit(U[nt-2],U[nt-4],U[nt],"");break;case 80:X.commit(U[nt-4],U[nt],X.commitType.NORMAL,U[nt-2]);break;case 81:X.commit(U[nt-4],U[nt-2],X.commitType.NORMAL,U[nt]);break;case 82:X.commit(U[nt-2],U[nt],X.commitType.NORMAL,U[nt-4]);break;case 83:X.commit(U[nt],U[nt-2],X.commitType.NORMAL,U[nt-4]);break;case 84:X.commit(U[nt],U[nt-4],X.commitType.NORMAL,U[nt-2]);break;case 85:X.commit(U[nt-2],U[nt-4],X.commitType.NORMAL,U[nt]);break;case 86:X.commit(U[nt-6],U[nt-4],U[nt-2],U[nt]);break;case 87:X.commit(U[nt-6],U[nt-4],U[nt],U[nt-2]);break;case 88:X.commit(U[nt-6],U[nt-2],U[nt-4],U[nt]);break;case 89:X.commit(U[nt-6],U[nt],U[nt-4],U[nt-2]);break;case 90:X.commit(U[nt-6],U[nt-2],U[nt],U[nt-4]);break;case 91:X.commit(U[nt-6],U[nt],U[nt-2],U[nt-4]);break;case 92:X.commit(U[nt-4],U[nt-6],U[nt-2],U[nt]);break;case 93:X.commit(U[nt-4],U[nt-6],U[nt],U[nt-2]);break;case 94:X.commit(U[nt-2],U[nt-6],U[nt-4],U[nt]);break;case 95:X.commit(U[nt],U[nt-6],U[nt-4],U[nt-2]);break;case 96:X.commit(U[nt-2],U[nt-6],U[nt],U[nt-4]);break;case 97:X.commit(U[nt],U[nt-6],U[nt-2],U[nt-4]);break;case 98:X.commit(U[nt],U[nt-4],U[nt-2],U[nt-6]);break;case 99:X.commit(U[nt-2],U[nt-4],U[nt],U[nt-6]);break;case 100:X.commit(U[nt],U[nt-2],U[nt-4],U[nt-6]);break;case 101:X.commit(U[nt-2],U[nt],U[nt-4],U[nt-6]);break;case 102:X.commit(U[nt-4],U[nt-2],U[nt],U[nt-6]);break;case 103:X.commit(U[nt-4],U[nt],U[nt-2],U[nt-6]);break;case 104:X.commit(U[nt-2],U[nt-4],U[nt-6],U[nt]);break;case 105:X.commit(U[nt],U[nt-4],U[nt-6],U[nt-2]);break;case 106:X.commit(U[nt-2],U[nt],U[nt-6],U[nt-4]);break;case 107:X.commit(U[nt],U[nt-2],U[nt-6],U[nt-4]);break;case 108:X.commit(U[nt-4],U[nt-2],U[nt-6],U[nt]);break;case 109:X.commit(U[nt-4],U[nt],U[nt-6],U[nt-2]);break;case 110:this.$="";break;case 111:this.$=U[nt];break;case 112:this.$=X.commitType.NORMAL;break;case 113:this.$=X.commitType.REVERSE;break;case 114:this.$=X.commitType.HIGHLIGHT;break}},table:[{3:1,4:2,5:a,7:f,13:p,46:w},{1:[3]},{3:7,4:2,5:a,7:f,13:p,46:w},{6:8,7:m,8:[1,9],9:[1,10],10:11,13:b},i(E,[2,117]),i(E,[2,118]),i(E,[2,119]),{1:[2,1]},{7:[1,13]},{6:14,7:m,10:11,13:b},{8:[1,15]},i(_,[2,9],{11:16,12:[1,17]}),i(A,[2,8]),{1:[2,2]},{7:[1,18]},{6:19,7:m,10:11,13:b},{7:[2,6],13:[1,22],14:20,15:21,16:23,17:24,18:25,19:[1,26],21:[1,27],23:[1,28],24:[1,29],25:30,26:[1,31],28:[1,35],31:[1,34],36:[1,33],39:[1,32]},i(A,[2,7]),{1:[2,3]},{7:[1,36]},i(_,[2,10]),{4:37,7:f,13:p,46:w},i(_,[2,12]),i(I,[2,13]),i(I,[2,14]),i(I,[2,15]),{20:[1,38]},{22:[1,39]},i(I,[2,18]),i(I,[2,19]),i(I,[2,20]),{27:40,33:B,45:N},i(I,[2,110],{40:43,32:[1,46],33:[1,48],34:[1,44],37:[1,45],41:[1,47]}),{27:49,33:B,45:N},{32:[1,50],34:[1,51]},{27:52,33:B,45:N},{1:[2,4]},i(_,[2,11]),i(I,[2,16]),i(I,[2,17]),i(I,[2,21]),i(R,[2,115]),i(R,[2,116]),i(I,[2,45]),{33:[1,53]},{38:54,42:z,43:W,44:et},{33:[1,58]},{33:[1,59]},i(I,[2,111]),i(I,[2,29],{32:[1,60],34:[1,62],37:[1,61]}),{33:[1,63]},{33:[1,64],35:[1,65]},i(I,[2,22],{29:[1,66]}),i(I,[2,46],{32:[1,68],37:[1,67],41:[1,69]}),i(I,[2,47],{32:[1,71],34:[1,70],41:[1,72]}),i(st,[2,112]),i(st,[2,113]),i(st,[2,114]),i(I,[2,50],{34:[1,73],37:[1,74],41:[1,75]}),i(I,[2,61],{32:[1,78],34:[1,76],37:[1,77]}),{33:[1,79]},{38:80,42:z,43:W,44:et},{33:[1,81]},i(I,[2,24],{34:[1,82]}),{32:[1,83]},{32:[1,84]},{30:[1,85]},{38:86,42:z,43:W,44:et},{33:[1,87]},{33:[1,88]},{33:[1,89]},{33:[1,90]},{33:[1,91]},{33:[1,92]},{38:93,42:z,43:W,44:et},{33:[1,94]},{33:[1,95]},{38:96,42:z,43:W,44:et},{33:[1,97]},i(I,[2,30],{34:[1,99],37:[1,98]}),i(I,[2,31],{32:[1,101],34:[1,100]}),i(I,[2,32],{32:[1,102],37:[1,103]}),{33:[1,104],35:[1,105]},{33:[1,106]},{33:[1,107]},i(I,[2,23]),i(I,[2,48],{32:[1,108],41:[1,109]}),i(I,[2,52],{37:[1,110],41:[1,111]}),i(I,[2,62],{32:[1,113],37:[1,112]}),i(I,[2,49],{32:[1,114],41:[1,115]}),i(I,[2,54],{34:[1,116],41:[1,117]}),i(I,[2,65],{32:[1,119],34:[1,118]}),i(I,[2,51],{37:[1,120],41:[1,121]}),i(I,[2,53],{34:[1,122],41:[1,123]}),i(I,[2,66],{34:[1,125],37:[1,124]}),i(I,[2,63],{32:[1,127],37:[1,126]}),i(I,[2,64],{32:[1,129],34:[1,128]}),i(I,[2,67],{34:[1,131],37:[1,130]}),{38:132,42:z,43:W,44:et},{33:[1,133]},{33:[1,134]},{33:[1,135]},{33:[1,136]},{38:137,42:z,43:W,44:et},i(I,[2,25]),i(I,[2,26]),i(I,[2,27]),i(I,[2,28]),{33:[1,138]},{33:[1,139]},{38:140,42:z,43:W,44:et},{33:[1,141]},{38:142,42:z,43:W,44:et},{33:[1,143]},{33:[1,144]},{33:[1,145]},{33:[1,146]},{33:[1,147]},{33:[1,148]},{33:[1,149]},{38:150,42:z,43:W,44:et},{33:[1,151]},{33:[1,152]},{33:[1,153]},{38:154,42:z,43:W,44:et},{33:[1,155]},{38:156,42:z,43:W,44:et},{33:[1,157]},{33:[1,158]},{33:[1,159]},{38:160,42:z,43:W,44:et},{33:[1,161]},i(I,[2,36],{34:[1,162]}),i(I,[2,37],{37:[1,163]}),i(I,[2,35],{32:[1,164]}),i(I,[2,38],{34:[1,165]}),i(I,[2,33],{37:[1,166]}),i(I,[2,34],{32:[1,167]}),i(I,[2,59],{41:[1,168]}),i(I,[2,72],{32:[1,169]}),i(I,[2,60],{41:[1,170]}),i(I,[2,83],{37:[1,171]}),i(I,[2,73],{32:[1,172]}),i(I,[2,82],{37:[1,173]}),i(I,[2,58],{41:[1,174]}),i(I,[2,71],{32:[1,175]}),i(I,[2,57],{41:[1,176]}),i(I,[2,77],{34:[1,177]}),i(I,[2,70],{32:[1,178]}),i(I,[2,76],{34:[1,179]}),i(I,[2,56],{41:[1,180]}),i(I,[2,84],{37:[1,181]}),i(I,[2,55],{41:[1,182]}),i(I,[2,78],{34:[1,183]}),i(I,[2,79],{34:[1,184]}),i(I,[2,85],{37:[1,185]}),i(I,[2,69],{32:[1,186]}),i(I,[2,80],{37:[1,187]}),i(I,[2,68],{32:[1,188]}),i(I,[2,74],{34:[1,189]}),i(I,[2,75],{34:[1,190]}),i(I,[2,81],{37:[1,191]}),{33:[1,192]},{38:193,42:z,43:W,44:et},{33:[1,194]},{33:[1,195]},{38:196,42:z,43:W,44:et},{33:[1,197]},{33:[1,198]},{33:[1,199]},{33:[1,200]},{38:201,42:z,43:W,44:et},{33:[1,202]},{38:203,42:z,43:W,44:et},{33:[1,204]},{33:[1,205]},{33:[1,206]},{33:[1,207]},{33:[1,208]},{33:[1,209]},{33:[1,210]},{38:211,42:z,43:W,44:et},{33:[1,212]},{33:[1,213]},{33:[1,214]},{38:215,42:z,43:W,44:et},{33:[1,216]},{38:217,42:z,43:W,44:et},{33:[1,218]},{33:[1,219]},{33:[1,220]},{38:221,42:z,43:W,44:et},i(I,[2,39]),i(I,[2,41]),i(I,[2,40]),i(I,[2,42]),i(I,[2,44]),i(I,[2,43]),i(I,[2,100]),i(I,[2,101]),i(I,[2,98]),i(I,[2,99]),i(I,[2,103]),i(I,[2,102]),i(I,[2,107]),i(I,[2,106]),i(I,[2,105]),i(I,[2,104]),i(I,[2,109]),i(I,[2,108]),i(I,[2,97]),i(I,[2,96]),i(I,[2,95]),i(I,[2,94]),i(I,[2,92]),i(I,[2,93]),i(I,[2,91]),i(I,[2,90]),i(I,[2,89]),i(I,[2,88]),i(I,[2,86]),i(I,[2,87])],defaultActions:{7:[2,1],13:[2,2],18:[2,3],36:[2,4]},parseError:function(ft,ut){if(ut.recoverable)this.trace(ft);else{var vt=new Error(ft);throw vt.hash=ut,vt}},parse:function(ft){var ut=this,vt=[0],X=[],pt=[null],U=[],Tt=this.table,nt="",It=0,Ot=0,Bt=2,Et=1,Z=U.slice.call(arguments,1),Ct=Object.create(this.lexer),xt={yy:{}};for(var Ht in this.yy)Object.prototype.hasOwnProperty.call(this.yy,Ht)&&(xt.yy[Ht]=this.yy[Ht]);Ct.setInput(ft,xt.yy),xt.yy.lexer=Ct,xt.yy.parser=this,typeof Ct.yylloc>"u"&&(Ct.yylloc={});var Le=Ct.yylloc;U.push(Le);var Ft=Ct.options&&Ct.options.ranges;typeof xt.yy.parseError=="function"?this.parseError=xt.yy.parseError:this.parseError=Object.getPrototypeOf(this).parseError;function gn(){var te;return te=X.pop()||Ct.lex()||Et,typeof te!="number"&&(te instanceof Array&&(X=te,te=X.pop()),te=ut.symbols_[te]||te),te}for(var Se,me,Ve,Ye,ce={},ke,zt,re,se;;){if(me=vt[vt.length-1],this.defaultActions[me]?Ve=this.defaultActions[me]:((Se===null||typeof Se>"u")&&(Se=gn()),Ve=Tt[me]&&Tt[me][Se]),typeof Ve>"u"||!Ve.length||!Ve[0]){var Pe="";se=[];for(ke in Tt[me])this.terminals_[ke]&&ke>Bt&&se.push("'"+this.terminals_[ke]+"'");Ct.showPosition?Pe="Parse error on line "+(It+1)+`: +`+Ct.showPosition()+` +Expecting `+se.join(", ")+", got '"+(this.terminals_[Se]||Se)+"'":Pe="Parse error on line "+(It+1)+": Unexpected "+(Se==Et?"end of input":"'"+(this.terminals_[Se]||Se)+"'"),this.parseError(Pe,{text:Ct.match,token:this.terminals_[Se]||Se,line:Ct.yylineno,loc:Le,expected:se})}if(Ve[0]instanceof Array&&Ve.length>1)throw new Error("Parse Error: multiple actions possible at state: "+me+", token: "+Se);switch(Ve[0]){case 1:vt.push(Se),pt.push(Ct.yytext),U.push(Ct.yylloc),vt.push(Ve[1]),Se=null,Ot=Ct.yyleng,nt=Ct.yytext,It=Ct.yylineno,Le=Ct.yylloc;break;case 2:if(zt=this.productions_[Ve[1]][1],ce.$=pt[pt.length-zt],ce._$={first_line:U[U.length-(zt||1)].first_line,last_line:U[U.length-1].last_line,first_column:U[U.length-(zt||1)].first_column,last_column:U[U.length-1].last_column},Ft&&(ce._$.range=[U[U.length-(zt||1)].range[0],U[U.length-1].range[1]]),Ye=this.performAction.apply(ce,[nt,Ot,It,xt.yy,Ve[1],pt,U].concat(Z)),typeof Ye<"u")return Ye;zt&&(vt=vt.slice(0,-1*zt*2),pt=pt.slice(0,-1*zt),U=U.slice(0,-1*zt)),vt.push(this.productions_[Ve[1]][0]),pt.push(ce.$),U.push(ce._$),re=Tt[vt[vt.length-2]][vt[vt.length-1]],vt.push(re);break;case 3:return!0}}return!0}},bt=function(){var yt={EOF:1,parseError:function(ut,vt){if(this.yy.parser)this.yy.parser.parseError(ut,vt);else throw new Error(ut)},setInput:function(ft,ut){return this.yy=ut||this.yy||{},this._input=ft,this._more=this._backtrack=this.done=!1,this.yylineno=this.yyleng=0,this.yytext=this.matched=this.match="",this.conditionStack=["INITIAL"],this.yylloc={first_line:1,first_column:0,last_line:1,last_column:0},this.options.ranges&&(this.yylloc.range=[0,0]),this.offset=0,this},input:function(){var ft=this._input[0];this.yytext+=ft,this.yyleng++,this.offset++,this.match+=ft,this.matched+=ft;var ut=ft.match(/(?:\r\n?|\n).*/g);return ut?(this.yylineno++,this.yylloc.last_line++):this.yylloc.last_column++,this.options.ranges&&this.yylloc.range[1]++,this._input=this._input.slice(1),ft},unput:function(ft){var ut=ft.length,vt=ft.split(/(?:\r\n?|\n)/g);this._input=ft+this._input,this.yytext=this.yytext.substr(0,this.yytext.length-ut),this.offset-=ut;var X=this.match.split(/(?:\r\n?|\n)/g);this.match=this.match.substr(0,this.match.length-1),this.matched=this.matched.substr(0,this.matched.length-1),vt.length-1&&(this.yylineno-=vt.length-1);var pt=this.yylloc.range;return this.yylloc={first_line:this.yylloc.first_line,last_line:this.yylineno+1,first_column:this.yylloc.first_column,last_column:vt?(vt.length===X.length?this.yylloc.first_column:0)+X[X.length-vt.length].length-vt[0].length:this.yylloc.first_column-ut},this.options.ranges&&(this.yylloc.range=[pt[0],pt[0]+this.yyleng-ut]),this.yyleng=this.yytext.length,this},more:function(){return this._more=!0,this},reject:function(){if(this.options.backtrack_lexer)this._backtrack=!0;else return this.parseError("Lexical error on line "+(this.yylineno+1)+`. You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true). +`+this.showPosition(),{text:"",token:null,line:this.yylineno});return this},less:function(ft){this.unput(this.match.slice(ft))},pastInput:function(){var ft=this.matched.substr(0,this.matched.length-this.match.length);return(ft.length>20?"...":"")+ft.substr(-20).replace(/\n/g,"")},upcomingInput:function(){var ft=this.match;return ft.length<20&&(ft+=this._input.substr(0,20-ft.length)),(ft.substr(0,20)+(ft.length>20?"...":"")).replace(/\n/g,"")},showPosition:function(){var ft=this.pastInput(),ut=new Array(ft.length+1).join("-");return ft+this.upcomingInput()+` +`+ut+"^"},test_match:function(ft,ut){var vt,X,pt;if(this.options.backtrack_lexer&&(pt={yylineno:this.yylineno,yylloc:{first_line:this.yylloc.first_line,last_line:this.last_line,first_column:this.yylloc.first_column,last_column:this.yylloc.last_column},yytext:this.yytext,match:this.match,matches:this.matches,matched:this.matched,yyleng:this.yyleng,offset:this.offset,_more:this._more,_input:this._input,yy:this.yy,conditionStack:this.conditionStack.slice(0),done:this.done},this.options.ranges&&(pt.yylloc.range=this.yylloc.range.slice(0))),X=ft[0].match(/(?:\r\n?|\n).*/g),X&&(this.yylineno+=X.length),this.yylloc={first_line:this.yylloc.last_line,last_line:this.yylineno+1,first_column:this.yylloc.last_column,last_column:X?X[X.length-1].length-X[X.length-1].match(/\r?\n?/)[0].length:this.yylloc.last_column+ft[0].length},this.yytext+=ft[0],this.match+=ft[0],this.matches=ft,this.yyleng=this.yytext.length,this.options.ranges&&(this.yylloc.range=[this.offset,this.offset+=this.yyleng]),this._more=!1,this._backtrack=!1,this._input=this._input.slice(ft[0].length),this.matched+=ft[0],vt=this.performAction.call(this,this.yy,this,ut,this.conditionStack[this.conditionStack.length-1]),this.done&&this._input&&(this.done=!1),vt)return vt;if(this._backtrack){for(var U in pt)this[U]=pt[U];return!1}return!1},next:function(){if(this.done)return this.EOF;this._input||(this.done=!0);var ft,ut,vt,X;this._more||(this.yytext="",this.match="");for(var pt=this._currentRules(),U=0;Uut[0].length)){if(ut=vt,X=U,this.options.backtrack_lexer){if(ft=this.test_match(vt,pt[U]),ft!==!1)return ft;if(this._backtrack){ut=!1;continue}else return!1}else if(!this.options.flex)break}return ut?(ft=this.test_match(ut,pt[X]),ft!==!1?ft:!1):this._input===""?this.EOF:this.parseError("Lexical error on line "+(this.yylineno+1)+`. Unrecognized text. +`+this.showPosition(),{text:"",token:null,line:this.yylineno})},lex:function(){var ut=this.next();return ut||this.lex()},begin:function(ut){this.conditionStack.push(ut)},popState:function(){var ut=this.conditionStack.length-1;return ut>0?this.conditionStack.pop():this.conditionStack[0]},_currentRules:function(){return this.conditionStack.length&&this.conditionStack[this.conditionStack.length-1]?this.conditions[this.conditionStack[this.conditionStack.length-1]].rules:this.conditions.INITIAL.rules},topState:function(ut){return ut=this.conditionStack.length-1-Math.abs(ut||0),ut>=0?this.conditionStack[ut]:"INITIAL"},pushState:function(ut){this.begin(ut)},stateStackSize:function(){return this.conditionStack.length},options:{"case-insensitive":!0},performAction:function(ut,vt,X,pt){switch(X){case 0:return this.begin("acc_title"),19;case 1:return this.popState(),"acc_title_value";case 2:return this.begin("acc_descr"),21;case 3:return this.popState(),"acc_descr_value";case 4:this.begin("acc_descr_multiline");break;case 5:this.popState();break;case 6:return"acc_descr_multiline_value";case 7:return 13;case 8:break;case 9:break;case 10:return 5;case 11:return 39;case 12:return 32;case 13:return 37;case 14:return 41;case 15:return 42;case 16:return 43;case 17:return 44;case 18:return 34;case 19:return 28;case 20:return 29;case 21:return 36;case 22:return 31;case 23:return 26;case 24:return 9;case 25:return 9;case 26:return 8;case 27:return"CARET";case 28:this.begin("options");break;case 29:this.popState();break;case 30:return 12;case 31:return 35;case 32:this.begin("string");break;case 33:this.popState();break;case 34:return 33;case 35:return 30;case 36:return 45;case 37:return 7}},rules:[/^(?:accTitle\s*:\s*)/i,/^(?:(?!\n||)*[^\n]*)/i,/^(?:accDescr\s*:\s*)/i,/^(?:(?!\n||)*[^\n]*)/i,/^(?:accDescr\s*\{\s*)/i,/^(?:[\}])/i,/^(?:[^\}]*)/i,/^(?:(\r?\n)+)/i,/^(?:#[^\n]*)/i,/^(?:%[^\n]*)/i,/^(?:gitGraph\b)/i,/^(?:commit(?=\s|$))/i,/^(?:id:)/i,/^(?:type:)/i,/^(?:msg:)/i,/^(?:NORMAL\b)/i,/^(?:REVERSE\b)/i,/^(?:HIGHLIGHT\b)/i,/^(?:tag:)/i,/^(?:branch(?=\s|$))/i,/^(?:order:)/i,/^(?:merge(?=\s|$))/i,/^(?:cherry-pick(?=\s|$))/i,/^(?:checkout(?=\s|$))/i,/^(?:LR\b)/i,/^(?:TB\b)/i,/^(?::)/i,/^(?:\^)/i,/^(?:options\r?\n)/i,/^(?:[ \r\n\t]+end\b)/i,/^(?:[\s\S]+(?=[ \r\n\t]+end))/i,/^(?:["]["])/i,/^(?:["])/i,/^(?:["])/i,/^(?:[^"]*)/i,/^(?:[0-9]+(?=\s|$))/i,/^(?:\w([-\./\w]*[-\w])?)/i,/^(?:$)/i,/^(?:\s+)/i],conditions:{acc_descr_multiline:{rules:[5,6],inclusive:!1},acc_descr:{rules:[3],inclusive:!1},acc_title:{rules:[1],inclusive:!1},options:{rules:[29,30],inclusive:!1},string:{rules:[33,34],inclusive:!1},INITIAL:{rules:[0,2,4,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,31,32,35,36,37,38],inclusive:!0}}};return yt}();at.lexer=bt;function mt(){this.yy={}}return mt.prototype=at,at.Parser=mt,new mt}();z0t.parser=z0t;const Nze=z0t;let MY=Oe().gitGraph.mainBranchName,Bze=Oe().gitGraph.mainBranchOrder,l1={},vg=null,AF={};AF[MY]={name:MY,order:Bze};let Nf={};Nf[MY]=vg;let J1=MY,BBt="LR",ET=0;function q0t(){return GIt({length:7})}function Rze(i,a){const f=Object.create(null);return i.reduce((p,w)=>{const m=a(w);return f[m]||(f[m]=!0,p.push(w)),p},[])}const jze=function(i){BBt=i};let RBt={};const $ze=function(i){Ut.debug("options str",i),i=i&&i.trim(),i=i||"{}";try{RBt=JSON.parse(i)}catch(a){Ut.error("error while parsing gitGraph options",a.message)}},zze=function(){return RBt},qze=function(i,a,f,p){Ut.debug("Entering commit:",i,a,f,p),a=Kr.sanitizeText(a,Oe()),i=Kr.sanitizeText(i,Oe()),p=Kr.sanitizeText(p,Oe());const w={id:a||ET+"-"+q0t(),message:i,seq:ET++,type:f||LF.NORMAL,tag:p||"",parents:vg==null?[]:[vg.id],branch:J1};vg=w,l1[w.id]=w,Nf[J1]=w.id,Ut.debug("in pushCommit "+w.id)},Hze=function(i,a){if(i=Kr.sanitizeText(i,Oe()),Nf[i]===void 0)Nf[i]=vg!=null?vg.id:null,AF[i]={name:i,order:a?parseInt(a,10):null},jBt(i),Ut.debug("in createBranch");else{let f=new Error('Trying to create an existing branch. (Help: Either use a new name if you want create a new branch or try using "checkout '+i+'")');throw f.hash={text:"branch "+i,token:"branch "+i,line:"1",loc:{first_line:1,last_line:1,first_column:1,last_column:1},expected:['"checkout '+i+'"']},f}},Vze=function(i,a,f,p){i=Kr.sanitizeText(i,Oe()),a=Kr.sanitizeText(a,Oe());const w=l1[Nf[J1]],m=l1[Nf[i]];if(J1===i){let E=new Error('Incorrect usage of "merge". Cannot merge a branch to itself');throw E.hash={text:"merge "+i,token:"merge "+i,line:"1",loc:{first_line:1,last_line:1,first_column:1,last_column:1},expected:["branch abc"]},E}else if(w===void 0||!w){let E=new Error('Incorrect usage of "merge". Current branch ('+J1+")has no commits");throw E.hash={text:"merge "+i,token:"merge "+i,line:"1",loc:{first_line:1,last_line:1,first_column:1,last_column:1},expected:["commit"]},E}else if(Nf[i]===void 0){let E=new Error('Incorrect usage of "merge". Branch to be merged ('+i+") does not exist");throw E.hash={text:"merge "+i,token:"merge "+i,line:"1",loc:{first_line:1,last_line:1,first_column:1,last_column:1},expected:["branch "+i]},E}else if(m===void 0||!m){let E=new Error('Incorrect usage of "merge". Branch to be merged ('+i+") has no commits");throw E.hash={text:"merge "+i,token:"merge "+i,line:"1",loc:{first_line:1,last_line:1,first_column:1,last_column:1},expected:['"commit"']},E}else if(w===m){let E=new Error('Incorrect usage of "merge". Both branches have same head');throw E.hash={text:"merge "+i,token:"merge "+i,line:"1",loc:{first_line:1,last_line:1,first_column:1,last_column:1},expected:["branch abc"]},E}else if(a&&l1[a]!==void 0){let E=new Error('Incorrect usage of "merge". Commit with id:'+a+" already exists, use different custom Id");throw E.hash={text:"merge "+i+a+f+p,token:"merge "+i+a+f+p,line:"1",loc:{first_line:1,last_line:1,first_column:1,last_column:1},expected:["merge "+i+" "+a+"_UNIQUE "+f+" "+p]},E}const b={id:a||ET+"-"+q0t(),message:"merged branch "+i+" into "+J1,seq:ET++,parents:[vg==null?null:vg.id,Nf[i]],branch:J1,type:LF.MERGE,customType:f,customId:!!a,tag:p||""};vg=b,l1[b.id]=b,Nf[J1]=b.id,Ut.debug(Nf),Ut.debug("in mergeBranch")},Gze=function(i,a,f){if(Ut.debug("Entering cherryPick:",i,a,f),i=Kr.sanitizeText(i,Oe()),a=Kr.sanitizeText(a,Oe()),f=Kr.sanitizeText(f,Oe()),!i||l1[i]===void 0){let m=new Error('Incorrect usage of "cherryPick". Source commit id should exist and provided');throw m.hash={text:"cherryPick "+i+" "+a,token:"cherryPick "+i+" "+a,line:"1",loc:{first_line:1,last_line:1,first_column:1,last_column:1},expected:["cherry-pick abc"]},m}let p=l1[i],w=p.branch;if(p.type===LF.MERGE){let m=new Error('Incorrect usage of "cherryPick". Source commit should not be a merge commit');throw m.hash={text:"cherryPick "+i+" "+a,token:"cherryPick "+i+" "+a,line:"1",loc:{first_line:1,last_line:1,first_column:1,last_column:1},expected:["cherry-pick abc"]},m}if(!a||l1[a]===void 0){if(w===J1){let E=new Error('Incorrect usage of "cherryPick". Source commit is already on current branch');throw E.hash={text:"cherryPick "+i+" "+a,token:"cherryPick "+i+" "+a,line:"1",loc:{first_line:1,last_line:1,first_column:1,last_column:1},expected:["cherry-pick abc"]},E}const m=l1[Nf[J1]];if(m===void 0||!m){let E=new Error('Incorrect usage of "cherry-pick". Current branch ('+J1+")has no commits");throw E.hash={text:"cherryPick "+i+" "+a,token:"cherryPick "+i+" "+a,line:"1",loc:{first_line:1,last_line:1,first_column:1,last_column:1},expected:["cherry-pick abc"]},E}const b={id:ET+"-"+q0t(),message:"cherry-picked "+p+" into "+J1,seq:ET++,parents:[vg==null?null:vg.id,p.id],branch:J1,type:LF.CHERRY_PICK,tag:f??"cherry-pick:"+p.id};vg=b,l1[b.id]=b,Nf[J1]=b.id,Ut.debug(Nf),Ut.debug("in cherryPick")}},jBt=function(i){if(i=Kr.sanitizeText(i,Oe()),Nf[i]===void 0){let a=new Error('Trying to checkout branch which is not yet created. (Help try using "branch '+i+'")');throw a.hash={text:"checkout "+i,token:"checkout "+i,line:"1",loc:{first_line:1,last_line:1,first_column:1,last_column:1},expected:['"branch '+i+'"']},a}else{J1=i;const a=Nf[J1];vg=l1[a]}};function $Bt(i,a,f){const p=i.indexOf(a);p===-1?i.push(f):i.splice(p,1,f)}function zBt(i){const a=i.reduce((w,m)=>w.seq>m.seq?w:m,i[0]);let f="";i.forEach(function(w){w===a?f+=" *":f+=" |"});const p=[f,a.id,a.seq];for(let w in Nf)Nf[w]===a.id&&p.push(w);if(Ut.debug(p.join(" ")),a.parents&&a.parents.length==2){const w=l1[a.parents[0]];$Bt(i,a,w),i.push(l1[a.parents[1]])}else{if(a.parents.length==0)return;{const w=l1[a.parents];$Bt(i,a,w)}}i=Rze(i,w=>w.id),zBt(i)}const Uze=function(){Ut.debug(l1);const i=qBt()[0];zBt([i])},Wze=function(){l1={},vg=null;let i=Oe().gitGraph.mainBranchName,a=Oe().gitGraph.mainBranchOrder;Nf={},Nf[i]=null,AF={},AF[i]={name:i,order:a},J1=i,ET=0,hg()},Yze=function(){return Object.values(AF).map((a,f)=>a.order!==null?a:{...a,order:parseFloat(`0.${f}`,10)}).sort((a,f)=>a.order-f.order).map(({name:a})=>({name:a}))},Kze=function(){return Nf},Xze=function(){return l1},qBt=function(){const i=Object.keys(l1).map(function(a){return l1[a]});return i.forEach(function(a){Ut.debug(a.id)}),i.sort((a,f)=>a.seq-f.seq),i},Qze=function(){return J1},Zze=function(){return BBt},Jze=function(){return vg},LF={NORMAL:0,REVERSE:1,HIGHLIGHT:2,MERGE:3,CHERRY_PICK:4},tqe={getConfig:()=>Oe().gitGraph,setDirection:jze,setOptions:$ze,getOptions:zze,commit:qze,branch:Hze,merge:Vze,cherryPick:Gze,checkout:jBt,prettyPrint:Uze,clear:Wze,getBranchesAsObjArray:Yze,getBranches:Kze,getCommits:Xze,getCommitsArray:qBt,getCurrentBranch:Qze,getDirection:Zze,getHead:Jze,setAccTitle:E0,getAccTitle:fg,getAccDescription:gg,setAccDescription:dg,setDiagramTitle:Nb,getDiagramTitle:pg,commitType:LF};let MF={};const $b={NORMAL:0,REVERSE:1,HIGHLIGHT:2,MERGE:3,CHERRY_PICK:4},TT=8;let td={},DF={},DY=[],IF=0,C0="LR";const eqe=()=>{td={},DF={},MF={},IF=0,DY=[],C0="LR"},HBt=i=>{const a=document.createElementNS("http://www.w3.org/2000/svg","text");let f=[];typeof i=="string"?f=i.split(/\\n|\n|/gi):Array.isArray(i)?f=i:f=[];for(const p of f){const w=document.createElementNS("http://www.w3.org/2000/svg","tspan");w.setAttributeNS("http://www.w3.org/XML/1998/namespace","xml:space","preserve"),w.setAttribute("dy","1em"),w.setAttribute("x","0"),w.setAttribute("class","row"),w.textContent=p.trim(),a.appendChild(w)}return a},VBt=(i,a,f)=>{const p=Oe().gitGraph,w=i.append("g").attr("class","commit-bullets"),m=i.append("g").attr("class","commit-labels");let b=0;C0==="TB"&&(b=30),Object.keys(a).sort((A,I)=>a[A].seq-a[I].seq).forEach(A=>{const I=a[A],B=C0==="TB"?b+10:td[I.branch].pos,N=C0==="TB"?td[I.branch].pos:b+10;if(f){let R,z=I.customType!==void 0&&I.customType!==""?I.customType:I.type;switch(z){case $b.NORMAL:R="commit-normal";break;case $b.REVERSE:R="commit-reverse";break;case $b.HIGHLIGHT:R="commit-highlight";break;case $b.MERGE:R="commit-merge";break;case $b.CHERRY_PICK:R="commit-cherry-pick";break;default:R="commit-normal"}if(z===$b.HIGHLIGHT){const W=w.append("rect");W.attr("x",N-10),W.attr("y",B-10),W.attr("height",20),W.attr("width",20),W.attr("class",`commit ${I.id} commit-highlight${td[I.branch].index%TT} ${R}-outer`),w.append("rect").attr("x",N-6).attr("y",B-6).attr("height",12).attr("width",12).attr("class",`commit ${I.id} commit${td[I.branch].index%TT} ${R}-inner`)}else if(z===$b.CHERRY_PICK)w.append("circle").attr("cx",N).attr("cy",B).attr("r",10).attr("class",`commit ${I.id} ${R}`),w.append("circle").attr("cx",N-3).attr("cy",B+2).attr("r",2.75).attr("fill","#fff").attr("class",`commit ${I.id} ${R}`),w.append("circle").attr("cx",N+3).attr("cy",B+2).attr("r",2.75).attr("fill","#fff").attr("class",`commit ${I.id} ${R}`),w.append("line").attr("x1",N+3).attr("y1",B+1).attr("x2",N).attr("y2",B-5).attr("stroke","#fff").attr("class",`commit ${I.id} ${R}`),w.append("line").attr("x1",N-3).attr("y1",B+1).attr("x2",N).attr("y2",B-5).attr("stroke","#fff").attr("class",`commit ${I.id} ${R}`);else{const W=w.append("circle");if(W.attr("cx",N),W.attr("cy",B),W.attr("r",I.type===$b.MERGE?9:10),W.attr("class",`commit ${I.id} commit${td[I.branch].index%TT}`),z===$b.MERGE){const et=w.append("circle");et.attr("cx",N),et.attr("cy",B),et.attr("r",6),et.attr("class",`commit ${R} ${I.id} commit${td[I.branch].index%TT}`)}z===$b.REVERSE&&w.append("path").attr("d",`M ${N-5},${B-5}L${N+5},${B+5}M${N-5},${B+5}L${N+5},${B-5}`).attr("class",`commit ${R} ${I.id} commit${td[I.branch].index%TT}`)}}if(C0==="TB"?DF[I.id]={x:N,y:b+10}:DF[I.id]={x:b+10,y:B},f){if(I.type!==$b.CHERRY_PICK&&(I.customId&&I.type===$b.MERGE||I.type!==$b.MERGE)&&p.showCommitLabel){const W=m.append("g"),et=W.insert("rect").attr("class","commit-label-bkg"),st=W.append("text").attr("x",b).attr("y",B+25).attr("class","commit-label").text(I.id);let at=st.node().getBBox();if(et.attr("x",b+10-at.width/2-2).attr("y",B+13.5).attr("width",at.width+2*2).attr("height",at.height+2*2),C0==="TB"&&(et.attr("x",N-(at.width+4*4+5)).attr("y",B-12),st.attr("x",N-(at.width+4*4)).attr("y",B+at.height-12)),C0!=="TB"&&st.attr("x",b+10-at.width/2),p.rotateCommitLabel)if(C0==="TB")st.attr("transform","rotate(-45, "+N+", "+B+")"),et.attr("transform","rotate(-45, "+N+", "+B+")");else{let bt=-7.5-(at.width+10)/25*9.5,mt=10+at.width/25*8.5;W.attr("transform","translate("+bt+", "+mt+") rotate(-45, "+b+", "+B+")")}}if(I.tag){const W=m.insert("polygon"),et=m.append("circle"),st=m.append("text").attr("y",B-16).attr("class","tag-label").text(I.tag);let at=st.node().getBBox();st.attr("x",b+10-at.width/2);const bt=at.height/2,mt=B-19.2;W.attr("class","tag-label-bkg").attr("points",` + ${b-at.width/2-4/2},${mt+2} + ${b-at.width/2-4/2},${mt-2} + ${b+10-at.width/2-4},${mt-bt-2} + ${b+10+at.width/2+4},${mt-bt-2} + ${b+10+at.width/2+4},${mt+bt+2} + ${b+10-at.width/2-4},${mt+bt+2}`),et.attr("cx",b-at.width/2+4/2).attr("cy",mt).attr("r",1.5).attr("class","tag-hole"),C0==="TB"&&(W.attr("class","tag-label-bkg").attr("points",` + ${N},${b+2} + ${N},${b-2} + ${N+10},${b-bt-2} + ${N+10+at.width+4},${b-bt-2} + ${N+10+at.width+4},${b+bt+2} + ${N+10},${b+bt+2}`).attr("transform","translate(12,12) rotate(45, "+N+","+b+")"),et.attr("cx",N+4/2).attr("cy",b).attr("transform","translate(12,12) rotate(45, "+N+","+b+")"),st.attr("x",N+5).attr("y",b+3).attr("transform","translate(14,14) rotate(45, "+N+","+b+")"))}}b+=50,b>IF&&(IF=b)})},nqe=(i,a,f)=>Object.keys(f).filter(m=>f[m].branch===a.branch&&f[m].seq>i.seq&&f[m].seq0,OF=(i,a,f=0)=>{const p=i+Math.abs(i-a)/2;if(f>5)return p;if(DY.every(b=>Math.abs(b-p)>=10))return DY.push(p),p;const m=Math.abs(i-a);return OF(i,a-m/5,f+1)},rqe=(i,a,f,p)=>{const w=DF[a.id],m=DF[f.id],b=nqe(a,f,p);let E="",_="",A=0,I=0,B=td[f.branch].index,N;if(b){E="A 10 10, 0, 0, 0,",_="A 10 10, 0, 0, 1,",A=10,I=10,B=td[f.branch].index;const R=w.ym.x&&(E="A 20 20, 0, 0, 0,",_="A 20 20, 0, 0, 1,",A=20,I=20,B=td[a.branch].index,N=`M ${w.x} ${w.y} L ${w.x} ${m.y-A} ${_} ${w.x-I} ${m.y} L ${m.x} ${m.y}`),w.x===m.x&&(B=td[a.branch].index,N=`M ${w.x} ${w.y} L ${w.x+A} ${w.y} ${E} ${w.x+I} ${m.y+A} L ${m.x} ${m.y}`)):(w.ym.y&&(E="A 20 20, 0, 0, 0,",A=20,I=20,B=td[a.branch].index,N=`M ${w.x} ${w.y} L ${m.x-A} ${w.y} ${E} ${m.x} ${w.y-I} L ${m.x} ${m.y}`),w.y===m.y&&(B=td[a.branch].index,N=`M ${w.x} ${w.y} L ${w.x} ${m.y-A} ${E} ${w.x+I} ${m.y} L ${m.x} ${m.y}`));i.append("path").attr("d",N).attr("class","arrow arrow"+B%TT)},iqe=(i,a)=>{const f=i.append("g").attr("class","commit-arrows");Object.keys(a).forEach(p=>{const w=a[p];w.parents&&w.parents.length>0&&w.parents.forEach(m=>{rqe(f,a[m],w,a)})})},sqe=(i,a)=>{const f=Oe().gitGraph,p=i.append("g");a.forEach((w,m)=>{const b=m%TT,E=td[w.name].pos,_=p.append("line");_.attr("x1",0),_.attr("y1",E),_.attr("x2",IF),_.attr("y2",E),_.attr("class","branch branch"+b),C0==="TB"&&(_.attr("y1",30),_.attr("x1",E),_.attr("y2",IF),_.attr("x2",E)),DY.push(E);let A=w.name;const I=HBt(A),B=p.insert("rect"),R=p.insert("g").attr("class","branchLabel").insert("g").attr("class","label branch-label"+b);R.node().appendChild(I);let z=I.getBBox();B.attr("class","branchLabelBkg label"+b).attr("rx",4).attr("ry",4).attr("x",-z.width-4-(f.rotateCommitLabel===!0?30:0)).attr("y",-z.height/2+8).attr("width",z.width+18).attr("height",z.height+4),R.attr("transform","translate("+(-z.width-14-(f.rotateCommitLabel===!0?30:0))+", "+(E-z.height/2-1)+")"),C0==="TB"&&(B.attr("x",E-z.width/2-10).attr("y",0),R.attr("transform","translate("+(E-z.width/2-5)+", 0)")),C0!=="TB"&&B.attr("transform","translate(-19, "+(E-z.height/2)+")")})},aqe=Object.freeze(Object.defineProperty({__proto__:null,diagram:{parser:Nze,db:tqe,renderer:{draw:function(i,a,f,p){eqe();const w=Oe(),m=w.gitGraph;Ut.debug("in gitgraph renderer",i+` +`,"id:",a,f),MF=p.db.getCommits();const b=p.db.getBranchesAsObjArray();C0=p.db.getDirection();const E=yr(`[id="${a}"]`);let _=0;b.forEach((A,I)=>{const B=HBt(A.name),N=E.append("g"),R=N.insert("g").attr("class","branchLabel"),z=R.insert("g").attr("class","label branch-label");z.node().appendChild(B);let W=B.getBBox();td[A.name]={pos:_,index:I},_+=50+(m.rotateCommitLabel?40:0)+(C0==="TB"?W.width/2:0),z.remove(),R.remove(),N.remove()}),VBt(E,MF,!1),m.showBranches&&sqe(E,b),iqe(E,MF),VBt(E,MF,!0),$a.insertTitle(E,"gitTitleText",m.titleTopMargin,p.db.getDiagramTitle()),AOt(void 0,E,m.diagramPadding,m.useMaxWidth??w.useMaxWidth)}},styles:i=>` + .commit-id, + .commit-msg, + .branch-label { + fill: lightgrey; + color: lightgrey; + font-family: 'trebuchet ms', verdana, arial, sans-serif; + font-family: var(--mermaid-font-family); + } + ${[0,1,2,3,4,5,6,7].map(a=>` + .branch-label${a} { fill: ${i["gitBranchLabel"+a]}; } + .commit${a} { stroke: ${i["git"+a]}; fill: ${i["git"+a]}; } + .commit-highlight${a} { stroke: ${i["gitInv"+a]}; fill: ${i["gitInv"+a]}; } + .label${a} { fill: ${i["git"+a]}; } + .arrow${a} { stroke: ${i["git"+a]}; } + `).join(` +`)} + + .branch { + stroke-width: 1; + stroke: ${i.lineColor}; + stroke-dasharray: 2; + } + .commit-label { font-size: ${i.commitLabelFontSize}; fill: ${i.commitLabelColor};} + .commit-label-bkg { font-size: ${i.commitLabelFontSize}; fill: ${i.commitLabelBackground}; opacity: 0.5; } + .tag-label { font-size: ${i.tagLabelFontSize}; fill: ${i.tagLabelColor};} + .tag-label-bkg { fill: ${i.tagLabelBackground}; stroke: ${i.tagLabelBorder}; } + .tag-hole { fill: ${i.textColor}; } + + .commit-merge { + stroke: ${i.primaryColor}; + fill: ${i.primaryColor}; + } + .commit-reverse { + stroke: ${i.primaryColor}; + fill: ${i.primaryColor}; + stroke-width: 3; + } + .commit-highlight-outer { + } + .commit-highlight-inner { + stroke: ${i.primaryColor}; + fill: ${i.primaryColor}; + } + + .arrow { stroke-width: 8; stroke-linecap: round; fill: none} + .gitTitleText { + text-anchor: middle; + font-size: 18px; + fill: ${i.textColor}; + } +`}},Symbol.toStringTag,{value:"Module"}));var H0t=function(){var i=function(U,Tt,nt,It){for(nt=nt||{},It=U.length;It--;nt[U[It]]=Tt);return nt},a=[6,8,10,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,30,32,33,35,37],f=[1,25],p=[1,26],w=[1,27],m=[1,28],b=[1,29],E=[1,30],_=[1,31],A=[1,9],I=[1,10],B=[1,11],N=[1,12],R=[1,13],z=[1,14],W=[1,15],et=[1,16],st=[1,18],at=[1,19],bt=[1,20],mt=[1,21],yt=[1,22],ft=[1,24],ut=[1,32],vt={trace:function(){},yy:{},symbols_:{error:2,start:3,gantt:4,document:5,EOF:6,line:7,SPACE:8,statement:9,NL:10,weekday:11,weekday_monday:12,weekday_tuesday:13,weekday_wednesday:14,weekday_thursday:15,weekday_friday:16,weekday_saturday:17,weekday_sunday:18,dateFormat:19,inclusiveEndDates:20,topAxis:21,axisFormat:22,tickInterval:23,excludes:24,includes:25,todayMarker:26,title:27,acc_title:28,acc_title_value:29,acc_descr:30,acc_descr_value:31,acc_descr_multiline_value:32,section:33,clickStatement:34,taskTxt:35,taskData:36,click:37,callbackname:38,callbackargs:39,href:40,clickStatementDebug:41,$accept:0,$end:1},terminals_:{2:"error",4:"gantt",6:"EOF",8:"SPACE",10:"NL",12:"weekday_monday",13:"weekday_tuesday",14:"weekday_wednesday",15:"weekday_thursday",16:"weekday_friday",17:"weekday_saturday",18:"weekday_sunday",19:"dateFormat",20:"inclusiveEndDates",21:"topAxis",22:"axisFormat",23:"tickInterval",24:"excludes",25:"includes",26:"todayMarker",27:"title",28:"acc_title",29:"acc_title_value",30:"acc_descr",31:"acc_descr_value",32:"acc_descr_multiline_value",33:"section",35:"taskTxt",36:"taskData",37:"click",38:"callbackname",39:"callbackargs",40:"href"},productions_:[0,[3,3],[5,0],[5,2],[7,2],[7,1],[7,1],[7,1],[11,1],[11,1],[11,1],[11,1],[11,1],[11,1],[11,1],[9,1],[9,1],[9,1],[9,1],[9,1],[9,1],[9,1],[9,1],[9,1],[9,1],[9,2],[9,2],[9,1],[9,1],[9,1],[9,2],[34,2],[34,3],[34,3],[34,4],[34,3],[34,4],[34,2],[41,2],[41,3],[41,3],[41,4],[41,3],[41,4],[41,2]],performAction:function(Tt,nt,It,Ot,Bt,Et,Z){var Ct=Et.length-1;switch(Bt){case 1:return Et[Ct-1];case 2:this.$=[];break;case 3:Et[Ct-1].push(Et[Ct]),this.$=Et[Ct-1];break;case 4:case 5:this.$=Et[Ct];break;case 6:case 7:this.$=[];break;case 8:Ot.setWeekday("monday");break;case 9:Ot.setWeekday("tuesday");break;case 10:Ot.setWeekday("wednesday");break;case 11:Ot.setWeekday("thursday");break;case 12:Ot.setWeekday("friday");break;case 13:Ot.setWeekday("saturday");break;case 14:Ot.setWeekday("sunday");break;case 15:Ot.setDateFormat(Et[Ct].substr(11)),this.$=Et[Ct].substr(11);break;case 16:Ot.enableInclusiveEndDates(),this.$=Et[Ct].substr(18);break;case 17:Ot.TopAxis(),this.$=Et[Ct].substr(8);break;case 18:Ot.setAxisFormat(Et[Ct].substr(11)),this.$=Et[Ct].substr(11);break;case 19:Ot.setTickInterval(Et[Ct].substr(13)),this.$=Et[Ct].substr(13);break;case 20:Ot.setExcludes(Et[Ct].substr(9)),this.$=Et[Ct].substr(9);break;case 21:Ot.setIncludes(Et[Ct].substr(9)),this.$=Et[Ct].substr(9);break;case 22:Ot.setTodayMarker(Et[Ct].substr(12)),this.$=Et[Ct].substr(12);break;case 24:Ot.setDiagramTitle(Et[Ct].substr(6)),this.$=Et[Ct].substr(6);break;case 25:this.$=Et[Ct].trim(),Ot.setAccTitle(this.$);break;case 26:case 27:this.$=Et[Ct].trim(),Ot.setAccDescription(this.$);break;case 28:Ot.addSection(Et[Ct].substr(8)),this.$=Et[Ct].substr(8);break;case 30:Ot.addTask(Et[Ct-1],Et[Ct]),this.$="task";break;case 31:this.$=Et[Ct-1],Ot.setClickEvent(Et[Ct-1],Et[Ct],null);break;case 32:this.$=Et[Ct-2],Ot.setClickEvent(Et[Ct-2],Et[Ct-1],Et[Ct]);break;case 33:this.$=Et[Ct-2],Ot.setClickEvent(Et[Ct-2],Et[Ct-1],null),Ot.setLink(Et[Ct-2],Et[Ct]);break;case 34:this.$=Et[Ct-3],Ot.setClickEvent(Et[Ct-3],Et[Ct-2],Et[Ct-1]),Ot.setLink(Et[Ct-3],Et[Ct]);break;case 35:this.$=Et[Ct-2],Ot.setClickEvent(Et[Ct-2],Et[Ct],null),Ot.setLink(Et[Ct-2],Et[Ct-1]);break;case 36:this.$=Et[Ct-3],Ot.setClickEvent(Et[Ct-3],Et[Ct-1],Et[Ct]),Ot.setLink(Et[Ct-3],Et[Ct-2]);break;case 37:this.$=Et[Ct-1],Ot.setLink(Et[Ct-1],Et[Ct]);break;case 38:case 44:this.$=Et[Ct-1]+" "+Et[Ct];break;case 39:case 40:case 42:this.$=Et[Ct-2]+" "+Et[Ct-1]+" "+Et[Ct];break;case 41:case 43:this.$=Et[Ct-3]+" "+Et[Ct-2]+" "+Et[Ct-1]+" "+Et[Ct];break}},table:[{3:1,4:[1,2]},{1:[3]},i(a,[2,2],{5:3}),{6:[1,4],7:5,8:[1,6],9:7,10:[1,8],11:17,12:f,13:p,14:w,15:m,16:b,17:E,18:_,19:A,20:I,21:B,22:N,23:R,24:z,25:W,26:et,27:st,28:at,30:bt,32:mt,33:yt,34:23,35:ft,37:ut},i(a,[2,7],{1:[2,1]}),i(a,[2,3]),{9:33,11:17,12:f,13:p,14:w,15:m,16:b,17:E,18:_,19:A,20:I,21:B,22:N,23:R,24:z,25:W,26:et,27:st,28:at,30:bt,32:mt,33:yt,34:23,35:ft,37:ut},i(a,[2,5]),i(a,[2,6]),i(a,[2,15]),i(a,[2,16]),i(a,[2,17]),i(a,[2,18]),i(a,[2,19]),i(a,[2,20]),i(a,[2,21]),i(a,[2,22]),i(a,[2,23]),i(a,[2,24]),{29:[1,34]},{31:[1,35]},i(a,[2,27]),i(a,[2,28]),i(a,[2,29]),{36:[1,36]},i(a,[2,8]),i(a,[2,9]),i(a,[2,10]),i(a,[2,11]),i(a,[2,12]),i(a,[2,13]),i(a,[2,14]),{38:[1,37],40:[1,38]},i(a,[2,4]),i(a,[2,25]),i(a,[2,26]),i(a,[2,30]),i(a,[2,31],{39:[1,39],40:[1,40]}),i(a,[2,37],{38:[1,41]}),i(a,[2,32],{40:[1,42]}),i(a,[2,33]),i(a,[2,35],{39:[1,43]}),i(a,[2,34]),i(a,[2,36])],defaultActions:{},parseError:function(Tt,nt){if(nt.recoverable)this.trace(Tt);else{var It=new Error(Tt);throw It.hash=nt,It}},parse:function(Tt){var nt=this,It=[0],Ot=[],Bt=[null],Et=[],Z=this.table,Ct="",xt=0,Ht=0,Le=2,Ft=1,gn=Et.slice.call(arguments,1),Se=Object.create(this.lexer),me={yy:{}};for(var Ve in this.yy)Object.prototype.hasOwnProperty.call(this.yy,Ve)&&(me.yy[Ve]=this.yy[Ve]);Se.setInput(Tt,me.yy),me.yy.lexer=Se,me.yy.parser=this,typeof Se.yylloc>"u"&&(Se.yylloc={});var Ye=Se.yylloc;Et.push(Ye);var ce=Se.options&&Se.options.ranges;typeof me.yy.parseError=="function"?this.parseError=me.yy.parseError:this.parseError=Object.getPrototypeOf(this).parseError;function ke(){var ws;return ws=Ot.pop()||Se.lex()||Ft,typeof ws!="number"&&(ws instanceof Array&&(Ot=ws,ws=Ot.pop()),ws=nt.symbols_[ws]||ws),ws}for(var zt,re,se,Pe,te={},Me,de,on,ni;;){if(re=It[It.length-1],this.defaultActions[re]?se=this.defaultActions[re]:((zt===null||typeof zt>"u")&&(zt=ke()),se=Z[re]&&Z[re][zt]),typeof se>"u"||!se.length||!se[0]){var Ks="";ni=[];for(Me in Z[re])this.terminals_[Me]&&Me>Le&&ni.push("'"+this.terminals_[Me]+"'");Se.showPosition?Ks="Parse error on line "+(xt+1)+`: +`+Se.showPosition()+` +Expecting `+ni.join(", ")+", got '"+(this.terminals_[zt]||zt)+"'":Ks="Parse error on line "+(xt+1)+": Unexpected "+(zt==Ft?"end of input":"'"+(this.terminals_[zt]||zt)+"'"),this.parseError(Ks,{text:Se.match,token:this.terminals_[zt]||zt,line:Se.yylineno,loc:Ye,expected:ni})}if(se[0]instanceof Array&&se.length>1)throw new Error("Parse Error: multiple actions possible at state: "+re+", token: "+zt);switch(se[0]){case 1:It.push(zt),Bt.push(Se.yytext),Et.push(Se.yylloc),It.push(se[1]),zt=null,Ht=Se.yyleng,Ct=Se.yytext,xt=Se.yylineno,Ye=Se.yylloc;break;case 2:if(de=this.productions_[se[1]][1],te.$=Bt[Bt.length-de],te._$={first_line:Et[Et.length-(de||1)].first_line,last_line:Et[Et.length-1].last_line,first_column:Et[Et.length-(de||1)].first_column,last_column:Et[Et.length-1].last_column},ce&&(te._$.range=[Et[Et.length-(de||1)].range[0],Et[Et.length-1].range[1]]),Pe=this.performAction.apply(te,[Ct,Ht,xt,me.yy,se[1],Bt,Et].concat(gn)),typeof Pe<"u")return Pe;de&&(It=It.slice(0,-1*de*2),Bt=Bt.slice(0,-1*de),Et=Et.slice(0,-1*de)),It.push(this.productions_[se[1]][0]),Bt.push(te.$),Et.push(te._$),on=Z[It[It.length-2]][It[It.length-1]],It.push(on);break;case 3:return!0}}return!0}},X=function(){var U={EOF:1,parseError:function(nt,It){if(this.yy.parser)this.yy.parser.parseError(nt,It);else throw new Error(nt)},setInput:function(Tt,nt){return this.yy=nt||this.yy||{},this._input=Tt,this._more=this._backtrack=this.done=!1,this.yylineno=this.yyleng=0,this.yytext=this.matched=this.match="",this.conditionStack=["INITIAL"],this.yylloc={first_line:1,first_column:0,last_line:1,last_column:0},this.options.ranges&&(this.yylloc.range=[0,0]),this.offset=0,this},input:function(){var Tt=this._input[0];this.yytext+=Tt,this.yyleng++,this.offset++,this.match+=Tt,this.matched+=Tt;var nt=Tt.match(/(?:\r\n?|\n).*/g);return nt?(this.yylineno++,this.yylloc.last_line++):this.yylloc.last_column++,this.options.ranges&&this.yylloc.range[1]++,this._input=this._input.slice(1),Tt},unput:function(Tt){var nt=Tt.length,It=Tt.split(/(?:\r\n?|\n)/g);this._input=Tt+this._input,this.yytext=this.yytext.substr(0,this.yytext.length-nt),this.offset-=nt;var Ot=this.match.split(/(?:\r\n?|\n)/g);this.match=this.match.substr(0,this.match.length-1),this.matched=this.matched.substr(0,this.matched.length-1),It.length-1&&(this.yylineno-=It.length-1);var Bt=this.yylloc.range;return this.yylloc={first_line:this.yylloc.first_line,last_line:this.yylineno+1,first_column:this.yylloc.first_column,last_column:It?(It.length===Ot.length?this.yylloc.first_column:0)+Ot[Ot.length-It.length].length-It[0].length:this.yylloc.first_column-nt},this.options.ranges&&(this.yylloc.range=[Bt[0],Bt[0]+this.yyleng-nt]),this.yyleng=this.yytext.length,this},more:function(){return this._more=!0,this},reject:function(){if(this.options.backtrack_lexer)this._backtrack=!0;else return this.parseError("Lexical error on line "+(this.yylineno+1)+`. You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true). +`+this.showPosition(),{text:"",token:null,line:this.yylineno});return this},less:function(Tt){this.unput(this.match.slice(Tt))},pastInput:function(){var Tt=this.matched.substr(0,this.matched.length-this.match.length);return(Tt.length>20?"...":"")+Tt.substr(-20).replace(/\n/g,"")},upcomingInput:function(){var Tt=this.match;return Tt.length<20&&(Tt+=this._input.substr(0,20-Tt.length)),(Tt.substr(0,20)+(Tt.length>20?"...":"")).replace(/\n/g,"")},showPosition:function(){var Tt=this.pastInput(),nt=new Array(Tt.length+1).join("-");return Tt+this.upcomingInput()+` +`+nt+"^"},test_match:function(Tt,nt){var It,Ot,Bt;if(this.options.backtrack_lexer&&(Bt={yylineno:this.yylineno,yylloc:{first_line:this.yylloc.first_line,last_line:this.last_line,first_column:this.yylloc.first_column,last_column:this.yylloc.last_column},yytext:this.yytext,match:this.match,matches:this.matches,matched:this.matched,yyleng:this.yyleng,offset:this.offset,_more:this._more,_input:this._input,yy:this.yy,conditionStack:this.conditionStack.slice(0),done:this.done},this.options.ranges&&(Bt.yylloc.range=this.yylloc.range.slice(0))),Ot=Tt[0].match(/(?:\r\n?|\n).*/g),Ot&&(this.yylineno+=Ot.length),this.yylloc={first_line:this.yylloc.last_line,last_line:this.yylineno+1,first_column:this.yylloc.last_column,last_column:Ot?Ot[Ot.length-1].length-Ot[Ot.length-1].match(/\r?\n?/)[0].length:this.yylloc.last_column+Tt[0].length},this.yytext+=Tt[0],this.match+=Tt[0],this.matches=Tt,this.yyleng=this.yytext.length,this.options.ranges&&(this.yylloc.range=[this.offset,this.offset+=this.yyleng]),this._more=!1,this._backtrack=!1,this._input=this._input.slice(Tt[0].length),this.matched+=Tt[0],It=this.performAction.call(this,this.yy,this,nt,this.conditionStack[this.conditionStack.length-1]),this.done&&this._input&&(this.done=!1),It)return It;if(this._backtrack){for(var Et in Bt)this[Et]=Bt[Et];return!1}return!1},next:function(){if(this.done)return this.EOF;this._input||(this.done=!0);var Tt,nt,It,Ot;this._more||(this.yytext="",this.match="");for(var Bt=this._currentRules(),Et=0;Etnt[0].length)){if(nt=It,Ot=Et,this.options.backtrack_lexer){if(Tt=this.test_match(It,Bt[Et]),Tt!==!1)return Tt;if(this._backtrack){nt=!1;continue}else return!1}else if(!this.options.flex)break}return nt?(Tt=this.test_match(nt,Bt[Ot]),Tt!==!1?Tt:!1):this._input===""?this.EOF:this.parseError("Lexical error on line "+(this.yylineno+1)+`. Unrecognized text. +`+this.showPosition(),{text:"",token:null,line:this.yylineno})},lex:function(){var nt=this.next();return nt||this.lex()},begin:function(nt){this.conditionStack.push(nt)},popState:function(){var nt=this.conditionStack.length-1;return nt>0?this.conditionStack.pop():this.conditionStack[0]},_currentRules:function(){return this.conditionStack.length&&this.conditionStack[this.conditionStack.length-1]?this.conditions[this.conditionStack[this.conditionStack.length-1]].rules:this.conditions.INITIAL.rules},topState:function(nt){return nt=this.conditionStack.length-1-Math.abs(nt||0),nt>=0?this.conditionStack[nt]:"INITIAL"},pushState:function(nt){this.begin(nt)},stateStackSize:function(){return this.conditionStack.length},options:{"case-insensitive":!0},performAction:function(nt,It,Ot,Bt){switch(Ot){case 0:return this.begin("open_directive"),"open_directive";case 1:return this.begin("acc_title"),28;case 2:return this.popState(),"acc_title_value";case 3:return this.begin("acc_descr"),30;case 4:return this.popState(),"acc_descr_value";case 5:this.begin("acc_descr_multiline");break;case 6:this.popState();break;case 7:return"acc_descr_multiline_value";case 8:break;case 9:break;case 10:break;case 11:return 10;case 12:break;case 13:break;case 14:break;case 15:this.begin("href");break;case 16:this.popState();break;case 17:return 40;case 18:this.begin("callbackname");break;case 19:this.popState();break;case 20:this.popState(),this.begin("callbackargs");break;case 21:return 38;case 22:this.popState();break;case 23:return 39;case 24:this.begin("click");break;case 25:this.popState();break;case 26:return 37;case 27:return 4;case 28:return 19;case 29:return 20;case 30:return 21;case 31:return 22;case 32:return 23;case 33:return 25;case 34:return 24;case 35:return 26;case 36:return 12;case 37:return 13;case 38:return 14;case 39:return 15;case 40:return 16;case 41:return 17;case 42:return 18;case 43:return"date";case 44:return 27;case 45:return"accDescription";case 46:return 33;case 47:return 35;case 48:return 36;case 49:return":";case 50:return 6;case 51:return"INVALID"}},rules:[/^(?:%%\{)/i,/^(?:accTitle\s*:\s*)/i,/^(?:(?!\n||)*[^\n]*)/i,/^(?:accDescr\s*:\s*)/i,/^(?:(?!\n||)*[^\n]*)/i,/^(?:accDescr\s*\{\s*)/i,/^(?:[\}])/i,/^(?:[^\}]*)/i,/^(?:%%(?!\{)*[^\n]*)/i,/^(?:[^\}]%%*[^\n]*)/i,/^(?:%%*[^\n]*[\n]*)/i,/^(?:[\n]+)/i,/^(?:\s+)/i,/^(?:#[^\n]*)/i,/^(?:%[^\n]*)/i,/^(?:href[\s]+["])/i,/^(?:["])/i,/^(?:[^"]*)/i,/^(?:call[\s]+)/i,/^(?:\([\s]*\))/i,/^(?:\()/i,/^(?:[^(]*)/i,/^(?:\))/i,/^(?:[^)]*)/i,/^(?:click[\s]+)/i,/^(?:[\s\n])/i,/^(?:[^\s\n]*)/i,/^(?:gantt\b)/i,/^(?:dateFormat\s[^#\n;]+)/i,/^(?:inclusiveEndDates\b)/i,/^(?:topAxis\b)/i,/^(?:axisFormat\s[^#\n;]+)/i,/^(?:tickInterval\s[^#\n;]+)/i,/^(?:includes\s[^#\n;]+)/i,/^(?:excludes\s[^#\n;]+)/i,/^(?:todayMarker\s[^\n;]+)/i,/^(?:weekday\s+monday\b)/i,/^(?:weekday\s+tuesday\b)/i,/^(?:weekday\s+wednesday\b)/i,/^(?:weekday\s+thursday\b)/i,/^(?:weekday\s+friday\b)/i,/^(?:weekday\s+saturday\b)/i,/^(?:weekday\s+sunday\b)/i,/^(?:\d\d\d\d-\d\d-\d\d\b)/i,/^(?:title\s[^#\n;]+)/i,/^(?:accDescription\s[^#\n;]+)/i,/^(?:section\s[^#:\n;]+)/i,/^(?:[^#:\n;]+)/i,/^(?::[^#\n;]+)/i,/^(?::)/i,/^(?:$)/i,/^(?:.)/i],conditions:{acc_descr_multiline:{rules:[6,7],inclusive:!1},acc_descr:{rules:[4],inclusive:!1},acc_title:{rules:[2],inclusive:!1},callbackargs:{rules:[22,23],inclusive:!1},callbackname:{rules:[19,20,21],inclusive:!1},href:{rules:[16,17],inclusive:!1},click:{rules:[25,26],inclusive:!1},INITIAL:{rules:[0,1,3,5,8,9,10,11,12,13,14,15,18,24,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51],inclusive:!0}}};return U}();vt.lexer=X;function pt(){this.yy={}}return pt.prototype=vt,vt.Parser=pt,new pt}();H0t.parser=H0t;const oqe=H0t;var GBt={exports:{}};(function(i,a){(function(f,p){i.exports=p()})(b0,function(){var f="day";return function(p,w,m){var b=function(A){return A.add(4-A.isoWeekday(),f)},E=w.prototype;E.isoWeekYear=function(){return b(this).year()},E.isoWeek=function(A){if(!this.$utils().u(A))return this.add(7*(A-this.isoWeek()),f);var I,B,N,R,z=b(this),W=(I=this.isoWeekYear(),B=this.$u,N=(B?m.utc:m)().year(I).startOf("year"),R=4-N.isoWeekday(),N.isoWeekday()>4&&(R+=7),N.add(R,f));return z.diff(W,"week")+1},E.isoWeekday=function(A){return this.$utils().u(A)?this.day()||7:this.day(this.day()%7?A:A-7)};var _=E.startOf;E.startOf=function(A,I){var B=this.$utils(),N=!!B.u(I)||I;return B.p(A)==="isoweek"?N?this.date(this.date()-(this.isoWeekday()-1)).startOf("day"):this.date(this.date()-1-(this.isoWeekday()-1)+7).endOf("day"):_.bind(this)(A,I)}}})})(GBt);var cqe=GBt.exports;const uqe=G7(cqe);var UBt={exports:{}};(function(i,a){(function(f,p){i.exports=p()})(b0,function(){var f={LTS:"h:mm:ss A",LT:"h:mm A",L:"MM/DD/YYYY",LL:"MMMM D, YYYY",LLL:"MMMM D, YYYY h:mm A",LLLL:"dddd, MMMM D, YYYY h:mm A"},p=/(\[[^[]*\])|([-_:/.,()\s]+)|(A|a|YYYY|YY?|MM?M?M?|Do|DD?|hh?|HH?|mm?|ss?|S{1,3}|z|ZZ?)/g,w=/\d\d/,m=/\d\d?/,b=/\d*[^-_:/,()\s\d]+/,E={},_=function(W){return(W=+W)+(W>68?1900:2e3)},A=function(W){return function(et){this[W]=+et}},I=[/[+-]\d\d:?(\d\d)?|Z/,function(W){(this.zone||(this.zone={})).offset=function(et){if(!et||et==="Z")return 0;var st=et.match(/([+-]|\d\d)/g),at=60*st[1]+(+st[2]||0);return at===0?0:st[0]==="+"?-at:at}(W)}],B=function(W){var et=E[W];return et&&(et.indexOf?et:et.s.concat(et.f))},N=function(W,et){var st,at=E.meridiem;if(at){for(var bt=1;bt<=24;bt+=1)if(W.indexOf(at(bt,0,et))>-1){st=bt>12;break}}else st=W===(et?"pm":"PM");return st},R={A:[b,function(W){this.afternoon=N(W,!1)}],a:[b,function(W){this.afternoon=N(W,!0)}],S:[/\d/,function(W){this.milliseconds=100*+W}],SS:[w,function(W){this.milliseconds=10*+W}],SSS:[/\d{3}/,function(W){this.milliseconds=+W}],s:[m,A("seconds")],ss:[m,A("seconds")],m:[m,A("minutes")],mm:[m,A("minutes")],H:[m,A("hours")],h:[m,A("hours")],HH:[m,A("hours")],hh:[m,A("hours")],D:[m,A("day")],DD:[w,A("day")],Do:[b,function(W){var et=E.ordinal,st=W.match(/\d+/);if(this.day=st[0],et)for(var at=1;at<=31;at+=1)et(at).replace(/\[|\]/g,"")===W&&(this.day=at)}],M:[m,A("month")],MM:[w,A("month")],MMM:[b,function(W){var et=B("months"),st=(B("monthsShort")||et.map(function(at){return at.slice(0,3)})).indexOf(W)+1;if(st<1)throw new Error;this.month=st%12||st}],MMMM:[b,function(W){var et=B("months").indexOf(W)+1;if(et<1)throw new Error;this.month=et%12||et}],Y:[/[+-]?\d+/,A("year")],YY:[w,function(W){this.year=_(W)}],YYYY:[/\d{4}/,A("year")],Z:I,ZZ:I};function z(W){var et,st;et=W,st=E&&E.formats;for(var at=(W=et.replace(/(\[[^\]]+])|(LTS?|l{1,4}|L{1,4})/g,function(X,pt,U){var Tt=U&&U.toUpperCase();return pt||st[U]||f[U]||st[Tt].replace(/(\[[^\]]+])|(MMMM|MM|DD|dddd)/g,function(nt,It,Ot){return It||Ot.slice(1)})})).match(p),bt=at.length,mt=0;mt-1)return new Date((Et==="X"?1e3:1)*Bt);var Ct=z(Et)(Bt),xt=Ct.year,Ht=Ct.month,Le=Ct.day,Ft=Ct.hours,gn=Ct.minutes,Se=Ct.seconds,me=Ct.milliseconds,Ve=Ct.zone,Ye=new Date,ce=Le||(xt||Ht?1:Ye.getDate()),ke=xt||Ye.getFullYear(),zt=0;xt&&!Ht||(zt=Ht>0?Ht-1:Ye.getMonth());var re=Ft||0,se=gn||0,Pe=Se||0,te=me||0;return Ve?new Date(Date.UTC(ke,zt,ce,re,se,Pe,te+60*Ve.offset*1e3)):Z?new Date(Date.UTC(ke,zt,ce,re,se,Pe,te)):new Date(ke,zt,ce,re,se,Pe,te)}catch{return new Date("")}}(yt,vt,ft),this.init(),Tt&&Tt!==!0&&(this.$L=this.locale(Tt).$L),U&&yt!=this.format(vt)&&(this.$d=new Date("")),E={}}else if(vt instanceof Array)for(var nt=vt.length,It=1;It<=nt;It+=1){ut[1]=vt[It-1];var Ot=st.apply(this,ut);if(Ot.isValid()){this.$d=Ot.$d,this.$L=Ot.$L,this.init();break}It===nt&&(this.$d=new Date(""))}else bt.call(this,mt)}}})})(UBt);var lqe=UBt.exports;const hqe=G7(lqe);var WBt={exports:{}};(function(i,a){(function(f,p){i.exports=p()})(b0,function(){return function(f,p){var w=p.prototype,m=w.format;w.format=function(b){var E=this,_=this.$locale();if(!this.isValid())return m.bind(this)(b);var A=this.$utils(),I=(b||"YYYY-MM-DDTHH:mm:ssZ").replace(/\[([^\]]+)]|Q|wo|ww|w|WW|W|zzz|z|gggg|GGGG|Do|X|x|k{1,2}|S/g,function(B){switch(B){case"Q":return Math.ceil((E.$M+1)/3);case"Do":return _.ordinal(E.$D);case"gggg":return E.weekYear();case"GGGG":return E.isoWeekYear();case"wo":return _.ordinal(E.week(),"W");case"w":case"ww":return A.s(E.week(),B==="w"?1:2,"0");case"W":case"WW":return A.s(E.isoWeek(),B==="W"?1:2,"0");case"k":case"kk":return A.s(String(E.$H===0?24:E.$H),B==="k"?1:2,"0");case"X":return Math.floor(E.$d.getTime()/1e3);case"x":return E.$d.getTime();case"z":return"["+E.offsetName()+"]";case"zzz":return"["+E.offsetName("long")+"]";default:return B}});return m.bind(this)(I)}}})})(WBt);var fqe=WBt.exports;const dqe=G7(fqe);w0.extend(uqe),w0.extend(hqe),w0.extend(dqe);let x3="",V0t="",G0t,U0t="",PF=[],FF=[],W0t={},Y0t=[],IY=[],uL="",K0t="";const YBt=["active","done","crit","milestone"];let X0t=[],NF=!1,Q0t=!1,Z0t="sunday",J0t=0;const gqe=function(){Y0t=[],IY=[],uL="",X0t=[],OY=0,egt=void 0,PY=void 0,h1=[],x3="",V0t="",K0t="",G0t=void 0,U0t="",PF=[],FF=[],NF=!1,Q0t=!1,J0t=0,W0t={},hg(),Z0t="sunday"},pqe=function(i){V0t=i},bqe=function(){return V0t},wqe=function(i){G0t=i},vqe=function(){return G0t},mqe=function(i){U0t=i},yqe=function(){return U0t},xqe=function(i){x3=i},kqe=function(){NF=!0},Eqe=function(){return NF},Tqe=function(){Q0t=!0},Cqe=function(){return Q0t},_qe=function(i){K0t=i},Sqe=function(){return K0t},Aqe=function(){return x3},Lqe=function(i){PF=i.toLowerCase().split(/[\s,]+/)},Mqe=function(){return PF},Dqe=function(i){FF=i.toLowerCase().split(/[\s,]+/)},Iqe=function(){return FF},Oqe=function(){return W0t},Pqe=function(i){uL=i,Y0t.push(i)},Fqe=function(){return Y0t},Nqe=function(){let i=tRt();const a=10;let f=0;for(;!i&&f=6&&f.includes("weekends")||f.includes(i.format("dddd").toLowerCase())?!0:f.includes(i.format(a.trim()))},Bqe=function(i){Z0t=i},Rqe=function(){return Z0t},XBt=function(i,a,f,p){if(!f.length||i.manualEndTime)return;let w;i.startTime instanceof Date?w=w0(i.startTime):w=w0(i.startTime,a,!0),w=w.add(1,"d");let m;i.endTime instanceof Date?m=w0(i.endTime):m=w0(i.endTime,a,!0);const[b,E]=jqe(w,m,a,f,p);i.endTime=b.toDate(),i.renderEndTime=E},jqe=function(i,a,f,p,w){let m=!1,b=null;for(;i<=a;)m||(b=a.toDate()),m=KBt(i,f,p,w),m&&(a=a.add(1,"d")),i=i.add(1,"d");return[a,b]},tgt=function(i,a,f){f=f.trim();const w=/^after\s+([\d\w- ]+)/.exec(f.trim());if(w!==null){let b=null;if(w[1].split(" ").forEach(function(E){let _=hL(E);_!==void 0&&(b?_.endTime>b.endTime&&(b=_):b=_)}),b)return b.endTime;{const E=new Date;return E.setHours(0,0,0,0),E}}let m=w0(f,a.trim(),!0);if(m.isValid())return m.toDate();{Ut.debug("Invalid date:"+f),Ut.debug("With date format:"+a.trim());const b=new Date(f);if(b===void 0||isNaN(b.getTime())||b.getFullYear()<-1e4||b.getFullYear()>1e4)throw new Error("Invalid date:"+f);return b}},QBt=function(i){const a=/^(\d+(?:\.\d+)?)([Mdhmswy]|ms)$/.exec(i.trim());return a!==null?[Number.parseFloat(a[1]),a[2]]:[NaN,"ms"]},ZBt=function(i,a,f,p=!1){f=f.trim();let w=w0(f,a.trim(),!0);if(w.isValid())return p&&(w=w.add(1,"d")),w.toDate();let m=w0(i);const[b,E]=QBt(f);if(!Number.isNaN(b)){const _=m.add(b,E);_.isValid()&&(m=_)}return m.toDate()};let OY=0;const lL=function(i){return i===void 0?(OY=OY+1,"task"+OY):i},$qe=function(i,a){let f;a.substr(0,1)===":"?f=a.substr(1,a.length):f=a;const p=f.split(","),w={};rRt(p,w,YBt);for(let b=0;b{window.open(f,"_self")}),W0t[p]=f)}),eRt(i,"clickable")},eRt=function(i,a){i.split(",").forEach(function(f){let p=hL(f);p!==void 0&&p.classes.push(a)})},Gqe=function(i,a,f){if(Oe().securityLevel!=="loose"||a===void 0)return;let p=[];if(typeof f=="string"){p=f.split(/,(?=(?:(?:[^"]*"){2})*[^"]*$)/);for(let m=0;m{$a.runFunc(a,...p)})},nRt=function(i,a){X0t.push(function(){const f=document.querySelector(`[id="${i}"]`);f!==null&&f.addEventListener("click",function(){a()})},function(){const f=document.querySelector(`[id="${i}-text"]`);f!==null&&f.addEventListener("click",function(){a()})})},Uqe={getConfig:()=>Oe().gantt,clear:gqe,setDateFormat:xqe,getDateFormat:Aqe,enableInclusiveEndDates:kqe,endDatesAreInclusive:Eqe,enableTopAxis:Tqe,topAxisEnabled:Cqe,setAxisFormat:pqe,getAxisFormat:bqe,setTickInterval:wqe,getTickInterval:vqe,setTodayMarker:mqe,getTodayMarker:yqe,setAccTitle:E0,getAccTitle:fg,setDiagramTitle:Nb,getDiagramTitle:pg,setDisplayMode:_qe,getDisplayMode:Sqe,setAccDescription:dg,getAccDescription:gg,addSection:Pqe,getSections:Fqe,getTasks:Nqe,addTask:qqe,findTaskById:hL,addTaskOrg:Hqe,setIncludes:Lqe,getIncludes:Mqe,setExcludes:Dqe,getExcludes:Iqe,setClickEvent:function(i,a,f){i.split(",").forEach(function(p){Gqe(p,a,f)}),eRt(i,"clickable")},setLink:Vqe,getLinks:Oqe,bindFunctions:function(i){X0t.forEach(function(a){a(i)})},parseDuration:QBt,isInvalidDate:KBt,setWeekday:Bqe,getWeekday:Rqe};function rRt(i,a,f){let p=!0;for(;p;)p=!1,f.forEach(function(w){const m="^\\s*"+w+"\\s*$",b=new RegExp(m);i[0].match(b)&&(a[w]=!0,i.shift(1),p=!0)})}const Wqe=function(){Ut.debug("Something is calling, setConf, remove the call")},iRt={monday:BP,tuesday:JMt,wednesday:tDt,thursday:tT,friday:eDt,saturday:nDt,sunday:NP},Yqe=(i,a)=>{let f=[...i].map(()=>-1/0),p=[...i].sort((m,b)=>m.startTime-b.startTime||m.order-b.order),w=0;for(const m of p)for(let b=0;b=f[b]){f[b]=m.endTime,m.order=b+a,b>w&&(w=b);break}return w};let N5;const Kqe=Object.freeze(Object.defineProperty({__proto__:null,diagram:{parser:oqe,db:Uqe,renderer:{setConf:Wqe,draw:function(i,a,f,p){const w=Oe().gantt,m=Oe().securityLevel;let b;m==="sandbox"&&(b=yr("#i"+a));const E=yr(m==="sandbox"?b.nodes()[0].contentDocument.body:"body"),_=m==="sandbox"?b.nodes()[0].contentDocument:document,A=_.getElementById(a);N5=A.parentElement.offsetWidth,N5===void 0&&(N5=1200),w.useWidth!==void 0&&(N5=w.useWidth);const I=p.db.getTasks();let B=[];for(const vt of I)B.push(vt.type);B=ut(B);const N={};let R=2*w.topPadding;if(p.db.getDisplayMode()==="compact"||w.displayMode==="compact"){const vt={};for(const pt of I)vt[pt.section]===void 0?vt[pt.section]=[pt]:vt[pt.section].push(pt);let X=0;for(const pt of Object.keys(vt)){const U=Yqe(vt[pt],X)+1;X+=U,R+=U*(w.barHeight+w.barGap),N[pt]=U}}else{R+=I.length*(w.barHeight+w.barGap);for(const vt of B)N[vt]=I.filter(X=>X.type===vt).length}A.setAttribute("viewBox","0 0 "+N5+" "+R);const z=E.select(`[id="${a}"]`),W=Y7e().domain([Mxe(I,function(vt){return vt.startTime}),Lxe(I,function(vt){return vt.endTime})]).rangeRound([0,N5-w.leftPadding-w.rightPadding]);function et(vt,X){const pt=vt.startTime,U=X.startTime;let Tt=0;return pt>U?Tt=1:ptxt.order))].map(xt=>vt.find(Ht=>Ht.order===xt));z.append("g").selectAll("rect").data(Bt).enter().append("rect").attr("x",0).attr("y",function(xt,Ht){return Ht=xt.order,Ht*X+pt-2}).attr("width",function(){return It-w.rightPadding/2}).attr("height",X).attr("class",function(xt){for(const[Ht,Le]of B.entries())if(xt.type===Le)return"section section"+Ht%w.numberSectionStyles;return"section section0"});const Et=z.append("g").selectAll("rect").data(vt).enter(),Z=p.db.getLinks();if(Et.append("rect").attr("id",function(xt){return xt.id}).attr("rx",3).attr("ry",3).attr("x",function(xt){return xt.milestone?W(xt.startTime)+U+.5*(W(xt.endTime)-W(xt.startTime))-.5*Tt:W(xt.startTime)+U}).attr("y",function(xt,Ht){return Ht=xt.order,Ht*X+pt}).attr("width",function(xt){return xt.milestone?Tt:W(xt.renderEndTime||xt.endTime)-W(xt.startTime)}).attr("height",Tt).attr("transform-origin",function(xt,Ht){return Ht=xt.order,(W(xt.startTime)+U+.5*(W(xt.endTime)-W(xt.startTime))).toString()+"px "+(Ht*X+pt+.5*Tt).toString()+"px"}).attr("class",function(xt){const Ht="task";let Le="";xt.classes.length>0&&(Le=xt.classes.join(" "));let Ft=0;for(const[Se,me]of B.entries())xt.type===me&&(Ft=Se%w.numberSectionStyles);let gn="";return xt.active?xt.crit?gn+=" activeCrit":gn=" active":xt.done?xt.crit?gn=" doneCrit":gn=" done":xt.crit&&(gn+=" crit"),gn.length===0&&(gn=" task"),xt.milestone&&(gn=" milestone "+gn),gn+=Ft,gn+=" "+Le,Ht+gn}),Et.append("text").attr("id",function(xt){return xt.id+"-text"}).text(function(xt){return xt.task}).attr("font-size",w.fontSize).attr("x",function(xt){let Ht=W(xt.startTime),Le=W(xt.renderEndTime||xt.endTime);xt.milestone&&(Ht+=.5*(W(xt.endTime)-W(xt.startTime))-.5*Tt),xt.milestone&&(Le=Ht+Tt);const Ft=this.getBBox().width;return Ft>Le-Ht?Le+Ft+1.5*w.leftPadding>It?Ht+U-5:Le+U+5:(Le-Ht)/2+Ht+U}).attr("y",function(xt,Ht){return Ht=xt.order,Ht*X+w.barHeight/2+(w.fontSize/2-2)+pt}).attr("text-height",Tt).attr("class",function(xt){const Ht=W(xt.startTime);let Le=W(xt.endTime);xt.milestone&&(Le=Ht+Tt);const Ft=this.getBBox().width;let gn="";xt.classes.length>0&&(gn=xt.classes.join(" "));let Se=0;for(const[Ve,Ye]of B.entries())xt.type===Ye&&(Se=Ve%w.numberSectionStyles);let me="";return xt.active&&(xt.crit?me="activeCritText"+Se:me="activeText"+Se),xt.done?xt.crit?me=me+" doneCritText"+Se:me=me+" doneText"+Se:xt.crit&&(me=me+" critText"+Se),xt.milestone&&(me+=" milestoneText"),Ft>Le-Ht?Le+Ft+1.5*w.leftPadding>It?gn+" taskTextOutsideLeft taskTextOutside"+Se+" "+me:gn+" taskTextOutsideRight taskTextOutside"+Se+" "+me+" width-"+Ft:gn+" taskText taskText"+Se+" "+me+" width-"+Ft}),Oe().securityLevel==="sandbox"){let xt;xt=yr("#i"+a);const Ht=xt.nodes()[0].contentDocument;Et.filter(function(Le){return Z[Le.id]!==void 0}).each(function(Le){var Ft=Ht.querySelector("#"+Le.id),gn=Ht.querySelector("#"+Le.id+"-text");const Se=Ft.parentNode;var me=Ht.createElement("a");me.setAttribute("xlink:href",Z[Le.id]),me.setAttribute("target","_top"),Se.appendChild(me),me.appendChild(Ft),me.appendChild(gn)})}}function bt(vt,X,pt,U,Tt,nt,It,Ot){if(It.length===0&&Ot.length===0)return;let Bt,Et;for(const{startTime:Ft,endTime:gn}of nt)(Bt===void 0||FtEt)&&(Et=gn);if(!Bt||!Et)return;if(w0(Et).diff(w0(Bt),"year")>5){Ut.warn("The difference between the min and max time is more than 5 years. This will cause performance issues. Skipping drawing exclude days.");return}const Z=p.db.getDateFormat(),Ct=[];let xt=null,Ht=w0(Bt);for(;Ht.valueOf()<=Et;)p.db.isInvalidDate(Ht,Z,It,Ot)?xt?xt.end=Ht:xt={start:Ht,end:Ht}:xt&&(Ct.push(xt),xt=null),Ht=Ht.add(1,"d");z.append("g").selectAll("rect").data(Ct).enter().append("rect").attr("id",function(Ft){return"exclude-"+Ft.start.format("YYYY-MM-DD")}).attr("x",function(Ft){return W(Ft.start)+pt}).attr("y",w.gridLineStartPadding).attr("width",function(Ft){const gn=Ft.end.add(1,"day");return W(gn)-W(Ft.start)}).attr("height",Tt-X-w.gridLineStartPadding).attr("transform-origin",function(Ft,gn){return(W(Ft.start)+pt+.5*(W(Ft.end)-W(Ft.start))).toString()+"px "+(gn*vt+.5*Tt).toString()+"px"}).attr("class","exclude-range")}function mt(vt,X,pt,U){let Tt=jxe(W).tickSize(-U+X+w.gridLineStartPadding).tickFormat(ZU(p.db.getAxisFormat()||w.axisFormat||"%Y-%m-%d"));const It=/^([1-9]\d*)(millisecond|second|minute|hour|day|week|month)$/.exec(p.db.getTickInterval()||w.tickInterval);if(It!==null){const Ot=It[1],Bt=It[2],Et=p.db.getWeekday()||w.weekday;switch(Bt){case"millisecond":Tt.ticks(LA.every(Ot));break;case"second":Tt.ticks(sk.every(Ot));break;case"minute":Tt.ticks(PP.every(Ot));break;case"hour":Tt.ticks(FP.every(Ot));break;case"day":Tt.ticks(Z7.every(Ot));break;case"week":Tt.ticks(iRt[Et].every(Ot));break;case"month":Tt.ticks(RP.every(Ot));break}}if(z.append("g").attr("class","grid").attr("transform","translate("+vt+", "+(U-50)+")").call(Tt).selectAll("text").style("text-anchor","middle").attr("fill","#000").attr("stroke","none").attr("font-size",10).attr("dy","1em"),p.db.topAxisEnabled()||w.topAxis){let Ot=Rxe(W).tickSize(-U+X+w.gridLineStartPadding).tickFormat(ZU(p.db.getAxisFormat()||w.axisFormat||"%Y-%m-%d"));if(It!==null){const Bt=It[1],Et=It[2],Z=p.db.getWeekday()||w.weekday;switch(Et){case"millisecond":Ot.ticks(LA.every(Bt));break;case"second":Ot.ticks(sk.every(Bt));break;case"minute":Ot.ticks(PP.every(Bt));break;case"hour":Ot.ticks(FP.every(Bt));break;case"day":Ot.ticks(Z7.every(Bt));break;case"week":Ot.ticks(iRt[Z].every(Bt));break;case"month":Ot.ticks(RP.every(Bt));break}}z.append("g").attr("class","grid").attr("transform","translate("+vt+", "+X+")").call(Ot).selectAll("text").style("text-anchor","middle").attr("fill","#000").attr("stroke","none").attr("font-size",10)}}function yt(vt,X){let pt=0;const U=Object.keys(N).map(Tt=>[Tt,N[Tt]]);z.append("g").selectAll("text").data(U).enter().append(function(Tt){const nt=Tt[0].split(Kr.lineBreakRegex),It=-(nt.length-1)/2,Ot=_.createElementNS("http://www.w3.org/2000/svg","text");Ot.setAttribute("dy",It+"em");for(const[Bt,Et]of nt.entries()){const Z=_.createElementNS("http://www.w3.org/2000/svg","tspan");Z.setAttribute("alignment-baseline","central"),Z.setAttribute("x","10"),Bt>0&&Z.setAttribute("dy","1em"),Z.textContent=Et,Ot.appendChild(Z)}return Ot}).attr("x",10).attr("y",function(Tt,nt){if(nt>0)for(let It=0;It` + .mermaid-main-font { + font-family: "trebuchet ms", verdana, arial, sans-serif; + font-family: var(--mermaid-font-family); + } + .exclude-range { + fill: ${i.excludeBkgColor}; + } + + .section { + stroke: none; + opacity: 0.2; + } + + .section0 { + fill: ${i.sectionBkgColor}; + } + + .section2 { + fill: ${i.sectionBkgColor2}; + } + + .section1, + .section3 { + fill: ${i.altSectionBkgColor}; + opacity: 0.2; + } + + .sectionTitle0 { + fill: ${i.titleColor}; + } + + .sectionTitle1 { + fill: ${i.titleColor}; + } + + .sectionTitle2 { + fill: ${i.titleColor}; + } + + .sectionTitle3 { + fill: ${i.titleColor}; + } + + .sectionTitle { + text-anchor: start; + // font-size: ${i.ganttFontSize}; + // text-height: 14px; + font-family: 'trebuchet ms', verdana, arial, sans-serif; + font-family: var(--mermaid-font-family); + + } + + + /* Grid and axis */ + + .grid .tick { + stroke: ${i.gridColor}; + opacity: 0.8; + shape-rendering: crispEdges; + text { + font-family: ${i.fontFamily}; + fill: ${i.textColor}; + } + } + + .grid path { + stroke-width: 0; + } + + + /* Today line */ + + .today { + fill: none; + stroke: ${i.todayLineColor}; + stroke-width: 2px; + } + + + /* Task styling */ + + /* Default task */ + + .task { + stroke-width: 2; + } + + .taskText { + text-anchor: middle; + font-family: 'trebuchet ms', verdana, arial, sans-serif; + font-family: var(--mermaid-font-family); + } + + // .taskText:not([font-size]) { + // font-size: ${i.ganttFontSize}; + // } + + .taskTextOutsideRight { + fill: ${i.taskTextDarkColor}; + text-anchor: start; + // font-size: ${i.ganttFontSize}; + font-family: 'trebuchet ms', verdana, arial, sans-serif; + font-family: var(--mermaid-font-family); + + } + + .taskTextOutsideLeft { + fill: ${i.taskTextDarkColor}; + text-anchor: end; + // font-size: ${i.ganttFontSize}; + } + + /* Special case clickable */ + .task.clickable { + cursor: pointer; + } + .taskText.clickable { + cursor: pointer; + fill: ${i.taskTextClickableColor} !important; + font-weight: bold; + } + + .taskTextOutsideLeft.clickable { + cursor: pointer; + fill: ${i.taskTextClickableColor} !important; + font-weight: bold; + } + + .taskTextOutsideRight.clickable { + cursor: pointer; + fill: ${i.taskTextClickableColor} !important; + font-weight: bold; + } + + /* Specific task settings for the sections*/ + + .taskText0, + .taskText1, + .taskText2, + .taskText3 { + fill: ${i.taskTextColor}; + } + + .task0, + .task1, + .task2, + .task3 { + fill: ${i.taskBkgColor}; + stroke: ${i.taskBorderColor}; + } + + .taskTextOutside0, + .taskTextOutside2 + { + fill: ${i.taskTextOutsideColor}; + } + + .taskTextOutside1, + .taskTextOutside3 { + fill: ${i.taskTextOutsideColor}; + } + + + /* Active task */ + + .active0, + .active1, + .active2, + .active3 { + fill: ${i.activeTaskBkgColor}; + stroke: ${i.activeTaskBorderColor}; + } + + .activeText0, + .activeText1, + .activeText2, + .activeText3 { + fill: ${i.taskTextDarkColor} !important; + } + + + /* Completed task */ + + .done0, + .done1, + .done2, + .done3 { + stroke: ${i.doneTaskBorderColor}; + fill: ${i.doneTaskBkgColor}; + stroke-width: 2; + } + + .doneText0, + .doneText1, + .doneText2, + .doneText3 { + fill: ${i.taskTextDarkColor} !important; + } + + + /* Tasks on the critical line */ + + .crit0, + .crit1, + .crit2, + .crit3 { + stroke: ${i.critBorderColor}; + fill: ${i.critBkgColor}; + stroke-width: 2; + } + + .activeCrit0, + .activeCrit1, + .activeCrit2, + .activeCrit3 { + stroke: ${i.critBorderColor}; + fill: ${i.activeTaskBkgColor}; + stroke-width: 2; + } + + .doneCrit0, + .doneCrit1, + .doneCrit2, + .doneCrit3 { + stroke: ${i.critBorderColor}; + fill: ${i.doneTaskBkgColor}; + stroke-width: 2; + cursor: pointer; + shape-rendering: crispEdges; + } + + .milestone { + transform: rotate(45deg) scale(0.8,0.8); + } + + .milestoneText { + font-style: italic; + } + .doneCritText0, + .doneCritText1, + .doneCritText2, + .doneCritText3 { + fill: ${i.taskTextDarkColor} !important; + } + + .activeCritText0, + .activeCritText1, + .activeCritText2, + .activeCritText3 { + fill: ${i.taskTextDarkColor} !important; + } + + .titleText { + text-anchor: middle; + font-size: 18px; + fill: ${i.textColor} ; + font-family: 'trebuchet ms', verdana, arial, sans-serif; + font-family: var(--mermaid-font-family); + } +`}},Symbol.toStringTag,{value:"Module"}));var ngt=function(){var i=function(m,b,E,_){for(E=E||{},_=m.length;_--;E[m[_]]=b);return E},a=[6,9,10],f={trace:function(){},yy:{},symbols_:{error:2,start:3,info:4,document:5,EOF:6,line:7,statement:8,NL:9,showInfo:10,$accept:0,$end:1},terminals_:{2:"error",4:"info",6:"EOF",9:"NL",10:"showInfo"},productions_:[0,[3,3],[5,0],[5,2],[7,1],[7,1],[8,1]],performAction:function(b,E,_,A,I,B,N){switch(B.length-1,I){case 1:return A;case 4:break;case 6:A.setInfo(!0);break}},table:[{3:1,4:[1,2]},{1:[3]},i(a,[2,2],{5:3}),{6:[1,4],7:5,8:6,9:[1,7],10:[1,8]},{1:[2,1]},i(a,[2,3]),i(a,[2,4]),i(a,[2,5]),i(a,[2,6])],defaultActions:{4:[2,1]},parseError:function(b,E){if(E.recoverable)this.trace(b);else{var _=new Error(b);throw _.hash=E,_}},parse:function(b){var E=this,_=[0],A=[],I=[null],B=[],N=this.table,R="",z=0,W=0,et=2,st=1,at=B.slice.call(arguments,1),bt=Object.create(this.lexer),mt={yy:{}};for(var yt in this.yy)Object.prototype.hasOwnProperty.call(this.yy,yt)&&(mt.yy[yt]=this.yy[yt]);bt.setInput(b,mt.yy),mt.yy.lexer=bt,mt.yy.parser=this,typeof bt.yylloc>"u"&&(bt.yylloc={});var ft=bt.yylloc;B.push(ft);var ut=bt.options&&bt.options.ranges;typeof mt.yy.parseError=="function"?this.parseError=mt.yy.parseError:this.parseError=Object.getPrototypeOf(this).parseError;function vt(){var Ct;return Ct=A.pop()||bt.lex()||st,typeof Ct!="number"&&(Ct instanceof Array&&(A=Ct,Ct=A.pop()),Ct=E.symbols_[Ct]||Ct),Ct}for(var X,pt,U,Tt,nt={},It,Ot,Bt,Et;;){if(pt=_[_.length-1],this.defaultActions[pt]?U=this.defaultActions[pt]:((X===null||typeof X>"u")&&(X=vt()),U=N[pt]&&N[pt][X]),typeof U>"u"||!U.length||!U[0]){var Z="";Et=[];for(It in N[pt])this.terminals_[It]&&It>et&&Et.push("'"+this.terminals_[It]+"'");bt.showPosition?Z="Parse error on line "+(z+1)+`: +`+bt.showPosition()+` +Expecting `+Et.join(", ")+", got '"+(this.terminals_[X]||X)+"'":Z="Parse error on line "+(z+1)+": Unexpected "+(X==st?"end of input":"'"+(this.terminals_[X]||X)+"'"),this.parseError(Z,{text:bt.match,token:this.terminals_[X]||X,line:bt.yylineno,loc:ft,expected:Et})}if(U[0]instanceof Array&&U.length>1)throw new Error("Parse Error: multiple actions possible at state: "+pt+", token: "+X);switch(U[0]){case 1:_.push(X),I.push(bt.yytext),B.push(bt.yylloc),_.push(U[1]),X=null,W=bt.yyleng,R=bt.yytext,z=bt.yylineno,ft=bt.yylloc;break;case 2:if(Ot=this.productions_[U[1]][1],nt.$=I[I.length-Ot],nt._$={first_line:B[B.length-(Ot||1)].first_line,last_line:B[B.length-1].last_line,first_column:B[B.length-(Ot||1)].first_column,last_column:B[B.length-1].last_column},ut&&(nt._$.range=[B[B.length-(Ot||1)].range[0],B[B.length-1].range[1]]),Tt=this.performAction.apply(nt,[R,W,z,mt.yy,U[1],I,B].concat(at)),typeof Tt<"u")return Tt;Ot&&(_=_.slice(0,-1*Ot*2),I=I.slice(0,-1*Ot),B=B.slice(0,-1*Ot)),_.push(this.productions_[U[1]][0]),I.push(nt.$),B.push(nt._$),Bt=N[_[_.length-2]][_[_.length-1]],_.push(Bt);break;case 3:return!0}}return!0}},p=function(){var m={EOF:1,parseError:function(E,_){if(this.yy.parser)this.yy.parser.parseError(E,_);else throw new Error(E)},setInput:function(b,E){return this.yy=E||this.yy||{},this._input=b,this._more=this._backtrack=this.done=!1,this.yylineno=this.yyleng=0,this.yytext=this.matched=this.match="",this.conditionStack=["INITIAL"],this.yylloc={first_line:1,first_column:0,last_line:1,last_column:0},this.options.ranges&&(this.yylloc.range=[0,0]),this.offset=0,this},input:function(){var b=this._input[0];this.yytext+=b,this.yyleng++,this.offset++,this.match+=b,this.matched+=b;var E=b.match(/(?:\r\n?|\n).*/g);return E?(this.yylineno++,this.yylloc.last_line++):this.yylloc.last_column++,this.options.ranges&&this.yylloc.range[1]++,this._input=this._input.slice(1),b},unput:function(b){var E=b.length,_=b.split(/(?:\r\n?|\n)/g);this._input=b+this._input,this.yytext=this.yytext.substr(0,this.yytext.length-E),this.offset-=E;var A=this.match.split(/(?:\r\n?|\n)/g);this.match=this.match.substr(0,this.match.length-1),this.matched=this.matched.substr(0,this.matched.length-1),_.length-1&&(this.yylineno-=_.length-1);var I=this.yylloc.range;return this.yylloc={first_line:this.yylloc.first_line,last_line:this.yylineno+1,first_column:this.yylloc.first_column,last_column:_?(_.length===A.length?this.yylloc.first_column:0)+A[A.length-_.length].length-_[0].length:this.yylloc.first_column-E},this.options.ranges&&(this.yylloc.range=[I[0],I[0]+this.yyleng-E]),this.yyleng=this.yytext.length,this},more:function(){return this._more=!0,this},reject:function(){if(this.options.backtrack_lexer)this._backtrack=!0;else return this.parseError("Lexical error on line "+(this.yylineno+1)+`. You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true). +`+this.showPosition(),{text:"",token:null,line:this.yylineno});return this},less:function(b){this.unput(this.match.slice(b))},pastInput:function(){var b=this.matched.substr(0,this.matched.length-this.match.length);return(b.length>20?"...":"")+b.substr(-20).replace(/\n/g,"")},upcomingInput:function(){var b=this.match;return b.length<20&&(b+=this._input.substr(0,20-b.length)),(b.substr(0,20)+(b.length>20?"...":"")).replace(/\n/g,"")},showPosition:function(){var b=this.pastInput(),E=new Array(b.length+1).join("-");return b+this.upcomingInput()+` +`+E+"^"},test_match:function(b,E){var _,A,I;if(this.options.backtrack_lexer&&(I={yylineno:this.yylineno,yylloc:{first_line:this.yylloc.first_line,last_line:this.last_line,first_column:this.yylloc.first_column,last_column:this.yylloc.last_column},yytext:this.yytext,match:this.match,matches:this.matches,matched:this.matched,yyleng:this.yyleng,offset:this.offset,_more:this._more,_input:this._input,yy:this.yy,conditionStack:this.conditionStack.slice(0),done:this.done},this.options.ranges&&(I.yylloc.range=this.yylloc.range.slice(0))),A=b[0].match(/(?:\r\n?|\n).*/g),A&&(this.yylineno+=A.length),this.yylloc={first_line:this.yylloc.last_line,last_line:this.yylineno+1,first_column:this.yylloc.last_column,last_column:A?A[A.length-1].length-A[A.length-1].match(/\r?\n?/)[0].length:this.yylloc.last_column+b[0].length},this.yytext+=b[0],this.match+=b[0],this.matches=b,this.yyleng=this.yytext.length,this.options.ranges&&(this.yylloc.range=[this.offset,this.offset+=this.yyleng]),this._more=!1,this._backtrack=!1,this._input=this._input.slice(b[0].length),this.matched+=b[0],_=this.performAction.call(this,this.yy,this,E,this.conditionStack[this.conditionStack.length-1]),this.done&&this._input&&(this.done=!1),_)return _;if(this._backtrack){for(var B in I)this[B]=I[B];return!1}return!1},next:function(){if(this.done)return this.EOF;this._input||(this.done=!0);var b,E,_,A;this._more||(this.yytext="",this.match="");for(var I=this._currentRules(),B=0;BE[0].length)){if(E=_,A=B,this.options.backtrack_lexer){if(b=this.test_match(_,I[B]),b!==!1)return b;if(this._backtrack){E=!1;continue}else return!1}else if(!this.options.flex)break}return E?(b=this.test_match(E,I[A]),b!==!1?b:!1):this._input===""?this.EOF:this.parseError("Lexical error on line "+(this.yylineno+1)+`. Unrecognized text. +`+this.showPosition(),{text:"",token:null,line:this.yylineno})},lex:function(){var E=this.next();return E||this.lex()},begin:function(E){this.conditionStack.push(E)},popState:function(){var E=this.conditionStack.length-1;return E>0?this.conditionStack.pop():this.conditionStack[0]},_currentRules:function(){return this.conditionStack.length&&this.conditionStack[this.conditionStack.length-1]?this.conditions[this.conditionStack[this.conditionStack.length-1]].rules:this.conditions.INITIAL.rules},topState:function(E){return E=this.conditionStack.length-1-Math.abs(E||0),E>=0?this.conditionStack[E]:"INITIAL"},pushState:function(E){this.begin(E)},stateStackSize:function(){return this.conditionStack.length},options:{"case-insensitive":!0},performAction:function(E,_,A,I){switch(A){case 0:return 4;case 1:return 9;case 2:return"space";case 3:return 10;case 4:return 6;case 5:return"TXT"}},rules:[/^(?:info\b)/i,/^(?:[\s\n\r]+)/i,/^(?:[\s]+)/i,/^(?:showInfo\b)/i,/^(?:$)/i,/^(?:.)/i],conditions:{INITIAL:{rules:[0,1,2,3,4,5],inclusive:!0}}};return m}();f.lexer=p;function w(){this.yy={}}return w.prototype=f,f.Parser=w,new w}();ngt.parser=ngt;const Xqe=ngt,sRt={info:!1};let rgt=sRt.info;const Qqe=Object.freeze(Object.defineProperty({__proto__:null,diagram:{parser:Xqe,db:{clear:()=>{rgt=sRt.info},setInfo:i=>{rgt=i},getInfo:()=>rgt},renderer:{draw:(i,a,f)=>{Ut.debug(`rendering info diagram +`+i);const p=VW(a);k0(p,100,400,!0),p.append("g").append("text").attr("x",100).attr("y",40).attr("class","version").attr("font-size",32).style("text-anchor","middle").text(`v${f}`)}}}},Symbol.toStringTag,{value:"Module"}));var igt=function(){var i=function(bt,mt,yt,ft){for(yt=yt||{},ft=bt.length;ft--;yt[bt[ft]]=mt);return yt},a=[1,3],f=[1,4],p=[1,5],w=[1,6],m=[1,10,12,14,16,18,19,20,21,22],b=[2,4],E=[1,5,10,12,14,16,18,19,20,21,22],_=[20,21,22],A=[2,7],I=[1,12],B=[1,13],N=[1,14],R=[1,15],z=[1,16],W=[1,17],et={trace:function(){},yy:{},symbols_:{error:2,start:3,eol:4,PIE:5,document:6,showData:7,line:8,statement:9,txt:10,value:11,title:12,title_value:13,acc_title:14,acc_title_value:15,acc_descr:16,acc_descr_value:17,acc_descr_multiline_value:18,section:19,NEWLINE:20,";":21,EOF:22,$accept:0,$end:1},terminals_:{2:"error",5:"PIE",7:"showData",10:"txt",11:"value",12:"title",13:"title_value",14:"acc_title",15:"acc_title_value",16:"acc_descr",17:"acc_descr_value",18:"acc_descr_multiline_value",19:"section",20:"NEWLINE",21:";",22:"EOF"},productions_:[0,[3,2],[3,2],[3,3],[6,0],[6,2],[8,2],[9,0],[9,2],[9,2],[9,2],[9,2],[9,1],[9,1],[4,1],[4,1],[4,1]],performAction:function(mt,yt,ft,ut,vt,X,pt){var U=X.length-1;switch(vt){case 3:ut.setShowData(!0);break;case 6:this.$=X[U-1];break;case 8:ut.addSection(X[U-1],ut.cleanupValue(X[U]));break;case 9:this.$=X[U].trim(),ut.setDiagramTitle(this.$);break;case 10:this.$=X[U].trim(),ut.setAccTitle(this.$);break;case 11:case 12:this.$=X[U].trim(),ut.setAccDescription(this.$);break;case 13:ut.addSection(X[U].substr(8)),this.$=X[U].substr(8);break}},table:[{3:1,4:2,5:a,20:f,21:p,22:w},{1:[3]},{3:7,4:2,5:a,20:f,21:p,22:w},i(m,b,{6:8,7:[1,9]}),i(E,[2,14]),i(E,[2,15]),i(E,[2,16]),{1:[2,1]},i(_,A,{8:10,9:11,1:[2,2],10:I,12:B,14:N,16:R,18:z,19:W}),i(m,b,{6:18}),i(m,[2,5]),{4:19,20:f,21:p,22:w},{11:[1,20]},{13:[1,21]},{15:[1,22]},{17:[1,23]},i(_,[2,12]),i(_,[2,13]),i(_,A,{8:10,9:11,1:[2,3],10:I,12:B,14:N,16:R,18:z,19:W}),i(m,[2,6]),i(_,[2,8]),i(_,[2,9]),i(_,[2,10]),i(_,[2,11])],defaultActions:{7:[2,1]},parseError:function(mt,yt){if(yt.recoverable)this.trace(mt);else{var ft=new Error(mt);throw ft.hash=yt,ft}},parse:function(mt){var yt=this,ft=[0],ut=[],vt=[null],X=[],pt=this.table,U="",Tt=0,nt=0,It=2,Ot=1,Bt=X.slice.call(arguments,1),Et=Object.create(this.lexer),Z={yy:{}};for(var Ct in this.yy)Object.prototype.hasOwnProperty.call(this.yy,Ct)&&(Z.yy[Ct]=this.yy[Ct]);Et.setInput(mt,Z.yy),Z.yy.lexer=Et,Z.yy.parser=this,typeof Et.yylloc>"u"&&(Et.yylloc={});var xt=Et.yylloc;X.push(xt);var Ht=Et.options&&Et.options.ranges;typeof Z.yy.parseError=="function"?this.parseError=Z.yy.parseError:this.parseError=Object.getPrototypeOf(this).parseError;function Le(){var se;return se=ut.pop()||Et.lex()||Ot,typeof se!="number"&&(se instanceof Array&&(ut=se,se=ut.pop()),se=yt.symbols_[se]||se),se}for(var Ft,gn,Se,me,Ve={},Ye,ce,ke,zt;;){if(gn=ft[ft.length-1],this.defaultActions[gn]?Se=this.defaultActions[gn]:((Ft===null||typeof Ft>"u")&&(Ft=Le()),Se=pt[gn]&&pt[gn][Ft]),typeof Se>"u"||!Se.length||!Se[0]){var re="";zt=[];for(Ye in pt[gn])this.terminals_[Ye]&&Ye>It&&zt.push("'"+this.terminals_[Ye]+"'");Et.showPosition?re="Parse error on line "+(Tt+1)+`: +`+Et.showPosition()+` +Expecting `+zt.join(", ")+", got '"+(this.terminals_[Ft]||Ft)+"'":re="Parse error on line "+(Tt+1)+": Unexpected "+(Ft==Ot?"end of input":"'"+(this.terminals_[Ft]||Ft)+"'"),this.parseError(re,{text:Et.match,token:this.terminals_[Ft]||Ft,line:Et.yylineno,loc:xt,expected:zt})}if(Se[0]instanceof Array&&Se.length>1)throw new Error("Parse Error: multiple actions possible at state: "+gn+", token: "+Ft);switch(Se[0]){case 1:ft.push(Ft),vt.push(Et.yytext),X.push(Et.yylloc),ft.push(Se[1]),Ft=null,nt=Et.yyleng,U=Et.yytext,Tt=Et.yylineno,xt=Et.yylloc;break;case 2:if(ce=this.productions_[Se[1]][1],Ve.$=vt[vt.length-ce],Ve._$={first_line:X[X.length-(ce||1)].first_line,last_line:X[X.length-1].last_line,first_column:X[X.length-(ce||1)].first_column,last_column:X[X.length-1].last_column},Ht&&(Ve._$.range=[X[X.length-(ce||1)].range[0],X[X.length-1].range[1]]),me=this.performAction.apply(Ve,[U,nt,Tt,Z.yy,Se[1],vt,X].concat(Bt)),typeof me<"u")return me;ce&&(ft=ft.slice(0,-1*ce*2),vt=vt.slice(0,-1*ce),X=X.slice(0,-1*ce)),ft.push(this.productions_[Se[1]][0]),vt.push(Ve.$),X.push(Ve._$),ke=pt[ft[ft.length-2]][ft[ft.length-1]],ft.push(ke);break;case 3:return!0}}return!0}},st=function(){var bt={EOF:1,parseError:function(yt,ft){if(this.yy.parser)this.yy.parser.parseError(yt,ft);else throw new Error(yt)},setInput:function(mt,yt){return this.yy=yt||this.yy||{},this._input=mt,this._more=this._backtrack=this.done=!1,this.yylineno=this.yyleng=0,this.yytext=this.matched=this.match="",this.conditionStack=["INITIAL"],this.yylloc={first_line:1,first_column:0,last_line:1,last_column:0},this.options.ranges&&(this.yylloc.range=[0,0]),this.offset=0,this},input:function(){var mt=this._input[0];this.yytext+=mt,this.yyleng++,this.offset++,this.match+=mt,this.matched+=mt;var yt=mt.match(/(?:\r\n?|\n).*/g);return yt?(this.yylineno++,this.yylloc.last_line++):this.yylloc.last_column++,this.options.ranges&&this.yylloc.range[1]++,this._input=this._input.slice(1),mt},unput:function(mt){var yt=mt.length,ft=mt.split(/(?:\r\n?|\n)/g);this._input=mt+this._input,this.yytext=this.yytext.substr(0,this.yytext.length-yt),this.offset-=yt;var ut=this.match.split(/(?:\r\n?|\n)/g);this.match=this.match.substr(0,this.match.length-1),this.matched=this.matched.substr(0,this.matched.length-1),ft.length-1&&(this.yylineno-=ft.length-1);var vt=this.yylloc.range;return this.yylloc={first_line:this.yylloc.first_line,last_line:this.yylineno+1,first_column:this.yylloc.first_column,last_column:ft?(ft.length===ut.length?this.yylloc.first_column:0)+ut[ut.length-ft.length].length-ft[0].length:this.yylloc.first_column-yt},this.options.ranges&&(this.yylloc.range=[vt[0],vt[0]+this.yyleng-yt]),this.yyleng=this.yytext.length,this},more:function(){return this._more=!0,this},reject:function(){if(this.options.backtrack_lexer)this._backtrack=!0;else return this.parseError("Lexical error on line "+(this.yylineno+1)+`. You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true). +`+this.showPosition(),{text:"",token:null,line:this.yylineno});return this},less:function(mt){this.unput(this.match.slice(mt))},pastInput:function(){var mt=this.matched.substr(0,this.matched.length-this.match.length);return(mt.length>20?"...":"")+mt.substr(-20).replace(/\n/g,"")},upcomingInput:function(){var mt=this.match;return mt.length<20&&(mt+=this._input.substr(0,20-mt.length)),(mt.substr(0,20)+(mt.length>20?"...":"")).replace(/\n/g,"")},showPosition:function(){var mt=this.pastInput(),yt=new Array(mt.length+1).join("-");return mt+this.upcomingInput()+` +`+yt+"^"},test_match:function(mt,yt){var ft,ut,vt;if(this.options.backtrack_lexer&&(vt={yylineno:this.yylineno,yylloc:{first_line:this.yylloc.first_line,last_line:this.last_line,first_column:this.yylloc.first_column,last_column:this.yylloc.last_column},yytext:this.yytext,match:this.match,matches:this.matches,matched:this.matched,yyleng:this.yyleng,offset:this.offset,_more:this._more,_input:this._input,yy:this.yy,conditionStack:this.conditionStack.slice(0),done:this.done},this.options.ranges&&(vt.yylloc.range=this.yylloc.range.slice(0))),ut=mt[0].match(/(?:\r\n?|\n).*/g),ut&&(this.yylineno+=ut.length),this.yylloc={first_line:this.yylloc.last_line,last_line:this.yylineno+1,first_column:this.yylloc.last_column,last_column:ut?ut[ut.length-1].length-ut[ut.length-1].match(/\r?\n?/)[0].length:this.yylloc.last_column+mt[0].length},this.yytext+=mt[0],this.match+=mt[0],this.matches=mt,this.yyleng=this.yytext.length,this.options.ranges&&(this.yylloc.range=[this.offset,this.offset+=this.yyleng]),this._more=!1,this._backtrack=!1,this._input=this._input.slice(mt[0].length),this.matched+=mt[0],ft=this.performAction.call(this,this.yy,this,yt,this.conditionStack[this.conditionStack.length-1]),this.done&&this._input&&(this.done=!1),ft)return ft;if(this._backtrack){for(var X in vt)this[X]=vt[X];return!1}return!1},next:function(){if(this.done)return this.EOF;this._input||(this.done=!0);var mt,yt,ft,ut;this._more||(this.yytext="",this.match="");for(var vt=this._currentRules(),X=0;Xyt[0].length)){if(yt=ft,ut=X,this.options.backtrack_lexer){if(mt=this.test_match(ft,vt[X]),mt!==!1)return mt;if(this._backtrack){yt=!1;continue}else return!1}else if(!this.options.flex)break}return yt?(mt=this.test_match(yt,vt[ut]),mt!==!1?mt:!1):this._input===""?this.EOF:this.parseError("Lexical error on line "+(this.yylineno+1)+`. Unrecognized text. +`+this.showPosition(),{text:"",token:null,line:this.yylineno})},lex:function(){var yt=this.next();return yt||this.lex()},begin:function(yt){this.conditionStack.push(yt)},popState:function(){var yt=this.conditionStack.length-1;return yt>0?this.conditionStack.pop():this.conditionStack[0]},_currentRules:function(){return this.conditionStack.length&&this.conditionStack[this.conditionStack.length-1]?this.conditions[this.conditionStack[this.conditionStack.length-1]].rules:this.conditions.INITIAL.rules},topState:function(yt){return yt=this.conditionStack.length-1-Math.abs(yt||0),yt>=0?this.conditionStack[yt]:"INITIAL"},pushState:function(yt){this.begin(yt)},stateStackSize:function(){return this.conditionStack.length},options:{"case-insensitive":!0},performAction:function(yt,ft,ut,vt){switch(ut){case 0:break;case 1:break;case 2:return 20;case 3:break;case 4:break;case 5:return this.begin("title"),12;case 6:return this.popState(),"title_value";case 7:return this.begin("acc_title"),14;case 8:return this.popState(),"acc_title_value";case 9:return this.begin("acc_descr"),16;case 10:return this.popState(),"acc_descr_value";case 11:this.begin("acc_descr_multiline");break;case 12:this.popState();break;case 13:return"acc_descr_multiline_value";case 14:this.begin("string");break;case 15:this.popState();break;case 16:return"txt";case 17:return 5;case 18:return 7;case 19:return"value";case 20:return 22}},rules:[/^(?:%%(?!\{)[^\n]*)/i,/^(?:[^\}]%%[^\n]*)/i,/^(?:[\n\r]+)/i,/^(?:%%[^\n]*)/i,/^(?:[\s]+)/i,/^(?:title\b)/i,/^(?:(?!\n||)*[^\n]*)/i,/^(?:accTitle\s*:\s*)/i,/^(?:(?!\n||)*[^\n]*)/i,/^(?:accDescr\s*:\s*)/i,/^(?:(?!\n||)*[^\n]*)/i,/^(?:accDescr\s*\{\s*)/i,/^(?:[\}])/i,/^(?:[^\}]*)/i,/^(?:["])/i,/^(?:["])/i,/^(?:[^"]*)/i,/^(?:pie\b)/i,/^(?:showData\b)/i,/^(?::[\s]*[\d]+(?:\.[\d]+)?)/i,/^(?:$)/i],conditions:{acc_descr_multiline:{rules:[12,13],inclusive:!1},acc_descr:{rules:[10],inclusive:!1},acc_title:{rules:[8],inclusive:!1},title:{rules:[6],inclusive:!1},string:{rules:[15,16],inclusive:!1},INITIAL:{rules:[0,1,2,3,4,5,7,9,11,14,17,18,19,20],inclusive:!0}}};return bt}();et.lexer=st;function at(){this.yy={}}return at.prototype=et,et.Parser=at,new at}();igt.parser=igt;const Zqe=igt,aRt=Zh.pie,FY={sections:{},showData:!1,config:aRt};let NY=FY.sections,sgt=FY.showData;const Jqe=structuredClone(aRt),tHe={getConfig:()=>structuredClone(Jqe),clear:()=>{NY=structuredClone(FY.sections),sgt=FY.showData,hg()},setDiagramTitle:Nb,getDiagramTitle:pg,setAccTitle:E0,getAccTitle:fg,setAccDescription:dg,getAccDescription:gg,addSection:(i,a)=>{i=Q1(i,Oe()),NY[i]===void 0&&(NY[i]=a,Ut.debug(`added new section: ${i}, with value: ${a}`))},getSections:()=>NY,cleanupValue:i=>(i.substring(0,1)===":"&&(i=i.substring(1).trim()),Number(i.trim())),setShowData:i=>{sgt=i},getShowData:()=>sgt},eHe=i=>` + .pieCircle{ + stroke: ${i.pieStrokeColor}; + stroke-width : ${i.pieStrokeWidth}; + opacity : ${i.pieOpacity}; + } + .pieOuterCircle{ + stroke: ${i.pieOuterStrokeColor}; + stroke-width: ${i.pieOuterStrokeWidth}; + fill: none; + } + .pieTitleText { + text-anchor: middle; + font-size: ${i.pieTitleTextSize}; + fill: ${i.pieTitleTextColor}; + font-family: ${i.fontFamily}; + } + .slice { + font-family: ${i.fontFamily}; + fill: ${i.pieSectionTextColor}; + font-size:${i.pieSectionTextSize}; + // fill: white; + } + .legend text { + fill: ${i.pieLegendTextColor}; + font-family: ${i.fontFamily}; + font-size: ${i.pieLegendTextSize}; + } +`,nHe=i=>{const a=Object.entries(i).map(p=>({label:p[0],value:p[1]})).sort((p,w)=>w.value-p.value);return uTe().value(p=>p.value)(a)},rHe=Object.freeze(Object.defineProperty({__proto__:null,diagram:{parser:Zqe,db:tHe,renderer:{draw:(i,a,f,p)=>{var pt,U;Ut.debug(`rendering pie chart +`+i);const w=p.db,m=Oe(),b=rF(w.getConfig(),m.pie),E=450,_=((U=(pt=document.getElementById(a))==null?void 0:pt.parentElement)==null?void 0:U.offsetWidth)??b.useWidth,A=VW(a);A.attr("viewBox",`0 0 ${_} ${E}`),k0(A,E,_,b.useMaxWidth);const I=40,B=18,N=4,R=A.append("g");R.attr("transform","translate("+_/2+","+E/2+")");const{themeVariables:z}=m;let[W]=VA(z.pieOuterStrokeWidth);W??(W=2);const et=b.textPosition,st=Math.min(_,E)/2-I,at=OA().innerRadius(0).outerRadius(st),bt=OA().innerRadius(st*et).outerRadius(st*et);R.append("circle").attr("cx",0).attr("cy",0).attr("r",st+W/2).attr("class","pieOuterCircle");const mt=w.getSections(),yt=nHe(mt),ft=[z.pie1,z.pie2,z.pie3,z.pie4,z.pie5,z.pie6,z.pie7,z.pie8,z.pie9,z.pie10,z.pie11,z.pie12],ut=XU(ft);R.selectAll("mySlices").data(yt).enter().append("path").attr("d",at).attr("fill",Tt=>ut(Tt.data.label)).attr("class","pieCircle");let vt=0;Object.keys(mt).forEach(Tt=>{vt+=mt[Tt]}),R.selectAll("mySlices").data(yt).enter().append("text").text(Tt=>(Tt.data.value/vt*100).toFixed(0)+"%").attr("transform",Tt=>"translate("+bt.centroid(Tt)+")").style("text-anchor","middle").attr("class","slice"),R.append("text").text(w.getDiagramTitle()).attr("x",0).attr("y",-(E-50)/2).attr("class","pieTitleText");const X=R.selectAll(".legend").data(ut.domain()).enter().append("g").attr("class","legend").attr("transform",(Tt,nt)=>{const It=B+N,Ot=It*ut.domain().length/2,Bt=12*B,Et=nt*It-Ot;return"translate("+Bt+","+Et+")"});X.append("rect").attr("width",B).attr("height",B).style("fill",ut).style("stroke",ut),X.data(yt).append("text").attr("x",B+N).attr("y",B-N).text(Tt=>{const{label:nt,value:It}=Tt.data;return w.getShowData()?`${nt} [${It}]`:nt})}},styles:eHe}},Symbol.toStringTag,{value:"Module"}));var agt=function(){var i=function(Se,me,Ve,Ye){for(Ve=Ve||{},Ye=Se.length;Ye--;Ve[Se[Ye]]=me);return Ve},a=[1,3],f=[1,4],p=[1,5],w=[1,6],m=[1,7],b=[1,5,13,15,17,19,20,25,27,28,29,30,31,32,33,34,37,38,40,41,42,43,44,45,46,47,48,49,50],E=[1,5,6,13,15,17,19,20,25,27,28,29,30,31,32,33,34,37,38,40,41,42,43,44,45,46,47,48,49,50],_=[32,33,34],A=[2,7],I=[1,13],B=[1,17],N=[1,18],R=[1,19],z=[1,20],W=[1,21],et=[1,22],st=[1,23],at=[1,24],bt=[1,25],mt=[1,26],yt=[1,27],ft=[1,30],ut=[1,31],vt=[1,32],X=[1,33],pt=[1,34],U=[1,35],Tt=[1,36],nt=[1,37],It=[1,38],Ot=[1,39],Bt=[1,40],Et=[1,41],Z=[1,42],Ct=[1,57],xt=[1,58],Ht=[5,22,26,32,33,34,40,41,42,43,44,45,46,47,48,49,50,51],Le={trace:function(){},yy:{},symbols_:{error:2,start:3,eol:4,SPACE:5,QUADRANT:6,document:7,line:8,statement:9,axisDetails:10,quadrantDetails:11,points:12,title:13,title_value:14,acc_title:15,acc_title_value:16,acc_descr:17,acc_descr_value:18,acc_descr_multiline_value:19,section:20,text:21,point_start:22,point_x:23,point_y:24,"X-AXIS":25,"AXIS-TEXT-DELIMITER":26,"Y-AXIS":27,QUADRANT_1:28,QUADRANT_2:29,QUADRANT_3:30,QUADRANT_4:31,NEWLINE:32,SEMI:33,EOF:34,alphaNumToken:35,textNoTagsToken:36,STR:37,MD_STR:38,alphaNum:39,PUNCTUATION:40,AMP:41,NUM:42,ALPHA:43,COMMA:44,PLUS:45,EQUALS:46,MULT:47,DOT:48,BRKT:49,UNDERSCORE:50,MINUS:51,$accept:0,$end:1},terminals_:{2:"error",5:"SPACE",6:"QUADRANT",13:"title",14:"title_value",15:"acc_title",16:"acc_title_value",17:"acc_descr",18:"acc_descr_value",19:"acc_descr_multiline_value",20:"section",22:"point_start",23:"point_x",24:"point_y",25:"X-AXIS",26:"AXIS-TEXT-DELIMITER",27:"Y-AXIS",28:"QUADRANT_1",29:"QUADRANT_2",30:"QUADRANT_3",31:"QUADRANT_4",32:"NEWLINE",33:"SEMI",34:"EOF",37:"STR",38:"MD_STR",40:"PUNCTUATION",41:"AMP",42:"NUM",43:"ALPHA",44:"COMMA",45:"PLUS",46:"EQUALS",47:"MULT",48:"DOT",49:"BRKT",50:"UNDERSCORE",51:"MINUS"},productions_:[0,[3,2],[3,2],[3,2],[7,0],[7,2],[8,2],[9,0],[9,2],[9,1],[9,1],[9,1],[9,2],[9,2],[9,2],[9,1],[9,1],[12,4],[10,4],[10,3],[10,2],[10,4],[10,3],[10,2],[11,2],[11,2],[11,2],[11,2],[4,1],[4,1],[4,1],[21,1],[21,2],[21,1],[21,1],[39,1],[39,2],[35,1],[35,1],[35,1],[35,1],[35,1],[35,1],[35,1],[35,1],[35,1],[35,1],[35,1],[36,1],[36,1],[36,1]],performAction:function(me,Ve,Ye,ce,ke,zt,re){var se=zt.length-1;switch(ke){case 12:this.$=zt[se].trim(),ce.setDiagramTitle(this.$);break;case 13:this.$=zt[se].trim(),ce.setAccTitle(this.$);break;case 14:case 15:this.$=zt[se].trim(),ce.setAccDescription(this.$);break;case 16:ce.addSection(zt[se].substr(8)),this.$=zt[se].substr(8);break;case 17:ce.addPoint(zt[se-3],zt[se-1],zt[se]);break;case 18:ce.setXAxisLeftText(zt[se-2]),ce.setXAxisRightText(zt[se]);break;case 19:zt[se-1].text+=" ⟶ ",ce.setXAxisLeftText(zt[se-1]);break;case 20:ce.setXAxisLeftText(zt[se]);break;case 21:ce.setYAxisBottomText(zt[se-2]),ce.setYAxisTopText(zt[se]);break;case 22:zt[se-1].text+=" ⟶ ",ce.setYAxisBottomText(zt[se-1]);break;case 23:ce.setYAxisBottomText(zt[se]);break;case 24:ce.setQuadrant1Text(zt[se]);break;case 25:ce.setQuadrant2Text(zt[se]);break;case 26:ce.setQuadrant3Text(zt[se]);break;case 27:ce.setQuadrant4Text(zt[se]);break;case 31:this.$={text:zt[se],type:"text"};break;case 32:this.$={text:zt[se-1].text+""+zt[se],type:zt[se-1].type};break;case 33:this.$={text:zt[se],type:"text"};break;case 34:this.$={text:zt[se],type:"markdown"};break;case 35:this.$=zt[se];break;case 36:this.$=zt[se-1]+""+zt[se];break}},table:[{3:1,4:2,5:a,6:f,32:p,33:w,34:m},{1:[3]},{3:8,4:2,5:a,6:f,32:p,33:w,34:m},{3:9,4:2,5:a,6:f,32:p,33:w,34:m},i(b,[2,4],{7:10}),i(E,[2,28]),i(E,[2,29]),i(E,[2,30]),{1:[2,1]},{1:[2,2]},i(_,A,{8:11,9:12,10:14,11:15,12:16,21:28,35:29,1:[2,3],5:I,13:B,15:N,17:R,19:z,20:W,25:et,27:st,28:at,29:bt,30:mt,31:yt,37:ft,38:ut,40:vt,41:X,42:pt,43:U,44:Tt,45:nt,46:It,47:Ot,48:Bt,49:Et,50:Z}),i(b,[2,5]),{4:43,32:p,33:w,34:m},i(_,A,{10:14,11:15,12:16,21:28,35:29,9:44,5:I,13:B,15:N,17:R,19:z,20:W,25:et,27:st,28:at,29:bt,30:mt,31:yt,37:ft,38:ut,40:vt,41:X,42:pt,43:U,44:Tt,45:nt,46:It,47:Ot,48:Bt,49:Et,50:Z}),i(_,[2,9]),i(_,[2,10]),i(_,[2,11]),{14:[1,45]},{16:[1,46]},{18:[1,47]},i(_,[2,15]),i(_,[2,16]),{21:48,35:29,37:ft,38:ut,40:vt,41:X,42:pt,43:U,44:Tt,45:nt,46:It,47:Ot,48:Bt,49:Et,50:Z},{21:49,35:29,37:ft,38:ut,40:vt,41:X,42:pt,43:U,44:Tt,45:nt,46:It,47:Ot,48:Bt,49:Et,50:Z},{21:50,35:29,37:ft,38:ut,40:vt,41:X,42:pt,43:U,44:Tt,45:nt,46:It,47:Ot,48:Bt,49:Et,50:Z},{21:51,35:29,37:ft,38:ut,40:vt,41:X,42:pt,43:U,44:Tt,45:nt,46:It,47:Ot,48:Bt,49:Et,50:Z},{21:52,35:29,37:ft,38:ut,40:vt,41:X,42:pt,43:U,44:Tt,45:nt,46:It,47:Ot,48:Bt,49:Et,50:Z},{21:53,35:29,37:ft,38:ut,40:vt,41:X,42:pt,43:U,44:Tt,45:nt,46:It,47:Ot,48:Bt,49:Et,50:Z},{5:Ct,22:[1,54],35:56,36:55,40:vt,41:X,42:pt,43:U,44:Tt,45:nt,46:It,47:Ot,48:Bt,49:Et,50:Z,51:xt},i(Ht,[2,31]),i(Ht,[2,33]),i(Ht,[2,34]),i(Ht,[2,37]),i(Ht,[2,38]),i(Ht,[2,39]),i(Ht,[2,40]),i(Ht,[2,41]),i(Ht,[2,42]),i(Ht,[2,43]),i(Ht,[2,44]),i(Ht,[2,45]),i(Ht,[2,46]),i(Ht,[2,47]),i(b,[2,6]),i(_,[2,8]),i(_,[2,12]),i(_,[2,13]),i(_,[2,14]),i(_,[2,20],{36:55,35:56,5:Ct,26:[1,59],40:vt,41:X,42:pt,43:U,44:Tt,45:nt,46:It,47:Ot,48:Bt,49:Et,50:Z,51:xt}),i(_,[2,23],{36:55,35:56,5:Ct,26:[1,60],40:vt,41:X,42:pt,43:U,44:Tt,45:nt,46:It,47:Ot,48:Bt,49:Et,50:Z,51:xt}),i(_,[2,24],{36:55,35:56,5:Ct,40:vt,41:X,42:pt,43:U,44:Tt,45:nt,46:It,47:Ot,48:Bt,49:Et,50:Z,51:xt}),i(_,[2,25],{36:55,35:56,5:Ct,40:vt,41:X,42:pt,43:U,44:Tt,45:nt,46:It,47:Ot,48:Bt,49:Et,50:Z,51:xt}),i(_,[2,26],{36:55,35:56,5:Ct,40:vt,41:X,42:pt,43:U,44:Tt,45:nt,46:It,47:Ot,48:Bt,49:Et,50:Z,51:xt}),i(_,[2,27],{36:55,35:56,5:Ct,40:vt,41:X,42:pt,43:U,44:Tt,45:nt,46:It,47:Ot,48:Bt,49:Et,50:Z,51:xt}),{23:[1,61]},i(Ht,[2,32]),i(Ht,[2,48]),i(Ht,[2,49]),i(Ht,[2,50]),i(_,[2,19],{35:29,21:62,37:ft,38:ut,40:vt,41:X,42:pt,43:U,44:Tt,45:nt,46:It,47:Ot,48:Bt,49:Et,50:Z}),i(_,[2,22],{35:29,21:63,37:ft,38:ut,40:vt,41:X,42:pt,43:U,44:Tt,45:nt,46:It,47:Ot,48:Bt,49:Et,50:Z}),{24:[1,64]},i(_,[2,18],{36:55,35:56,5:Ct,40:vt,41:X,42:pt,43:U,44:Tt,45:nt,46:It,47:Ot,48:Bt,49:Et,50:Z,51:xt}),i(_,[2,21],{36:55,35:56,5:Ct,40:vt,41:X,42:pt,43:U,44:Tt,45:nt,46:It,47:Ot,48:Bt,49:Et,50:Z,51:xt}),i(_,[2,17])],defaultActions:{8:[2,1],9:[2,2]},parseError:function(me,Ve){if(Ve.recoverable)this.trace(me);else{var Ye=new Error(me);throw Ye.hash=Ve,Ye}},parse:function(me){var Ve=this,Ye=[0],ce=[],ke=[null],zt=[],re=this.table,se="",Pe=0,te=0,Me=2,de=1,on=zt.slice.call(arguments,1),ni=Object.create(this.lexer),Ks={yy:{}};for(var ws in this.yy)Object.prototype.hasOwnProperty.call(this.yy,ws)&&(Ks.yy[ws]=this.yy[ws]);ni.setInput(me,Ks.yy),Ks.yy.lexer=ni,Ks.yy.parser=this,typeof ni.yylloc>"u"&&(ni.yylloc={});var fo=ni.yylloc;zt.push(fo);var Xi=ni.options&&ni.options.ranges;typeof Ks.yy.parseError=="function"?this.parseError=Ks.yy.parseError:this.parseError=Object.getPrototypeOf(this).parseError;function Er(){var Gs;return Gs=ce.pop()||ni.lex()||de,typeof Gs!="number"&&(Gs instanceof Array&&(ce=Gs,Gs=ce.pop()),Gs=Ve.symbols_[Gs]||Gs),Gs}for(var Xn,di,Ee,Kn,He={},Ti,pn,Es,qa;;){if(di=Ye[Ye.length-1],this.defaultActions[di]?Ee=this.defaultActions[di]:((Xn===null||typeof Xn>"u")&&(Xn=Er()),Ee=re[di]&&re[di][Xn]),typeof Ee>"u"||!Ee.length||!Ee[0]){var Ma="";qa=[];for(Ti in re[di])this.terminals_[Ti]&&Ti>Me&&qa.push("'"+this.terminals_[Ti]+"'");ni.showPosition?Ma="Parse error on line "+(Pe+1)+`: +`+ni.showPosition()+` +Expecting `+qa.join(", ")+", got '"+(this.terminals_[Xn]||Xn)+"'":Ma="Parse error on line "+(Pe+1)+": Unexpected "+(Xn==de?"end of input":"'"+(this.terminals_[Xn]||Xn)+"'"),this.parseError(Ma,{text:ni.match,token:this.terminals_[Xn]||Xn,line:ni.yylineno,loc:fo,expected:qa})}if(Ee[0]instanceof Array&&Ee.length>1)throw new Error("Parse Error: multiple actions possible at state: "+di+", token: "+Xn);switch(Ee[0]){case 1:Ye.push(Xn),ke.push(ni.yytext),zt.push(ni.yylloc),Ye.push(Ee[1]),Xn=null,te=ni.yyleng,se=ni.yytext,Pe=ni.yylineno,fo=ni.yylloc;break;case 2:if(pn=this.productions_[Ee[1]][1],He.$=ke[ke.length-pn],He._$={first_line:zt[zt.length-(pn||1)].first_line,last_line:zt[zt.length-1].last_line,first_column:zt[zt.length-(pn||1)].first_column,last_column:zt[zt.length-1].last_column},Xi&&(He._$.range=[zt[zt.length-(pn||1)].range[0],zt[zt.length-1].range[1]]),Kn=this.performAction.apply(He,[se,te,Pe,Ks.yy,Ee[1],ke,zt].concat(on)),typeof Kn<"u")return Kn;pn&&(Ye=Ye.slice(0,-1*pn*2),ke=ke.slice(0,-1*pn),zt=zt.slice(0,-1*pn)),Ye.push(this.productions_[Ee[1]][0]),ke.push(He.$),zt.push(He._$),Es=re[Ye[Ye.length-2]][Ye[Ye.length-1]],Ye.push(Es);break;case 3:return!0}}return!0}},Ft=function(){var Se={EOF:1,parseError:function(Ve,Ye){if(this.yy.parser)this.yy.parser.parseError(Ve,Ye);else throw new Error(Ve)},setInput:function(me,Ve){return this.yy=Ve||this.yy||{},this._input=me,this._more=this._backtrack=this.done=!1,this.yylineno=this.yyleng=0,this.yytext=this.matched=this.match="",this.conditionStack=["INITIAL"],this.yylloc={first_line:1,first_column:0,last_line:1,last_column:0},this.options.ranges&&(this.yylloc.range=[0,0]),this.offset=0,this},input:function(){var me=this._input[0];this.yytext+=me,this.yyleng++,this.offset++,this.match+=me,this.matched+=me;var Ve=me.match(/(?:\r\n?|\n).*/g);return Ve?(this.yylineno++,this.yylloc.last_line++):this.yylloc.last_column++,this.options.ranges&&this.yylloc.range[1]++,this._input=this._input.slice(1),me},unput:function(me){var Ve=me.length,Ye=me.split(/(?:\r\n?|\n)/g);this._input=me+this._input,this.yytext=this.yytext.substr(0,this.yytext.length-Ve),this.offset-=Ve;var ce=this.match.split(/(?:\r\n?|\n)/g);this.match=this.match.substr(0,this.match.length-1),this.matched=this.matched.substr(0,this.matched.length-1),Ye.length-1&&(this.yylineno-=Ye.length-1);var ke=this.yylloc.range;return this.yylloc={first_line:this.yylloc.first_line,last_line:this.yylineno+1,first_column:this.yylloc.first_column,last_column:Ye?(Ye.length===ce.length?this.yylloc.first_column:0)+ce[ce.length-Ye.length].length-Ye[0].length:this.yylloc.first_column-Ve},this.options.ranges&&(this.yylloc.range=[ke[0],ke[0]+this.yyleng-Ve]),this.yyleng=this.yytext.length,this},more:function(){return this._more=!0,this},reject:function(){if(this.options.backtrack_lexer)this._backtrack=!0;else return this.parseError("Lexical error on line "+(this.yylineno+1)+`. You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true). +`+this.showPosition(),{text:"",token:null,line:this.yylineno});return this},less:function(me){this.unput(this.match.slice(me))},pastInput:function(){var me=this.matched.substr(0,this.matched.length-this.match.length);return(me.length>20?"...":"")+me.substr(-20).replace(/\n/g,"")},upcomingInput:function(){var me=this.match;return me.length<20&&(me+=this._input.substr(0,20-me.length)),(me.substr(0,20)+(me.length>20?"...":"")).replace(/\n/g,"")},showPosition:function(){var me=this.pastInput(),Ve=new Array(me.length+1).join("-");return me+this.upcomingInput()+` +`+Ve+"^"},test_match:function(me,Ve){var Ye,ce,ke;if(this.options.backtrack_lexer&&(ke={yylineno:this.yylineno,yylloc:{first_line:this.yylloc.first_line,last_line:this.last_line,first_column:this.yylloc.first_column,last_column:this.yylloc.last_column},yytext:this.yytext,match:this.match,matches:this.matches,matched:this.matched,yyleng:this.yyleng,offset:this.offset,_more:this._more,_input:this._input,yy:this.yy,conditionStack:this.conditionStack.slice(0),done:this.done},this.options.ranges&&(ke.yylloc.range=this.yylloc.range.slice(0))),ce=me[0].match(/(?:\r\n?|\n).*/g),ce&&(this.yylineno+=ce.length),this.yylloc={first_line:this.yylloc.last_line,last_line:this.yylineno+1,first_column:this.yylloc.last_column,last_column:ce?ce[ce.length-1].length-ce[ce.length-1].match(/\r?\n?/)[0].length:this.yylloc.last_column+me[0].length},this.yytext+=me[0],this.match+=me[0],this.matches=me,this.yyleng=this.yytext.length,this.options.ranges&&(this.yylloc.range=[this.offset,this.offset+=this.yyleng]),this._more=!1,this._backtrack=!1,this._input=this._input.slice(me[0].length),this.matched+=me[0],Ye=this.performAction.call(this,this.yy,this,Ve,this.conditionStack[this.conditionStack.length-1]),this.done&&this._input&&(this.done=!1),Ye)return Ye;if(this._backtrack){for(var zt in ke)this[zt]=ke[zt];return!1}return!1},next:function(){if(this.done)return this.EOF;this._input||(this.done=!0);var me,Ve,Ye,ce;this._more||(this.yytext="",this.match="");for(var ke=this._currentRules(),zt=0;ztVe[0].length)){if(Ve=Ye,ce=zt,this.options.backtrack_lexer){if(me=this.test_match(Ye,ke[zt]),me!==!1)return me;if(this._backtrack){Ve=!1;continue}else return!1}else if(!this.options.flex)break}return Ve?(me=this.test_match(Ve,ke[ce]),me!==!1?me:!1):this._input===""?this.EOF:this.parseError("Lexical error on line "+(this.yylineno+1)+`. Unrecognized text. +`+this.showPosition(),{text:"",token:null,line:this.yylineno})},lex:function(){var Ve=this.next();return Ve||this.lex()},begin:function(Ve){this.conditionStack.push(Ve)},popState:function(){var Ve=this.conditionStack.length-1;return Ve>0?this.conditionStack.pop():this.conditionStack[0]},_currentRules:function(){return this.conditionStack.length&&this.conditionStack[this.conditionStack.length-1]?this.conditions[this.conditionStack[this.conditionStack.length-1]].rules:this.conditions.INITIAL.rules},topState:function(Ve){return Ve=this.conditionStack.length-1-Math.abs(Ve||0),Ve>=0?this.conditionStack[Ve]:"INITIAL"},pushState:function(Ve){this.begin(Ve)},stateStackSize:function(){return this.conditionStack.length},options:{"case-insensitive":!0},performAction:function(Ve,Ye,ce,ke){switch(ce){case 0:break;case 1:break;case 2:return 32;case 3:break;case 4:return this.begin("title"),13;case 5:return this.popState(),"title_value";case 6:return this.begin("acc_title"),15;case 7:return this.popState(),"acc_title_value";case 8:return this.begin("acc_descr"),17;case 9:return this.popState(),"acc_descr_value";case 10:this.begin("acc_descr_multiline");break;case 11:this.popState();break;case 12:return"acc_descr_multiline_value";case 13:return 25;case 14:return 27;case 15:return 26;case 16:return 28;case 17:return 29;case 18:return 30;case 19:return 31;case 20:this.begin("md_string");break;case 21:return"MD_STR";case 22:this.popState();break;case 23:this.begin("string");break;case 24:this.popState();break;case 25:return"STR";case 26:return this.begin("point_start"),22;case 27:return this.begin("point_x"),23;case 28:this.popState();break;case 29:this.popState(),this.begin("point_y");break;case 30:return this.popState(),24;case 31:return 6;case 32:return 43;case 33:return"COLON";case 34:return 45;case 35:return 44;case 36:return 46;case 37:return 46;case 38:return 47;case 39:return 49;case 40:return 50;case 41:return 48;case 42:return 41;case 43:return 51;case 44:return 42;case 45:return 5;case 46:return 33;case 47:return 40;case 48:return 34}},rules:[/^(?:%%(?!\{)[^\n]*)/i,/^(?:[^\}]%%[^\n]*)/i,/^(?:[\n\r]+)/i,/^(?:%%[^\n]*)/i,/^(?:title\b)/i,/^(?:(?!\n||)*[^\n]*)/i,/^(?:accTitle\s*:\s*)/i,/^(?:(?!\n||)*[^\n]*)/i,/^(?:accDescr\s*:\s*)/i,/^(?:(?!\n||)*[^\n]*)/i,/^(?:accDescr\s*\{\s*)/i,/^(?:[\}])/i,/^(?:[^\}]*)/i,/^(?: *x-axis *)/i,/^(?: *y-axis *)/i,/^(?: *--+> *)/i,/^(?: *quadrant-1 *)/i,/^(?: *quadrant-2 *)/i,/^(?: *quadrant-3 *)/i,/^(?: *quadrant-4 *)/i,/^(?:["][`])/i,/^(?:[^`"]+)/i,/^(?:[`]["])/i,/^(?:["])/i,/^(?:["])/i,/^(?:[^"]*)/i,/^(?:\s*:\s*\[\s*)/i,/^(?:(1)|(0(.\d+)?))/i,/^(?:\s*\] *)/i,/^(?:\s*,\s*)/i,/^(?:(1)|(0(.\d+)?))/i,/^(?: *quadrantChart *)/i,/^(?:[A-Za-z]+)/i,/^(?::)/i,/^(?:\+)/i,/^(?:,)/i,/^(?:=)/i,/^(?:=)/i,/^(?:\*)/i,/^(?:#)/i,/^(?:[\_])/i,/^(?:\.)/i,/^(?:&)/i,/^(?:-)/i,/^(?:[0-9]+)/i,/^(?:\s)/i,/^(?:;)/i,/^(?:[!"#$%&'*+,-.`?\\_/])/i,/^(?:$)/i],conditions:{point_y:{rules:[30],inclusive:!1},point_x:{rules:[29],inclusive:!1},point_start:{rules:[27,28],inclusive:!1},acc_descr_multiline:{rules:[11,12],inclusive:!1},acc_descr:{rules:[9],inclusive:!1},acc_title:{rules:[7],inclusive:!1},title:{rules:[5],inclusive:!1},md_string:{rules:[21,22],inclusive:!1},string:{rules:[24,25],inclusive:!1},INITIAL:{rules:[0,1,2,3,4,6,8,10,13,14,15,16,17,18,19,20,23,26,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48],inclusive:!0}}};return Se}();Le.lexer=Ft;function gn(){this.yy={}}return gn.prototype=Le,Le.Parser=gn,new gn}();agt.parser=agt;const iHe=agt,mg=X1t();class sHe{constructor(){this.config=this.getDefaultConfig(),this.themeConfig=this.getDefaultThemeConfig(),this.data=this.getDefaultData()}getDefaultData(){return{titleText:"",quadrant1Text:"",quadrant2Text:"",quadrant3Text:"",quadrant4Text:"",xAxisLeftText:"",xAxisRightText:"",yAxisBottomText:"",yAxisTopText:"",points:[]}}getDefaultConfig(){var a,f,p,w,m,b,E,_,A,I,B,N,R,z,W,et,st,at;return{showXAxis:!0,showYAxis:!0,showTitle:!0,chartHeight:((a=Zh.quadrantChart)==null?void 0:a.chartWidth)||500,chartWidth:((f=Zh.quadrantChart)==null?void 0:f.chartHeight)||500,titlePadding:((p=Zh.quadrantChart)==null?void 0:p.titlePadding)||10,titleFontSize:((w=Zh.quadrantChart)==null?void 0:w.titleFontSize)||20,quadrantPadding:((m=Zh.quadrantChart)==null?void 0:m.quadrantPadding)||5,xAxisLabelPadding:((b=Zh.quadrantChart)==null?void 0:b.xAxisLabelPadding)||5,yAxisLabelPadding:((E=Zh.quadrantChart)==null?void 0:E.yAxisLabelPadding)||5,xAxisLabelFontSize:((_=Zh.quadrantChart)==null?void 0:_.xAxisLabelFontSize)||16,yAxisLabelFontSize:((A=Zh.quadrantChart)==null?void 0:A.yAxisLabelFontSize)||16,quadrantLabelFontSize:((I=Zh.quadrantChart)==null?void 0:I.quadrantLabelFontSize)||16,quadrantTextTopPadding:((B=Zh.quadrantChart)==null?void 0:B.quadrantTextTopPadding)||5,pointTextPadding:((N=Zh.quadrantChart)==null?void 0:N.pointTextPadding)||5,pointLabelFontSize:((R=Zh.quadrantChart)==null?void 0:R.pointLabelFontSize)||12,pointRadius:((z=Zh.quadrantChart)==null?void 0:z.pointRadius)||5,xAxisPosition:((W=Zh.quadrantChart)==null?void 0:W.xAxisPosition)||"top",yAxisPosition:((et=Zh.quadrantChart)==null?void 0:et.yAxisPosition)||"left",quadrantInternalBorderStrokeWidth:((st=Zh.quadrantChart)==null?void 0:st.quadrantInternalBorderStrokeWidth)||1,quadrantExternalBorderStrokeWidth:((at=Zh.quadrantChart)==null?void 0:at.quadrantExternalBorderStrokeWidth)||2}}getDefaultThemeConfig(){return{quadrant1Fill:mg.quadrant1Fill,quadrant2Fill:mg.quadrant2Fill,quadrant3Fill:mg.quadrant3Fill,quadrant4Fill:mg.quadrant4Fill,quadrant1TextFill:mg.quadrant1TextFill,quadrant2TextFill:mg.quadrant2TextFill,quadrant3TextFill:mg.quadrant3TextFill,quadrant4TextFill:mg.quadrant4TextFill,quadrantPointFill:mg.quadrantPointFill,quadrantPointTextFill:mg.quadrantPointTextFill,quadrantXAxisTextFill:mg.quadrantXAxisTextFill,quadrantYAxisTextFill:mg.quadrantYAxisTextFill,quadrantTitleFill:mg.quadrantTitleFill,quadrantInternalBorderStrokeFill:mg.quadrantInternalBorderStrokeFill,quadrantExternalBorderStrokeFill:mg.quadrantExternalBorderStrokeFill}}clear(){this.config=this.getDefaultConfig(),this.themeConfig=this.getDefaultThemeConfig(),this.data=this.getDefaultData(),Ut.info("clear called")}setData(a){this.data={...this.data,...a}}addPoints(a){this.data.points=[...a,...this.data.points]}setConfig(a){Ut.trace("setConfig called with: ",a),this.config={...this.config,...a}}setThemeConfig(a){Ut.trace("setThemeConfig called with: ",a),this.themeConfig={...this.themeConfig,...a}}calculateSpace(a,f,p,w){const m=this.config.xAxisLabelPadding*2+this.config.xAxisLabelFontSize,b={top:a==="top"&&f?m:0,bottom:a==="bottom"&&f?m:0},E=this.config.yAxisLabelPadding*2+this.config.yAxisLabelFontSize,_={left:this.config.yAxisPosition==="left"&&p?E:0,right:this.config.yAxisPosition==="right"&&p?E:0},A=this.config.titleFontSize+this.config.titlePadding*2,I={top:w?A:0},B=this.config.quadrantPadding+_.left,N=this.config.quadrantPadding+b.top+I.top,R=this.config.chartWidth-this.config.quadrantPadding*2-_.left-_.right,z=this.config.chartHeight-this.config.quadrantPadding*2-b.top-b.bottom-I.top,W=R/2,et=z/2;return{xAxisSpace:b,yAxisSpace:_,titleSpace:I,quadrantSpace:{quadrantLeft:B,quadrantTop:N,quadrantWidth:R,quadrantHalfWidth:W,quadrantHeight:z,quadrantHalfHeight:et}}}getAxisLabels(a,f,p,w){const{quadrantSpace:m,titleSpace:b}=w,{quadrantHalfHeight:E,quadrantHeight:_,quadrantLeft:A,quadrantHalfWidth:I,quadrantTop:B,quadrantWidth:N}=m,R=!!this.data.xAxisRightText,z=!!this.data.yAxisTopText,W=[];return this.data.xAxisLeftText&&f&&W.push({text:this.data.xAxisLeftText,fill:this.themeConfig.quadrantXAxisTextFill,x:A+(R?I/2:0),y:a==="top"?this.config.xAxisLabelPadding+b.top:this.config.xAxisLabelPadding+B+_+this.config.quadrantPadding,fontSize:this.config.xAxisLabelFontSize,verticalPos:R?"center":"left",horizontalPos:"top",rotation:0}),this.data.xAxisRightText&&f&&W.push({text:this.data.xAxisRightText,fill:this.themeConfig.quadrantXAxisTextFill,x:A+I+(R?I/2:0),y:a==="top"?this.config.xAxisLabelPadding+b.top:this.config.xAxisLabelPadding+B+_+this.config.quadrantPadding,fontSize:this.config.xAxisLabelFontSize,verticalPos:R?"center":"left",horizontalPos:"top",rotation:0}),this.data.yAxisBottomText&&p&&W.push({text:this.data.yAxisBottomText,fill:this.themeConfig.quadrantYAxisTextFill,x:this.config.yAxisPosition==="left"?this.config.yAxisLabelPadding:this.config.yAxisLabelPadding+A+N+this.config.quadrantPadding,y:B+_-(z?E/2:0),fontSize:this.config.yAxisLabelFontSize,verticalPos:z?"center":"left",horizontalPos:"top",rotation:-90}),this.data.yAxisTopText&&p&&W.push({text:this.data.yAxisTopText,fill:this.themeConfig.quadrantYAxisTextFill,x:this.config.yAxisPosition==="left"?this.config.yAxisLabelPadding:this.config.yAxisLabelPadding+A+N+this.config.quadrantPadding,y:B+E-(z?E/2:0),fontSize:this.config.yAxisLabelFontSize,verticalPos:z?"center":"left",horizontalPos:"top",rotation:-90}),W}getQuadrants(a){const{quadrantSpace:f}=a,{quadrantHalfHeight:p,quadrantLeft:w,quadrantHalfWidth:m,quadrantTop:b}=f,E=[{text:{text:this.data.quadrant1Text,fill:this.themeConfig.quadrant1TextFill,x:0,y:0,fontSize:this.config.quadrantLabelFontSize,verticalPos:"center",horizontalPos:"middle",rotation:0},x:w+m,y:b,width:m,height:p,fill:this.themeConfig.quadrant1Fill},{text:{text:this.data.quadrant2Text,fill:this.themeConfig.quadrant2TextFill,x:0,y:0,fontSize:this.config.quadrantLabelFontSize,verticalPos:"center",horizontalPos:"middle",rotation:0},x:w,y:b,width:m,height:p,fill:this.themeConfig.quadrant2Fill},{text:{text:this.data.quadrant3Text,fill:this.themeConfig.quadrant3TextFill,x:0,y:0,fontSize:this.config.quadrantLabelFontSize,verticalPos:"center",horizontalPos:"middle",rotation:0},x:w,y:b+p,width:m,height:p,fill:this.themeConfig.quadrant3Fill},{text:{text:this.data.quadrant4Text,fill:this.themeConfig.quadrant4TextFill,x:0,y:0,fontSize:this.config.quadrantLabelFontSize,verticalPos:"center",horizontalPos:"middle",rotation:0},x:w+m,y:b+p,width:m,height:p,fill:this.themeConfig.quadrant4Fill}];for(const _ of E)_.text.x=_.x+_.width/2,this.data.points.length===0?(_.text.y=_.y+_.height/2,_.text.horizontalPos="middle"):(_.text.y=_.y+this.config.quadrantTextTopPadding,_.text.horizontalPos="top");return E}getQuadrantPoints(a){const{quadrantSpace:f}=a,{quadrantHeight:p,quadrantLeft:w,quadrantTop:m,quadrantWidth:b}=f,E=AA().domain([0,1]).range([w,b+w]),_=AA().domain([0,1]).range([p+m,m]);return this.data.points.map(I=>({x:E(I.x),y:_(I.y),fill:this.themeConfig.quadrantPointFill,radius:this.config.pointRadius,text:{text:I.text,fill:this.themeConfig.quadrantPointTextFill,x:E(I.x),y:_(I.y)+this.config.pointTextPadding,verticalPos:"center",horizontalPos:"top",fontSize:this.config.pointLabelFontSize,rotation:0}}))}getBorders(a){const f=this.config.quadrantExternalBorderStrokeWidth/2,{quadrantSpace:p}=a,{quadrantHalfHeight:w,quadrantHeight:m,quadrantLeft:b,quadrantHalfWidth:E,quadrantTop:_,quadrantWidth:A}=p;return[{strokeFill:this.themeConfig.quadrantExternalBorderStrokeFill,strokeWidth:this.config.quadrantExternalBorderStrokeWidth,x1:b-f,y1:_,x2:b+A+f,y2:_},{strokeFill:this.themeConfig.quadrantExternalBorderStrokeFill,strokeWidth:this.config.quadrantExternalBorderStrokeWidth,x1:b+A,y1:_+f,x2:b+A,y2:_+m-f},{strokeFill:this.themeConfig.quadrantExternalBorderStrokeFill,strokeWidth:this.config.quadrantExternalBorderStrokeWidth,x1:b-f,y1:_+m,x2:b+A+f,y2:_+m},{strokeFill:this.themeConfig.quadrantExternalBorderStrokeFill,strokeWidth:this.config.quadrantExternalBorderStrokeWidth,x1:b,y1:_+f,x2:b,y2:_+m-f},{strokeFill:this.themeConfig.quadrantInternalBorderStrokeFill,strokeWidth:this.config.quadrantInternalBorderStrokeWidth,x1:b+E,y1:_+f,x2:b+E,y2:_+m-f},{strokeFill:this.themeConfig.quadrantInternalBorderStrokeFill,strokeWidth:this.config.quadrantInternalBorderStrokeWidth,x1:b+f,y1:_+w,x2:b+A-f,y2:_+w}]}getTitle(a){if(a)return{text:this.data.titleText,fill:this.themeConfig.quadrantTitleFill,fontSize:this.config.titleFontSize,horizontalPos:"top",verticalPos:"center",rotation:0,y:this.config.titlePadding,x:this.config.chartWidth/2}}build(){const a=this.config.showXAxis&&!!(this.data.xAxisLeftText||this.data.xAxisRightText),f=this.config.showYAxis&&!!(this.data.yAxisTopText||this.data.yAxisBottomText),p=this.config.showTitle&&!!this.data.titleText,w=this.data.points.length>0?"bottom":this.config.xAxisPosition,m=this.calculateSpace(w,a,f,p);return{points:this.getQuadrantPoints(m),quadrants:this.getQuadrants(m),axisLabels:this.getAxisLabels(w,a,f,m),borderLines:this.getBorders(m),title:this.getTitle(p)}}}const aHe=Oe();function B5(i){return Q1(i.trim(),aHe)}const _0=new sHe;function oHe(i){_0.setData({quadrant1Text:B5(i.text)})}function cHe(i){_0.setData({quadrant2Text:B5(i.text)})}function uHe(i){_0.setData({quadrant3Text:B5(i.text)})}function lHe(i){_0.setData({quadrant4Text:B5(i.text)})}function hHe(i){_0.setData({xAxisLeftText:B5(i.text)})}function fHe(i){_0.setData({xAxisRightText:B5(i.text)})}function dHe(i){_0.setData({yAxisTopText:B5(i.text)})}function gHe(i){_0.setData({yAxisBottomText:B5(i.text)})}function pHe(i,a,f){_0.addPoints([{x:a,y:f,text:B5(i.text)}])}function bHe(i){_0.setConfig({chartWidth:i})}function wHe(i){_0.setConfig({chartHeight:i})}function vHe(){const i=Oe(),{themeVariables:a,quadrantChart:f}=i;return f&&_0.setConfig(f),_0.setThemeConfig({quadrant1Fill:a.quadrant1Fill,quadrant2Fill:a.quadrant2Fill,quadrant3Fill:a.quadrant3Fill,quadrant4Fill:a.quadrant4Fill,quadrant1TextFill:a.quadrant1TextFill,quadrant2TextFill:a.quadrant2TextFill,quadrant3TextFill:a.quadrant3TextFill,quadrant4TextFill:a.quadrant4TextFill,quadrantPointFill:a.quadrantPointFill,quadrantPointTextFill:a.quadrantPointTextFill,quadrantXAxisTextFill:a.quadrantXAxisTextFill,quadrantYAxisTextFill:a.quadrantYAxisTextFill,quadrantExternalBorderStrokeFill:a.quadrantExternalBorderStrokeFill,quadrantInternalBorderStrokeFill:a.quadrantInternalBorderStrokeFill,quadrantTitleFill:a.quadrantTitleFill}),_0.setData({titleText:pg()}),_0.build()}const mHe=Object.freeze(Object.defineProperty({__proto__:null,diagram:{parser:iHe,db:{setWidth:bHe,setHeight:wHe,setQuadrant1Text:oHe,setQuadrant2Text:cHe,setQuadrant3Text:uHe,setQuadrant4Text:lHe,setXAxisLeftText:hHe,setXAxisRightText:fHe,setYAxisTopText:dHe,setYAxisBottomText:gHe,addPoint:pHe,getQuadrantData:vHe,clear:function(){_0.clear(),hg()},setAccTitle:E0,getAccTitle:fg,setDiagramTitle:Nb,getDiagramTitle:pg,getAccDescription:gg,setAccDescription:dg},renderer:{draw:(i,a,f,p)=>{var vt,X,pt;function w(U){return U==="top"?"hanging":"middle"}function m(U){return U==="left"?"start":"middle"}function b(U){return`translate(${U.x}, ${U.y}) rotate(${U.rotation||0})`}const E=Oe();Ut.debug(`Rendering quadrant chart +`+i);const _=E.securityLevel;let A;_==="sandbox"&&(A=yr("#i"+a));const B=yr(_==="sandbox"?A.nodes()[0].contentDocument.body:"body").select(`[id="${a}"]`),N=B.append("g").attr("class","main"),R=((vt=E.quadrantChart)==null?void 0:vt.chartWidth)||500,z=((X=E.quadrantChart)==null?void 0:X.chartHeight)||500;k0(B,z,R,((pt=E.quadrantChart)==null?void 0:pt.useMaxWidth)||!0),B.attr("viewBox","0 0 "+R+" "+z),p.db.setHeight(z),p.db.setWidth(R);const W=p.db.getQuadrantData(),et=N.append("g").attr("class","quadrants"),st=N.append("g").attr("class","border"),at=N.append("g").attr("class","data-points"),bt=N.append("g").attr("class","labels"),mt=N.append("g").attr("class","title");W.title&&mt.append("text").attr("x",0).attr("y",0).attr("fill",W.title.fill).attr("font-size",W.title.fontSize).attr("dominant-baseline",w(W.title.horizontalPos)).attr("text-anchor",m(W.title.verticalPos)).attr("transform",b(W.title)).text(W.title.text),W.borderLines&&st.selectAll("line").data(W.borderLines).enter().append("line").attr("x1",U=>U.x1).attr("y1",U=>U.y1).attr("x2",U=>U.x2).attr("y2",U=>U.y2).style("stroke",U=>U.strokeFill).style("stroke-width",U=>U.strokeWidth);const yt=et.selectAll("g.quadrant").data(W.quadrants).enter().append("g").attr("class","quadrant");yt.append("rect").attr("x",U=>U.x).attr("y",U=>U.y).attr("width",U=>U.width).attr("height",U=>U.height).attr("fill",U=>U.fill),yt.append("text").attr("x",0).attr("y",0).attr("fill",U=>U.text.fill).attr("font-size",U=>U.text.fontSize).attr("dominant-baseline",U=>w(U.text.horizontalPos)).attr("text-anchor",U=>m(U.text.verticalPos)).attr("transform",U=>b(U.text)).text(U=>U.text.text),bt.selectAll("g.label").data(W.axisLabels).enter().append("g").attr("class","label").append("text").attr("x",0).attr("y",0).text(U=>U.text).attr("fill",U=>U.fill).attr("font-size",U=>U.fontSize).attr("dominant-baseline",U=>w(U.horizontalPos)).attr("text-anchor",U=>m(U.verticalPos)).attr("transform",U=>b(U));const ut=at.selectAll("g.data-point").data(W.points).enter().append("g").attr("class","data-point");ut.append("circle").attr("cx",U=>U.x).attr("cy",U=>U.y).attr("r",U=>U.radius).attr("fill",U=>U.fill),ut.append("text").attr("x",0).attr("y",0).text(U=>U.text.text).attr("fill",U=>U.text.fill).attr("font-size",U=>U.text.fontSize).attr("dominant-baseline",U=>w(U.text.horizontalPos)).attr("text-anchor",U=>m(U.text.verticalPos)).attr("transform",U=>b(U.text))}},styles:()=>""}},Symbol.toStringTag,{value:"Module"}));var ogt=function(){var i=function(Ot,Bt,Et,Z){for(Et=Et||{},Z=Ot.length;Z--;Et[Ot[Z]]=Bt);return Et},a=[1,10,12,14,16,18,19,21,23],f=[2,6],p=[1,3],w=[1,5],m=[1,6],b=[1,7],E=[1,5,10,12,14,16,18,19,21,23,34,35,36],_=[1,25],A=[1,26],I=[1,28],B=[1,29],N=[1,30],R=[1,31],z=[1,32],W=[1,33],et=[1,34],st=[1,35],at=[1,36],bt=[1,37],mt=[1,43],yt=[1,42],ft=[1,47],ut=[1,50],vt=[1,10,12,14,16,18,19,21,23,34,35,36],X=[1,10,12,14,16,18,19,21,23,24,26,27,28,34,35,36],pt=[1,10,12,14,16,18,19,21,23,24,26,27,28,34,35,36,41,42,43,44,45,46,47,48,49,50],U=[1,64],Tt={trace:function(){},yy:{},symbols_:{error:2,start:3,eol:4,XYCHART:5,chartConfig:6,document:7,CHART_ORIENTATION:8,statement:9,title:10,text:11,X_AXIS:12,parseXAxis:13,Y_AXIS:14,parseYAxis:15,LINE:16,plotData:17,BAR:18,acc_title:19,acc_title_value:20,acc_descr:21,acc_descr_value:22,acc_descr_multiline_value:23,SQUARE_BRACES_START:24,commaSeparatedNumbers:25,SQUARE_BRACES_END:26,NUMBER_WITH_DECIMAL:27,COMMA:28,xAxisData:29,bandData:30,ARROW_DELIMITER:31,commaSeparatedTexts:32,yAxisData:33,NEWLINE:34,SEMI:35,EOF:36,alphaNum:37,STR:38,MD_STR:39,alphaNumToken:40,AMP:41,NUM:42,ALPHA:43,PLUS:44,EQUALS:45,MULT:46,DOT:47,BRKT:48,MINUS:49,UNDERSCORE:50,$accept:0,$end:1},terminals_:{2:"error",5:"XYCHART",8:"CHART_ORIENTATION",10:"title",12:"X_AXIS",14:"Y_AXIS",16:"LINE",18:"BAR",19:"acc_title",20:"acc_title_value",21:"acc_descr",22:"acc_descr_value",23:"acc_descr_multiline_value",24:"SQUARE_BRACES_START",26:"SQUARE_BRACES_END",27:"NUMBER_WITH_DECIMAL",28:"COMMA",31:"ARROW_DELIMITER",34:"NEWLINE",35:"SEMI",36:"EOF",38:"STR",39:"MD_STR",41:"AMP",42:"NUM",43:"ALPHA",44:"PLUS",45:"EQUALS",46:"MULT",47:"DOT",48:"BRKT",49:"MINUS",50:"UNDERSCORE"},productions_:[0,[3,2],[3,3],[3,2],[3,1],[6,1],[7,0],[7,2],[9,2],[9,2],[9,2],[9,2],[9,2],[9,3],[9,2],[9,3],[9,2],[9,2],[9,1],[17,3],[25,3],[25,1],[13,1],[13,2],[13,1],[29,1],[29,3],[30,3],[32,3],[32,1],[15,1],[15,2],[15,1],[33,3],[4,1],[4,1],[4,1],[11,1],[11,1],[11,1],[37,1],[37,2],[40,1],[40,1],[40,1],[40,1],[40,1],[40,1],[40,1],[40,1],[40,1],[40,1]],performAction:function(Bt,Et,Z,Ct,xt,Ht,Le){var Ft=Ht.length-1;switch(xt){case 5:Ct.setOrientation(Ht[Ft]);break;case 9:Ct.setDiagramTitle(Ht[Ft].text.trim());break;case 12:Ct.setLineData({text:"",type:"text"},Ht[Ft]);break;case 13:Ct.setLineData(Ht[Ft-1],Ht[Ft]);break;case 14:Ct.setBarData({text:"",type:"text"},Ht[Ft]);break;case 15:Ct.setBarData(Ht[Ft-1],Ht[Ft]);break;case 16:this.$=Ht[Ft].trim(),Ct.setAccTitle(this.$);break;case 17:case 18:this.$=Ht[Ft].trim(),Ct.setAccDescription(this.$);break;case 19:this.$=Ht[Ft-1];break;case 20:this.$=[Number(Ht[Ft-2]),...Ht[Ft]];break;case 21:this.$=[Number(Ht[Ft])];break;case 22:Ct.setXAxisTitle(Ht[Ft]);break;case 23:Ct.setXAxisTitle(Ht[Ft-1]);break;case 24:Ct.setXAxisTitle({type:"text",text:""});break;case 25:Ct.setXAxisBand(Ht[Ft]);break;case 26:Ct.setXAxisRangeData(Number(Ht[Ft-2]),Number(Ht[Ft]));break;case 27:this.$=Ht[Ft-1];break;case 28:this.$=[Ht[Ft-2],...Ht[Ft]];break;case 29:this.$=[Ht[Ft]];break;case 30:Ct.setYAxisTitle(Ht[Ft]);break;case 31:Ct.setYAxisTitle(Ht[Ft-1]);break;case 32:Ct.setYAxisTitle({type:"text",text:""});break;case 33:Ct.setYAxisRangeData(Number(Ht[Ft-2]),Number(Ht[Ft]));break;case 37:this.$={text:Ht[Ft],type:"text"};break;case 38:this.$={text:Ht[Ft],type:"text"};break;case 39:this.$={text:Ht[Ft],type:"markdown"};break;case 40:this.$=Ht[Ft];break;case 41:this.$=Ht[Ft-1]+""+Ht[Ft];break}},table:[i(a,f,{3:1,4:2,7:4,5:p,34:w,35:m,36:b}),{1:[3]},i(a,f,{4:2,7:4,3:8,5:p,34:w,35:m,36:b}),i(a,f,{4:2,7:4,6:9,3:10,5:p,8:[1,11],34:w,35:m,36:b}),{1:[2,4],9:12,10:[1,13],12:[1,14],14:[1,15],16:[1,16],18:[1,17],19:[1,18],21:[1,19],23:[1,20]},i(E,[2,34]),i(E,[2,35]),i(E,[2,36]),{1:[2,1]},i(a,f,{4:2,7:4,3:21,5:p,34:w,35:m,36:b}),{1:[2,3]},i(E,[2,5]),i(a,[2,7],{4:22,34:w,35:m,36:b}),{11:23,37:24,38:_,39:A,40:27,41:I,42:B,43:N,44:R,45:z,46:W,47:et,48:st,49:at,50:bt},{11:39,13:38,24:mt,27:yt,29:40,30:41,37:24,38:_,39:A,40:27,41:I,42:B,43:N,44:R,45:z,46:W,47:et,48:st,49:at,50:bt},{11:45,15:44,27:ft,33:46,37:24,38:_,39:A,40:27,41:I,42:B,43:N,44:R,45:z,46:W,47:et,48:st,49:at,50:bt},{11:49,17:48,24:ut,37:24,38:_,39:A,40:27,41:I,42:B,43:N,44:R,45:z,46:W,47:et,48:st,49:at,50:bt},{11:52,17:51,24:ut,37:24,38:_,39:A,40:27,41:I,42:B,43:N,44:R,45:z,46:W,47:et,48:st,49:at,50:bt},{20:[1,53]},{22:[1,54]},i(vt,[2,18]),{1:[2,2]},i(vt,[2,8]),i(vt,[2,9]),i(X,[2,37],{40:55,41:I,42:B,43:N,44:R,45:z,46:W,47:et,48:st,49:at,50:bt}),i(X,[2,38]),i(X,[2,39]),i(pt,[2,40]),i(pt,[2,42]),i(pt,[2,43]),i(pt,[2,44]),i(pt,[2,45]),i(pt,[2,46]),i(pt,[2,47]),i(pt,[2,48]),i(pt,[2,49]),i(pt,[2,50]),i(pt,[2,51]),i(vt,[2,10]),i(vt,[2,22],{30:41,29:56,24:mt,27:yt}),i(vt,[2,24]),i(vt,[2,25]),{31:[1,57]},{11:59,32:58,37:24,38:_,39:A,40:27,41:I,42:B,43:N,44:R,45:z,46:W,47:et,48:st,49:at,50:bt},i(vt,[2,11]),i(vt,[2,30],{33:60,27:ft}),i(vt,[2,32]),{31:[1,61]},i(vt,[2,12]),{17:62,24:ut},{25:63,27:U},i(vt,[2,14]),{17:65,24:ut},i(vt,[2,16]),i(vt,[2,17]),i(pt,[2,41]),i(vt,[2,23]),{27:[1,66]},{26:[1,67]},{26:[2,29],28:[1,68]},i(vt,[2,31]),{27:[1,69]},i(vt,[2,13]),{26:[1,70]},{26:[2,21],28:[1,71]},i(vt,[2,15]),i(vt,[2,26]),i(vt,[2,27]),{11:59,32:72,37:24,38:_,39:A,40:27,41:I,42:B,43:N,44:R,45:z,46:W,47:et,48:st,49:at,50:bt},i(vt,[2,33]),i(vt,[2,19]),{25:73,27:U},{26:[2,28]},{26:[2,20]}],defaultActions:{8:[2,1],10:[2,3],21:[2,2],72:[2,28],73:[2,20]},parseError:function(Bt,Et){if(Et.recoverable)this.trace(Bt);else{var Z=new Error(Bt);throw Z.hash=Et,Z}},parse:function(Bt){var Et=this,Z=[0],Ct=[],xt=[null],Ht=[],Le=this.table,Ft="",gn=0,Se=0,me=2,Ve=1,Ye=Ht.slice.call(arguments,1),ce=Object.create(this.lexer),ke={yy:{}};for(var zt in this.yy)Object.prototype.hasOwnProperty.call(this.yy,zt)&&(ke.yy[zt]=this.yy[zt]);ce.setInput(Bt,ke.yy),ke.yy.lexer=ce,ke.yy.parser=this,typeof ce.yylloc>"u"&&(ce.yylloc={});var re=ce.yylloc;Ht.push(re);var se=ce.options&&ce.options.ranges;typeof ke.yy.parseError=="function"?this.parseError=ke.yy.parseError:this.parseError=Object.getPrototypeOf(this).parseError;function Pe(){var Xn;return Xn=Ct.pop()||ce.lex()||Ve,typeof Xn!="number"&&(Xn instanceof Array&&(Ct=Xn,Xn=Ct.pop()),Xn=Et.symbols_[Xn]||Xn),Xn}for(var te,Me,de,on,ni={},Ks,ws,fo,Xi;;){if(Me=Z[Z.length-1],this.defaultActions[Me]?de=this.defaultActions[Me]:((te===null||typeof te>"u")&&(te=Pe()),de=Le[Me]&&Le[Me][te]),typeof de>"u"||!de.length||!de[0]){var Er="";Xi=[];for(Ks in Le[Me])this.terminals_[Ks]&&Ks>me&&Xi.push("'"+this.terminals_[Ks]+"'");ce.showPosition?Er="Parse error on line "+(gn+1)+`: +`+ce.showPosition()+` +Expecting `+Xi.join(", ")+", got '"+(this.terminals_[te]||te)+"'":Er="Parse error on line "+(gn+1)+": Unexpected "+(te==Ve?"end of input":"'"+(this.terminals_[te]||te)+"'"),this.parseError(Er,{text:ce.match,token:this.terminals_[te]||te,line:ce.yylineno,loc:re,expected:Xi})}if(de[0]instanceof Array&&de.length>1)throw new Error("Parse Error: multiple actions possible at state: "+Me+", token: "+te);switch(de[0]){case 1:Z.push(te),xt.push(ce.yytext),Ht.push(ce.yylloc),Z.push(de[1]),te=null,Se=ce.yyleng,Ft=ce.yytext,gn=ce.yylineno,re=ce.yylloc;break;case 2:if(ws=this.productions_[de[1]][1],ni.$=xt[xt.length-ws],ni._$={first_line:Ht[Ht.length-(ws||1)].first_line,last_line:Ht[Ht.length-1].last_line,first_column:Ht[Ht.length-(ws||1)].first_column,last_column:Ht[Ht.length-1].last_column},se&&(ni._$.range=[Ht[Ht.length-(ws||1)].range[0],Ht[Ht.length-1].range[1]]),on=this.performAction.apply(ni,[Ft,Se,gn,ke.yy,de[1],xt,Ht].concat(Ye)),typeof on<"u")return on;ws&&(Z=Z.slice(0,-1*ws*2),xt=xt.slice(0,-1*ws),Ht=Ht.slice(0,-1*ws)),Z.push(this.productions_[de[1]][0]),xt.push(ni.$),Ht.push(ni._$),fo=Le[Z[Z.length-2]][Z[Z.length-1]],Z.push(fo);break;case 3:return!0}}return!0}},nt=function(){var Ot={EOF:1,parseError:function(Et,Z){if(this.yy.parser)this.yy.parser.parseError(Et,Z);else throw new Error(Et)},setInput:function(Bt,Et){return this.yy=Et||this.yy||{},this._input=Bt,this._more=this._backtrack=this.done=!1,this.yylineno=this.yyleng=0,this.yytext=this.matched=this.match="",this.conditionStack=["INITIAL"],this.yylloc={first_line:1,first_column:0,last_line:1,last_column:0},this.options.ranges&&(this.yylloc.range=[0,0]),this.offset=0,this},input:function(){var Bt=this._input[0];this.yytext+=Bt,this.yyleng++,this.offset++,this.match+=Bt,this.matched+=Bt;var Et=Bt.match(/(?:\r\n?|\n).*/g);return Et?(this.yylineno++,this.yylloc.last_line++):this.yylloc.last_column++,this.options.ranges&&this.yylloc.range[1]++,this._input=this._input.slice(1),Bt},unput:function(Bt){var Et=Bt.length,Z=Bt.split(/(?:\r\n?|\n)/g);this._input=Bt+this._input,this.yytext=this.yytext.substr(0,this.yytext.length-Et),this.offset-=Et;var Ct=this.match.split(/(?:\r\n?|\n)/g);this.match=this.match.substr(0,this.match.length-1),this.matched=this.matched.substr(0,this.matched.length-1),Z.length-1&&(this.yylineno-=Z.length-1);var xt=this.yylloc.range;return this.yylloc={first_line:this.yylloc.first_line,last_line:this.yylineno+1,first_column:this.yylloc.first_column,last_column:Z?(Z.length===Ct.length?this.yylloc.first_column:0)+Ct[Ct.length-Z.length].length-Z[0].length:this.yylloc.first_column-Et},this.options.ranges&&(this.yylloc.range=[xt[0],xt[0]+this.yyleng-Et]),this.yyleng=this.yytext.length,this},more:function(){return this._more=!0,this},reject:function(){if(this.options.backtrack_lexer)this._backtrack=!0;else return this.parseError("Lexical error on line "+(this.yylineno+1)+`. You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true). +`+this.showPosition(),{text:"",token:null,line:this.yylineno});return this},less:function(Bt){this.unput(this.match.slice(Bt))},pastInput:function(){var Bt=this.matched.substr(0,this.matched.length-this.match.length);return(Bt.length>20?"...":"")+Bt.substr(-20).replace(/\n/g,"")},upcomingInput:function(){var Bt=this.match;return Bt.length<20&&(Bt+=this._input.substr(0,20-Bt.length)),(Bt.substr(0,20)+(Bt.length>20?"...":"")).replace(/\n/g,"")},showPosition:function(){var Bt=this.pastInput(),Et=new Array(Bt.length+1).join("-");return Bt+this.upcomingInput()+` +`+Et+"^"},test_match:function(Bt,Et){var Z,Ct,xt;if(this.options.backtrack_lexer&&(xt={yylineno:this.yylineno,yylloc:{first_line:this.yylloc.first_line,last_line:this.last_line,first_column:this.yylloc.first_column,last_column:this.yylloc.last_column},yytext:this.yytext,match:this.match,matches:this.matches,matched:this.matched,yyleng:this.yyleng,offset:this.offset,_more:this._more,_input:this._input,yy:this.yy,conditionStack:this.conditionStack.slice(0),done:this.done},this.options.ranges&&(xt.yylloc.range=this.yylloc.range.slice(0))),Ct=Bt[0].match(/(?:\r\n?|\n).*/g),Ct&&(this.yylineno+=Ct.length),this.yylloc={first_line:this.yylloc.last_line,last_line:this.yylineno+1,first_column:this.yylloc.last_column,last_column:Ct?Ct[Ct.length-1].length-Ct[Ct.length-1].match(/\r?\n?/)[0].length:this.yylloc.last_column+Bt[0].length},this.yytext+=Bt[0],this.match+=Bt[0],this.matches=Bt,this.yyleng=this.yytext.length,this.options.ranges&&(this.yylloc.range=[this.offset,this.offset+=this.yyleng]),this._more=!1,this._backtrack=!1,this._input=this._input.slice(Bt[0].length),this.matched+=Bt[0],Z=this.performAction.call(this,this.yy,this,Et,this.conditionStack[this.conditionStack.length-1]),this.done&&this._input&&(this.done=!1),Z)return Z;if(this._backtrack){for(var Ht in xt)this[Ht]=xt[Ht];return!1}return!1},next:function(){if(this.done)return this.EOF;this._input||(this.done=!0);var Bt,Et,Z,Ct;this._more||(this.yytext="",this.match="");for(var xt=this._currentRules(),Ht=0;HtEt[0].length)){if(Et=Z,Ct=Ht,this.options.backtrack_lexer){if(Bt=this.test_match(Z,xt[Ht]),Bt!==!1)return Bt;if(this._backtrack){Et=!1;continue}else return!1}else if(!this.options.flex)break}return Et?(Bt=this.test_match(Et,xt[Ct]),Bt!==!1?Bt:!1):this._input===""?this.EOF:this.parseError("Lexical error on line "+(this.yylineno+1)+`. Unrecognized text. +`+this.showPosition(),{text:"",token:null,line:this.yylineno})},lex:function(){var Et=this.next();return Et||this.lex()},begin:function(Et){this.conditionStack.push(Et)},popState:function(){var Et=this.conditionStack.length-1;return Et>0?this.conditionStack.pop():this.conditionStack[0]},_currentRules:function(){return this.conditionStack.length&&this.conditionStack[this.conditionStack.length-1]?this.conditions[this.conditionStack[this.conditionStack.length-1]].rules:this.conditions.INITIAL.rules},topState:function(Et){return Et=this.conditionStack.length-1-Math.abs(Et||0),Et>=0?this.conditionStack[Et]:"INITIAL"},pushState:function(Et){this.begin(Et)},stateStackSize:function(){return this.conditionStack.length},options:{"case-insensitive":!0},performAction:function(Et,Z,Ct,xt){switch(Ct){case 0:break;case 1:break;case 2:return this.popState(),34;case 3:return this.popState(),34;case 4:return 34;case 5:break;case 6:return 10;case 7:return this.pushState("acc_title"),19;case 8:return this.popState(),"acc_title_value";case 9:return this.pushState("acc_descr"),21;case 10:return this.popState(),"acc_descr_value";case 11:this.pushState("acc_descr_multiline");break;case 12:this.popState();break;case 13:return"acc_descr_multiline_value";case 14:return 5;case 15:return 8;case 16:return this.pushState("axis_data"),"X_AXIS";case 17:return this.pushState("axis_data"),"Y_AXIS";case 18:return this.pushState("axis_band_data"),24;case 19:return 31;case 20:return this.pushState("data"),16;case 21:return this.pushState("data"),18;case 22:return this.pushState("data_inner"),24;case 23:return 27;case 24:return this.popState(),26;case 25:this.popState();break;case 26:this.pushState("string");break;case 27:this.popState();break;case 28:return"STR";case 29:return 24;case 30:return 26;case 31:return 43;case 32:return"COLON";case 33:return 44;case 34:return 28;case 35:return 45;case 36:return 46;case 37:return 48;case 38:return 50;case 39:return 47;case 40:return 41;case 41:return 49;case 42:return 42;case 43:break;case 44:return 35;case 45:return 36}},rules:[/^(?:%%(?!\{)[^\n]*)/i,/^(?:[^\}]%%[^\n]*)/i,/^(?:(\r?\n))/i,/^(?:(\r?\n))/i,/^(?:[\n\r]+)/i,/^(?:%%[^\n]*)/i,/^(?:title\b)/i,/^(?:accTitle\s*:\s*)/i,/^(?:(?!\n||)*[^\n]*)/i,/^(?:accDescr\s*:\s*)/i,/^(?:(?!\n||)*[^\n]*)/i,/^(?:accDescr\s*\{\s*)/i,/^(?:\{)/i,/^(?:[^\}]*)/i,/^(?:xychart-beta\b)/i,/^(?:(?:vertical|horizontal))/i,/^(?:x-axis\b)/i,/^(?:y-axis\b)/i,/^(?:\[)/i,/^(?:-->)/i,/^(?:line\b)/i,/^(?:bar\b)/i,/^(?:\[)/i,/^(?:[+-]?(?:\d+(?:\.\d+)?|\.\d+))/i,/^(?:\])/i,/^(?:(?:`\) \{ this\.pushState\(md_string\); \}\n\(\?:\(\?!`"\)\.\)\+ \{ return MD_STR; \}\n\(\?:`))/i,/^(?:["])/i,/^(?:["])/i,/^(?:[^"]*)/i,/^(?:\[)/i,/^(?:\])/i,/^(?:[A-Za-z]+)/i,/^(?::)/i,/^(?:\+)/i,/^(?:,)/i,/^(?:=)/i,/^(?:\*)/i,/^(?:#)/i,/^(?:[\_])/i,/^(?:\.)/i,/^(?:&)/i,/^(?:-)/i,/^(?:[0-9]+)/i,/^(?:\s+)/i,/^(?:;)/i,/^(?:$)/i],conditions:{data_inner:{rules:[0,1,4,5,6,7,9,11,14,15,16,17,20,21,23,24,25,26,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45],inclusive:!0},data:{rules:[0,1,3,4,5,6,7,9,11,14,15,16,17,20,21,22,25,26,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45],inclusive:!0},axis_band_data:{rules:[0,1,4,5,6,7,9,11,14,15,16,17,20,21,24,25,26,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45],inclusive:!0},axis_data:{rules:[0,1,2,4,5,6,7,9,11,14,15,16,17,18,19,20,21,23,25,26,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45],inclusive:!0},acc_descr_multiline:{rules:[12,13],inclusive:!1},acc_descr:{rules:[10],inclusive:!1},acc_title:{rules:[8],inclusive:!1},title:{rules:[],inclusive:!1},md_string:{rules:[],inclusive:!1},string:{rules:[27,28],inclusive:!1},INITIAL:{rules:[0,1,4,5,6,7,9,11,14,15,16,17,20,21,25,26,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45],inclusive:!0}}};return Ot}();Tt.lexer=nt;function It(){this.yy={}}return It.prototype=Tt,Tt.Parser=It,new It}();ogt.parser=ogt;const yHe=ogt;function oRt(i){return i.type==="bar"}function cRt(i){return i.type==="band"}function BF(i){return i.type==="linear"}class uRt{constructor(a){this.parentGroup=a}getMaxDimension(a,f){if(!this.parentGroup)return{width:a.reduce((m,b)=>Math.max(b.length,m),0)*f,height:f};const p={width:0,height:0},w=this.parentGroup.append("g").attr("visibility","hidden").attr("font-size",f);for(const m of a){const b=k$e(w,1,m),E=b?b.width:m.length*f,_=b?b.height:f;p.width=Math.max(p.width,E),p.height=Math.max(p.height,_)}return w.remove(),p}}const lRt=.7,hRt=.2;class fRt{constructor(a,f,p,w){this.axisConfig=a,this.title=f,this.textDimensionCalculator=p,this.axisThemeConfig=w,this.boundingRect={x:0,y:0,width:0,height:0},this.axisPosition="left",this.showTitle=!1,this.showLabel=!1,this.showTick=!1,this.showAxisLine=!1,this.outerPadding=0,this.titleTextHeight=0,this.labelTextHeight=0,this.range=[0,10],this.boundingRect={x:0,y:0,width:0,height:0},this.axisPosition="left"}setRange(a){this.range=a,this.axisPosition==="left"||this.axisPosition==="right"?this.boundingRect.height=a[1]-a[0]:this.boundingRect.width=a[1]-a[0],this.recalculateScale()}getRange(){return[this.range[0]+this.outerPadding,this.range[1]-this.outerPadding]}setAxisPosition(a){this.axisPosition=a,this.setRange(this.range)}getTickDistance(){const a=this.getRange();return Math.abs(a[0]-a[1])/this.getTickValues().length}getAxisOuterPadding(){return this.outerPadding}getLabelDimension(){return this.textDimensionCalculator.getMaxDimension(this.getTickValues().map(a=>a.toString()),this.axisConfig.labelFontSize)}recalculateOuterPaddingToDrawBar(){lRt*this.getTickDistance()>this.outerPadding*2&&(this.outerPadding=Math.floor(lRt*this.getTickDistance()/2)),this.recalculateScale()}calculateSpaceIfDrawnHorizontally(a){let f=a.height;if(this.axisConfig.showAxisLine&&f>this.axisConfig.axisLineWidth&&(f-=this.axisConfig.axisLineWidth,this.showAxisLine=!0),this.axisConfig.showLabel){const p=this.getLabelDimension(),w=hRt*a.width;this.outerPadding=Math.min(p.width/2,w);const m=p.height+this.axisConfig.labelPadding*2;this.labelTextHeight=p.height,m<=f&&(f-=m,this.showLabel=!0)}if(this.axisConfig.showTick&&f>=this.axisConfig.tickLength&&(this.showTick=!0,f-=this.axisConfig.tickLength),this.axisConfig.showTitle&&this.title){const p=this.textDimensionCalculator.getMaxDimension([this.title],this.axisConfig.titleFontSize),w=p.height+this.axisConfig.titlePadding*2;this.titleTextHeight=p.height,w<=f&&(f-=w,this.showTitle=!0)}this.boundingRect.width=a.width,this.boundingRect.height=a.height-f}calculateSpaceIfDrawnVertical(a){let f=a.width;if(this.axisConfig.showAxisLine&&f>this.axisConfig.axisLineWidth&&(f-=this.axisConfig.axisLineWidth,this.showAxisLine=!0),this.axisConfig.showLabel){const p=this.getLabelDimension(),w=hRt*a.height;this.outerPadding=Math.min(p.height/2,w);const m=p.width+this.axisConfig.labelPadding*2;m<=f&&(f-=m,this.showLabel=!0)}if(this.axisConfig.showTick&&f>=this.axisConfig.tickLength&&(this.showTick=!0,f-=this.axisConfig.tickLength),this.axisConfig.showTitle&&this.title){const p=this.textDimensionCalculator.getMaxDimension([this.title],this.axisConfig.titleFontSize),w=p.height+this.axisConfig.titlePadding*2;this.titleTextHeight=p.height,w<=f&&(f-=w,this.showTitle=!0)}this.boundingRect.width=a.width-f,this.boundingRect.height=a.height}calculateSpace(a){return this.axisPosition==="left"||this.axisPosition==="right"?this.calculateSpaceIfDrawnVertical(a):this.calculateSpaceIfDrawnHorizontally(a),this.recalculateScale(),{width:this.boundingRect.width,height:this.boundingRect.height}}setBoundingBoxXY(a){this.boundingRect.x=a.x,this.boundingRect.y=a.y}getDrawableElementsForLeftAxis(){const a=[];if(this.showAxisLine){const f=this.boundingRect.x+this.boundingRect.width-this.axisConfig.axisLineWidth/2;a.push({type:"path",groupTexts:["left-axis","axisl-line"],data:[{path:`M ${f},${this.boundingRect.y} L ${f},${this.boundingRect.y+this.boundingRect.height} `,strokeFill:this.axisThemeConfig.axisLineColor,strokeWidth:this.axisConfig.axisLineWidth}]})}if(this.showLabel&&a.push({type:"text",groupTexts:["left-axis","label"],data:this.getTickValues().map(f=>({text:f.toString(),x:this.boundingRect.x+this.boundingRect.width-(this.showLabel?this.axisConfig.labelPadding:0)-(this.showTick?this.axisConfig.tickLength:0)-(this.showAxisLine?this.axisConfig.axisLineWidth:0),y:this.getScaleValue(f),fill:this.axisThemeConfig.labelColor,fontSize:this.axisConfig.labelFontSize,rotation:0,verticalPos:"middle",horizontalPos:"right"}))}),this.showTick){const f=this.boundingRect.x+this.boundingRect.width-(this.showAxisLine?this.axisConfig.axisLineWidth:0);a.push({type:"path",groupTexts:["left-axis","ticks"],data:this.getTickValues().map(p=>({path:`M ${f},${this.getScaleValue(p)} L ${f-this.axisConfig.tickLength},${this.getScaleValue(p)}`,strokeFill:this.axisThemeConfig.tickColor,strokeWidth:this.axisConfig.tickWidth}))})}return this.showTitle&&a.push({type:"text",groupTexts:["left-axis","title"],data:[{text:this.title,x:this.boundingRect.x+this.axisConfig.titlePadding,y:this.boundingRect.y+this.boundingRect.height/2,fill:this.axisThemeConfig.titleColor,fontSize:this.axisConfig.titleFontSize,rotation:270,verticalPos:"top",horizontalPos:"center"}]}),a}getDrawableElementsForBottomAxis(){const a=[];if(this.showAxisLine){const f=this.boundingRect.y+this.axisConfig.axisLineWidth/2;a.push({type:"path",groupTexts:["bottom-axis","axis-line"],data:[{path:`M ${this.boundingRect.x},${f} L ${this.boundingRect.x+this.boundingRect.width},${f}`,strokeFill:this.axisThemeConfig.axisLineColor,strokeWidth:this.axisConfig.axisLineWidth}]})}if(this.showLabel&&a.push({type:"text",groupTexts:["bottom-axis","label"],data:this.getTickValues().map(f=>({text:f.toString(),x:this.getScaleValue(f),y:this.boundingRect.y+this.axisConfig.labelPadding+(this.showTick?this.axisConfig.tickLength:0)+(this.showAxisLine?this.axisConfig.axisLineWidth:0),fill:this.axisThemeConfig.labelColor,fontSize:this.axisConfig.labelFontSize,rotation:0,verticalPos:"top",horizontalPos:"center"}))}),this.showTick){const f=this.boundingRect.y+(this.showAxisLine?this.axisConfig.axisLineWidth:0);a.push({type:"path",groupTexts:["bottom-axis","ticks"],data:this.getTickValues().map(p=>({path:`M ${this.getScaleValue(p)},${f} L ${this.getScaleValue(p)},${f+this.axisConfig.tickLength}`,strokeFill:this.axisThemeConfig.tickColor,strokeWidth:this.axisConfig.tickWidth}))})}return this.showTitle&&a.push({type:"text",groupTexts:["bottom-axis","title"],data:[{text:this.title,x:this.range[0]+(this.range[1]-this.range[0])/2,y:this.boundingRect.y+this.boundingRect.height-this.axisConfig.titlePadding-this.titleTextHeight,fill:this.axisThemeConfig.titleColor,fontSize:this.axisConfig.titleFontSize,rotation:0,verticalPos:"top",horizontalPos:"center"}]}),a}getDrawableElementsForTopAxis(){const a=[];if(this.showAxisLine){const f=this.boundingRect.y+this.boundingRect.height-this.axisConfig.axisLineWidth/2;a.push({type:"path",groupTexts:["top-axis","axis-line"],data:[{path:`M ${this.boundingRect.x},${f} L ${this.boundingRect.x+this.boundingRect.width},${f}`,strokeFill:this.axisThemeConfig.axisLineColor,strokeWidth:this.axisConfig.axisLineWidth}]})}if(this.showLabel&&a.push({type:"text",groupTexts:["top-axis","label"],data:this.getTickValues().map(f=>({text:f.toString(),x:this.getScaleValue(f),y:this.boundingRect.y+(this.showTitle?this.titleTextHeight+this.axisConfig.titlePadding*2:0)+this.axisConfig.labelPadding,fill:this.axisThemeConfig.labelColor,fontSize:this.axisConfig.labelFontSize,rotation:0,verticalPos:"top",horizontalPos:"center"}))}),this.showTick){const f=this.boundingRect.y;a.push({type:"path",groupTexts:["top-axis","ticks"],data:this.getTickValues().map(p=>({path:`M ${this.getScaleValue(p)},${f+this.boundingRect.height-(this.showAxisLine?this.axisConfig.axisLineWidth:0)} L ${this.getScaleValue(p)},${f+this.boundingRect.height-this.axisConfig.tickLength-(this.showAxisLine?this.axisConfig.axisLineWidth:0)}`,strokeFill:this.axisThemeConfig.tickColor,strokeWidth:this.axisConfig.tickWidth}))})}return this.showTitle&&a.push({type:"text",groupTexts:["top-axis","title"],data:[{text:this.title,x:this.boundingRect.x+this.boundingRect.width/2,y:this.boundingRect.y+this.axisConfig.titlePadding,fill:this.axisThemeConfig.titleColor,fontSize:this.axisConfig.titleFontSize,rotation:0,verticalPos:"top",horizontalPos:"center"}]}),a}getDrawableElements(){if(this.axisPosition==="left")return this.getDrawableElementsForLeftAxis();if(this.axisPosition==="right")throw Error("Drawing of right axis is not implemented");return this.axisPosition==="bottom"?this.getDrawableElementsForBottomAxis():this.axisPosition==="top"?this.getDrawableElementsForTopAxis():[]}}class xHe extends fRt{constructor(a,f,p,w,m){super(a,w,m,f),this.categories=p,this.scale=S1t().domain(this.categories).range(this.getRange())}setRange(a){super.setRange(a)}recalculateScale(){this.scale=S1t().domain(this.categories).range(this.getRange()).paddingInner(1).paddingOuter(0).align(.5),Ut.trace("BandAxis axis final categories, range: ",this.categories,this.getRange())}getTickValues(){return this.categories}getScaleValue(a){return this.scale(a)||this.getRange()[0]}}class kHe extends fRt{constructor(a,f,p,w,m){super(a,w,m,f),this.domain=p,this.scale=AA().domain(this.domain).range(this.getRange())}getTickValues(){return this.scale.ticks()}recalculateScale(){const a=[...this.domain];this.axisPosition==="left"&&a.reverse(),this.scale=AA().domain(a).range(this.getRange())}getScaleValue(a){return this.scale(a)}}function dRt(i,a,f,p){const w=new uRt(p);return cRt(i)?new xHe(a,f,i.categories,i.title,w):new kHe(a,f,[i.min,i.max],i.title,w)}class EHe{constructor(a,f,p,w){this.textDimensionCalculator=a,this.chartConfig=f,this.chartData=p,this.chartThemeConfig=w,this.boundingRect={x:0,y:0,width:0,height:0},this.showChartTitle=!1}setBoundingBoxXY(a){this.boundingRect.x=a.x,this.boundingRect.y=a.y}calculateSpace(a){const f=this.textDimensionCalculator.getMaxDimension([this.chartData.title],this.chartConfig.titleFontSize),p=Math.max(f.width,a.width),w=f.height+2*this.chartConfig.titlePadding;return f.width<=p&&f.height<=w&&this.chartConfig.showTitle&&this.chartData.title&&(this.boundingRect.width=p,this.boundingRect.height=w,this.showChartTitle=!0),{width:this.boundingRect.width,height:this.boundingRect.height}}getDrawableElements(){const a=[];return this.showChartTitle&&a.push({groupTexts:["chart-title"],type:"text",data:[{fontSize:this.chartConfig.titleFontSize,text:this.chartData.title,verticalPos:"middle",horizontalPos:"center",x:this.boundingRect.x+this.boundingRect.width/2,y:this.boundingRect.y+this.boundingRect.height/2,fill:this.chartThemeConfig.titleColor,rotation:0}]}),a}}function THe(i,a,f,p){const w=new uRt(p);return new EHe(w,i,a,f)}class CHe{constructor(a,f,p,w,m){this.plotData=a,this.xAxis=f,this.yAxis=p,this.orientation=w,this.plotIndex=m}getDrawableElement(){const a=this.plotData.data.map(p=>[this.xAxis.getScaleValue(p[0]),this.yAxis.getScaleValue(p[1])]);let f;return this.orientation==="horizontal"?f=E5().y(p=>p[0]).x(p=>p[1])(a):f=E5().x(p=>p[0]).y(p=>p[1])(a),f?[{groupTexts:["plot",`line-plot-${this.plotIndex}`],type:"path",data:[{path:f,strokeFill:this.plotData.strokeFill,strokeWidth:this.plotData.strokeWidth}]}]:[]}}class _He{constructor(a,f,p,w,m,b){this.barData=a,this.boundingRect=f,this.xAxis=p,this.yAxis=w,this.orientation=m,this.plotIndex=b}getDrawableElement(){const a=this.barData.data.map(m=>[this.xAxis.getScaleValue(m[0]),this.yAxis.getScaleValue(m[1])]),f=.05,p=Math.min(this.xAxis.getAxisOuterPadding()*2,this.xAxis.getTickDistance())*(1-f),w=p/2;return this.orientation==="horizontal"?[{groupTexts:["plot",`bar-plot-${this.plotIndex}`],type:"rect",data:a.map(m=>({x:this.boundingRect.x,y:m[0]-w,height:p,width:m[1]-this.boundingRect.x,fill:this.barData.fill,strokeWidth:0,strokeFill:this.barData.fill}))}]:[{groupTexts:["plot",`bar-plot-${this.plotIndex}`],type:"rect",data:a.map(m=>({x:m[0]-w,y:m[1],width:p,height:this.boundingRect.y+this.boundingRect.height-m[1],fill:this.barData.fill,strokeWidth:0,strokeFill:this.barData.fill}))}]}}class SHe{constructor(a,f,p){this.chartConfig=a,this.chartData=f,this.chartThemeConfig=p,this.boundingRect={x:0,y:0,width:0,height:0}}setAxes(a,f){this.xAxis=a,this.yAxis=f}setBoundingBoxXY(a){this.boundingRect.x=a.x,this.boundingRect.y=a.y}calculateSpace(a){return this.boundingRect.width=a.width,this.boundingRect.height=a.height,{width:this.boundingRect.width,height:this.boundingRect.height}}getDrawableElements(){if(!(this.xAxis&&this.yAxis))throw Error("Axes must be passed to render Plots");const a=[];for(const[f,p]of this.chartData.plots.entries())switch(p.type){case"line":{const w=new CHe(p,this.xAxis,this.yAxis,this.chartConfig.chartOrientation,f);a.push(...w.getDrawableElement())}break;case"bar":{const w=new _He(p,this.boundingRect,this.xAxis,this.yAxis,this.chartConfig.chartOrientation,f);a.push(...w.getDrawableElement())}break}return a}}function AHe(i,a,f){return new SHe(i,a,f)}class LHe{constructor(a,f,p,w){this.chartConfig=a,this.chartData=f,this.componentStore={title:THe(a,f,p,w),plot:AHe(a,f,p),xAxis:dRt(f.xAxis,a.xAxis,{titleColor:p.xAxisTitleColor,labelColor:p.xAxisLabelColor,tickColor:p.xAxisTickColor,axisLineColor:p.xAxisLineColor},w),yAxis:dRt(f.yAxis,a.yAxis,{titleColor:p.yAxisTitleColor,labelColor:p.yAxisLabelColor,tickColor:p.yAxisTickColor,axisLineColor:p.yAxisLineColor},w)}}calculateVerticalSpace(){let a=this.chartConfig.width,f=this.chartConfig.height,p=0,w=0,m=Math.floor(a*this.chartConfig.plotReservedSpacePercent/100),b=Math.floor(f*this.chartConfig.plotReservedSpacePercent/100),E=this.componentStore.plot.calculateSpace({width:m,height:b});a-=E.width,f-=E.height,E=this.componentStore.title.calculateSpace({width:this.chartConfig.width,height:f}),w=E.height,f-=E.height,this.componentStore.xAxis.setAxisPosition("bottom"),E=this.componentStore.xAxis.calculateSpace({width:a,height:f}),f-=E.height,this.componentStore.yAxis.setAxisPosition("left"),E=this.componentStore.yAxis.calculateSpace({width:a,height:f}),p=E.width,a-=E.width,a>0&&(m+=a,a=0),f>0&&(b+=f,f=0),this.componentStore.plot.calculateSpace({width:m,height:b}),this.componentStore.plot.setBoundingBoxXY({x:p,y:w}),this.componentStore.xAxis.setRange([p,p+m]),this.componentStore.xAxis.setBoundingBoxXY({x:p,y:w+b}),this.componentStore.yAxis.setRange([w,w+b]),this.componentStore.yAxis.setBoundingBoxXY({x:0,y:w}),this.chartData.plots.some(_=>oRt(_))&&this.componentStore.xAxis.recalculateOuterPaddingToDrawBar()}calculateHorizonatalSpace(){let a=this.chartConfig.width,f=this.chartConfig.height,p=0,w=0,m=0,b=Math.floor(a*this.chartConfig.plotReservedSpacePercent/100),E=Math.floor(f*this.chartConfig.plotReservedSpacePercent/100),_=this.componentStore.plot.calculateSpace({width:b,height:E});a-=_.width,f-=_.height,_=this.componentStore.title.calculateSpace({width:this.chartConfig.width,height:f}),p=_.height,f-=_.height,this.componentStore.xAxis.setAxisPosition("left"),_=this.componentStore.xAxis.calculateSpace({width:a,height:f}),a-=_.width,w=_.width,this.componentStore.yAxis.setAxisPosition("top"),_=this.componentStore.yAxis.calculateSpace({width:a,height:f}),f-=_.height,m=p+_.height,a>0&&(b+=a,a=0),f>0&&(E+=f,f=0),this.componentStore.plot.calculateSpace({width:b,height:E}),this.componentStore.plot.setBoundingBoxXY({x:w,y:m}),this.componentStore.yAxis.setRange([w,w+b]),this.componentStore.yAxis.setBoundingBoxXY({x:w,y:p}),this.componentStore.xAxis.setRange([m,m+E]),this.componentStore.xAxis.setBoundingBoxXY({x:0,y:m}),this.chartData.plots.some(A=>oRt(A))&&this.componentStore.xAxis.recalculateOuterPaddingToDrawBar()}calculateSpace(){this.chartConfig.chartOrientation==="horizontal"?this.calculateHorizonatalSpace():this.calculateVerticalSpace()}getDrawableElement(){this.calculateSpace();const a=[];this.componentStore.plot.setAxes(this.componentStore.xAxis,this.componentStore.yAxis);for(const f of Object.values(this.componentStore))a.push(...f.getDrawableElements());return a}}class MHe{static build(a,f,p,w){return new LHe(a,f,p,w).getDrawableElement()}}let RF=0,gRt,jF=bRt(),$F=pRt(),fu=wRt(),cgt=$F.plotColorPalette.split(",").map(i=>i.trim()),BY=!1,ugt=!1;function pRt(){const i=X1t(),a=Fd();return rF(i.xyChart,a.themeVariables.xyChart)}function bRt(){const i=Fd();return rF(Zh.xyChart,i.xyChart)}function wRt(){return{yAxis:{type:"linear",title:"",min:1/0,max:-1/0},xAxis:{type:"band",title:"",categories:[]},title:"",plots:[]}}function lgt(i){const a=Fd();return Q1(i.trim(),a)}function DHe(i){gRt=i}function IHe(i){i==="horizontal"?jF.chartOrientation="horizontal":jF.chartOrientation="vertical"}function OHe(i){fu.xAxis.title=lgt(i.text)}function vRt(i,a){fu.xAxis={type:"linear",title:fu.xAxis.title,min:i,max:a},BY=!0}function PHe(i){fu.xAxis={type:"band",title:fu.xAxis.title,categories:i.map(a=>lgt(a.text))},BY=!0}function FHe(i){fu.yAxis.title=lgt(i.text)}function NHe(i,a){fu.yAxis={type:"linear",title:fu.yAxis.title,min:i,max:a},ugt=!0}function BHe(i){const a=Math.min(...i),f=Math.max(...i),p=BF(fu.yAxis)?fu.yAxis.min:1/0,w=BF(fu.yAxis)?fu.yAxis.max:-1/0;fu.yAxis={type:"linear",title:fu.yAxis.title,min:Math.min(p,a),max:Math.max(w,f)}}function mRt(i){let a=[];if(i.length===0)return a;if(!BY){const f=BF(fu.xAxis)?fu.xAxis.min:1/0,p=BF(fu.xAxis)?fu.xAxis.max:-1/0;vRt(Math.min(f,1),Math.max(p,i.length))}if(ugt||BHe(i),cRt(fu.xAxis)&&(a=fu.xAxis.categories.map((f,p)=>[f,i[p]])),BF(fu.xAxis)){const f=fu.xAxis.min,p=fu.xAxis.max,w=(p-f+1)/i.length,m=[];for(let b=f;b<=p;b+=w)m.push(`${b}`);a=m.map((b,E)=>[b,i[E]])}return a}function yRt(i){return cgt[i===0?0:i%cgt.length]}function RHe(i,a){const f=mRt(a);fu.plots.push({type:"line",strokeFill:yRt(RF),strokeWidth:2,data:f}),RF++}function jHe(i,a){const f=mRt(a);fu.plots.push({type:"bar",fill:yRt(RF),data:f}),RF++}function $He(){if(fu.plots.length===0)throw Error("No Plot to render, please provide a plot with some data");return fu.title=pg(),MHe.build(jF,fu,$F,gRt)}function zHe(){return $F}function qHe(){return jF}const HHe=Object.freeze(Object.defineProperty({__proto__:null,diagram:{parser:yHe,db:{getDrawableElem:$He,clear:function(){hg(),RF=0,jF=bRt(),fu=wRt(),$F=pRt(),cgt=$F.plotColorPalette.split(",").map(i=>i.trim()),BY=!1,ugt=!1},setAccTitle:E0,getAccTitle:fg,setDiagramTitle:Nb,getDiagramTitle:pg,getAccDescription:gg,setAccDescription:dg,setOrientation:IHe,setXAxisTitle:OHe,setXAxisRangeData:vRt,setXAxisBand:PHe,setYAxisTitle:FHe,setYAxisRangeData:NHe,setLineData:RHe,setBarData:jHe,setTmpSVGG:DHe,getChartThemeConfig:zHe,getChartConfig:qHe},renderer:{draw:(i,a,f,p)=>{const w=p.db,m=w.getChartThemeConfig(),b=w.getChartConfig();function E(et){return et==="top"?"text-before-edge":"middle"}function _(et){return et==="left"?"start":et==="right"?"end":"middle"}function A(et){return`translate(${et.x}, ${et.y}) rotate(${et.rotation||0})`}Ut.debug(`Rendering xychart chart +`+i);const I=VW(a),B=I.append("g").attr("class","main"),N=B.append("rect").attr("width",b.width).attr("height",b.height).attr("class","background");k0(I,b.height,b.width,!0),I.attr("viewBox",`0 0 ${b.width} ${b.height}`),N.attr("fill",m.backgroundColor),w.setTmpSVGG(I.append("g").attr("class","mermaid-tmp-group"));const R=w.getDrawableElem(),z={};function W(et){let st=B,at="";for(const[bt]of et.entries()){let mt=B;bt>0&&z[at]&&(mt=z[at]),at+=et[bt],st=z[at],st||(st=z[at]=mt.append("g").attr("class",et[bt]))}return st}for(const et of R){if(et.data.length===0)continue;const st=W(et.groupTexts);switch(et.type){case"rect":st.selectAll("rect").data(et.data).enter().append("rect").attr("x",at=>at.x).attr("y",at=>at.y).attr("width",at=>at.width).attr("height",at=>at.height).attr("fill",at=>at.fill).attr("stroke",at=>at.strokeFill).attr("stroke-width",at=>at.strokeWidth);break;case"text":st.selectAll("text").data(et.data).enter().append("text").attr("x",0).attr("y",0).attr("fill",at=>at.fill).attr("font-size",at=>at.fontSize).attr("dominant-baseline",at=>E(at.verticalPos)).attr("text-anchor",at=>_(at.horizontalPos)).attr("transform",at=>A(at)).text(at=>at.text);break;case"path":st.selectAll("path").data(et.data).enter().append("path").attr("d",at=>at.path).attr("fill",at=>at.fill?at.fill:"none").attr("stroke",at=>at.strokeFill).attr("stroke-width",at=>at.strokeWidth);break}}}}}},Symbol.toStringTag,{value:"Module"}));var hgt=function(){var i=function(Se,me,Ve,Ye){for(Ve=Ve||{},Ye=Se.length;Ye--;Ve[Se[Ye]]=me);return Ve},a=[1,3],f=[1,4],p=[1,5],w=[1,6],m=[5,6,8,9,11,13,31,32,33,34,35,36,44,62,63],b=[1,18],E=[2,7],_=[1,22],A=[1,23],I=[1,24],B=[1,25],N=[1,26],R=[1,27],z=[1,20],W=[1,28],et=[1,29],st=[62,63],at=[5,8,9,11,13,31,32,33,34,35,36,44,51,53,62,63],bt=[1,47],mt=[1,48],yt=[1,49],ft=[1,50],ut=[1,51],vt=[1,52],X=[1,53],pt=[53,54],U=[1,64],Tt=[1,60],nt=[1,61],It=[1,62],Ot=[1,63],Bt=[1,65],Et=[1,69],Z=[1,70],Ct=[1,67],xt=[1,68],Ht=[5,8,9,11,13,31,32,33,34,35,36,44,62,63],Le={trace:function(){},yy:{},symbols_:{error:2,start:3,directive:4,NEWLINE:5,RD:6,diagram:7,EOF:8,acc_title:9,acc_title_value:10,acc_descr:11,acc_descr_value:12,acc_descr_multiline_value:13,requirementDef:14,elementDef:15,relationshipDef:16,requirementType:17,requirementName:18,STRUCT_START:19,requirementBody:20,ID:21,COLONSEP:22,id:23,TEXT:24,text:25,RISK:26,riskLevel:27,VERIFYMTHD:28,verifyType:29,STRUCT_STOP:30,REQUIREMENT:31,FUNCTIONAL_REQUIREMENT:32,INTERFACE_REQUIREMENT:33,PERFORMANCE_REQUIREMENT:34,PHYSICAL_REQUIREMENT:35,DESIGN_CONSTRAINT:36,LOW_RISK:37,MED_RISK:38,HIGH_RISK:39,VERIFY_ANALYSIS:40,VERIFY_DEMONSTRATION:41,VERIFY_INSPECTION:42,VERIFY_TEST:43,ELEMENT:44,elementName:45,elementBody:46,TYPE:47,type:48,DOCREF:49,ref:50,END_ARROW_L:51,relationship:52,LINE:53,END_ARROW_R:54,CONTAINS:55,COPIES:56,DERIVES:57,SATISFIES:58,VERIFIES:59,REFINES:60,TRACES:61,unqString:62,qString:63,$accept:0,$end:1},terminals_:{2:"error",5:"NEWLINE",6:"RD",8:"EOF",9:"acc_title",10:"acc_title_value",11:"acc_descr",12:"acc_descr_value",13:"acc_descr_multiline_value",19:"STRUCT_START",21:"ID",22:"COLONSEP",24:"TEXT",26:"RISK",28:"VERIFYMTHD",30:"STRUCT_STOP",31:"REQUIREMENT",32:"FUNCTIONAL_REQUIREMENT",33:"INTERFACE_REQUIREMENT",34:"PERFORMANCE_REQUIREMENT",35:"PHYSICAL_REQUIREMENT",36:"DESIGN_CONSTRAINT",37:"LOW_RISK",38:"MED_RISK",39:"HIGH_RISK",40:"VERIFY_ANALYSIS",41:"VERIFY_DEMONSTRATION",42:"VERIFY_INSPECTION",43:"VERIFY_TEST",44:"ELEMENT",47:"TYPE",49:"DOCREF",51:"END_ARROW_L",53:"LINE",54:"END_ARROW_R",55:"CONTAINS",56:"COPIES",57:"DERIVES",58:"SATISFIES",59:"VERIFIES",60:"REFINES",61:"TRACES",62:"unqString",63:"qString"},productions_:[0,[3,3],[3,2],[3,4],[4,2],[4,2],[4,1],[7,0],[7,2],[7,2],[7,2],[7,2],[7,2],[14,5],[20,5],[20,5],[20,5],[20,5],[20,2],[20,1],[17,1],[17,1],[17,1],[17,1],[17,1],[17,1],[27,1],[27,1],[27,1],[29,1],[29,1],[29,1],[29,1],[15,5],[46,5],[46,5],[46,2],[46,1],[16,5],[16,5],[52,1],[52,1],[52,1],[52,1],[52,1],[52,1],[52,1],[18,1],[18,1],[23,1],[23,1],[25,1],[25,1],[45,1],[45,1],[48,1],[48,1],[50,1],[50,1]],performAction:function(me,Ve,Ye,ce,ke,zt,re){var se=zt.length-1;switch(ke){case 4:this.$=zt[se].trim(),ce.setAccTitle(this.$);break;case 5:case 6:this.$=zt[se].trim(),ce.setAccDescription(this.$);break;case 7:this.$=[];break;case 13:ce.addRequirement(zt[se-3],zt[se-4]);break;case 14:ce.setNewReqId(zt[se-2]);break;case 15:ce.setNewReqText(zt[se-2]);break;case 16:ce.setNewReqRisk(zt[se-2]);break;case 17:ce.setNewReqVerifyMethod(zt[se-2]);break;case 20:this.$=ce.RequirementType.REQUIREMENT;break;case 21:this.$=ce.RequirementType.FUNCTIONAL_REQUIREMENT;break;case 22:this.$=ce.RequirementType.INTERFACE_REQUIREMENT;break;case 23:this.$=ce.RequirementType.PERFORMANCE_REQUIREMENT;break;case 24:this.$=ce.RequirementType.PHYSICAL_REQUIREMENT;break;case 25:this.$=ce.RequirementType.DESIGN_CONSTRAINT;break;case 26:this.$=ce.RiskLevel.LOW_RISK;break;case 27:this.$=ce.RiskLevel.MED_RISK;break;case 28:this.$=ce.RiskLevel.HIGH_RISK;break;case 29:this.$=ce.VerifyType.VERIFY_ANALYSIS;break;case 30:this.$=ce.VerifyType.VERIFY_DEMONSTRATION;break;case 31:this.$=ce.VerifyType.VERIFY_INSPECTION;break;case 32:this.$=ce.VerifyType.VERIFY_TEST;break;case 33:ce.addElement(zt[se-3]);break;case 34:ce.setNewElementType(zt[se-2]);break;case 35:ce.setNewElementDocRef(zt[se-2]);break;case 38:ce.addRelationship(zt[se-2],zt[se],zt[se-4]);break;case 39:ce.addRelationship(zt[se-2],zt[se-4],zt[se]);break;case 40:this.$=ce.Relationships.CONTAINS;break;case 41:this.$=ce.Relationships.COPIES;break;case 42:this.$=ce.Relationships.DERIVES;break;case 43:this.$=ce.Relationships.SATISFIES;break;case 44:this.$=ce.Relationships.VERIFIES;break;case 45:this.$=ce.Relationships.REFINES;break;case 46:this.$=ce.Relationships.TRACES;break}},table:[{3:1,4:2,6:a,9:f,11:p,13:w},{1:[3]},{3:8,4:2,5:[1,7],6:a,9:f,11:p,13:w},{5:[1,9]},{10:[1,10]},{12:[1,11]},i(m,[2,6]),{3:12,4:2,6:a,9:f,11:p,13:w},{1:[2,2]},{4:17,5:b,7:13,8:E,9:f,11:p,13:w,14:14,15:15,16:16,17:19,23:21,31:_,32:A,33:I,34:B,35:N,36:R,44:z,62:W,63:et},i(m,[2,4]),i(m,[2,5]),{1:[2,1]},{8:[1,30]},{4:17,5:b,7:31,8:E,9:f,11:p,13:w,14:14,15:15,16:16,17:19,23:21,31:_,32:A,33:I,34:B,35:N,36:R,44:z,62:W,63:et},{4:17,5:b,7:32,8:E,9:f,11:p,13:w,14:14,15:15,16:16,17:19,23:21,31:_,32:A,33:I,34:B,35:N,36:R,44:z,62:W,63:et},{4:17,5:b,7:33,8:E,9:f,11:p,13:w,14:14,15:15,16:16,17:19,23:21,31:_,32:A,33:I,34:B,35:N,36:R,44:z,62:W,63:et},{4:17,5:b,7:34,8:E,9:f,11:p,13:w,14:14,15:15,16:16,17:19,23:21,31:_,32:A,33:I,34:B,35:N,36:R,44:z,62:W,63:et},{4:17,5:b,7:35,8:E,9:f,11:p,13:w,14:14,15:15,16:16,17:19,23:21,31:_,32:A,33:I,34:B,35:N,36:R,44:z,62:W,63:et},{18:36,62:[1,37],63:[1,38]},{45:39,62:[1,40],63:[1,41]},{51:[1,42],53:[1,43]},i(st,[2,20]),i(st,[2,21]),i(st,[2,22]),i(st,[2,23]),i(st,[2,24]),i(st,[2,25]),i(at,[2,49]),i(at,[2,50]),{1:[2,3]},{8:[2,8]},{8:[2,9]},{8:[2,10]},{8:[2,11]},{8:[2,12]},{19:[1,44]},{19:[2,47]},{19:[2,48]},{19:[1,45]},{19:[2,53]},{19:[2,54]},{52:46,55:bt,56:mt,57:yt,58:ft,59:ut,60:vt,61:X},{52:54,55:bt,56:mt,57:yt,58:ft,59:ut,60:vt,61:X},{5:[1,55]},{5:[1,56]},{53:[1,57]},i(pt,[2,40]),i(pt,[2,41]),i(pt,[2,42]),i(pt,[2,43]),i(pt,[2,44]),i(pt,[2,45]),i(pt,[2,46]),{54:[1,58]},{5:U,20:59,21:Tt,24:nt,26:It,28:Ot,30:Bt},{5:Et,30:Z,46:66,47:Ct,49:xt},{23:71,62:W,63:et},{23:72,62:W,63:et},i(Ht,[2,13]),{22:[1,73]},{22:[1,74]},{22:[1,75]},{22:[1,76]},{5:U,20:77,21:Tt,24:nt,26:It,28:Ot,30:Bt},i(Ht,[2,19]),i(Ht,[2,33]),{22:[1,78]},{22:[1,79]},{5:Et,30:Z,46:80,47:Ct,49:xt},i(Ht,[2,37]),i(Ht,[2,38]),i(Ht,[2,39]),{23:81,62:W,63:et},{25:82,62:[1,83],63:[1,84]},{27:85,37:[1,86],38:[1,87],39:[1,88]},{29:89,40:[1,90],41:[1,91],42:[1,92],43:[1,93]},i(Ht,[2,18]),{48:94,62:[1,95],63:[1,96]},{50:97,62:[1,98],63:[1,99]},i(Ht,[2,36]),{5:[1,100]},{5:[1,101]},{5:[2,51]},{5:[2,52]},{5:[1,102]},{5:[2,26]},{5:[2,27]},{5:[2,28]},{5:[1,103]},{5:[2,29]},{5:[2,30]},{5:[2,31]},{5:[2,32]},{5:[1,104]},{5:[2,55]},{5:[2,56]},{5:[1,105]},{5:[2,57]},{5:[2,58]},{5:U,20:106,21:Tt,24:nt,26:It,28:Ot,30:Bt},{5:U,20:107,21:Tt,24:nt,26:It,28:Ot,30:Bt},{5:U,20:108,21:Tt,24:nt,26:It,28:Ot,30:Bt},{5:U,20:109,21:Tt,24:nt,26:It,28:Ot,30:Bt},{5:Et,30:Z,46:110,47:Ct,49:xt},{5:Et,30:Z,46:111,47:Ct,49:xt},i(Ht,[2,14]),i(Ht,[2,15]),i(Ht,[2,16]),i(Ht,[2,17]),i(Ht,[2,34]),i(Ht,[2,35])],defaultActions:{8:[2,2],12:[2,1],30:[2,3],31:[2,8],32:[2,9],33:[2,10],34:[2,11],35:[2,12],37:[2,47],38:[2,48],40:[2,53],41:[2,54],83:[2,51],84:[2,52],86:[2,26],87:[2,27],88:[2,28],90:[2,29],91:[2,30],92:[2,31],93:[2,32],95:[2,55],96:[2,56],98:[2,57],99:[2,58]},parseError:function(me,Ve){if(Ve.recoverable)this.trace(me);else{var Ye=new Error(me);throw Ye.hash=Ve,Ye}},parse:function(me){var Ve=this,Ye=[0],ce=[],ke=[null],zt=[],re=this.table,se="",Pe=0,te=0,Me=2,de=1,on=zt.slice.call(arguments,1),ni=Object.create(this.lexer),Ks={yy:{}};for(var ws in this.yy)Object.prototype.hasOwnProperty.call(this.yy,ws)&&(Ks.yy[ws]=this.yy[ws]);ni.setInput(me,Ks.yy),Ks.yy.lexer=ni,Ks.yy.parser=this,typeof ni.yylloc>"u"&&(ni.yylloc={});var fo=ni.yylloc;zt.push(fo);var Xi=ni.options&&ni.options.ranges;typeof Ks.yy.parseError=="function"?this.parseError=Ks.yy.parseError:this.parseError=Object.getPrototypeOf(this).parseError;function Er(){var Gs;return Gs=ce.pop()||ni.lex()||de,typeof Gs!="number"&&(Gs instanceof Array&&(ce=Gs,Gs=ce.pop()),Gs=Ve.symbols_[Gs]||Gs),Gs}for(var Xn,di,Ee,Kn,He={},Ti,pn,Es,qa;;){if(di=Ye[Ye.length-1],this.defaultActions[di]?Ee=this.defaultActions[di]:((Xn===null||typeof Xn>"u")&&(Xn=Er()),Ee=re[di]&&re[di][Xn]),typeof Ee>"u"||!Ee.length||!Ee[0]){var Ma="";qa=[];for(Ti in re[di])this.terminals_[Ti]&&Ti>Me&&qa.push("'"+this.terminals_[Ti]+"'");ni.showPosition?Ma="Parse error on line "+(Pe+1)+`: +`+ni.showPosition()+` +Expecting `+qa.join(", ")+", got '"+(this.terminals_[Xn]||Xn)+"'":Ma="Parse error on line "+(Pe+1)+": Unexpected "+(Xn==de?"end of input":"'"+(this.terminals_[Xn]||Xn)+"'"),this.parseError(Ma,{text:ni.match,token:this.terminals_[Xn]||Xn,line:ni.yylineno,loc:fo,expected:qa})}if(Ee[0]instanceof Array&&Ee.length>1)throw new Error("Parse Error: multiple actions possible at state: "+di+", token: "+Xn);switch(Ee[0]){case 1:Ye.push(Xn),ke.push(ni.yytext),zt.push(ni.yylloc),Ye.push(Ee[1]),Xn=null,te=ni.yyleng,se=ni.yytext,Pe=ni.yylineno,fo=ni.yylloc;break;case 2:if(pn=this.productions_[Ee[1]][1],He.$=ke[ke.length-pn],He._$={first_line:zt[zt.length-(pn||1)].first_line,last_line:zt[zt.length-1].last_line,first_column:zt[zt.length-(pn||1)].first_column,last_column:zt[zt.length-1].last_column},Xi&&(He._$.range=[zt[zt.length-(pn||1)].range[0],zt[zt.length-1].range[1]]),Kn=this.performAction.apply(He,[se,te,Pe,Ks.yy,Ee[1],ke,zt].concat(on)),typeof Kn<"u")return Kn;pn&&(Ye=Ye.slice(0,-1*pn*2),ke=ke.slice(0,-1*pn),zt=zt.slice(0,-1*pn)),Ye.push(this.productions_[Ee[1]][0]),ke.push(He.$),zt.push(He._$),Es=re[Ye[Ye.length-2]][Ye[Ye.length-1]],Ye.push(Es);break;case 3:return!0}}return!0}},Ft=function(){var Se={EOF:1,parseError:function(Ve,Ye){if(this.yy.parser)this.yy.parser.parseError(Ve,Ye);else throw new Error(Ve)},setInput:function(me,Ve){return this.yy=Ve||this.yy||{},this._input=me,this._more=this._backtrack=this.done=!1,this.yylineno=this.yyleng=0,this.yytext=this.matched=this.match="",this.conditionStack=["INITIAL"],this.yylloc={first_line:1,first_column:0,last_line:1,last_column:0},this.options.ranges&&(this.yylloc.range=[0,0]),this.offset=0,this},input:function(){var me=this._input[0];this.yytext+=me,this.yyleng++,this.offset++,this.match+=me,this.matched+=me;var Ve=me.match(/(?:\r\n?|\n).*/g);return Ve?(this.yylineno++,this.yylloc.last_line++):this.yylloc.last_column++,this.options.ranges&&this.yylloc.range[1]++,this._input=this._input.slice(1),me},unput:function(me){var Ve=me.length,Ye=me.split(/(?:\r\n?|\n)/g);this._input=me+this._input,this.yytext=this.yytext.substr(0,this.yytext.length-Ve),this.offset-=Ve;var ce=this.match.split(/(?:\r\n?|\n)/g);this.match=this.match.substr(0,this.match.length-1),this.matched=this.matched.substr(0,this.matched.length-1),Ye.length-1&&(this.yylineno-=Ye.length-1);var ke=this.yylloc.range;return this.yylloc={first_line:this.yylloc.first_line,last_line:this.yylineno+1,first_column:this.yylloc.first_column,last_column:Ye?(Ye.length===ce.length?this.yylloc.first_column:0)+ce[ce.length-Ye.length].length-Ye[0].length:this.yylloc.first_column-Ve},this.options.ranges&&(this.yylloc.range=[ke[0],ke[0]+this.yyleng-Ve]),this.yyleng=this.yytext.length,this},more:function(){return this._more=!0,this},reject:function(){if(this.options.backtrack_lexer)this._backtrack=!0;else return this.parseError("Lexical error on line "+(this.yylineno+1)+`. You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true). +`+this.showPosition(),{text:"",token:null,line:this.yylineno});return this},less:function(me){this.unput(this.match.slice(me))},pastInput:function(){var me=this.matched.substr(0,this.matched.length-this.match.length);return(me.length>20?"...":"")+me.substr(-20).replace(/\n/g,"")},upcomingInput:function(){var me=this.match;return me.length<20&&(me+=this._input.substr(0,20-me.length)),(me.substr(0,20)+(me.length>20?"...":"")).replace(/\n/g,"")},showPosition:function(){var me=this.pastInput(),Ve=new Array(me.length+1).join("-");return me+this.upcomingInput()+` +`+Ve+"^"},test_match:function(me,Ve){var Ye,ce,ke;if(this.options.backtrack_lexer&&(ke={yylineno:this.yylineno,yylloc:{first_line:this.yylloc.first_line,last_line:this.last_line,first_column:this.yylloc.first_column,last_column:this.yylloc.last_column},yytext:this.yytext,match:this.match,matches:this.matches,matched:this.matched,yyleng:this.yyleng,offset:this.offset,_more:this._more,_input:this._input,yy:this.yy,conditionStack:this.conditionStack.slice(0),done:this.done},this.options.ranges&&(ke.yylloc.range=this.yylloc.range.slice(0))),ce=me[0].match(/(?:\r\n?|\n).*/g),ce&&(this.yylineno+=ce.length),this.yylloc={first_line:this.yylloc.last_line,last_line:this.yylineno+1,first_column:this.yylloc.last_column,last_column:ce?ce[ce.length-1].length-ce[ce.length-1].match(/\r?\n?/)[0].length:this.yylloc.last_column+me[0].length},this.yytext+=me[0],this.match+=me[0],this.matches=me,this.yyleng=this.yytext.length,this.options.ranges&&(this.yylloc.range=[this.offset,this.offset+=this.yyleng]),this._more=!1,this._backtrack=!1,this._input=this._input.slice(me[0].length),this.matched+=me[0],Ye=this.performAction.call(this,this.yy,this,Ve,this.conditionStack[this.conditionStack.length-1]),this.done&&this._input&&(this.done=!1),Ye)return Ye;if(this._backtrack){for(var zt in ke)this[zt]=ke[zt];return!1}return!1},next:function(){if(this.done)return this.EOF;this._input||(this.done=!0);var me,Ve,Ye,ce;this._more||(this.yytext="",this.match="");for(var ke=this._currentRules(),zt=0;ztVe[0].length)){if(Ve=Ye,ce=zt,this.options.backtrack_lexer){if(me=this.test_match(Ye,ke[zt]),me!==!1)return me;if(this._backtrack){Ve=!1;continue}else return!1}else if(!this.options.flex)break}return Ve?(me=this.test_match(Ve,ke[ce]),me!==!1?me:!1):this._input===""?this.EOF:this.parseError("Lexical error on line "+(this.yylineno+1)+`. Unrecognized text. +`+this.showPosition(),{text:"",token:null,line:this.yylineno})},lex:function(){var Ve=this.next();return Ve||this.lex()},begin:function(Ve){this.conditionStack.push(Ve)},popState:function(){var Ve=this.conditionStack.length-1;return Ve>0?this.conditionStack.pop():this.conditionStack[0]},_currentRules:function(){return this.conditionStack.length&&this.conditionStack[this.conditionStack.length-1]?this.conditions[this.conditionStack[this.conditionStack.length-1]].rules:this.conditions.INITIAL.rules},topState:function(Ve){return Ve=this.conditionStack.length-1-Math.abs(Ve||0),Ve>=0?this.conditionStack[Ve]:"INITIAL"},pushState:function(Ve){this.begin(Ve)},stateStackSize:function(){return this.conditionStack.length},options:{"case-insensitive":!0},performAction:function(Ve,Ye,ce,ke){switch(ce){case 0:return"title";case 1:return this.begin("acc_title"),9;case 2:return this.popState(),"acc_title_value";case 3:return this.begin("acc_descr"),11;case 4:return this.popState(),"acc_descr_value";case 5:this.begin("acc_descr_multiline");break;case 6:this.popState();break;case 7:return"acc_descr_multiline_value";case 8:return 5;case 9:break;case 10:break;case 11:break;case 12:return 8;case 13:return 6;case 14:return 19;case 15:return 30;case 16:return 22;case 17:return 21;case 18:return 24;case 19:return 26;case 20:return 28;case 21:return 31;case 22:return 32;case 23:return 33;case 24:return 34;case 25:return 35;case 26:return 36;case 27:return 37;case 28:return 38;case 29:return 39;case 30:return 40;case 31:return 41;case 32:return 42;case 33:return 43;case 34:return 44;case 35:return 55;case 36:return 56;case 37:return 57;case 38:return 58;case 39:return 59;case 40:return 60;case 41:return 61;case 42:return 47;case 43:return 49;case 44:return 51;case 45:return 54;case 46:return 53;case 47:this.begin("string");break;case 48:this.popState();break;case 49:return"qString";case 50:return Ye.yytext=Ye.yytext.trim(),62}},rules:[/^(?:title\s[^#\n;]+)/i,/^(?:accTitle\s*:\s*)/i,/^(?:(?!\n||)*[^\n]*)/i,/^(?:accDescr\s*:\s*)/i,/^(?:(?!\n||)*[^\n]*)/i,/^(?:accDescr\s*\{\s*)/i,/^(?:[\}])/i,/^(?:[^\}]*)/i,/^(?:(\r?\n)+)/i,/^(?:\s+)/i,/^(?:#[^\n]*)/i,/^(?:%[^\n]*)/i,/^(?:$)/i,/^(?:requirementDiagram\b)/i,/^(?:\{)/i,/^(?:\})/i,/^(?::)/i,/^(?:id\b)/i,/^(?:text\b)/i,/^(?:risk\b)/i,/^(?:verifyMethod\b)/i,/^(?:requirement\b)/i,/^(?:functionalRequirement\b)/i,/^(?:interfaceRequirement\b)/i,/^(?:performanceRequirement\b)/i,/^(?:physicalRequirement\b)/i,/^(?:designConstraint\b)/i,/^(?:low\b)/i,/^(?:medium\b)/i,/^(?:high\b)/i,/^(?:analysis\b)/i,/^(?:demonstration\b)/i,/^(?:inspection\b)/i,/^(?:test\b)/i,/^(?:element\b)/i,/^(?:contains\b)/i,/^(?:copies\b)/i,/^(?:derives\b)/i,/^(?:satisfies\b)/i,/^(?:verifies\b)/i,/^(?:refines\b)/i,/^(?:traces\b)/i,/^(?:type\b)/i,/^(?:docref\b)/i,/^(?:<-)/i,/^(?:->)/i,/^(?:-)/i,/^(?:["])/i,/^(?:["])/i,/^(?:[^"]*)/i,/^(?:[\w][^\r\n\{\<\>\-\=]*)/i],conditions:{acc_descr_multiline:{rules:[6,7],inclusive:!1},acc_descr:{rules:[4],inclusive:!1},acc_title:{rules:[2],inclusive:!1},unqString:{rules:[],inclusive:!1},token:{rules:[],inclusive:!1},string:{rules:[48,49],inclusive:!1},INITIAL:{rules:[0,1,3,5,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,50],inclusive:!0}}};return Se}();Le.lexer=Ft;function gn(){this.yy={}}return gn.prototype=Le,Le.Parser=gn,new gn}();hgt.parser=hgt;const VHe=hgt;let fgt=[],wp={},zF={},yk={},qF={};const GHe={RequirementType:{REQUIREMENT:"Requirement",FUNCTIONAL_REQUIREMENT:"Functional Requirement",INTERFACE_REQUIREMENT:"Interface Requirement",PERFORMANCE_REQUIREMENT:"Performance Requirement",PHYSICAL_REQUIREMENT:"Physical Requirement",DESIGN_CONSTRAINT:"Design Constraint"},RiskLevel:{LOW_RISK:"Low",MED_RISK:"Medium",HIGH_RISK:"High"},VerifyType:{VERIFY_ANALYSIS:"Analysis",VERIFY_DEMONSTRATION:"Demonstration",VERIFY_INSPECTION:"Inspection",VERIFY_TEST:"Test"},Relationships:{CONTAINS:"contains",COPIES:"copies",DERIVES:"derives",SATISFIES:"satisfies",VERIFIES:"verifies",REFINES:"refines",TRACES:"traces"},getConfig:()=>Oe().req,addRequirement:(i,a)=>(zF[i]===void 0&&(zF[i]={name:i,type:a,id:wp.id,text:wp.text,risk:wp.risk,verifyMethod:wp.verifyMethod}),wp={},zF[i]),getRequirements:()=>zF,setNewReqId:i=>{wp!==void 0&&(wp.id=i)},setNewReqText:i=>{wp!==void 0&&(wp.text=i)},setNewReqRisk:i=>{wp!==void 0&&(wp.risk=i)},setNewReqVerifyMethod:i=>{wp!==void 0&&(wp.verifyMethod=i)},setAccTitle:E0,getAccTitle:fg,setAccDescription:dg,getAccDescription:gg,addElement:i=>(qF[i]===void 0&&(qF[i]={name:i,type:yk.type,docRef:yk.docRef},Ut.info("Added new requirement: ",i)),yk={},qF[i]),getElements:()=>qF,setNewElementType:i=>{yk!==void 0&&(yk.type=i)},setNewElementDocRef:i=>{yk!==void 0&&(yk.docRef=i)},addRelationship:(i,a,f)=>{fgt.push({type:i,src:a,dst:f})},getRelationships:()=>fgt,clear:()=>{fgt=[],wp={},zF={},yk={},qF={},hg()}},UHe=i=>` + + marker { + fill: ${i.relationColor}; + stroke: ${i.relationColor}; + } + + marker.cross { + stroke: ${i.lineColor}; + } + + svg { + font-family: ${i.fontFamily}; + font-size: ${i.fontSize}; + } + + .reqBox { + fill: ${i.requirementBackground}; + fill-opacity: 1.0; + stroke: ${i.requirementBorderColor}; + stroke-width: ${i.requirementBorderSize}; + } + + .reqTitle, .reqLabel{ + fill: ${i.requirementTextColor}; + } + .reqLabelBox { + fill: ${i.relationLabelBackground}; + fill-opacity: 1.0; + } + + .req-title-line { + stroke: ${i.requirementBorderColor}; + stroke-width: ${i.requirementBorderSize}; + } + .relationshipLine { + stroke: ${i.relationColor}; + stroke-width: 1; + } + .relationshipLabel { + fill: ${i.relationLabelColor}; + } + +`,dgt={CONTAINS:"contains",ARROW:"arrow"},xRt={ReqMarkers:dgt,insertLineEndings:(i,a)=>{let f=i.append("defs").append("marker").attr("id",dgt.CONTAINS+"_line_ending").attr("refX",0).attr("refY",a.line_height/2).attr("markerWidth",a.line_height).attr("markerHeight",a.line_height).attr("orient","auto").append("g");f.append("circle").attr("cx",a.line_height/2).attr("cy",a.line_height/2).attr("r",a.line_height/2).attr("fill","none"),f.append("line").attr("x1",0).attr("x2",a.line_height).attr("y1",a.line_height/2).attr("y2",a.line_height/2).attr("stroke-width",1),f.append("line").attr("y1",0).attr("y2",a.line_height).attr("x1",a.line_height/2).attr("x2",a.line_height/2).attr("stroke-width",1),i.append("defs").append("marker").attr("id",dgt.ARROW+"_line_ending").attr("refX",a.line_height).attr("refY",.5*a.line_height).attr("markerWidth",a.line_height).attr("markerHeight",a.line_height).attr("orient","auto").append("path").attr("d",`M0,0 + L${a.line_height},${a.line_height/2} + M${a.line_height},${a.line_height/2} + L0,${a.line_height}`).attr("stroke-width",1)}};let Eh={},kRt=0;const ERt=(i,a)=>i.insert("rect","#"+a).attr("class","req reqBox").attr("x",0).attr("y",0).attr("width",Eh.rect_min_width+"px").attr("height",Eh.rect_min_height+"px"),TRt=(i,a,f)=>{let p=Eh.rect_min_width/2,w=i.append("text").attr("class","req reqLabel reqTitle").attr("id",a).attr("x",p).attr("y",Eh.rect_padding).attr("dominant-baseline","hanging"),m=0;f.forEach(A=>{m==0?w.append("tspan").attr("text-anchor","middle").attr("x",Eh.rect_min_width/2).attr("dy",0).text(A):w.append("tspan").attr("text-anchor","middle").attr("x",Eh.rect_min_width/2).attr("dy",Eh.line_height*.75).text(A),m++});let b=1.5*Eh.rect_padding,E=m*Eh.line_height*.75,_=b+E;return i.append("line").attr("class","req-title-line").attr("x1","0").attr("x2",Eh.rect_min_width).attr("y1",_).attr("y2",_),{titleNode:w,y:_}},CRt=(i,a,f,p)=>{let w=i.append("text").attr("class","req reqLabel").attr("id",a).attr("x",Eh.rect_padding).attr("y",p).attr("dominant-baseline","hanging"),m=0;const b=30;let E=[];return f.forEach(_=>{let A=_.length;for(;A>b&&m<3;){let I=_.substring(0,b);_=_.substring(b,_.length),A=_.length,E[E.length]=I,m++}if(m==3){let I=E[E.length-1];E[E.length-1]=I.substring(0,I.length-4)+"..."}else E[E.length]=_;m=0}),E.forEach(_=>{w.append("tspan").attr("x",Eh.rect_padding).attr("dy",Eh.line_height).text(_)}),w},WHe=(i,a,f,p)=>{const w=a.node().getTotalLength(),m=a.node().getPointAtLength(w*.5),b="rel"+kRt;kRt++;const _=i.append("text").attr("class","req relationshipLabel").attr("id",b).attr("x",m.x).attr("y",m.y).attr("text-anchor","middle").attr("dominant-baseline","middle").text(p).node().getBBox();i.insert("rect","#"+b).attr("class","req reqLabelBox").attr("x",m.x-_.width/2).attr("y",m.y-_.height/2).attr("width",_.width).attr("height",_.height).attr("fill","white").attr("fill-opacity","85%")},YHe=function(i,a,f,p,w){const m=f.edge(fL(a.src),fL(a.dst)),b=E5().x(function(_){return _.x}).y(function(_){return _.y}),E=i.insert("path","#"+p).attr("class","er relationshipLine").attr("d",b(m.points)).attr("fill","none");a.type==w.db.Relationships.CONTAINS?E.attr("marker-start","url("+Kr.getUrl(Eh.arrowMarkerAbsolute)+"#"+a.type+"_line_ending)"):(E.attr("stroke-dasharray","10,7"),E.attr("marker-end","url("+Kr.getUrl(Eh.arrowMarkerAbsolute)+"#"+xRt.ReqMarkers.ARROW+"_line_ending)")),WHe(i,E,Eh,`<<${a.type}>>`)},KHe=(i,a,f)=>{Object.keys(i).forEach(p=>{let w=i[p];p=fL(p),Ut.info("Added new requirement: ",p);const m=f.append("g").attr("id",p),b="req-"+p,E=ERt(m,b);let _=TRt(m,p+"_title",[`<<${w.type}>>`,`${w.name}`]);CRt(m,p+"_body",[`Id: ${w.id}`,`Text: ${w.text}`,`Risk: ${w.risk}`,`Verification: ${w.verifyMethod}`],_.y);const A=E.node().getBBox();a.setNode(p,{width:A.width,height:A.height,shape:"rect",id:p})})},XHe=(i,a,f)=>{Object.keys(i).forEach(p=>{let w=i[p];const m=fL(p),b=f.append("g").attr("id",m),E="element-"+m,_=ERt(b,E);let A=TRt(b,E+"_title",["<>",`${p}`]);CRt(b,E+"_body",[`Type: ${w.type||"Not Specified"}`,`Doc Ref: ${w.docRef||"None"}`],A.y);const I=_.node().getBBox();a.setNode(m,{width:I.width,height:I.height,shape:"rect",id:m})})},QHe=(i,a)=>(i.forEach(function(f){let p=fL(f.src),w=fL(f.dst);a.setEdge(p,w,{relationship:f})}),i),ZHe=function(i,a){a.nodes().forEach(function(f){f!==void 0&&a.node(f)!==void 0&&(i.select("#"+f),i.select("#"+f).attr("transform","translate("+(a.node(f).x-a.node(f).width/2)+","+(a.node(f).y-a.node(f).height/2)+" )"))})},fL=i=>i.replace(/\s/g,"").replace(/\./g,"_"),JHe=Object.freeze(Object.defineProperty({__proto__:null,diagram:{parser:VHe,db:GHe,renderer:{draw:(i,a,f,p)=>{Eh=Oe().requirement;const w=Eh.securityLevel;let m;w==="sandbox"&&(m=yr("#i"+a));const E=yr(w==="sandbox"?m.nodes()[0].contentDocument.body:"body").select(`[id='${a}']`);xRt.insertLineEndings(E,Eh);const _=new c1({multigraph:!1,compound:!1,directed:!0}).setGraph({rankdir:Eh.layoutDirection,marginx:20,marginy:20,nodesep:100,edgesep:100,ranksep:100}).setDefaultEdgeLabel(function(){return{}});let A=p.db.getRequirements(),I=p.db.getElements(),B=p.db.getRelationships();KHe(A,_,E),XHe(I,_,E),QHe(B,_),aL(_),ZHe(E,_),B.forEach(function(et){YHe(E,et,_,a,p)});const N=Eh.rect_padding,R=E.node().getBBox(),z=R.width+N*2,W=R.height+N*2;k0(E,W,z,Eh.useMaxWidth),E.attr("viewBox",`${R.x-N} ${R.y-N} ${z} ${W}`)}},styles:UHe}},Symbol.toStringTag,{value:"Module"}));var ggt=function(){var i=function(ce,ke,zt,re){for(zt=zt||{},re=ce.length;re--;zt[ce[re]]=ke);return zt},a=[1,2],f=[1,3],p=[1,4],w=[2,4],m=[1,9],b=[1,11],E=[1,13],_=[1,14],A=[1,16],I=[1,17],B=[1,18],N=[1,24],R=[1,25],z=[1,26],W=[1,27],et=[1,28],st=[1,29],at=[1,30],bt=[1,31],mt=[1,32],yt=[1,33],ft=[1,34],ut=[1,35],vt=[1,36],X=[1,37],pt=[1,38],U=[1,39],Tt=[1,41],nt=[1,42],It=[1,43],Ot=[1,44],Bt=[1,45],Et=[1,46],Z=[1,4,5,13,14,16,18,21,23,29,30,31,33,35,36,37,38,39,41,43,44,46,47,48,49,50,52,53,54,59,60,61,62,70],Ct=[4,5,16,50,52,53],xt=[4,5,13,14,16,18,21,23,29,30,31,33,35,36,37,38,39,41,43,44,46,50,52,53,54,59,60,61,62,70],Ht=[4,5,13,14,16,18,21,23,29,30,31,33,35,36,37,38,39,41,43,44,46,49,50,52,53,54,59,60,61,62,70],Le=[4,5,13,14,16,18,21,23,29,30,31,33,35,36,37,38,39,41,43,44,46,48,50,52,53,54,59,60,61,62,70],Ft=[4,5,13,14,16,18,21,23,29,30,31,33,35,36,37,38,39,41,43,44,46,47,50,52,53,54,59,60,61,62,70],gn=[68,69,70],Se=[1,120],me={trace:function(){},yy:{},symbols_:{error:2,start:3,SPACE:4,NEWLINE:5,SD:6,document:7,line:8,statement:9,box_section:10,box_line:11,participant_statement:12,create:13,box:14,restOfLine:15,end:16,signal:17,autonumber:18,NUM:19,off:20,activate:21,actor:22,deactivate:23,note_statement:24,links_statement:25,link_statement:26,properties_statement:27,details_statement:28,title:29,legacy_title:30,acc_title:31,acc_title_value:32,acc_descr:33,acc_descr_value:34,acc_descr_multiline_value:35,loop:36,rect:37,opt:38,alt:39,else_sections:40,par:41,par_sections:42,par_over:43,critical:44,option_sections:45,break:46,option:47,and:48,else:49,participant:50,AS:51,participant_actor:52,destroy:53,note:54,placement:55,text2:56,over:57,actor_pair:58,links:59,link:60,properties:61,details:62,spaceList:63,",":64,left_of:65,right_of:66,signaltype:67,"+":68,"-":69,ACTOR:70,SOLID_OPEN_ARROW:71,DOTTED_OPEN_ARROW:72,SOLID_ARROW:73,DOTTED_ARROW:74,SOLID_CROSS:75,DOTTED_CROSS:76,SOLID_POINT:77,DOTTED_POINT:78,TXT:79,$accept:0,$end:1},terminals_:{2:"error",4:"SPACE",5:"NEWLINE",6:"SD",13:"create",14:"box",15:"restOfLine",16:"end",18:"autonumber",19:"NUM",20:"off",21:"activate",23:"deactivate",29:"title",30:"legacy_title",31:"acc_title",32:"acc_title_value",33:"acc_descr",34:"acc_descr_value",35:"acc_descr_multiline_value",36:"loop",37:"rect",38:"opt",39:"alt",41:"par",43:"par_over",44:"critical",46:"break",47:"option",48:"and",49:"else",50:"participant",51:"AS",52:"participant_actor",53:"destroy",54:"note",57:"over",59:"links",60:"link",61:"properties",62:"details",64:",",65:"left_of",66:"right_of",68:"+",69:"-",70:"ACTOR",71:"SOLID_OPEN_ARROW",72:"DOTTED_OPEN_ARROW",73:"SOLID_ARROW",74:"DOTTED_ARROW",75:"SOLID_CROSS",76:"DOTTED_CROSS",77:"SOLID_POINT",78:"DOTTED_POINT",79:"TXT"},productions_:[0,[3,2],[3,2],[3,2],[7,0],[7,2],[8,2],[8,1],[8,1],[10,0],[10,2],[11,2],[11,1],[11,1],[9,1],[9,2],[9,4],[9,2],[9,4],[9,3],[9,3],[9,2],[9,3],[9,3],[9,2],[9,2],[9,2],[9,2],[9,2],[9,1],[9,1],[9,2],[9,2],[9,1],[9,4],[9,4],[9,4],[9,4],[9,4],[9,4],[9,4],[9,4],[45,1],[45,4],[42,1],[42,4],[40,1],[40,4],[12,5],[12,3],[12,5],[12,3],[12,3],[24,4],[24,4],[25,3],[26,3],[27,3],[28,3],[63,2],[63,1],[58,3],[58,1],[55,1],[55,1],[17,5],[17,5],[17,4],[22,1],[67,1],[67,1],[67,1],[67,1],[67,1],[67,1],[67,1],[67,1],[56,1]],performAction:function(ke,zt,re,se,Pe,te,Me){var de=te.length-1;switch(Pe){case 3:return se.apply(te[de]),te[de];case 4:case 9:this.$=[];break;case 5:case 10:te[de-1].push(te[de]),this.$=te[de-1];break;case 6:case 7:case 11:case 12:this.$=te[de];break;case 8:case 13:this.$=[];break;case 15:te[de].type="createParticipant",this.$=te[de];break;case 16:te[de-1].unshift({type:"boxStart",boxData:se.parseBoxData(te[de-2])}),te[de-1].push({type:"boxEnd",boxText:te[de-2]}),this.$=te[de-1];break;case 18:this.$={type:"sequenceIndex",sequenceIndex:Number(te[de-2]),sequenceIndexStep:Number(te[de-1]),sequenceVisible:!0,signalType:se.LINETYPE.AUTONUMBER};break;case 19:this.$={type:"sequenceIndex",sequenceIndex:Number(te[de-1]),sequenceIndexStep:1,sequenceVisible:!0,signalType:se.LINETYPE.AUTONUMBER};break;case 20:this.$={type:"sequenceIndex",sequenceVisible:!1,signalType:se.LINETYPE.AUTONUMBER};break;case 21:this.$={type:"sequenceIndex",sequenceVisible:!0,signalType:se.LINETYPE.AUTONUMBER};break;case 22:this.$={type:"activeStart",signalType:se.LINETYPE.ACTIVE_START,actor:te[de-1]};break;case 23:this.$={type:"activeEnd",signalType:se.LINETYPE.ACTIVE_END,actor:te[de-1]};break;case 29:se.setDiagramTitle(te[de].substring(6)),this.$=te[de].substring(6);break;case 30:se.setDiagramTitle(te[de].substring(7)),this.$=te[de].substring(7);break;case 31:this.$=te[de].trim(),se.setAccTitle(this.$);break;case 32:case 33:this.$=te[de].trim(),se.setAccDescription(this.$);break;case 34:te[de-1].unshift({type:"loopStart",loopText:se.parseMessage(te[de-2]),signalType:se.LINETYPE.LOOP_START}),te[de-1].push({type:"loopEnd",loopText:te[de-2],signalType:se.LINETYPE.LOOP_END}),this.$=te[de-1];break;case 35:te[de-1].unshift({type:"rectStart",color:se.parseMessage(te[de-2]),signalType:se.LINETYPE.RECT_START}),te[de-1].push({type:"rectEnd",color:se.parseMessage(te[de-2]),signalType:se.LINETYPE.RECT_END}),this.$=te[de-1];break;case 36:te[de-1].unshift({type:"optStart",optText:se.parseMessage(te[de-2]),signalType:se.LINETYPE.OPT_START}),te[de-1].push({type:"optEnd",optText:se.parseMessage(te[de-2]),signalType:se.LINETYPE.OPT_END}),this.$=te[de-1];break;case 37:te[de-1].unshift({type:"altStart",altText:se.parseMessage(te[de-2]),signalType:se.LINETYPE.ALT_START}),te[de-1].push({type:"altEnd",signalType:se.LINETYPE.ALT_END}),this.$=te[de-1];break;case 38:te[de-1].unshift({type:"parStart",parText:se.parseMessage(te[de-2]),signalType:se.LINETYPE.PAR_START}),te[de-1].push({type:"parEnd",signalType:se.LINETYPE.PAR_END}),this.$=te[de-1];break;case 39:te[de-1].unshift({type:"parStart",parText:se.parseMessage(te[de-2]),signalType:se.LINETYPE.PAR_OVER_START}),te[de-1].push({type:"parEnd",signalType:se.LINETYPE.PAR_END}),this.$=te[de-1];break;case 40:te[de-1].unshift({type:"criticalStart",criticalText:se.parseMessage(te[de-2]),signalType:se.LINETYPE.CRITICAL_START}),te[de-1].push({type:"criticalEnd",signalType:se.LINETYPE.CRITICAL_END}),this.$=te[de-1];break;case 41:te[de-1].unshift({type:"breakStart",breakText:se.parseMessage(te[de-2]),signalType:se.LINETYPE.BREAK_START}),te[de-1].push({type:"breakEnd",optText:se.parseMessage(te[de-2]),signalType:se.LINETYPE.BREAK_END}),this.$=te[de-1];break;case 43:this.$=te[de-3].concat([{type:"option",optionText:se.parseMessage(te[de-1]),signalType:se.LINETYPE.CRITICAL_OPTION},te[de]]);break;case 45:this.$=te[de-3].concat([{type:"and",parText:se.parseMessage(te[de-1]),signalType:se.LINETYPE.PAR_AND},te[de]]);break;case 47:this.$=te[de-3].concat([{type:"else",altText:se.parseMessage(te[de-1]),signalType:se.LINETYPE.ALT_ELSE},te[de]]);break;case 48:te[de-3].draw="participant",te[de-3].type="addParticipant",te[de-3].description=se.parseMessage(te[de-1]),this.$=te[de-3];break;case 49:te[de-1].draw="participant",te[de-1].type="addParticipant",this.$=te[de-1];break;case 50:te[de-3].draw="actor",te[de-3].type="addParticipant",te[de-3].description=se.parseMessage(te[de-1]),this.$=te[de-3];break;case 51:te[de-1].draw="actor",te[de-1].type="addParticipant",this.$=te[de-1];break;case 52:te[de-1].type="destroyParticipant",this.$=te[de-1];break;case 53:this.$=[te[de-1],{type:"addNote",placement:te[de-2],actor:te[de-1].actor,text:te[de]}];break;case 54:te[de-2]=[].concat(te[de-1],te[de-1]).slice(0,2),te[de-2][0]=te[de-2][0].actor,te[de-2][1]=te[de-2][1].actor,this.$=[te[de-1],{type:"addNote",placement:se.PLACEMENT.OVER,actor:te[de-2].slice(0,2),text:te[de]}];break;case 55:this.$=[te[de-1],{type:"addLinks",actor:te[de-1].actor,text:te[de]}];break;case 56:this.$=[te[de-1],{type:"addALink",actor:te[de-1].actor,text:te[de]}];break;case 57:this.$=[te[de-1],{type:"addProperties",actor:te[de-1].actor,text:te[de]}];break;case 58:this.$=[te[de-1],{type:"addDetails",actor:te[de-1].actor,text:te[de]}];break;case 61:this.$=[te[de-2],te[de]];break;case 62:this.$=te[de];break;case 63:this.$=se.PLACEMENT.LEFTOF;break;case 64:this.$=se.PLACEMENT.RIGHTOF;break;case 65:this.$=[te[de-4],te[de-1],{type:"addMessage",from:te[de-4].actor,to:te[de-1].actor,signalType:te[de-3],msg:te[de],activate:!0},{type:"activeStart",signalType:se.LINETYPE.ACTIVE_START,actor:te[de-1]}];break;case 66:this.$=[te[de-4],te[de-1],{type:"addMessage",from:te[de-4].actor,to:te[de-1].actor,signalType:te[de-3],msg:te[de]},{type:"activeEnd",signalType:se.LINETYPE.ACTIVE_END,actor:te[de-4]}];break;case 67:this.$=[te[de-3],te[de-1],{type:"addMessage",from:te[de-3].actor,to:te[de-1].actor,signalType:te[de-2],msg:te[de]}];break;case 68:this.$={type:"addParticipant",actor:te[de]};break;case 69:this.$=se.LINETYPE.SOLID_OPEN;break;case 70:this.$=se.LINETYPE.DOTTED_OPEN;break;case 71:this.$=se.LINETYPE.SOLID;break;case 72:this.$=se.LINETYPE.DOTTED;break;case 73:this.$=se.LINETYPE.SOLID_CROSS;break;case 74:this.$=se.LINETYPE.DOTTED_CROSS;break;case 75:this.$=se.LINETYPE.SOLID_POINT;break;case 76:this.$=se.LINETYPE.DOTTED_POINT;break;case 77:this.$=se.parseMessage(te[de].trim().substring(1));break}},table:[{3:1,4:a,5:f,6:p},{1:[3]},{3:5,4:a,5:f,6:p},{3:6,4:a,5:f,6:p},i([1,4,5,13,14,18,21,23,29,30,31,33,35,36,37,38,39,41,43,44,46,50,52,53,54,59,60,61,62,70],w,{7:7}),{1:[2,1]},{1:[2,2]},{1:[2,3],4:m,5:b,8:8,9:10,12:12,13:E,14:_,17:15,18:A,21:I,22:40,23:B,24:19,25:20,26:21,27:22,28:23,29:N,30:R,31:z,33:W,35:et,36:st,37:at,38:bt,39:mt,41:yt,43:ft,44:ut,46:vt,50:X,52:pt,53:U,54:Tt,59:nt,60:It,61:Ot,62:Bt,70:Et},i(Z,[2,5]),{9:47,12:12,13:E,14:_,17:15,18:A,21:I,22:40,23:B,24:19,25:20,26:21,27:22,28:23,29:N,30:R,31:z,33:W,35:et,36:st,37:at,38:bt,39:mt,41:yt,43:ft,44:ut,46:vt,50:X,52:pt,53:U,54:Tt,59:nt,60:It,61:Ot,62:Bt,70:Et},i(Z,[2,7]),i(Z,[2,8]),i(Z,[2,14]),{12:48,50:X,52:pt,53:U},{15:[1,49]},{5:[1,50]},{5:[1,53],19:[1,51],20:[1,52]},{22:54,70:Et},{22:55,70:Et},{5:[1,56]},{5:[1,57]},{5:[1,58]},{5:[1,59]},{5:[1,60]},i(Z,[2,29]),i(Z,[2,30]),{32:[1,61]},{34:[1,62]},i(Z,[2,33]),{15:[1,63]},{15:[1,64]},{15:[1,65]},{15:[1,66]},{15:[1,67]},{15:[1,68]},{15:[1,69]},{15:[1,70]},{22:71,70:Et},{22:72,70:Et},{22:73,70:Et},{67:74,71:[1,75],72:[1,76],73:[1,77],74:[1,78],75:[1,79],76:[1,80],77:[1,81],78:[1,82]},{55:83,57:[1,84],65:[1,85],66:[1,86]},{22:87,70:Et},{22:88,70:Et},{22:89,70:Et},{22:90,70:Et},i([5,51,64,71,72,73,74,75,76,77,78,79],[2,68]),i(Z,[2,6]),i(Z,[2,15]),i(Ct,[2,9],{10:91}),i(Z,[2,17]),{5:[1,93],19:[1,92]},{5:[1,94]},i(Z,[2,21]),{5:[1,95]},{5:[1,96]},i(Z,[2,24]),i(Z,[2,25]),i(Z,[2,26]),i(Z,[2,27]),i(Z,[2,28]),i(Z,[2,31]),i(Z,[2,32]),i(xt,w,{7:97}),i(xt,w,{7:98}),i(xt,w,{7:99}),i(Ht,w,{40:100,7:101}),i(Le,w,{42:102,7:103}),i(Le,w,{7:103,42:104}),i(Ft,w,{45:105,7:106}),i(xt,w,{7:107}),{5:[1,109],51:[1,108]},{5:[1,111],51:[1,110]},{5:[1,112]},{22:115,68:[1,113],69:[1,114],70:Et},i(gn,[2,69]),i(gn,[2,70]),i(gn,[2,71]),i(gn,[2,72]),i(gn,[2,73]),i(gn,[2,74]),i(gn,[2,75]),i(gn,[2,76]),{22:116,70:Et},{22:118,58:117,70:Et},{70:[2,63]},{70:[2,64]},{56:119,79:Se},{56:121,79:Se},{56:122,79:Se},{56:123,79:Se},{4:[1,126],5:[1,128],11:125,12:127,16:[1,124],50:X,52:pt,53:U},{5:[1,129]},i(Z,[2,19]),i(Z,[2,20]),i(Z,[2,22]),i(Z,[2,23]),{4:m,5:b,8:8,9:10,12:12,13:E,14:_,16:[1,130],17:15,18:A,21:I,22:40,23:B,24:19,25:20,26:21,27:22,28:23,29:N,30:R,31:z,33:W,35:et,36:st,37:at,38:bt,39:mt,41:yt,43:ft,44:ut,46:vt,50:X,52:pt,53:U,54:Tt,59:nt,60:It,61:Ot,62:Bt,70:Et},{4:m,5:b,8:8,9:10,12:12,13:E,14:_,16:[1,131],17:15,18:A,21:I,22:40,23:B,24:19,25:20,26:21,27:22,28:23,29:N,30:R,31:z,33:W,35:et,36:st,37:at,38:bt,39:mt,41:yt,43:ft,44:ut,46:vt,50:X,52:pt,53:U,54:Tt,59:nt,60:It,61:Ot,62:Bt,70:Et},{4:m,5:b,8:8,9:10,12:12,13:E,14:_,16:[1,132],17:15,18:A,21:I,22:40,23:B,24:19,25:20,26:21,27:22,28:23,29:N,30:R,31:z,33:W,35:et,36:st,37:at,38:bt,39:mt,41:yt,43:ft,44:ut,46:vt,50:X,52:pt,53:U,54:Tt,59:nt,60:It,61:Ot,62:Bt,70:Et},{16:[1,133]},{4:m,5:b,8:8,9:10,12:12,13:E,14:_,16:[2,46],17:15,18:A,21:I,22:40,23:B,24:19,25:20,26:21,27:22,28:23,29:N,30:R,31:z,33:W,35:et,36:st,37:at,38:bt,39:mt,41:yt,43:ft,44:ut,46:vt,49:[1,134],50:X,52:pt,53:U,54:Tt,59:nt,60:It,61:Ot,62:Bt,70:Et},{16:[1,135]},{4:m,5:b,8:8,9:10,12:12,13:E,14:_,16:[2,44],17:15,18:A,21:I,22:40,23:B,24:19,25:20,26:21,27:22,28:23,29:N,30:R,31:z,33:W,35:et,36:st,37:at,38:bt,39:mt,41:yt,43:ft,44:ut,46:vt,48:[1,136],50:X,52:pt,53:U,54:Tt,59:nt,60:It,61:Ot,62:Bt,70:Et},{16:[1,137]},{16:[1,138]},{4:m,5:b,8:8,9:10,12:12,13:E,14:_,16:[2,42],17:15,18:A,21:I,22:40,23:B,24:19,25:20,26:21,27:22,28:23,29:N,30:R,31:z,33:W,35:et,36:st,37:at,38:bt,39:mt,41:yt,43:ft,44:ut,46:vt,47:[1,139],50:X,52:pt,53:U,54:Tt,59:nt,60:It,61:Ot,62:Bt,70:Et},{4:m,5:b,8:8,9:10,12:12,13:E,14:_,16:[1,140],17:15,18:A,21:I,22:40,23:B,24:19,25:20,26:21,27:22,28:23,29:N,30:R,31:z,33:W,35:et,36:st,37:at,38:bt,39:mt,41:yt,43:ft,44:ut,46:vt,50:X,52:pt,53:U,54:Tt,59:nt,60:It,61:Ot,62:Bt,70:Et},{15:[1,141]},i(Z,[2,49]),{15:[1,142]},i(Z,[2,51]),i(Z,[2,52]),{22:143,70:Et},{22:144,70:Et},{56:145,79:Se},{56:146,79:Se},{56:147,79:Se},{64:[1,148],79:[2,62]},{5:[2,55]},{5:[2,77]},{5:[2,56]},{5:[2,57]},{5:[2,58]},i(Z,[2,16]),i(Ct,[2,10]),{12:149,50:X,52:pt,53:U},i(Ct,[2,12]),i(Ct,[2,13]),i(Z,[2,18]),i(Z,[2,34]),i(Z,[2,35]),i(Z,[2,36]),i(Z,[2,37]),{15:[1,150]},i(Z,[2,38]),{15:[1,151]},i(Z,[2,39]),i(Z,[2,40]),{15:[1,152]},i(Z,[2,41]),{5:[1,153]},{5:[1,154]},{56:155,79:Se},{56:156,79:Se},{5:[2,67]},{5:[2,53]},{5:[2,54]},{22:157,70:Et},i(Ct,[2,11]),i(Ht,w,{7:101,40:158}),i(Le,w,{7:103,42:159}),i(Ft,w,{7:106,45:160}),i(Z,[2,48]),i(Z,[2,50]),{5:[2,65]},{5:[2,66]},{79:[2,61]},{16:[2,47]},{16:[2,45]},{16:[2,43]}],defaultActions:{5:[2,1],6:[2,2],85:[2,63],86:[2,64],119:[2,55],120:[2,77],121:[2,56],122:[2,57],123:[2,58],145:[2,67],146:[2,53],147:[2,54],155:[2,65],156:[2,66],157:[2,61],158:[2,47],159:[2,45],160:[2,43]},parseError:function(ke,zt){if(zt.recoverable)this.trace(ke);else{var re=new Error(ke);throw re.hash=zt,re}},parse:function(ke){var zt=this,re=[0],se=[],Pe=[null],te=[],Me=this.table,de="",on=0,ni=0,Ks=2,ws=1,fo=te.slice.call(arguments,1),Xi=Object.create(this.lexer),Er={yy:{}};for(var Xn in this.yy)Object.prototype.hasOwnProperty.call(this.yy,Xn)&&(Er.yy[Xn]=this.yy[Xn]);Xi.setInput(ke,Er.yy),Er.yy.lexer=Xi,Er.yy.parser=this,typeof Xi.yylloc>"u"&&(Xi.yylloc={});var di=Xi.yylloc;te.push(di);var Ee=Xi.options&&Xi.options.ranges;typeof Er.yy.parseError=="function"?this.parseError=Er.yy.parseError:this.parseError=Object.getPrototypeOf(this).parseError;function Kn(){var zs;return zs=se.pop()||Xi.lex()||ws,typeof zs!="number"&&(zs instanceof Array&&(se=zs,zs=se.pop()),zs=zt.symbols_[zs]||zs),zs}for(var He,Ti,pn,Es,qa={},Ma,Gs,Po,vs;;){if(Ti=re[re.length-1],this.defaultActions[Ti]?pn=this.defaultActions[Ti]:((He===null||typeof He>"u")&&(He=Kn()),pn=Me[Ti]&&Me[Ti][He]),typeof pn>"u"||!pn.length||!pn[0]){var ru="";vs=[];for(Ma in Me[Ti])this.terminals_[Ma]&&Ma>Ks&&vs.push("'"+this.terminals_[Ma]+"'");Xi.showPosition?ru="Parse error on line "+(on+1)+`: +`+Xi.showPosition()+` +Expecting `+vs.join(", ")+", got '"+(this.terminals_[He]||He)+"'":ru="Parse error on line "+(on+1)+": Unexpected "+(He==ws?"end of input":"'"+(this.terminals_[He]||He)+"'"),this.parseError(ru,{text:Xi.match,token:this.terminals_[He]||He,line:Xi.yylineno,loc:di,expected:vs})}if(pn[0]instanceof Array&&pn.length>1)throw new Error("Parse Error: multiple actions possible at state: "+Ti+", token: "+He);switch(pn[0]){case 1:re.push(He),Pe.push(Xi.yytext),te.push(Xi.yylloc),re.push(pn[1]),He=null,ni=Xi.yyleng,de=Xi.yytext,on=Xi.yylineno,di=Xi.yylloc;break;case 2:if(Gs=this.productions_[pn[1]][1],qa.$=Pe[Pe.length-Gs],qa._$={first_line:te[te.length-(Gs||1)].first_line,last_line:te[te.length-1].last_line,first_column:te[te.length-(Gs||1)].first_column,last_column:te[te.length-1].last_column},Ee&&(qa._$.range=[te[te.length-(Gs||1)].range[0],te[te.length-1].range[1]]),Es=this.performAction.apply(qa,[de,ni,on,Er.yy,pn[1],Pe,te].concat(fo)),typeof Es<"u")return Es;Gs&&(re=re.slice(0,-1*Gs*2),Pe=Pe.slice(0,-1*Gs),te=te.slice(0,-1*Gs)),re.push(this.productions_[pn[1]][0]),Pe.push(qa.$),te.push(qa._$),Po=Me[re[re.length-2]][re[re.length-1]],re.push(Po);break;case 3:return!0}}return!0}},Ve=function(){var ce={EOF:1,parseError:function(zt,re){if(this.yy.parser)this.yy.parser.parseError(zt,re);else throw new Error(zt)},setInput:function(ke,zt){return this.yy=zt||this.yy||{},this._input=ke,this._more=this._backtrack=this.done=!1,this.yylineno=this.yyleng=0,this.yytext=this.matched=this.match="",this.conditionStack=["INITIAL"],this.yylloc={first_line:1,first_column:0,last_line:1,last_column:0},this.options.ranges&&(this.yylloc.range=[0,0]),this.offset=0,this},input:function(){var ke=this._input[0];this.yytext+=ke,this.yyleng++,this.offset++,this.match+=ke,this.matched+=ke;var zt=ke.match(/(?:\r\n?|\n).*/g);return zt?(this.yylineno++,this.yylloc.last_line++):this.yylloc.last_column++,this.options.ranges&&this.yylloc.range[1]++,this._input=this._input.slice(1),ke},unput:function(ke){var zt=ke.length,re=ke.split(/(?:\r\n?|\n)/g);this._input=ke+this._input,this.yytext=this.yytext.substr(0,this.yytext.length-zt),this.offset-=zt;var se=this.match.split(/(?:\r\n?|\n)/g);this.match=this.match.substr(0,this.match.length-1),this.matched=this.matched.substr(0,this.matched.length-1),re.length-1&&(this.yylineno-=re.length-1);var Pe=this.yylloc.range;return this.yylloc={first_line:this.yylloc.first_line,last_line:this.yylineno+1,first_column:this.yylloc.first_column,last_column:re?(re.length===se.length?this.yylloc.first_column:0)+se[se.length-re.length].length-re[0].length:this.yylloc.first_column-zt},this.options.ranges&&(this.yylloc.range=[Pe[0],Pe[0]+this.yyleng-zt]),this.yyleng=this.yytext.length,this},more:function(){return this._more=!0,this},reject:function(){if(this.options.backtrack_lexer)this._backtrack=!0;else return this.parseError("Lexical error on line "+(this.yylineno+1)+`. You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true). +`+this.showPosition(),{text:"",token:null,line:this.yylineno});return this},less:function(ke){this.unput(this.match.slice(ke))},pastInput:function(){var ke=this.matched.substr(0,this.matched.length-this.match.length);return(ke.length>20?"...":"")+ke.substr(-20).replace(/\n/g,"")},upcomingInput:function(){var ke=this.match;return ke.length<20&&(ke+=this._input.substr(0,20-ke.length)),(ke.substr(0,20)+(ke.length>20?"...":"")).replace(/\n/g,"")},showPosition:function(){var ke=this.pastInput(),zt=new Array(ke.length+1).join("-");return ke+this.upcomingInput()+` +`+zt+"^"},test_match:function(ke,zt){var re,se,Pe;if(this.options.backtrack_lexer&&(Pe={yylineno:this.yylineno,yylloc:{first_line:this.yylloc.first_line,last_line:this.last_line,first_column:this.yylloc.first_column,last_column:this.yylloc.last_column},yytext:this.yytext,match:this.match,matches:this.matches,matched:this.matched,yyleng:this.yyleng,offset:this.offset,_more:this._more,_input:this._input,yy:this.yy,conditionStack:this.conditionStack.slice(0),done:this.done},this.options.ranges&&(Pe.yylloc.range=this.yylloc.range.slice(0))),se=ke[0].match(/(?:\r\n?|\n).*/g),se&&(this.yylineno+=se.length),this.yylloc={first_line:this.yylloc.last_line,last_line:this.yylineno+1,first_column:this.yylloc.last_column,last_column:se?se[se.length-1].length-se[se.length-1].match(/\r?\n?/)[0].length:this.yylloc.last_column+ke[0].length},this.yytext+=ke[0],this.match+=ke[0],this.matches=ke,this.yyleng=this.yytext.length,this.options.ranges&&(this.yylloc.range=[this.offset,this.offset+=this.yyleng]),this._more=!1,this._backtrack=!1,this._input=this._input.slice(ke[0].length),this.matched+=ke[0],re=this.performAction.call(this,this.yy,this,zt,this.conditionStack[this.conditionStack.length-1]),this.done&&this._input&&(this.done=!1),re)return re;if(this._backtrack){for(var te in Pe)this[te]=Pe[te];return!1}return!1},next:function(){if(this.done)return this.EOF;this._input||(this.done=!0);var ke,zt,re,se;this._more||(this.yytext="",this.match="");for(var Pe=this._currentRules(),te=0;tezt[0].length)){if(zt=re,se=te,this.options.backtrack_lexer){if(ke=this.test_match(re,Pe[te]),ke!==!1)return ke;if(this._backtrack){zt=!1;continue}else return!1}else if(!this.options.flex)break}return zt?(ke=this.test_match(zt,Pe[se]),ke!==!1?ke:!1):this._input===""?this.EOF:this.parseError("Lexical error on line "+(this.yylineno+1)+`. Unrecognized text. +`+this.showPosition(),{text:"",token:null,line:this.yylineno})},lex:function(){var zt=this.next();return zt||this.lex()},begin:function(zt){this.conditionStack.push(zt)},popState:function(){var zt=this.conditionStack.length-1;return zt>0?this.conditionStack.pop():this.conditionStack[0]},_currentRules:function(){return this.conditionStack.length&&this.conditionStack[this.conditionStack.length-1]?this.conditions[this.conditionStack[this.conditionStack.length-1]].rules:this.conditions.INITIAL.rules},topState:function(zt){return zt=this.conditionStack.length-1-Math.abs(zt||0),zt>=0?this.conditionStack[zt]:"INITIAL"},pushState:function(zt){this.begin(zt)},stateStackSize:function(){return this.conditionStack.length},options:{"case-insensitive":!0},performAction:function(zt,re,se,Pe){switch(se){case 0:return 5;case 1:break;case 2:break;case 3:break;case 4:break;case 5:break;case 6:return 19;case 7:return this.begin("LINE"),14;case 8:return this.begin("ID"),50;case 9:return this.begin("ID"),52;case 10:return 13;case 11:return this.begin("ID"),53;case 12:return re.yytext=re.yytext.trim(),this.begin("ALIAS"),70;case 13:return this.popState(),this.popState(),this.begin("LINE"),51;case 14:return this.popState(),this.popState(),5;case 15:return this.begin("LINE"),36;case 16:return this.begin("LINE"),37;case 17:return this.begin("LINE"),38;case 18:return this.begin("LINE"),39;case 19:return this.begin("LINE"),49;case 20:return this.begin("LINE"),41;case 21:return this.begin("LINE"),43;case 22:return this.begin("LINE"),48;case 23:return this.begin("LINE"),44;case 24:return this.begin("LINE"),47;case 25:return this.begin("LINE"),46;case 26:return this.popState(),15;case 27:return 16;case 28:return 65;case 29:return 66;case 30:return 59;case 31:return 60;case 32:return 61;case 33:return 62;case 34:return 57;case 35:return 54;case 36:return this.begin("ID"),21;case 37:return this.begin("ID"),23;case 38:return 29;case 39:return 30;case 40:return this.begin("acc_title"),31;case 41:return this.popState(),"acc_title_value";case 42:return this.begin("acc_descr"),33;case 43:return this.popState(),"acc_descr_value";case 44:this.begin("acc_descr_multiline");break;case 45:this.popState();break;case 46:return"acc_descr_multiline_value";case 47:return 6;case 48:return 18;case 49:return 20;case 50:return 64;case 51:return 5;case 52:return re.yytext=re.yytext.trim(),70;case 53:return 73;case 54:return 74;case 55:return 71;case 56:return 72;case 57:return 75;case 58:return 76;case 59:return 77;case 60:return 78;case 61:return 79;case 62:return 68;case 63:return 69;case 64:return 5;case 65:return"INVALID"}},rules:[/^(?:[\n]+)/i,/^(?:\s+)/i,/^(?:((?!\n)\s)+)/i,/^(?:#[^\n]*)/i,/^(?:%(?!\{)[^\n]*)/i,/^(?:[^\}]%%[^\n]*)/i,/^(?:[0-9]+(?=[ \n]+))/i,/^(?:box\b)/i,/^(?:participant\b)/i,/^(?:actor\b)/i,/^(?:create\b)/i,/^(?:destroy\b)/i,/^(?:[^\->:\n,;]+?([\-]*[^\->:\n,;]+?)*?(?=((?!\n)\s)+as(?!\n)\s|[#\n;]|$))/i,/^(?:as\b)/i,/^(?:(?:))/i,/^(?:loop\b)/i,/^(?:rect\b)/i,/^(?:opt\b)/i,/^(?:alt\b)/i,/^(?:else\b)/i,/^(?:par\b)/i,/^(?:par_over\b)/i,/^(?:and\b)/i,/^(?:critical\b)/i,/^(?:option\b)/i,/^(?:break\b)/i,/^(?:(?:[:]?(?:no)?wrap)?[^#\n;]*)/i,/^(?:end\b)/i,/^(?:left of\b)/i,/^(?:right of\b)/i,/^(?:links\b)/i,/^(?:link\b)/i,/^(?:properties\b)/i,/^(?:details\b)/i,/^(?:over\b)/i,/^(?:note\b)/i,/^(?:activate\b)/i,/^(?:deactivate\b)/i,/^(?:title\s[^#\n;]+)/i,/^(?:title:\s[^#\n;]+)/i,/^(?:accTitle\s*:\s*)/i,/^(?:(?!\n||)*[^\n]*)/i,/^(?:accDescr\s*:\s*)/i,/^(?:(?!\n||)*[^\n]*)/i,/^(?:accDescr\s*\{\s*)/i,/^(?:[\}])/i,/^(?:[^\}]*)/i,/^(?:sequenceDiagram\b)/i,/^(?:autonumber\b)/i,/^(?:off\b)/i,/^(?:,)/i,/^(?:;)/i,/^(?:[^\+\->:\n,;]+((?!(-x|--x|-\)|--\)))[\-]*[^\+\->:\n,;]+)*)/i,/^(?:->>)/i,/^(?:-->>)/i,/^(?:->)/i,/^(?:-->)/i,/^(?:-[x])/i,/^(?:--[x])/i,/^(?:-[\)])/i,/^(?:--[\)])/i,/^(?::(?:(?:no)?wrap)?[^#\n;]+)/i,/^(?:\+)/i,/^(?:-)/i,/^(?:$)/i,/^(?:.)/i],conditions:{acc_descr_multiline:{rules:[45,46],inclusive:!1},acc_descr:{rules:[43],inclusive:!1},acc_title:{rules:[41],inclusive:!1},ID:{rules:[2,3,12],inclusive:!1},ALIAS:{rules:[2,3,13,14],inclusive:!1},LINE:{rules:[2,3,26],inclusive:!1},INITIAL:{rules:[0,1,3,4,5,6,7,8,9,10,11,15,16,17,18,19,20,21,22,23,24,25,27,28,29,30,31,32,33,34,35,36,37,38,39,40,42,44,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65],inclusive:!0}}};return ce}();me.lexer=Ve;function Ye(){this.yy={}}return Ye.prototype=me,me.Parser=Ye,new Ye}();ggt.parser=ggt;const tVe=ggt;let HF,R5={},pgt={},bgt={},dL=[],zb=[],RY=!1,wgt,j5,VF,gL;const eVe=function(i){dL.push({name:i.text,wrap:i.wrap===void 0&&CT()||!!i.wrap,fill:i.color,actorKeys:[]}),j5=dL.slice(-1)[0]},vgt=function(i,a,f,p){let w=j5;const m=R5[i];if(m){if(j5&&m.box&&j5!==m.box)throw new Error("A same participant should only be defined in one Box: "+m.name+" can't be in '"+m.box.name+"' and in '"+j5.name+"' at the same time.");if(w=m.box?m.box:j5,m.box=w,m&&a===m.name&&f==null)return}(f==null||f.text==null)&&(f={text:a,wrap:null,type:p}),(p==null||f.text==null)&&(f={text:a,wrap:null,type:p}),R5[i]={box:w,name:a,description:f.text,wrap:f.wrap===void 0&&CT()||!!f.wrap,prevActor:HF,links:{},properties:{},actorCnt:null,rectData:null,type:p||"participant"},HF&&R5[HF]&&(R5[HF].nextActor=i),j5&&j5.actorKeys.push(i),HF=i},nVe=i=>{let a,f=0;for(a=0;a>-",token:"->>-",line:"1",loc:{first_line:1,last_line:1,first_column:1,last_column:1},expected:["'ACTIVE_PARTICIPANT'"]},b}return zb.push({from:i,to:a,message:f.text,wrap:f.wrap===void 0&&CT()||!!f.wrap,type:p,activate:w}),!0},iVe=function(){return dL.length>0},sVe=function(){return dL.some(i=>i.name)},aVe=function(){return zb},oVe=function(){return dL},cVe=function(){return R5},uVe=function(){return pgt},lVe=function(){return bgt},GF=function(i){return R5[i]},hVe=function(){return Object.keys(R5)},fVe=function(){RY=!0},dVe=function(){RY=!1},gVe=()=>RY,pVe=function(i){wgt=i},CT=()=>wgt!==void 0?wgt:Oe().sequence.wrap,bVe=function(){R5={},pgt={},bgt={},dL=[],zb=[],RY=!1,hg()},wVe=function(i){const a=i.trim(),f={text:a.replace(/^:?(?:no)?wrap:/,"").trim(),wrap:a.match(/^:?wrap:/)!==null?!0:a.match(/^:?nowrap:/)!==null?!1:void 0};return Ut.debug("parseMessage:",f),f},vVe=function(i){const a=i.match(/^((?:rgba?|hsla?)\s*\(.*\)|\w*)(.*)$/);let f=a!=null&&a[1]?a[1].trim():"transparent",p=a!=null&&a[2]?a[2].trim():void 0;if(window&&window.CSS)window.CSS.supports("color",f)||(f="transparent",p=i.trim());else{const m=new Option().style;m.color=f,m.color!==f&&(f="transparent",p=i.trim())}return{color:f,text:p!==void 0?Q1(p.replace(/^:?(?:no)?wrap:/,""),Oe()):void 0,wrap:p!==void 0?p.match(/^:?wrap:/)!==null?!0:p.match(/^:?nowrap:/)!==null?!1:void 0:void 0}},UF={SOLID:0,DOTTED:1,NOTE:2,SOLID_CROSS:3,DOTTED_CROSS:4,SOLID_OPEN:5,DOTTED_OPEN:6,LOOP_START:10,LOOP_END:11,ALT_START:12,ALT_ELSE:13,ALT_END:14,OPT_START:15,OPT_END:16,ACTIVE_START:17,ACTIVE_END:18,PAR_START:19,PAR_AND:20,PAR_END:21,RECT_START:22,RECT_END:23,SOLID_POINT:24,DOTTED_POINT:25,AUTONUMBER:26,CRITICAL_START:27,CRITICAL_OPTION:28,CRITICAL_END:29,BREAK_START:30,BREAK_END:31,PAR_OVER_START:32},mVe={FILLED:0,OPEN:1},yVe={LEFTOF:0,RIGHTOF:1,OVER:2},_Rt=function(i,a,f){f.text,f.wrap===void 0&&CT()||f.wrap;const p=[].concat(i,i);zb.push({from:p[0],to:p[1],message:f.text,wrap:f.wrap===void 0&&CT()||!!f.wrap,type:UF.NOTE,placement:a})},SRt=function(i,a){const f=GF(i);try{let p=Q1(a.text,Oe());p=p.replace(/&/g,"&"),p=p.replace(/=/g,"=");const w=JSON.parse(p);mgt(f,w)}catch(p){Ut.error("error while parsing actor link text",p)}},xVe=function(i,a){const f=GF(i);try{const b={};let E=Q1(a.text,Oe());var p=E.indexOf("@");E=E.replace(/&/g,"&"),E=E.replace(/=/g,"=");var w=E.slice(0,p-1).trim(),m=E.slice(p+1).trim();b[w]=m,mgt(f,b)}catch(b){Ut.error("error while parsing actor link text",b)}};function mgt(i,a){if(i.links==null)i.links=a;else for(let f in a)i.links[f]=a[f]}const ARt=function(i,a){const f=GF(i);try{let p=Q1(a.text,Oe());const w=JSON.parse(p);LRt(f,w)}catch(p){Ut.error("error while parsing actor properties text",p)}};function LRt(i,a){if(i.properties==null)i.properties=a;else for(let f in a)i.properties[f]=a[f]}function kVe(){j5=void 0}const MRt=function(i,a){const f=GF(i),p=document.getElementById(a.text);try{const w=p.innerHTML,m=JSON.parse(w);m.properties&&LRt(f,m.properties),m.links&&mgt(f,m.links)}catch(w){Ut.error("error while parsing actor details text",w)}},EVe=function(i,a){if(i!==void 0&&i.properties!==void 0)return i.properties[a]},DRt=function(i){if(Array.isArray(i))i.forEach(function(a){DRt(a)});else switch(i.type){case"sequenceIndex":zb.push({from:void 0,to:void 0,message:{start:i.sequenceIndex,step:i.sequenceIndexStep,visible:i.sequenceVisible},wrap:!1,type:i.signalType});break;case"addParticipant":vgt(i.actor,i.actor,i.description,i.draw);break;case"createParticipant":if(R5[i.actor])throw new Error("It is not possible to have actors with the same id, even if one is destroyed before the next is created. Use 'AS' aliases to simulate the behavior");VF=i.actor,vgt(i.actor,i.actor,i.description,i.draw),pgt[i.actor]=zb.length;break;case"destroyParticipant":gL=i.actor,bgt[i.actor]=zb.length;break;case"activeStart":ef(i.actor,void 0,void 0,i.signalType);break;case"activeEnd":ef(i.actor,void 0,void 0,i.signalType);break;case"addNote":_Rt(i.actor,i.placement,i.text);break;case"addLinks":SRt(i.actor,i.text);break;case"addALink":xVe(i.actor,i.text);break;case"addProperties":ARt(i.actor,i.text);break;case"addDetails":MRt(i.actor,i.text);break;case"addMessage":if(VF){if(i.to!==VF)throw new Error("The created participant "+VF+" does not have an associated creating message after its declaration. Please check the sequence diagram.");VF=void 0}else if(gL){if(i.to!==gL&&i.from!==gL)throw new Error("The destroyed participant "+gL+" does not have an associated destroying message after its declaration. Please check the sequence diagram.");gL=void 0}ef(i.from,i.to,i.msg,i.signalType,i.activate);break;case"boxStart":eVe(i.boxData);break;case"boxEnd":kVe();break;case"loopStart":ef(void 0,void 0,i.loopText,i.signalType);break;case"loopEnd":ef(void 0,void 0,void 0,i.signalType);break;case"rectStart":ef(void 0,void 0,i.color,i.signalType);break;case"rectEnd":ef(void 0,void 0,void 0,i.signalType);break;case"optStart":ef(void 0,void 0,i.optText,i.signalType);break;case"optEnd":ef(void 0,void 0,void 0,i.signalType);break;case"altStart":ef(void 0,void 0,i.altText,i.signalType);break;case"else":ef(void 0,void 0,i.altText,i.signalType);break;case"altEnd":ef(void 0,void 0,void 0,i.signalType);break;case"setAccTitle":E0(i.text);break;case"parStart":ef(void 0,void 0,i.parText,i.signalType);break;case"and":ef(void 0,void 0,i.parText,i.signalType);break;case"parEnd":ef(void 0,void 0,void 0,i.signalType);break;case"criticalStart":ef(void 0,void 0,i.criticalText,i.signalType);break;case"option":ef(void 0,void 0,i.optionText,i.signalType);break;case"criticalEnd":ef(void 0,void 0,void 0,i.signalType);break;case"breakStart":ef(void 0,void 0,i.breakText,i.signalType);break;case"breakEnd":ef(void 0,void 0,void 0,i.signalType);break}},IRt={addActor:vgt,addMessage:rVe,addSignal:ef,addLinks:SRt,addDetails:MRt,addProperties:ARt,autoWrap:CT,setWrap:pVe,enableSequenceNumbers:fVe,disableSequenceNumbers:dVe,showSequenceNumbers:gVe,getMessages:aVe,getActors:cVe,getCreatedActors:uVe,getDestroyedActors:lVe,getActor:GF,getActorKeys:hVe,getActorProperty:EVe,getAccTitle:fg,getBoxes:oVe,getDiagramTitle:pg,setDiagramTitle:Nb,getConfig:()=>Oe().sequence,clear:bVe,parseMessage:wVe,parseBoxData:vVe,LINETYPE:UF,ARROWTYPE:mVe,PLACEMENT:yVe,addNote:_Rt,setAccTitle:E0,apply:DRt,setAccDescription:dg,getAccDescription:gg,hasAtLeastOneBox:iVe,hasAtLeastOneBoxWithTitle:sVe},TVe=i=>`.actor { + stroke: ${i.actorBorder}; + fill: ${i.actorBkg}; + } + + text.actor > tspan { + fill: ${i.actorTextColor}; + stroke: none; + } + + .actor-line { + stroke: ${i.actorLineColor}; + } + + .messageLine0 { + stroke-width: 1.5; + stroke-dasharray: none; + stroke: ${i.signalColor}; + } + + .messageLine1 { + stroke-width: 1.5; + stroke-dasharray: 2, 2; + stroke: ${i.signalColor}; + } + + #arrowhead path { + fill: ${i.signalColor}; + stroke: ${i.signalColor}; + } + + .sequenceNumber { + fill: ${i.sequenceNumberColor}; + } + + #sequencenumber { + fill: ${i.signalColor}; + } + + #crosshead path { + fill: ${i.signalColor}; + stroke: ${i.signalColor}; + } + + .messageText { + fill: ${i.signalTextColor}; + stroke: none; + } + + .labelBox { + stroke: ${i.labelBoxBorderColor}; + fill: ${i.labelBoxBkgColor}; + } + + .labelText, .labelText > tspan { + fill: ${i.labelTextColor}; + stroke: none; + } + + .loopText, .loopText > tspan { + fill: ${i.loopTextColor}; + stroke: none; + } + + .loopLine { + stroke-width: 2px; + stroke-dasharray: 2, 2; + stroke: ${i.labelBoxBorderColor}; + fill: ${i.labelBoxBorderColor}; + } + + .note { + //stroke: #decc93; + stroke: ${i.noteBorderColor}; + fill: ${i.noteBkgColor}; + } + + .noteText, .noteText > tspan { + fill: ${i.noteTextColor}; + stroke: none; + } + + .activation0 { + fill: ${i.activationBkgColor}; + stroke: ${i.activationBorderColor}; + } + + .activation1 { + fill: ${i.activationBkgColor}; + stroke: ${i.activationBorderColor}; + } + + .activation2 { + fill: ${i.activationBkgColor}; + stroke: ${i.activationBorderColor}; + } + + .actorPopupMenu { + position: absolute; + } + + .actorPopupMenuPanel { + position: absolute; + fill: ${i.actorBkg}; + box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2); + filter: drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4)); +} + .actor-man line { + stroke: ${i.actorBorder}; + fill: ${i.actorBkg}; + } + .actor-man circle, line { + stroke: ${i.actorBorder}; + fill: ${i.actorBkg}; + stroke-width: 2px; + } +`,_T=18*2,ygt=function(i,a){return JW(i,a)},ORt=(i,a)=>{vAe(()=>{const f=document.querySelectorAll(i);f.length!==0&&(f[0].addEventListener("mouseover",function(){AVe("actor"+a+"_popup")}),f[0].addEventListener("mouseout",function(){LVe("actor"+a+"_popup")}))})},CVe=function(i,a,f,p,w){if(a.links===void 0||a.links===null||Object.keys(a.links).length===0)return{height:0,width:0};const m=a.links,b=a.actorCnt,E=a.rectData;var _="none";w&&(_="block !important");const A=i.append("g");A.attr("id","actor"+b+"_popup"),A.attr("class","actorPopupMenu"),A.attr("display",_),ORt("#actor"+b+"_popup",b);var I="";E.class!==void 0&&(I=" "+E.class);let B=E.width>f?E.width:f;const N=A.append("rect");if(N.attr("class","actorPopupMenuPanel"+I),N.attr("x",E.x),N.attr("y",E.height),N.attr("fill",E.fill),N.attr("stroke",E.stroke),N.attr("width",B),N.attr("height",E.height),N.attr("rx",E.rx),N.attr("ry",E.ry),m!=null){var R=20;for(let et in m){var z=A.append("a"),W=ik(m[et]);z.attr("xlink:href",W),z.attr("target","_blank"),GVe(p)(et,z,E.x+10,E.height+R,B,20,{class:"actor"},p),R+=30}}return N.attr("height",R),{height:E.height+R,width:B}},_Ve=function(i){return"var pu = document.getElementById('"+i+"'); if (pu != null) { pu.style.display = 'block'; }"},SVe=function(i){return"var pu = document.getElementById('"+i+"'); if (pu != null) { pu.style.display = 'none'; }"},AVe=function(i){var a=document.getElementById(i);a!=null&&(a.style.display="block")},LVe=function(i){var a=document.getElementById(i);a!=null&&(a.style.display="none")},pL=function(i,a){let f=0,p=0;const w=a.text.split(Kr.lineBreakRegex),[m,b]=VA(a.fontSize);let E=[],_=0,A=()=>a.y;if(a.valign!==void 0&&a.textMargin!==void 0&&a.textMargin>0)switch(a.valign){case"top":case"start":A=()=>Math.round(a.y+a.textMargin);break;case"middle":case"center":A=()=>Math.round(a.y+(f+p+a.textMargin)/2);break;case"bottom":case"end":A=()=>Math.round(a.y+(f+p+2*a.textMargin)-a.textMargin);break}if(a.anchor!==void 0&&a.textMargin!==void 0&&a.width!==void 0)switch(a.anchor){case"left":case"start":a.x=Math.round(a.x+a.textMargin),a.anchor="start",a.dominantBaseline="middle",a.alignmentBaseline="middle";break;case"middle":case"center":a.x=Math.round(a.x+a.width/2),a.anchor="middle",a.dominantBaseline="middle",a.alignmentBaseline="middle";break;case"right":case"end":a.x=Math.round(a.x+a.width-a.textMargin),a.anchor="end",a.dominantBaseline="middle",a.alignmentBaseline="middle";break}for(let[I,B]of w.entries()){a.textMargin!==void 0&&a.textMargin===0&&m!==void 0&&(_=I*m);const N=i.append("text");N.attr("x",a.x),N.attr("y",A()),a.anchor!==void 0&&N.attr("text-anchor",a.anchor).attr("dominant-baseline",a.dominantBaseline).attr("alignment-baseline",a.alignmentBaseline),a.fontFamily!==void 0&&N.style("font-family",a.fontFamily),b!==void 0&&N.style("font-size",b),a.fontWeight!==void 0&&N.style("font-weight",a.fontWeight),a.fill!==void 0&&N.attr("fill",a.fill),a.class!==void 0&&N.attr("class",a.class),a.dy!==void 0?N.attr("dy",a.dy):_!==0&&N.attr("dy",_);const R=B||jIt;if(a.tspan){const z=N.append("tspan");z.attr("x",a.x),a.fill!==void 0&&z.attr("fill",a.fill),z.text(R)}else N.text(R);a.valign!==void 0&&a.textMargin!==void 0&&a.textMargin>0&&(p+=(N._groups||N)[0][0].getBBox().height,f=p),E.push(N)}return E},PRt=function(i,a){function f(w,m,b,E,_){return w+","+m+" "+(w+b)+","+m+" "+(w+b)+","+(m+E-_)+" "+(w+b-_*1.2)+","+(m+E)+" "+w+","+(m+E)}const p=i.append("polygon");return p.attr("points",f(a.x,a.y,a.width,a.height,7)),p.attr("class","labelBox"),a.y=a.y+a.height/2,pL(i,a),p};let gm=-1;const FRt=(i,a,f,p)=>{i.select&&f.forEach(w=>{const m=a[w],b=i.select("#actor"+m.actorCnt);!p.mirrorActors&&m.stopy?b.attr("y2",m.stopy+m.height/2):p.mirrorActors&&b.attr("y2",m.stopy)})},MVe=function(i,a,f,p){const w=p?a.stopy:a.starty,m=a.x+a.width/2,b=w+5,E=i.append("g").lower();var _=E;p||(gm++,_.append("line").attr("id","actor"+gm).attr("x1",m).attr("y1",b).attr("x2",m).attr("y2",2e3).attr("class","actor-line").attr("class","200").attr("stroke-width","0.5px").attr("stroke","#999"),_=E.append("g"),a.actorCnt=gm,a.links!=null&&(_.attr("id","root-"+gm),ORt("#root-"+gm,gm)));const A=bT();var I="actor";a.properties!=null&&a.properties.class?I=a.properties.class:A.fill="#eaeaea",A.x=a.x,A.y=w,A.width=a.width,A.height=a.height,A.class=I,A.rx=3,A.ry=3;const B=ygt(_,A);if(a.rectData=A,a.properties!=null&&a.properties.icon){const R=a.properties.icon.trim();R.charAt(0)==="@"?$De(_,A.x+A.width-20,A.y+10,R.substr(1)):jDe(_,A.x+A.width-20,A.y+10,R)}xgt(f)(a.description,_,A.x,A.y,A.width,A.height,{class:"actor"},f);let N=a.height;if(B.node){const R=B.node().getBBox();a.height=R.height,N=R.height}return N},DVe=function(i,a,f,p){const w=p?a.stopy:a.starty,m=a.x+a.width/2,b=w+80;i.lower(),p||(gm++,i.append("line").attr("id","actor"+gm).attr("x1",m).attr("y1",b).attr("x2",m).attr("y2",2e3).attr("class","actor-line").attr("class","200").attr("stroke-width","0.5px").attr("stroke","#999"),a.actorCnt=gm);const E=i.append("g");E.attr("class","actor-man");const _=bT();_.x=a.x,_.y=w,_.fill="#eaeaea",_.width=a.width,_.height=a.height,_.class="actor",_.rx=3,_.ry=3,E.append("line").attr("id","actor-man-torso"+gm).attr("x1",m).attr("y1",w+25).attr("x2",m).attr("y2",w+45),E.append("line").attr("id","actor-man-arms"+gm).attr("x1",m-_T/2).attr("y1",w+33).attr("x2",m+_T/2).attr("y2",w+33),E.append("line").attr("x1",m-_T/2).attr("y1",w+60).attr("x2",m).attr("y2",w+45),E.append("line").attr("x1",m).attr("y1",w+45).attr("x2",m+_T/2-2).attr("y2",w+60);const A=E.append("circle");A.attr("cx",a.x+a.width/2),A.attr("cy",w+10),A.attr("r",15),A.attr("width",a.width),A.attr("height",a.height);const I=E.node().getBBox();return a.height=I.height,xgt(f)(a.description,E,_.x,_.y+35,_.width,_.height,{class:"actor"},f),a.height},IVe=function(i,a,f,p){switch(a.type){case"actor":return DVe(i,a,f,p);case"participant":return MVe(i,a,f,p)}},OVe=function(i,a,f){const w=i.append("g");NRt(w,a),a.name&&xgt(f)(a.name,w,a.x,a.y+(a.textMaxHeight||0)/2,a.width,0,{class:"text"},f),w.lower()},PVe=function(i){return i.append("g")},FVe=function(i,a,f,p,w){const m=bT(),b=a.anchored;m.x=a.startx,m.y=a.starty,m.class="activation"+w%3,m.width=a.stopx-a.startx,m.height=f-a.starty,ygt(b,m)},NVe=function(i,a,f,p){const{boxMargin:w,boxTextMargin:m,labelBoxHeight:b,labelBoxWidth:E,messageFontFamily:_,messageFontSize:A,messageFontWeight:I}=p,B=i.append("g"),N=function(W,et,st,at){return B.append("line").attr("x1",W).attr("y1",et).attr("x2",st).attr("y2",at).attr("class","loopLine")};N(a.startx,a.starty,a.stopx,a.starty),N(a.stopx,a.starty,a.stopx,a.stopy),N(a.startx,a.stopy,a.stopx,a.stopy),N(a.startx,a.starty,a.startx,a.stopy),a.sections!==void 0&&a.sections.forEach(function(W){N(a.startx,W.y,a.stopx,W.y).style("stroke-dasharray","3, 3")});let R=Rdt();R.text=f,R.x=a.startx,R.y=a.starty,R.fontFamily=_,R.fontSize=A,R.fontWeight=I,R.anchor="middle",R.valign="middle",R.tspan=!1,R.width=E||50,R.height=b||20,R.textMargin=m,R.class="labelText",PRt(B,R),R=BRt(),R.text=a.title,R.x=a.startx+E/2+(a.stopx-a.startx)/2,R.y=a.starty+w+m,R.anchor="middle",R.valign="middle",R.textMargin=m,R.class="loopText",R.fontFamily=_,R.fontSize=A,R.fontWeight=I,R.wrap=!0;let z=pL(B,R);return a.sectionTitles!==void 0&&a.sectionTitles.forEach(function(W,et){if(W.message){R.text=W.message,R.x=a.startx+(a.stopx-a.startx)/2,R.y=a.sections[et].y+w+m,R.class="loopText",R.anchor="middle",R.valign="middle",R.tspan=!1,R.fontFamily=_,R.fontSize=A,R.fontWeight=I,R.wrap=a.wrap,z=pL(B,R);let st=Math.round(z.map(at=>(at._groups||at)[0][0].getBBox().height).reduce((at,bt)=>at+bt));a.sections[et].height+=st-(w+m)}}),a.height=Math.round(a.stopy-a.starty),B},NRt=function(i,a){mPt(i,a)},BVe=function(i){i.append("defs").append("symbol").attr("id","database").attr("fill-rule","evenodd").attr("clip-rule","evenodd").append("path").attr("transform","scale(.5)").attr("d","M12.258.001l.256.004.255.005.253.008.251.01.249.012.247.015.246.016.242.019.241.02.239.023.236.024.233.027.231.028.229.031.225.032.223.034.22.036.217.038.214.04.211.041.208.043.205.045.201.046.198.048.194.05.191.051.187.053.183.054.18.056.175.057.172.059.168.06.163.061.16.063.155.064.15.066.074.033.073.033.071.034.07.034.069.035.068.035.067.035.066.035.064.036.064.036.062.036.06.036.06.037.058.037.058.037.055.038.055.038.053.038.052.038.051.039.05.039.048.039.047.039.045.04.044.04.043.04.041.04.04.041.039.041.037.041.036.041.034.041.033.042.032.042.03.042.029.042.027.042.026.043.024.043.023.043.021.043.02.043.018.044.017.043.015.044.013.044.012.044.011.045.009.044.007.045.006.045.004.045.002.045.001.045v17l-.001.045-.002.045-.004.045-.006.045-.007.045-.009.044-.011.045-.012.044-.013.044-.015.044-.017.043-.018.044-.02.043-.021.043-.023.043-.024.043-.026.043-.027.042-.029.042-.03.042-.032.042-.033.042-.034.041-.036.041-.037.041-.039.041-.04.041-.041.04-.043.04-.044.04-.045.04-.047.039-.048.039-.05.039-.051.039-.052.038-.053.038-.055.038-.055.038-.058.037-.058.037-.06.037-.06.036-.062.036-.064.036-.064.036-.066.035-.067.035-.068.035-.069.035-.07.034-.071.034-.073.033-.074.033-.15.066-.155.064-.16.063-.163.061-.168.06-.172.059-.175.057-.18.056-.183.054-.187.053-.191.051-.194.05-.198.048-.201.046-.205.045-.208.043-.211.041-.214.04-.217.038-.22.036-.223.034-.225.032-.229.031-.231.028-.233.027-.236.024-.239.023-.241.02-.242.019-.246.016-.247.015-.249.012-.251.01-.253.008-.255.005-.256.004-.258.001-.258-.001-.256-.004-.255-.005-.253-.008-.251-.01-.249-.012-.247-.015-.245-.016-.243-.019-.241-.02-.238-.023-.236-.024-.234-.027-.231-.028-.228-.031-.226-.032-.223-.034-.22-.036-.217-.038-.214-.04-.211-.041-.208-.043-.204-.045-.201-.046-.198-.048-.195-.05-.19-.051-.187-.053-.184-.054-.179-.056-.176-.057-.172-.059-.167-.06-.164-.061-.159-.063-.155-.064-.151-.066-.074-.033-.072-.033-.072-.034-.07-.034-.069-.035-.068-.035-.067-.035-.066-.035-.064-.036-.063-.036-.062-.036-.061-.036-.06-.037-.058-.037-.057-.037-.056-.038-.055-.038-.053-.038-.052-.038-.051-.039-.049-.039-.049-.039-.046-.039-.046-.04-.044-.04-.043-.04-.041-.04-.04-.041-.039-.041-.037-.041-.036-.041-.034-.041-.033-.042-.032-.042-.03-.042-.029-.042-.027-.042-.026-.043-.024-.043-.023-.043-.021-.043-.02-.043-.018-.044-.017-.043-.015-.044-.013-.044-.012-.044-.011-.045-.009-.044-.007-.045-.006-.045-.004-.045-.002-.045-.001-.045v-17l.001-.045.002-.045.004-.045.006-.045.007-.045.009-.044.011-.045.012-.044.013-.044.015-.044.017-.043.018-.044.02-.043.021-.043.023-.043.024-.043.026-.043.027-.042.029-.042.03-.042.032-.042.033-.042.034-.041.036-.041.037-.041.039-.041.04-.041.041-.04.043-.04.044-.04.046-.04.046-.039.049-.039.049-.039.051-.039.052-.038.053-.038.055-.038.056-.038.057-.037.058-.037.06-.037.061-.036.062-.036.063-.036.064-.036.066-.035.067-.035.068-.035.069-.035.07-.034.072-.034.072-.033.074-.033.151-.066.155-.064.159-.063.164-.061.167-.06.172-.059.176-.057.179-.056.184-.054.187-.053.19-.051.195-.05.198-.048.201-.046.204-.045.208-.043.211-.041.214-.04.217-.038.22-.036.223-.034.226-.032.228-.031.231-.028.234-.027.236-.024.238-.023.241-.02.243-.019.245-.016.247-.015.249-.012.251-.01.253-.008.255-.005.256-.004.258-.001.258.001zm-9.258 20.499v.01l.001.021.003.021.004.022.005.021.006.022.007.022.009.023.01.022.011.023.012.023.013.023.015.023.016.024.017.023.018.024.019.024.021.024.022.025.023.024.024.025.052.049.056.05.061.051.066.051.07.051.075.051.079.052.084.052.088.052.092.052.097.052.102.051.105.052.11.052.114.051.119.051.123.051.127.05.131.05.135.05.139.048.144.049.147.047.152.047.155.047.16.045.163.045.167.043.171.043.176.041.178.041.183.039.187.039.19.037.194.035.197.035.202.033.204.031.209.03.212.029.216.027.219.025.222.024.226.021.23.02.233.018.236.016.24.015.243.012.246.01.249.008.253.005.256.004.259.001.26-.001.257-.004.254-.005.25-.008.247-.011.244-.012.241-.014.237-.016.233-.018.231-.021.226-.021.224-.024.22-.026.216-.027.212-.028.21-.031.205-.031.202-.034.198-.034.194-.036.191-.037.187-.039.183-.04.179-.04.175-.042.172-.043.168-.044.163-.045.16-.046.155-.046.152-.047.148-.048.143-.049.139-.049.136-.05.131-.05.126-.05.123-.051.118-.052.114-.051.11-.052.106-.052.101-.052.096-.052.092-.052.088-.053.083-.051.079-.052.074-.052.07-.051.065-.051.06-.051.056-.05.051-.05.023-.024.023-.025.021-.024.02-.024.019-.024.018-.024.017-.024.015-.023.014-.024.013-.023.012-.023.01-.023.01-.022.008-.022.006-.022.006-.022.004-.022.004-.021.001-.021.001-.021v-4.127l-.077.055-.08.053-.083.054-.085.053-.087.052-.09.052-.093.051-.095.05-.097.05-.1.049-.102.049-.105.048-.106.047-.109.047-.111.046-.114.045-.115.045-.118.044-.12.043-.122.042-.124.042-.126.041-.128.04-.13.04-.132.038-.134.038-.135.037-.138.037-.139.035-.142.035-.143.034-.144.033-.147.032-.148.031-.15.03-.151.03-.153.029-.154.027-.156.027-.158.026-.159.025-.161.024-.162.023-.163.022-.165.021-.166.02-.167.019-.169.018-.169.017-.171.016-.173.015-.173.014-.175.013-.175.012-.177.011-.178.01-.179.008-.179.008-.181.006-.182.005-.182.004-.184.003-.184.002h-.37l-.184-.002-.184-.003-.182-.004-.182-.005-.181-.006-.179-.008-.179-.008-.178-.01-.176-.011-.176-.012-.175-.013-.173-.014-.172-.015-.171-.016-.17-.017-.169-.018-.167-.019-.166-.02-.165-.021-.163-.022-.162-.023-.161-.024-.159-.025-.157-.026-.156-.027-.155-.027-.153-.029-.151-.03-.15-.03-.148-.031-.146-.032-.145-.033-.143-.034-.141-.035-.14-.035-.137-.037-.136-.037-.134-.038-.132-.038-.13-.04-.128-.04-.126-.041-.124-.042-.122-.042-.12-.044-.117-.043-.116-.045-.113-.045-.112-.046-.109-.047-.106-.047-.105-.048-.102-.049-.1-.049-.097-.05-.095-.05-.093-.052-.09-.051-.087-.052-.085-.053-.083-.054-.08-.054-.077-.054v4.127zm0-5.654v.011l.001.021.003.021.004.021.005.022.006.022.007.022.009.022.01.022.011.023.012.023.013.023.015.024.016.023.017.024.018.024.019.024.021.024.022.024.023.025.024.024.052.05.056.05.061.05.066.051.07.051.075.052.079.051.084.052.088.052.092.052.097.052.102.052.105.052.11.051.114.051.119.052.123.05.127.051.131.05.135.049.139.049.144.048.147.048.152.047.155.046.16.045.163.045.167.044.171.042.176.042.178.04.183.04.187.038.19.037.194.036.197.034.202.033.204.032.209.03.212.028.216.027.219.025.222.024.226.022.23.02.233.018.236.016.24.014.243.012.246.01.249.008.253.006.256.003.259.001.26-.001.257-.003.254-.006.25-.008.247-.01.244-.012.241-.015.237-.016.233-.018.231-.02.226-.022.224-.024.22-.025.216-.027.212-.029.21-.03.205-.032.202-.033.198-.035.194-.036.191-.037.187-.039.183-.039.179-.041.175-.042.172-.043.168-.044.163-.045.16-.045.155-.047.152-.047.148-.048.143-.048.139-.05.136-.049.131-.05.126-.051.123-.051.118-.051.114-.052.11-.052.106-.052.101-.052.096-.052.092-.052.088-.052.083-.052.079-.052.074-.051.07-.052.065-.051.06-.05.056-.051.051-.049.023-.025.023-.024.021-.025.02-.024.019-.024.018-.024.017-.024.015-.023.014-.023.013-.024.012-.022.01-.023.01-.023.008-.022.006-.022.006-.022.004-.021.004-.022.001-.021.001-.021v-4.139l-.077.054-.08.054-.083.054-.085.052-.087.053-.09.051-.093.051-.095.051-.097.05-.1.049-.102.049-.105.048-.106.047-.109.047-.111.046-.114.045-.115.044-.118.044-.12.044-.122.042-.124.042-.126.041-.128.04-.13.039-.132.039-.134.038-.135.037-.138.036-.139.036-.142.035-.143.033-.144.033-.147.033-.148.031-.15.03-.151.03-.153.028-.154.028-.156.027-.158.026-.159.025-.161.024-.162.023-.163.022-.165.021-.166.02-.167.019-.169.018-.169.017-.171.016-.173.015-.173.014-.175.013-.175.012-.177.011-.178.009-.179.009-.179.007-.181.007-.182.005-.182.004-.184.003-.184.002h-.37l-.184-.002-.184-.003-.182-.004-.182-.005-.181-.007-.179-.007-.179-.009-.178-.009-.176-.011-.176-.012-.175-.013-.173-.014-.172-.015-.171-.016-.17-.017-.169-.018-.167-.019-.166-.02-.165-.021-.163-.022-.162-.023-.161-.024-.159-.025-.157-.026-.156-.027-.155-.028-.153-.028-.151-.03-.15-.03-.148-.031-.146-.033-.145-.033-.143-.033-.141-.035-.14-.036-.137-.036-.136-.037-.134-.038-.132-.039-.13-.039-.128-.04-.126-.041-.124-.042-.122-.043-.12-.043-.117-.044-.116-.044-.113-.046-.112-.046-.109-.046-.106-.047-.105-.048-.102-.049-.1-.049-.097-.05-.095-.051-.093-.051-.09-.051-.087-.053-.085-.052-.083-.054-.08-.054-.077-.054v4.139zm0-5.666v.011l.001.02.003.022.004.021.005.022.006.021.007.022.009.023.01.022.011.023.012.023.013.023.015.023.016.024.017.024.018.023.019.024.021.025.022.024.023.024.024.025.052.05.056.05.061.05.066.051.07.051.075.052.079.051.084.052.088.052.092.052.097.052.102.052.105.051.11.052.114.051.119.051.123.051.127.05.131.05.135.05.139.049.144.048.147.048.152.047.155.046.16.045.163.045.167.043.171.043.176.042.178.04.183.04.187.038.19.037.194.036.197.034.202.033.204.032.209.03.212.028.216.027.219.025.222.024.226.021.23.02.233.018.236.017.24.014.243.012.246.01.249.008.253.006.256.003.259.001.26-.001.257-.003.254-.006.25-.008.247-.01.244-.013.241-.014.237-.016.233-.018.231-.02.226-.022.224-.024.22-.025.216-.027.212-.029.21-.03.205-.032.202-.033.198-.035.194-.036.191-.037.187-.039.183-.039.179-.041.175-.042.172-.043.168-.044.163-.045.16-.045.155-.047.152-.047.148-.048.143-.049.139-.049.136-.049.131-.051.126-.05.123-.051.118-.052.114-.051.11-.052.106-.052.101-.052.096-.052.092-.052.088-.052.083-.052.079-.052.074-.052.07-.051.065-.051.06-.051.056-.05.051-.049.023-.025.023-.025.021-.024.02-.024.019-.024.018-.024.017-.024.015-.023.014-.024.013-.023.012-.023.01-.022.01-.023.008-.022.006-.022.006-.022.004-.022.004-.021.001-.021.001-.021v-4.153l-.077.054-.08.054-.083.053-.085.053-.087.053-.09.051-.093.051-.095.051-.097.05-.1.049-.102.048-.105.048-.106.048-.109.046-.111.046-.114.046-.115.044-.118.044-.12.043-.122.043-.124.042-.126.041-.128.04-.13.039-.132.039-.134.038-.135.037-.138.036-.139.036-.142.034-.143.034-.144.033-.147.032-.148.032-.15.03-.151.03-.153.028-.154.028-.156.027-.158.026-.159.024-.161.024-.162.023-.163.023-.165.021-.166.02-.167.019-.169.018-.169.017-.171.016-.173.015-.173.014-.175.013-.175.012-.177.01-.178.01-.179.009-.179.007-.181.006-.182.006-.182.004-.184.003-.184.001-.185.001-.185-.001-.184-.001-.184-.003-.182-.004-.182-.006-.181-.006-.179-.007-.179-.009-.178-.01-.176-.01-.176-.012-.175-.013-.173-.014-.172-.015-.171-.016-.17-.017-.169-.018-.167-.019-.166-.02-.165-.021-.163-.023-.162-.023-.161-.024-.159-.024-.157-.026-.156-.027-.155-.028-.153-.028-.151-.03-.15-.03-.148-.032-.146-.032-.145-.033-.143-.034-.141-.034-.14-.036-.137-.036-.136-.037-.134-.038-.132-.039-.13-.039-.128-.041-.126-.041-.124-.041-.122-.043-.12-.043-.117-.044-.116-.044-.113-.046-.112-.046-.109-.046-.106-.048-.105-.048-.102-.048-.1-.05-.097-.049-.095-.051-.093-.051-.09-.052-.087-.052-.085-.053-.083-.053-.08-.054-.077-.054v4.153zm8.74-8.179l-.257.004-.254.005-.25.008-.247.011-.244.012-.241.014-.237.016-.233.018-.231.021-.226.022-.224.023-.22.026-.216.027-.212.028-.21.031-.205.032-.202.033-.198.034-.194.036-.191.038-.187.038-.183.04-.179.041-.175.042-.172.043-.168.043-.163.045-.16.046-.155.046-.152.048-.148.048-.143.048-.139.049-.136.05-.131.05-.126.051-.123.051-.118.051-.114.052-.11.052-.106.052-.101.052-.096.052-.092.052-.088.052-.083.052-.079.052-.074.051-.07.052-.065.051-.06.05-.056.05-.051.05-.023.025-.023.024-.021.024-.02.025-.019.024-.018.024-.017.023-.015.024-.014.023-.013.023-.012.023-.01.023-.01.022-.008.022-.006.023-.006.021-.004.022-.004.021-.001.021-.001.021.001.021.001.021.004.021.004.022.006.021.006.023.008.022.01.022.01.023.012.023.013.023.014.023.015.024.017.023.018.024.019.024.02.025.021.024.023.024.023.025.051.05.056.05.06.05.065.051.07.052.074.051.079.052.083.052.088.052.092.052.096.052.101.052.106.052.11.052.114.052.118.051.123.051.126.051.131.05.136.05.139.049.143.048.148.048.152.048.155.046.16.046.163.045.168.043.172.043.175.042.179.041.183.04.187.038.191.038.194.036.198.034.202.033.205.032.21.031.212.028.216.027.22.026.224.023.226.022.231.021.233.018.237.016.241.014.244.012.247.011.25.008.254.005.257.004.26.001.26-.001.257-.004.254-.005.25-.008.247-.011.244-.012.241-.014.237-.016.233-.018.231-.021.226-.022.224-.023.22-.026.216-.027.212-.028.21-.031.205-.032.202-.033.198-.034.194-.036.191-.038.187-.038.183-.04.179-.041.175-.042.172-.043.168-.043.163-.045.16-.046.155-.046.152-.048.148-.048.143-.048.139-.049.136-.05.131-.05.126-.051.123-.051.118-.051.114-.052.11-.052.106-.052.101-.052.096-.052.092-.052.088-.052.083-.052.079-.052.074-.051.07-.052.065-.051.06-.05.056-.05.051-.05.023-.025.023-.024.021-.024.02-.025.019-.024.018-.024.017-.023.015-.024.014-.023.013-.023.012-.023.01-.023.01-.022.008-.022.006-.023.006-.021.004-.022.004-.021.001-.021.001-.021-.001-.021-.001-.021-.004-.021-.004-.022-.006-.021-.006-.023-.008-.022-.01-.022-.01-.023-.012-.023-.013-.023-.014-.023-.015-.024-.017-.023-.018-.024-.019-.024-.02-.025-.021-.024-.023-.024-.023-.025-.051-.05-.056-.05-.06-.05-.065-.051-.07-.052-.074-.051-.079-.052-.083-.052-.088-.052-.092-.052-.096-.052-.101-.052-.106-.052-.11-.052-.114-.052-.118-.051-.123-.051-.126-.051-.131-.05-.136-.05-.139-.049-.143-.048-.148-.048-.152-.048-.155-.046-.16-.046-.163-.045-.168-.043-.172-.043-.175-.042-.179-.041-.183-.04-.187-.038-.191-.038-.194-.036-.198-.034-.202-.033-.205-.032-.21-.031-.212-.028-.216-.027-.22-.026-.224-.023-.226-.022-.231-.021-.233-.018-.237-.016-.241-.014-.244-.012-.247-.011-.25-.008-.254-.005-.257-.004-.26-.001-.26.001z")},RVe=function(i){i.append("defs").append("symbol").attr("id","computer").attr("width","24").attr("height","24").append("path").attr("transform","scale(.5)").attr("d","M2 2v13h20v-13h-20zm18 11h-16v-9h16v9zm-10.228 6l.466-1h3.524l.467 1h-4.457zm14.228 3h-24l2-6h2.104l-1.33 4h18.45l-1.297-4h2.073l2 6zm-5-10h-14v-7h14v7z")},jVe=function(i){i.append("defs").append("symbol").attr("id","clock").attr("width","24").attr("height","24").append("path").attr("transform","scale(.5)").attr("d","M12 2c5.514 0 10 4.486 10 10s-4.486 10-10 10-10-4.486-10-10 4.486-10 10-10zm0-2c-6.627 0-12 5.373-12 12s5.373 12 12 12 12-5.373 12-12-5.373-12-12-12zm5.848 12.459c.202.038.202.333.001.372-1.907.361-6.045 1.111-6.547 1.111-.719 0-1.301-.582-1.301-1.301 0-.512.77-5.447 1.125-7.445.034-.192.312-.181.343.014l.985 6.238 5.394 1.011z")},$Ve=function(i){i.append("defs").append("marker").attr("id","arrowhead").attr("refX",7.9).attr("refY",5).attr("markerUnits","userSpaceOnUse").attr("markerWidth",12).attr("markerHeight",12).attr("orient","auto").append("path").attr("d","M 0 0 L 10 5 L 0 10 z")},zVe=function(i){i.append("defs").append("marker").attr("id","filled-head").attr("refX",15.5).attr("refY",7).attr("markerWidth",20).attr("markerHeight",28).attr("orient","auto").append("path").attr("d","M 18,7 L9,13 L14,7 L9,1 Z")},qVe=function(i){i.append("defs").append("marker").attr("id","sequencenumber").attr("refX",15).attr("refY",15).attr("markerWidth",60).attr("markerHeight",40).attr("orient","auto").append("circle").attr("cx",15).attr("cy",15).attr("r",6)},HVe=function(i){i.append("defs").append("marker").attr("id","crosshead").attr("markerWidth",15).attr("markerHeight",8).attr("orient","auto").attr("refX",4).attr("refY",4.5).append("path").attr("fill","none").attr("stroke","#000000").style("stroke-dasharray","0, 0").attr("stroke-width","1pt").attr("d","M 1,2 L 6,7 M 6,2 L 1,7")},BRt=function(){return{x:0,y:0,fill:void 0,anchor:void 0,style:"#666",width:void 0,height:void 0,textMargin:0,rx:0,ry:0,tspan:!0,valign:void 0}},VVe=function(){return{x:0,y:0,fill:"#EDF2AE",stroke:"#666",width:100,anchor:"start",height:100,rx:0,ry:0}},xgt=function(){function i(w,m,b,E,_,A,I){const B=m.append("text").attr("x",b+_/2).attr("y",E+A/2+5).style("text-anchor","middle").text(w);p(B,I)}function a(w,m,b,E,_,A,I,B){const{actorFontSize:N,actorFontFamily:R,actorFontWeight:z}=B,[W,et]=VA(N),st=w.split(Kr.lineBreakRegex);for(let at=0;ati.height||0))+(this.loops.length===0?0:this.loops.map(i=>i.height||0).reduce((i,a)=>i+a))+(this.messages.length===0?0:this.messages.map(i=>i.height||0).reduce((i,a)=>i+a))+(this.notes.length===0?0:this.notes.map(i=>i.height||0).reduce((i,a)=>i+a))},clear:function(){this.actors=[],this.boxes=[],this.loops=[],this.messages=[],this.notes=[]},addBox:function(i){this.boxes.push(i)},addActor:function(i){this.actors.push(i)},addLoop:function(i){this.loops.push(i)},addMessage:function(i){this.messages.push(i)},addNote:function(i){this.notes.push(i)},lastActor:function(){return this.actors[this.actors.length-1]},lastLoop:function(){return this.loops[this.loops.length-1]},lastMessage:function(){return this.messages[this.messages.length-1]},lastNote:function(){return this.notes[this.notes.length-1]},actors:[],boxes:[],loops:[],messages:[],notes:[]},init:function(){this.sequenceItems=[],this.activations=[],this.models.clear(),this.data={startx:void 0,stopx:void 0,starty:void 0,stopy:void 0},this.verticalPos=0,jRt(Oe())},updateVal:function(i,a,f,p){i[a]===void 0?i[a]=f:i[a]=p(f,i[a])},updateBounds:function(i,a,f,p){const w=this;let m=0;function b(E){return function(A){m++;const I=w.sequenceItems.length-m+1;w.updateVal(A,"starty",a-I*fn.boxMargin,Math.min),w.updateVal(A,"stopy",p+I*fn.boxMargin,Math.max),w.updateVal(Fr.data,"startx",i-I*fn.boxMargin,Math.min),w.updateVal(Fr.data,"stopx",f+I*fn.boxMargin,Math.max),E!=="activation"&&(w.updateVal(A,"startx",i-I*fn.boxMargin,Math.min),w.updateVal(A,"stopx",f+I*fn.boxMargin,Math.max),w.updateVal(Fr.data,"starty",a-I*fn.boxMargin,Math.min),w.updateVal(Fr.data,"stopy",p+I*fn.boxMargin,Math.max))}}this.sequenceItems.forEach(b()),this.activations.forEach(b("activation"))},insert:function(i,a,f,p){const w=Kr.getMin(i,f),m=Kr.getMax(i,f),b=Kr.getMin(a,p),E=Kr.getMax(a,p);this.updateVal(Fr.data,"startx",w,Math.min),this.updateVal(Fr.data,"starty",b,Math.min),this.updateVal(Fr.data,"stopx",m,Math.max),this.updateVal(Fr.data,"stopy",E,Math.max),this.updateBounds(w,b,m,E)},newActivation:function(i,a,f){const p=f[i.from.actor],w=jY(i.from.actor).length||0,m=p.x+p.width/2+(w-1)*fn.activationWidth/2;this.activations.push({startx:m,starty:this.verticalPos+2,stopx:m+fn.activationWidth,stopy:void 0,actor:i.from.actor,anchored:nf.anchorElement(a)})},endActivation:function(i){const a=this.activations.map(function(f){return f.actor}).lastIndexOf(i.from.actor);return this.activations.splice(a,1)[0]},createLoop:function(i={message:void 0,wrap:!1,width:void 0},a){return{startx:void 0,starty:this.verticalPos,stopx:void 0,stopy:void 0,title:i.message,wrap:i.wrap,width:i.width,height:0,fill:a}},newLoop:function(i={message:void 0,wrap:!1,width:void 0},a){this.sequenceItems.push(this.createLoop(i,a))},endLoop:function(){return this.sequenceItems.pop()},isLoopOverlap:function(){return this.sequenceItems.length?this.sequenceItems[this.sequenceItems.length-1].overlap:!1},addSectionToLoop:function(i){const a=this.sequenceItems.pop();a.sections=a.sections||[],a.sectionTitles=a.sectionTitles||[],a.sections.push({y:Fr.getVerticalPos(),height:0}),a.sectionTitles.push(i),this.sequenceItems.push(a)},saveVerticalPos:function(){this.isLoopOverlap()&&(this.savedVerticalPos=this.verticalPos)},resetVerticalPos:function(){this.isLoopOverlap()&&(this.verticalPos=this.savedVerticalPos)},bumpVerticalPos:function(i){this.verticalPos=this.verticalPos+i,this.data.stopy=Kr.getMax(this.data.stopy,this.verticalPos)},getVerticalPos:function(){return this.verticalPos},getBounds:function(){return{bounds:this.data,models:this.models}}},UVe=function(i,a){Fr.bumpVerticalPos(fn.boxMargin),a.height=fn.boxMargin,a.starty=Fr.getVerticalPos();const f=bT();f.x=a.startx,f.y=a.starty,f.width=a.width||fn.width,f.class="note";const p=i.append("g"),w=nf.drawRect(p,f),m=Rdt();m.x=a.startx,m.y=a.starty,m.width=f.width,m.dy="1em",m.text=a.message,m.class="noteText",m.fontFamily=fn.noteFontFamily,m.fontSize=fn.noteFontSize,m.fontWeight=fn.noteFontWeight,m.anchor=fn.noteAlign,m.textMargin=fn.noteMargin,m.valign="center";const b=pL(p,m),E=Math.round(b.map(_=>(_._groups||_)[0][0].getBBox().height).reduce((_,A)=>_+A));w.attr("height",E+2*fn.noteMargin),a.height+=E+2*fn.noteMargin,Fr.bumpVerticalPos(E+2*fn.noteMargin),a.stopy=a.starty+E+2*fn.noteMargin,a.stopx=a.startx+f.width,Fr.insert(a.startx,a.starty,a.stopx,a.stopy),Fr.models.addNote(a)},ST=i=>({fontFamily:i.messageFontFamily,fontSize:i.messageFontSize,fontWeight:i.messageFontWeight}),bL=i=>({fontFamily:i.noteFontFamily,fontSize:i.noteFontSize,fontWeight:i.noteFontWeight}),kgt=i=>({fontFamily:i.actorFontFamily,fontSize:i.actorFontSize,fontWeight:i.actorFontWeight});function WVe(i,a){Fr.bumpVerticalPos(10);const{startx:f,stopx:p,message:w}=a,m=Kr.splitBreaks(w).length,b=$a.calculateTextDimensions(w,ST(fn)),E=b.height/m;a.height+=E,Fr.bumpVerticalPos(E);let _,A=b.height-10;const I=b.width;if(f===p){_=Fr.getVerticalPos()+A,fn.rightAngles||(A+=fn.boxMargin,_=Fr.getVerticalPos()+A),A+=30;const B=Kr.getMax(I/2,fn.width/2);Fr.insert(f-B,Fr.getVerticalPos()-10+A,p+B,Fr.getVerticalPos()+30+A)}else A+=fn.boxMargin,_=Fr.getVerticalPos()+A,Fr.insert(f,_-10,p,_);return Fr.bumpVerticalPos(A),a.height+=A,a.stopy=a.starty+a.height,Fr.insert(a.fromBounds,a.starty,a.toBounds,a.stopy),_}const YVe=function(i,a,f,p){const{startx:w,stopx:m,starty:b,message:E,type:_,sequenceIndex:A,sequenceVisible:I}=a,B=$a.calculateTextDimensions(E,ST(fn)),N=Rdt();N.x=w,N.y=b+10,N.width=m-w,N.class="messageText",N.dy="1em",N.text=E,N.fontFamily=fn.messageFontFamily,N.fontSize=fn.messageFontSize,N.fontWeight=fn.messageFontWeight,N.anchor=fn.messageAlign,N.valign="center",N.textMargin=fn.wrapPadding,N.tspan=!1,pL(i,N);const R=B.width;let z;w===m?fn.rightAngles?z=i.append("path").attr("d",`M ${w},${f} H ${w+Kr.getMax(fn.width/2,R/2)} V ${f+25} H ${w}`):z=i.append("path").attr("d","M "+w+","+f+" C "+(w+60)+","+(f-10)+" "+(w+60)+","+(f+30)+" "+w+","+(f+20)):(z=i.append("line"),z.attr("x1",w),z.attr("y1",f),z.attr("x2",m),z.attr("y2",f)),_===p.db.LINETYPE.DOTTED||_===p.db.LINETYPE.DOTTED_CROSS||_===p.db.LINETYPE.DOTTED_POINT||_===p.db.LINETYPE.DOTTED_OPEN?(z.style("stroke-dasharray","3, 3"),z.attr("class","messageLine1")):z.attr("class","messageLine0");let W="";fn.arrowMarkerAbsolute&&(W=window.location.protocol+"//"+window.location.host+window.location.pathname+window.location.search,W=W.replace(/\(/g,"\\("),W=W.replace(/\)/g,"\\)")),z.attr("stroke-width",2),z.attr("stroke","none"),z.style("fill","none"),(_===p.db.LINETYPE.SOLID||_===p.db.LINETYPE.DOTTED)&&z.attr("marker-end","url("+W+"#arrowhead)"),(_===p.db.LINETYPE.SOLID_POINT||_===p.db.LINETYPE.DOTTED_POINT)&&z.attr("marker-end","url("+W+"#filled-head)"),(_===p.db.LINETYPE.SOLID_CROSS||_===p.db.LINETYPE.DOTTED_CROSS)&&z.attr("marker-end","url("+W+"#crosshead)"),(I||fn.showSequenceNumbers)&&(z.attr("marker-start","url("+W+"#sequencenumber)"),i.append("text").attr("x",w).attr("y",f+4).attr("font-family","sans-serif").attr("font-size","12px").attr("text-anchor","middle").attr("class","sequenceNumber").text(A))},KVe=function(i,a,f,p,w,m,b){let E=0,_=0,A,I=0;for(const B of p){const N=a[B],R=N.box;A&&A!=R&&(b||Fr.models.addBox(A),_+=fn.boxMargin+A.margin),R&&R!=A&&(b||(R.x=E+_,R.y=w),_+=R.margin),N.width=N.width||fn.width,N.height=Kr.getMax(N.height||fn.height,fn.height),N.margin=N.margin||fn.actorMargin,I=Kr.getMax(I,N.height),f[N.name]&&(_+=N.width/2),N.x=E+_,N.starty=Fr.getVerticalPos(),Fr.insert(N.x,w,N.x+N.width,N.height),E+=N.width+_,N.box&&(N.box.width=E+R.margin-N.box.x),_=N.margin,A=N.box,Fr.models.addActor(N)}A&&!b&&Fr.models.addBox(A),Fr.bumpVerticalPos(I)},Egt=function(i,a,f,p){if(p){let w=0;Fr.bumpVerticalPos(fn.boxMargin*2);for(const m of f){const b=a[m];b.stopy||(b.stopy=Fr.getVerticalPos());const E=nf.drawActor(i,b,fn,!0);w=Kr.getMax(w,E)}Fr.bumpVerticalPos(w+fn.boxMargin)}else for(const w of f){const m=a[w];nf.drawActor(i,m,fn,!1)}},RRt=function(i,a,f,p){let w=0,m=0;for(const b of f){const E=a[b],_=JVe(E),A=nf.drawPopup(i,E,_,fn,fn.forceMenus,p);A.height>w&&(w=A.height),A.width+E.x>m&&(m=A.width+E.x)}return{maxHeight:w,maxWidth:m}},jRt=function(i){Z1(fn,i),i.fontFamily&&(fn.actorFontFamily=fn.noteFontFamily=fn.messageFontFamily=i.fontFamily),i.fontSize&&(fn.actorFontSize=fn.noteFontSize=fn.messageFontSize=i.fontSize),i.fontWeight&&(fn.actorFontWeight=fn.noteFontWeight=fn.messageFontWeight=i.fontWeight)},jY=function(i){return Fr.activations.filter(function(a){return a.actor===i})},$Rt=function(i,a){const f=a[i],p=jY(i),w=p.reduce(function(b,E){return Kr.getMin(b,E.startx)},f.x+f.width/2-1),m=p.reduce(function(b,E){return Kr.getMax(b,E.stopx)},f.x+f.width/2+1);return[w,m]};function k3(i,a,f,p,w){Fr.bumpVerticalPos(f);let m=p;if(a.id&&a.message&&i[a.id]){const b=i[a.id].width,E=ST(fn);a.message=$a.wrapLabel(`[${a.message}]`,b-2*fn.wrapPadding,E),a.width=b,a.wrap=!0;const _=$a.calculateTextDimensions(a.message,E),A=Kr.getMax(_.height,fn.labelBoxHeight);m=p+A,Ut.debug(`${A} - ${a.message}`)}w(a),Fr.bumpVerticalPos(m)}function XVe(i,a,f,p,w,m,b){function E(A,I){A.x{Et.add(Z.from),Et.add(Z.to)}),z=z.filter(Z=>Et.has(Z))}KVe(A,I,B,z,0,W,!1);const mt=rGe(W,I,bt,p);nf.insertArrowHead(A),nf.insertArrowCrossHead(A),nf.insertArrowFilledHead(A),nf.insertSequenceNumber(A);function yt(Et,Z){const Ct=Fr.endActivation(Et);Ct.starty+18>Z&&(Ct.starty=Z-6,Z+=12),nf.drawActivation(A,Ct,Z,fn,jY(Et.from.actor).length),Fr.insert(Ct.startx,Z-10,Ct.stopx,Z)}let ft=1,ut=1;const vt=[],X=[];W.forEach(function(Et,Z){let Ct,xt,Ht;switch(Et.type){case p.db.LINETYPE.NOTE:Fr.resetVerticalPos(),xt=Et.noteModel,UVe(A,xt);break;case p.db.LINETYPE.ACTIVE_START:Fr.newActivation(Et,A,I);break;case p.db.LINETYPE.ACTIVE_END:yt(Et,Fr.getVerticalPos());break;case p.db.LINETYPE.LOOP_START:k3(mt,Et,fn.boxMargin,fn.boxMargin+fn.boxTextMargin,Le=>Fr.newLoop(Le));break;case p.db.LINETYPE.LOOP_END:Ct=Fr.endLoop(),nf.drawLoop(A,Ct,"loop",fn),Fr.bumpVerticalPos(Ct.stopy-Fr.getVerticalPos()),Fr.models.addLoop(Ct);break;case p.db.LINETYPE.RECT_START:k3(mt,Et,fn.boxMargin,fn.boxMargin,Le=>Fr.newLoop(void 0,Le.message));break;case p.db.LINETYPE.RECT_END:Ct=Fr.endLoop(),X.push(Ct),Fr.models.addLoop(Ct),Fr.bumpVerticalPos(Ct.stopy-Fr.getVerticalPos());break;case p.db.LINETYPE.OPT_START:k3(mt,Et,fn.boxMargin,fn.boxMargin+fn.boxTextMargin,Le=>Fr.newLoop(Le));break;case p.db.LINETYPE.OPT_END:Ct=Fr.endLoop(),nf.drawLoop(A,Ct,"opt",fn),Fr.bumpVerticalPos(Ct.stopy-Fr.getVerticalPos()),Fr.models.addLoop(Ct);break;case p.db.LINETYPE.ALT_START:k3(mt,Et,fn.boxMargin,fn.boxMargin+fn.boxTextMargin,Le=>Fr.newLoop(Le));break;case p.db.LINETYPE.ALT_ELSE:k3(mt,Et,fn.boxMargin+fn.boxTextMargin,fn.boxMargin,Le=>Fr.addSectionToLoop(Le));break;case p.db.LINETYPE.ALT_END:Ct=Fr.endLoop(),nf.drawLoop(A,Ct,"alt",fn),Fr.bumpVerticalPos(Ct.stopy-Fr.getVerticalPos()),Fr.models.addLoop(Ct);break;case p.db.LINETYPE.PAR_START:case p.db.LINETYPE.PAR_OVER_START:k3(mt,Et,fn.boxMargin,fn.boxMargin+fn.boxTextMargin,Le=>Fr.newLoop(Le)),Fr.saveVerticalPos();break;case p.db.LINETYPE.PAR_AND:k3(mt,Et,fn.boxMargin+fn.boxTextMargin,fn.boxMargin,Le=>Fr.addSectionToLoop(Le));break;case p.db.LINETYPE.PAR_END:Ct=Fr.endLoop(),nf.drawLoop(A,Ct,"par",fn),Fr.bumpVerticalPos(Ct.stopy-Fr.getVerticalPos()),Fr.models.addLoop(Ct);break;case p.db.LINETYPE.AUTONUMBER:ft=Et.message.start||ft,ut=Et.message.step||ut,Et.message.visible?p.db.enableSequenceNumbers():p.db.disableSequenceNumbers();break;case p.db.LINETYPE.CRITICAL_START:k3(mt,Et,fn.boxMargin,fn.boxMargin+fn.boxTextMargin,Le=>Fr.newLoop(Le));break;case p.db.LINETYPE.CRITICAL_OPTION:k3(mt,Et,fn.boxMargin+fn.boxTextMargin,fn.boxMargin,Le=>Fr.addSectionToLoop(Le));break;case p.db.LINETYPE.CRITICAL_END:Ct=Fr.endLoop(),nf.drawLoop(A,Ct,"critical",fn),Fr.bumpVerticalPos(Ct.stopy-Fr.getVerticalPos()),Fr.models.addLoop(Ct);break;case p.db.LINETYPE.BREAK_START:k3(mt,Et,fn.boxMargin,fn.boxMargin+fn.boxTextMargin,Le=>Fr.newLoop(Le));break;case p.db.LINETYPE.BREAK_END:Ct=Fr.endLoop(),nf.drawLoop(A,Ct,"break",fn),Fr.bumpVerticalPos(Ct.stopy-Fr.getVerticalPos()),Fr.models.addLoop(Ct);break;default:try{Ht=Et.msgModel,Ht.starty=Fr.getVerticalPos(),Ht.sequenceIndex=ft,Ht.sequenceVisible=p.db.showSequenceNumbers();const Le=WVe(A,Ht);XVe(Et,Ht,Le,Z,I,B,N),vt.push({messageModel:Ht,lineStartY:Le}),Fr.models.addMessage(Ht)}catch(Le){Ut.error("error while drawing message",Le)}}[p.db.LINETYPE.SOLID_OPEN,p.db.LINETYPE.DOTTED_OPEN,p.db.LINETYPE.SOLID,p.db.LINETYPE.DOTTED,p.db.LINETYPE.SOLID_CROSS,p.db.LINETYPE.DOTTED_CROSS,p.db.LINETYPE.SOLID_POINT,p.db.LINETYPE.DOTTED_POINT].includes(Et.type)&&(ft=ft+ut)}),Ut.debug("createdActors",B),Ut.debug("destroyedActors",N),Egt(A,I,z,!1),vt.forEach(Et=>YVe(A,Et.messageModel,Et.lineStartY,p)),fn.mirrorActors&&Egt(A,I,z,!0),X.forEach(Et=>nf.drawBackgroundRect(A,Et)),FRt(A,I,z,fn),Fr.models.boxes.forEach(function(Et){Et.height=Fr.getVerticalPos()-Et.y,Fr.insert(Et.x,Et.y,Et.x+Et.width,Et.height),Et.startx=Et.x,Et.starty=Et.y,Et.stopx=Et.startx+Et.width,Et.stopy=Et.starty+Et.height,Et.stroke="rgb(0,0,0, 0.5)",nf.drawBox(A,Et,fn)}),st&&Fr.bumpVerticalPos(fn.boxMargin);const pt=RRt(A,I,z,_),{bounds:U}=Fr.getBounds();let Tt=U.stopy-U.starty;Tt{const b=i[m];b.wrap&&(b.description=$a.wrapLabel(b.description,fn.width-2*fn.wrapPadding,kgt(fn)));const E=$a.calculateTextDimensions(b.description,kgt(fn));b.width=b.wrap?fn.width:Kr.getMax(fn.width,E.width+2*fn.wrapPadding),b.height=b.wrap?Kr.getMax(E.height,fn.height):fn.height,p=Kr.getMax(p,b.height)});for(const m in a){const b=i[m];if(!b)continue;const E=i[b.nextActor];if(!E){const B=a[m]+fn.actorMargin-b.width/2;b.margin=Kr.getMax(B,fn.actorMargin);continue}const A=a[m]+fn.actorMargin-b.width/2-E.width/2;b.margin=Kr.getMax(A,fn.actorMargin)}let w=0;return f.forEach(m=>{const b=ST(fn);let E=m.actorKeys.reduce((I,B)=>I+=i[B].width+(i[B].margin||0),0);E-=2*fn.boxTextMargin,m.wrap&&(m.name=$a.wrapLabel(m.name,E-2*fn.wrapPadding,b));const _=$a.calculateTextDimensions(m.name,b);w=Kr.getMax(_.height,w);const A=Kr.getMax(E,_.width+2*fn.wrapPadding);if(m.margin=fn.boxTextMargin,Em.textMaxHeight=w),Kr.getMax(p,fn.height)}const eGe=function(i,a,f){const p=a[i.from].x,w=a[i.to].x,m=i.wrap&&i.message;let b=$a.calculateTextDimensions(m?$a.wrapLabel(i.message,fn.width,bL(fn)):i.message,bL(fn));const E={width:m?fn.width:Kr.getMax(fn.width,b.width+2*fn.noteMargin),height:0,startx:a[i.from].x,stopx:0,starty:0,stopy:0,message:i.message};return i.placement===f.db.PLACEMENT.RIGHTOF?(E.width=m?Kr.getMax(fn.width,b.width):Kr.getMax(a[i.from].width/2+a[i.to].width/2,b.width+2*fn.noteMargin),E.startx=p+(a[i.from].width+fn.actorMargin)/2):i.placement===f.db.PLACEMENT.LEFTOF?(E.width=m?Kr.getMax(fn.width,b.width+2*fn.noteMargin):Kr.getMax(a[i.from].width/2+a[i.to].width/2,b.width+2*fn.noteMargin),E.startx=p-E.width+(a[i.from].width-fn.actorMargin)/2):i.to===i.from?(b=$a.calculateTextDimensions(m?$a.wrapLabel(i.message,Kr.getMax(fn.width,a[i.from].width),bL(fn)):i.message,bL(fn)),E.width=m?Kr.getMax(fn.width,a[i.from].width):Kr.getMax(a[i.from].width,fn.width,b.width+2*fn.noteMargin),E.startx=p+(a[i.from].width-E.width)/2):(E.width=Math.abs(p+a[i.from].width/2-(w+a[i.to].width/2))+fn.actorMargin,E.startx=p2,B=W=>E?-W:W;i.from===i.to?A=_:(i.activate&&!I&&(A+=B(fn.activationWidth/2-1)),[f.db.LINETYPE.SOLID_OPEN,f.db.LINETYPE.DOTTED_OPEN].includes(i.type)||(A+=B(3)));const N=[p,w,m,b],R=Math.abs(_-A);i.wrap&&i.message&&(i.message=$a.wrapLabel(i.message,Kr.getMax(R+2*fn.wrapPadding,fn.width),ST(fn)));const z=$a.calculateTextDimensions(i.message,ST(fn));return{width:Kr.getMax(i.wrap?0:z.width+2*fn.wrapPadding,R+2*fn.wrapPadding,fn.width),height:0,startx:_,stopx:A,starty:0,stopy:0,message:i.message,type:i.type,wrap:i.wrap,fromBounds:Math.min.apply(null,N),toBounds:Math.max.apply(null,N)}},rGe=function(i,a,f,p){const w={},m=[];let b,E,_;return i.forEach(function(A){switch(A.id=$a.random({length:10}),A.type){case p.db.LINETYPE.LOOP_START:case p.db.LINETYPE.ALT_START:case p.db.LINETYPE.OPT_START:case p.db.LINETYPE.PAR_START:case p.db.LINETYPE.PAR_OVER_START:case p.db.LINETYPE.CRITICAL_START:case p.db.LINETYPE.BREAK_START:m.push({id:A.id,msg:A.message,from:Number.MAX_SAFE_INTEGER,to:Number.MIN_SAFE_INTEGER,width:0});break;case p.db.LINETYPE.ALT_ELSE:case p.db.LINETYPE.PAR_AND:case p.db.LINETYPE.CRITICAL_OPTION:A.message&&(b=m.pop(),w[b.id]=b,w[A.id]=b,m.push(b));break;case p.db.LINETYPE.LOOP_END:case p.db.LINETYPE.ALT_END:case p.db.LINETYPE.OPT_END:case p.db.LINETYPE.PAR_END:case p.db.LINETYPE.CRITICAL_END:case p.db.LINETYPE.BREAK_END:b=m.pop(),w[b.id]=b;break;case p.db.LINETYPE.ACTIVE_START:{const B=a[A.from?A.from.actor:A.to.actor],N=jY(A.from?A.from.actor:A.to.actor).length,R=B.x+B.width/2+(N-1)*fn.activationWidth/2,z={startx:R,stopx:R+fn.activationWidth,actor:A.from.actor,enabled:!0};Fr.activations.push(z)}break;case p.db.LINETYPE.ACTIVE_END:{const B=Fr.activations.map(N=>N.actor).lastIndexOf(A.from.actor);delete Fr.activations.splice(B,1)[0]}break}A.placement!==void 0?(E=eGe(A,a,p),A.noteModel=E,m.forEach(B=>{b=B,b.from=Kr.getMin(b.from,E.startx),b.to=Kr.getMax(b.to,E.startx+E.width),b.width=Kr.getMax(b.width,Math.abs(b.from-b.to))-fn.labelBoxWidth})):(_=nGe(A,a,p),A.msgModel=_,_.startx&&_.stopx&&m.length>0&&m.forEach(B=>{if(b=B,_.startx===_.stopx){const N=a[A.from],R=a[A.to];b.from=Kr.getMin(N.x-_.width/2,N.x-N.width/2,b.from),b.to=Kr.getMax(R.x+_.width/2,R.x+N.width/2,b.to),b.width=Kr.getMax(b.width,Math.abs(b.to-b.from))-fn.labelBoxWidth}else b.from=Kr.getMin(_.startx,b.from),b.to=Kr.getMax(_.stopx,b.to),b.width=Kr.getMax(b.width,_.width)-fn.labelBoxWidth}))}),Fr.activations=[],Ut.debug("Loop type widths:",w),w},iGe=Object.freeze(Object.defineProperty({__proto__:null,diagram:{parser:tVe,db:IRt,renderer:{bounds:Fr,drawActors:Egt,drawActorsPopup:RRt,setConf:jRt,draw:QVe},styles:TVe,init:({wrap:i})=>{IRt.setWrap(i)}}},Symbol.toStringTag,{value:"Module"}));var Tgt=function(){var i=function(ke,zt,re,se){for(re=re||{},se=ke.length;se--;re[ke[se]]=zt);return re},a=[1,16],f=[1,17],p=[1,18],w=[1,37],m=[1,38],b=[1,24],E=[1,22],_=[1,23],A=[1,29],I=[1,30],B=[1,31],N=[1,32],R=[1,33],z=[1,34],W=[1,25],et=[1,26],st=[1,27],at=[1,28],bt=[1,42],mt=[1,39],yt=[1,40],ft=[1,41],ut=[1,43],vt=[1,9],X=[1,8,9],pt=[1,54],U=[1,55],Tt=[1,56],nt=[1,57],It=[1,58],Ot=[1,59],Bt=[1,60],Et=[1,8,9,38],Z=[1,71],Ct=[1,8,9,12,13,21,36,38,41,58,59,60,61,62,63,64,69,71],xt=[1,8,9,12,13,19,21,36,38,41,45,58,59,60,61,62,63,64,69,71,84,86,87,88,89],Ht=[13,84,86,87,88,89],Le=[13,63,64,84,86,87,88,89],Ft=[13,58,59,60,61,62,84,86,87,88,89],gn=[1,90],Se=[1,8,9,36,38,41],me=[1,8,9,21],Ve={trace:function(){},yy:{},symbols_:{error:2,start:3,mermaidDoc:4,statements:5,graphConfig:6,CLASS_DIAGRAM:7,NEWLINE:8,EOF:9,statement:10,classLabel:11,SQS:12,STR:13,SQE:14,namespaceName:15,alphaNumToken:16,className:17,classLiteralName:18,GENERICTYPE:19,relationStatement:20,LABEL:21,namespaceStatement:22,classStatement:23,memberStatement:24,annotationStatement:25,clickStatement:26,cssClassStatement:27,noteStatement:28,direction:29,acc_title:30,acc_title_value:31,acc_descr:32,acc_descr_value:33,acc_descr_multiline_value:34,namespaceIdentifier:35,STRUCT_START:36,classStatements:37,STRUCT_STOP:38,NAMESPACE:39,classIdentifier:40,STYLE_SEPARATOR:41,members:42,CLASS:43,ANNOTATION_START:44,ANNOTATION_END:45,MEMBER:46,SEPARATOR:47,relation:48,NOTE_FOR:49,noteText:50,NOTE:51,direction_tb:52,direction_bt:53,direction_rl:54,direction_lr:55,relationType:56,lineType:57,AGGREGATION:58,EXTENSION:59,COMPOSITION:60,DEPENDENCY:61,LOLLIPOP:62,LINE:63,DOTTED_LINE:64,CALLBACK:65,LINK:66,LINK_TARGET:67,CLICK:68,CALLBACK_NAME:69,CALLBACK_ARGS:70,HREF:71,CSSCLASS:72,commentToken:73,textToken:74,graphCodeTokens:75,textNoTagsToken:76,TAGSTART:77,TAGEND:78,"==":79,"--":80,PCT:81,DEFAULT:82,SPACE:83,MINUS:84,keywords:85,UNICODE_TEXT:86,NUM:87,ALPHA:88,BQUOTE_STR:89,$accept:0,$end:1},terminals_:{2:"error",7:"CLASS_DIAGRAM",8:"NEWLINE",9:"EOF",12:"SQS",13:"STR",14:"SQE",19:"GENERICTYPE",21:"LABEL",30:"acc_title",31:"acc_title_value",32:"acc_descr",33:"acc_descr_value",34:"acc_descr_multiline_value",36:"STRUCT_START",38:"STRUCT_STOP",39:"NAMESPACE",41:"STYLE_SEPARATOR",43:"CLASS",44:"ANNOTATION_START",45:"ANNOTATION_END",46:"MEMBER",47:"SEPARATOR",49:"NOTE_FOR",51:"NOTE",52:"direction_tb",53:"direction_bt",54:"direction_rl",55:"direction_lr",58:"AGGREGATION",59:"EXTENSION",60:"COMPOSITION",61:"DEPENDENCY",62:"LOLLIPOP",63:"LINE",64:"DOTTED_LINE",65:"CALLBACK",66:"LINK",67:"LINK_TARGET",68:"CLICK",69:"CALLBACK_NAME",70:"CALLBACK_ARGS",71:"HREF",72:"CSSCLASS",75:"graphCodeTokens",77:"TAGSTART",78:"TAGEND",79:"==",80:"--",81:"PCT",82:"DEFAULT",83:"SPACE",84:"MINUS",85:"keywords",86:"UNICODE_TEXT",87:"NUM",88:"ALPHA",89:"BQUOTE_STR"},productions_:[0,[3,1],[3,1],[4,1],[6,4],[5,1],[5,2],[5,3],[11,3],[15,1],[15,2],[17,1],[17,1],[17,2],[17,2],[17,2],[10,1],[10,2],[10,1],[10,1],[10,1],[10,1],[10,1],[10,1],[10,1],[10,1],[10,2],[10,2],[10,1],[22,4],[22,5],[35,2],[37,1],[37,2],[37,3],[23,1],[23,3],[23,4],[23,6],[40,2],[40,3],[25,4],[42,1],[42,2],[24,1],[24,2],[24,1],[24,1],[20,3],[20,4],[20,4],[20,5],[28,3],[28,2],[29,1],[29,1],[29,1],[29,1],[48,3],[48,2],[48,2],[48,1],[56,1],[56,1],[56,1],[56,1],[56,1],[57,1],[57,1],[26,3],[26,4],[26,3],[26,4],[26,4],[26,5],[26,3],[26,4],[26,4],[26,5],[26,4],[26,5],[26,5],[26,6],[27,3],[73,1],[73,1],[74,1],[74,1],[74,1],[74,1],[74,1],[74,1],[74,1],[76,1],[76,1],[76,1],[76,1],[16,1],[16,1],[16,1],[16,1],[18,1],[50,1]],performAction:function(zt,re,se,Pe,te,Me,de){var on=Me.length-1;switch(te){case 8:this.$=Me[on-1];break;case 9:case 11:case 12:this.$=Me[on];break;case 10:case 13:this.$=Me[on-1]+Me[on];break;case 14:case 15:this.$=Me[on-1]+"~"+Me[on]+"~";break;case 16:Pe.addRelation(Me[on]);break;case 17:Me[on-1].title=Pe.cleanupLabel(Me[on]),Pe.addRelation(Me[on-1]);break;case 26:this.$=Me[on].trim(),Pe.setAccTitle(this.$);break;case 27:case 28:this.$=Me[on].trim(),Pe.setAccDescription(this.$);break;case 29:Pe.addClassesToNamespace(Me[on-3],Me[on-1]);break;case 30:Pe.addClassesToNamespace(Me[on-4],Me[on-1]);break;case 31:this.$=Me[on],Pe.addNamespace(Me[on]);break;case 32:this.$=[Me[on]];break;case 33:this.$=[Me[on-1]];break;case 34:Me[on].unshift(Me[on-2]),this.$=Me[on];break;case 36:Pe.setCssClass(Me[on-2],Me[on]);break;case 37:Pe.addMembers(Me[on-3],Me[on-1]);break;case 38:Pe.setCssClass(Me[on-5],Me[on-3]),Pe.addMembers(Me[on-5],Me[on-1]);break;case 39:this.$=Me[on],Pe.addClass(Me[on]);break;case 40:this.$=Me[on-1],Pe.addClass(Me[on-1]),Pe.setClassLabel(Me[on-1],Me[on]);break;case 41:Pe.addAnnotation(Me[on],Me[on-2]);break;case 42:this.$=[Me[on]];break;case 43:Me[on].push(Me[on-1]),this.$=Me[on];break;case 44:break;case 45:Pe.addMember(Me[on-1],Pe.cleanupLabel(Me[on]));break;case 46:break;case 47:break;case 48:this.$={id1:Me[on-2],id2:Me[on],relation:Me[on-1],relationTitle1:"none",relationTitle2:"none"};break;case 49:this.$={id1:Me[on-3],id2:Me[on],relation:Me[on-1],relationTitle1:Me[on-2],relationTitle2:"none"};break;case 50:this.$={id1:Me[on-3],id2:Me[on],relation:Me[on-2],relationTitle1:"none",relationTitle2:Me[on-1]};break;case 51:this.$={id1:Me[on-4],id2:Me[on],relation:Me[on-2],relationTitle1:Me[on-3],relationTitle2:Me[on-1]};break;case 52:Pe.addNote(Me[on],Me[on-1]);break;case 53:Pe.addNote(Me[on]);break;case 54:Pe.setDirection("TB");break;case 55:Pe.setDirection("BT");break;case 56:Pe.setDirection("RL");break;case 57:Pe.setDirection("LR");break;case 58:this.$={type1:Me[on-2],type2:Me[on],lineType:Me[on-1]};break;case 59:this.$={type1:"none",type2:Me[on],lineType:Me[on-1]};break;case 60:this.$={type1:Me[on-1],type2:"none",lineType:Me[on]};break;case 61:this.$={type1:"none",type2:"none",lineType:Me[on]};break;case 62:this.$=Pe.relationType.AGGREGATION;break;case 63:this.$=Pe.relationType.EXTENSION;break;case 64:this.$=Pe.relationType.COMPOSITION;break;case 65:this.$=Pe.relationType.DEPENDENCY;break;case 66:this.$=Pe.relationType.LOLLIPOP;break;case 67:this.$=Pe.lineType.LINE;break;case 68:this.$=Pe.lineType.DOTTED_LINE;break;case 69:case 75:this.$=Me[on-2],Pe.setClickEvent(Me[on-1],Me[on]);break;case 70:case 76:this.$=Me[on-3],Pe.setClickEvent(Me[on-2],Me[on-1]),Pe.setTooltip(Me[on-2],Me[on]);break;case 71:this.$=Me[on-2],Pe.setLink(Me[on-1],Me[on]);break;case 72:this.$=Me[on-3],Pe.setLink(Me[on-2],Me[on-1],Me[on]);break;case 73:this.$=Me[on-3],Pe.setLink(Me[on-2],Me[on-1]),Pe.setTooltip(Me[on-2],Me[on]);break;case 74:this.$=Me[on-4],Pe.setLink(Me[on-3],Me[on-2],Me[on]),Pe.setTooltip(Me[on-3],Me[on-1]);break;case 77:this.$=Me[on-3],Pe.setClickEvent(Me[on-2],Me[on-1],Me[on]);break;case 78:this.$=Me[on-4],Pe.setClickEvent(Me[on-3],Me[on-2],Me[on-1]),Pe.setTooltip(Me[on-3],Me[on]);break;case 79:this.$=Me[on-3],Pe.setLink(Me[on-2],Me[on]);break;case 80:this.$=Me[on-4],Pe.setLink(Me[on-3],Me[on-1],Me[on]);break;case 81:this.$=Me[on-4],Pe.setLink(Me[on-3],Me[on-1]),Pe.setTooltip(Me[on-3],Me[on]);break;case 82:this.$=Me[on-5],Pe.setLink(Me[on-4],Me[on-2],Me[on]),Pe.setTooltip(Me[on-4],Me[on-1]);break;case 83:Pe.setCssClass(Me[on-1],Me[on]);break}},table:[{3:1,4:2,5:3,6:4,7:[1,6],10:5,16:35,17:19,18:36,20:7,22:8,23:9,24:10,25:11,26:12,27:13,28:14,29:15,30:a,32:f,34:p,35:20,39:w,40:21,43:m,44:b,46:E,47:_,49:A,51:I,52:B,53:N,54:R,55:z,65:W,66:et,68:st,72:at,84:bt,86:mt,87:yt,88:ft,89:ut},{1:[3]},{1:[2,1]},{1:[2,2]},{1:[2,3]},i(vt,[2,5],{8:[1,44]}),{8:[1,45]},i(X,[2,16],{21:[1,46]}),i(X,[2,18]),i(X,[2,19]),i(X,[2,20]),i(X,[2,21]),i(X,[2,22]),i(X,[2,23]),i(X,[2,24]),i(X,[2,25]),{31:[1,47]},{33:[1,48]},i(X,[2,28]),i(X,[2,44],{48:49,56:52,57:53,13:[1,50],21:[1,51],58:pt,59:U,60:Tt,61:nt,62:It,63:Ot,64:Bt}),{36:[1,61]},i(Et,[2,35],{36:[1,63],41:[1,62]}),i(X,[2,46]),i(X,[2,47]),{16:64,84:bt,86:mt,87:yt,88:ft},{16:35,17:65,18:36,84:bt,86:mt,87:yt,88:ft,89:ut},{16:35,17:66,18:36,84:bt,86:mt,87:yt,88:ft,89:ut},{16:35,17:67,18:36,84:bt,86:mt,87:yt,88:ft,89:ut},{13:[1,68]},{16:35,17:69,18:36,84:bt,86:mt,87:yt,88:ft,89:ut},{13:Z,50:70},i(X,[2,54]),i(X,[2,55]),i(X,[2,56]),i(X,[2,57]),i(Ct,[2,11],{16:35,18:36,17:72,19:[1,73],84:bt,86:mt,87:yt,88:ft,89:ut}),i(Ct,[2,12],{19:[1,74]}),{15:75,16:76,84:bt,86:mt,87:yt,88:ft},{16:35,17:77,18:36,84:bt,86:mt,87:yt,88:ft,89:ut},i(xt,[2,97]),i(xt,[2,98]),i(xt,[2,99]),i(xt,[2,100]),i([1,8,9,12,13,19,21,36,38,41,58,59,60,61,62,63,64,69,71],[2,101]),i(vt,[2,6],{10:5,20:7,22:8,23:9,24:10,25:11,26:12,27:13,28:14,29:15,17:19,35:20,40:21,16:35,18:36,5:78,30:a,32:f,34:p,39:w,43:m,44:b,46:E,47:_,49:A,51:I,52:B,53:N,54:R,55:z,65:W,66:et,68:st,72:at,84:bt,86:mt,87:yt,88:ft,89:ut}),{5:79,10:5,16:35,17:19,18:36,20:7,22:8,23:9,24:10,25:11,26:12,27:13,28:14,29:15,30:a,32:f,34:p,35:20,39:w,40:21,43:m,44:b,46:E,47:_,49:A,51:I,52:B,53:N,54:R,55:z,65:W,66:et,68:st,72:at,84:bt,86:mt,87:yt,88:ft,89:ut},i(X,[2,17]),i(X,[2,26]),i(X,[2,27]),{13:[1,81],16:35,17:80,18:36,84:bt,86:mt,87:yt,88:ft,89:ut},{48:82,56:52,57:53,58:pt,59:U,60:Tt,61:nt,62:It,63:Ot,64:Bt},i(X,[2,45]),{57:83,63:Ot,64:Bt},i(Ht,[2,61],{56:84,58:pt,59:U,60:Tt,61:nt,62:It}),i(Le,[2,62]),i(Le,[2,63]),i(Le,[2,64]),i(Le,[2,65]),i(Le,[2,66]),i(Ft,[2,67]),i(Ft,[2,68]),{8:[1,86],23:87,37:85,40:21,43:m},{16:88,84:bt,86:mt,87:yt,88:ft},{42:89,46:gn},{45:[1,91]},{13:[1,92]},{13:[1,93]},{69:[1,94],71:[1,95]},{16:96,84:bt,86:mt,87:yt,88:ft},{13:Z,50:97},i(X,[2,53]),i(X,[2,102]),i(Ct,[2,13]),i(Ct,[2,14]),i(Ct,[2,15]),{36:[2,31]},{15:98,16:76,36:[2,9],84:bt,86:mt,87:yt,88:ft},i(Se,[2,39],{11:99,12:[1,100]}),i(vt,[2,7]),{9:[1,101]},i(me,[2,48]),{16:35,17:102,18:36,84:bt,86:mt,87:yt,88:ft,89:ut},{13:[1,104],16:35,17:103,18:36,84:bt,86:mt,87:yt,88:ft,89:ut},i(Ht,[2,60],{56:105,58:pt,59:U,60:Tt,61:nt,62:It}),i(Ht,[2,59]),{38:[1,106]},{23:87,37:107,40:21,43:m},{8:[1,108],38:[2,32]},i(Et,[2,36],{36:[1,109]}),{38:[1,110]},{38:[2,42],42:111,46:gn},{16:35,17:112,18:36,84:bt,86:mt,87:yt,88:ft,89:ut},i(X,[2,69],{13:[1,113]}),i(X,[2,71],{13:[1,115],67:[1,114]}),i(X,[2,75],{13:[1,116],70:[1,117]}),{13:[1,118]},i(X,[2,83]),i(X,[2,52]),{36:[2,10]},i(Se,[2,40]),{13:[1,119]},{1:[2,4]},i(me,[2,50]),i(me,[2,49]),{16:35,17:120,18:36,84:bt,86:mt,87:yt,88:ft,89:ut},i(Ht,[2,58]),i(X,[2,29]),{38:[1,121]},{23:87,37:122,38:[2,33],40:21,43:m},{42:123,46:gn},i(Et,[2,37]),{38:[2,43]},i(X,[2,41]),i(X,[2,70]),i(X,[2,72]),i(X,[2,73],{67:[1,124]}),i(X,[2,76]),i(X,[2,77],{13:[1,125]}),i(X,[2,79],{13:[1,127],67:[1,126]}),{14:[1,128]},i(me,[2,51]),i(X,[2,30]),{38:[2,34]},{38:[1,129]},i(X,[2,74]),i(X,[2,78]),i(X,[2,80]),i(X,[2,81],{67:[1,130]}),i(Se,[2,8]),i(Et,[2,38]),i(X,[2,82])],defaultActions:{2:[2,1],3:[2,2],4:[2,3],75:[2,31],98:[2,10],101:[2,4],111:[2,43],122:[2,34]},parseError:function(zt,re){if(re.recoverable)this.trace(zt);else{var se=new Error(zt);throw se.hash=re,se}},parse:function(zt){var re=this,se=[0],Pe=[],te=[null],Me=[],de=this.table,on="",ni=0,Ks=0,ws=2,fo=1,Xi=Me.slice.call(arguments,1),Er=Object.create(this.lexer),Xn={yy:{}};for(var di in this.yy)Object.prototype.hasOwnProperty.call(this.yy,di)&&(Xn.yy[di]=this.yy[di]);Er.setInput(zt,Xn.yy),Xn.yy.lexer=Er,Xn.yy.parser=this,typeof Er.yylloc>"u"&&(Er.yylloc={});var Ee=Er.yylloc;Me.push(Ee);var Kn=Er.options&&Er.options.ranges;typeof Xn.yy.parseError=="function"?this.parseError=Xn.yy.parseError:this.parseError=Object.getPrototypeOf(this).parseError;function He(){var Du;return Du=Pe.pop()||Er.lex()||fo,typeof Du!="number"&&(Du instanceof Array&&(Pe=Du,Du=Pe.pop()),Du=re.symbols_[Du]||Du),Du}for(var Ti,pn,Es,qa,Ma={},Gs,Po,vs,ru;;){if(pn=se[se.length-1],this.defaultActions[pn]?Es=this.defaultActions[pn]:((Ti===null||typeof Ti>"u")&&(Ti=He()),Es=de[pn]&&de[pn][Ti]),typeof Es>"u"||!Es.length||!Es[0]){var zs="";ru=[];for(Gs in de[pn])this.terminals_[Gs]&&Gs>ws&&ru.push("'"+this.terminals_[Gs]+"'");Er.showPosition?zs="Parse error on line "+(ni+1)+`: +`+Er.showPosition()+` +Expecting `+ru.join(", ")+", got '"+(this.terminals_[Ti]||Ti)+"'":zs="Parse error on line "+(ni+1)+": Unexpected "+(Ti==fo?"end of input":"'"+(this.terminals_[Ti]||Ti)+"'"),this.parseError(zs,{text:Er.match,token:this.terminals_[Ti]||Ti,line:Er.yylineno,loc:Ee,expected:ru})}if(Es[0]instanceof Array&&Es.length>1)throw new Error("Parse Error: multiple actions possible at state: "+pn+", token: "+Ti);switch(Es[0]){case 1:se.push(Ti),te.push(Er.yytext),Me.push(Er.yylloc),se.push(Es[1]),Ti=null,Ks=Er.yyleng,on=Er.yytext,ni=Er.yylineno,Ee=Er.yylloc;break;case 2:if(Po=this.productions_[Es[1]][1],Ma.$=te[te.length-Po],Ma._$={first_line:Me[Me.length-(Po||1)].first_line,last_line:Me[Me.length-1].last_line,first_column:Me[Me.length-(Po||1)].first_column,last_column:Me[Me.length-1].last_column},Kn&&(Ma._$.range=[Me[Me.length-(Po||1)].range[0],Me[Me.length-1].range[1]]),qa=this.performAction.apply(Ma,[on,Ks,ni,Xn.yy,Es[1],te,Me].concat(Xi)),typeof qa<"u")return qa;Po&&(se=se.slice(0,-1*Po*2),te=te.slice(0,-1*Po),Me=Me.slice(0,-1*Po)),se.push(this.productions_[Es[1]][0]),te.push(Ma.$),Me.push(Ma._$),vs=de[se[se.length-2]][se[se.length-1]],se.push(vs);break;case 3:return!0}}return!0}},Ye=function(){var ke={EOF:1,parseError:function(re,se){if(this.yy.parser)this.yy.parser.parseError(re,se);else throw new Error(re)},setInput:function(zt,re){return this.yy=re||this.yy||{},this._input=zt,this._more=this._backtrack=this.done=!1,this.yylineno=this.yyleng=0,this.yytext=this.matched=this.match="",this.conditionStack=["INITIAL"],this.yylloc={first_line:1,first_column:0,last_line:1,last_column:0},this.options.ranges&&(this.yylloc.range=[0,0]),this.offset=0,this},input:function(){var zt=this._input[0];this.yytext+=zt,this.yyleng++,this.offset++,this.match+=zt,this.matched+=zt;var re=zt.match(/(?:\r\n?|\n).*/g);return re?(this.yylineno++,this.yylloc.last_line++):this.yylloc.last_column++,this.options.ranges&&this.yylloc.range[1]++,this._input=this._input.slice(1),zt},unput:function(zt){var re=zt.length,se=zt.split(/(?:\r\n?|\n)/g);this._input=zt+this._input,this.yytext=this.yytext.substr(0,this.yytext.length-re),this.offset-=re;var Pe=this.match.split(/(?:\r\n?|\n)/g);this.match=this.match.substr(0,this.match.length-1),this.matched=this.matched.substr(0,this.matched.length-1),se.length-1&&(this.yylineno-=se.length-1);var te=this.yylloc.range;return this.yylloc={first_line:this.yylloc.first_line,last_line:this.yylineno+1,first_column:this.yylloc.first_column,last_column:se?(se.length===Pe.length?this.yylloc.first_column:0)+Pe[Pe.length-se.length].length-se[0].length:this.yylloc.first_column-re},this.options.ranges&&(this.yylloc.range=[te[0],te[0]+this.yyleng-re]),this.yyleng=this.yytext.length,this},more:function(){return this._more=!0,this},reject:function(){if(this.options.backtrack_lexer)this._backtrack=!0;else return this.parseError("Lexical error on line "+(this.yylineno+1)+`. You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true). +`+this.showPosition(),{text:"",token:null,line:this.yylineno});return this},less:function(zt){this.unput(this.match.slice(zt))},pastInput:function(){var zt=this.matched.substr(0,this.matched.length-this.match.length);return(zt.length>20?"...":"")+zt.substr(-20).replace(/\n/g,"")},upcomingInput:function(){var zt=this.match;return zt.length<20&&(zt+=this._input.substr(0,20-zt.length)),(zt.substr(0,20)+(zt.length>20?"...":"")).replace(/\n/g,"")},showPosition:function(){var zt=this.pastInput(),re=new Array(zt.length+1).join("-");return zt+this.upcomingInput()+` +`+re+"^"},test_match:function(zt,re){var se,Pe,te;if(this.options.backtrack_lexer&&(te={yylineno:this.yylineno,yylloc:{first_line:this.yylloc.first_line,last_line:this.last_line,first_column:this.yylloc.first_column,last_column:this.yylloc.last_column},yytext:this.yytext,match:this.match,matches:this.matches,matched:this.matched,yyleng:this.yyleng,offset:this.offset,_more:this._more,_input:this._input,yy:this.yy,conditionStack:this.conditionStack.slice(0),done:this.done},this.options.ranges&&(te.yylloc.range=this.yylloc.range.slice(0))),Pe=zt[0].match(/(?:\r\n?|\n).*/g),Pe&&(this.yylineno+=Pe.length),this.yylloc={first_line:this.yylloc.last_line,last_line:this.yylineno+1,first_column:this.yylloc.last_column,last_column:Pe?Pe[Pe.length-1].length-Pe[Pe.length-1].match(/\r?\n?/)[0].length:this.yylloc.last_column+zt[0].length},this.yytext+=zt[0],this.match+=zt[0],this.matches=zt,this.yyleng=this.yytext.length,this.options.ranges&&(this.yylloc.range=[this.offset,this.offset+=this.yyleng]),this._more=!1,this._backtrack=!1,this._input=this._input.slice(zt[0].length),this.matched+=zt[0],se=this.performAction.call(this,this.yy,this,re,this.conditionStack[this.conditionStack.length-1]),this.done&&this._input&&(this.done=!1),se)return se;if(this._backtrack){for(var Me in te)this[Me]=te[Me];return!1}return!1},next:function(){if(this.done)return this.EOF;this._input||(this.done=!0);var zt,re,se,Pe;this._more||(this.yytext="",this.match="");for(var te=this._currentRules(),Me=0;Mere[0].length)){if(re=se,Pe=Me,this.options.backtrack_lexer){if(zt=this.test_match(se,te[Me]),zt!==!1)return zt;if(this._backtrack){re=!1;continue}else return!1}else if(!this.options.flex)break}return re?(zt=this.test_match(re,te[Pe]),zt!==!1?zt:!1):this._input===""?this.EOF:this.parseError("Lexical error on line "+(this.yylineno+1)+`. Unrecognized text. +`+this.showPosition(),{text:"",token:null,line:this.yylineno})},lex:function(){var re=this.next();return re||this.lex()},begin:function(re){this.conditionStack.push(re)},popState:function(){var re=this.conditionStack.length-1;return re>0?this.conditionStack.pop():this.conditionStack[0]},_currentRules:function(){return this.conditionStack.length&&this.conditionStack[this.conditionStack.length-1]?this.conditions[this.conditionStack[this.conditionStack.length-1]].rules:this.conditions.INITIAL.rules},topState:function(re){return re=this.conditionStack.length-1-Math.abs(re||0),re>=0?this.conditionStack[re]:"INITIAL"},pushState:function(re){this.begin(re)},stateStackSize:function(){return this.conditionStack.length},options:{},performAction:function(re,se,Pe,te){switch(Pe){case 0:return 52;case 1:return 53;case 2:return 54;case 3:return 55;case 4:break;case 5:break;case 6:return this.begin("acc_title"),30;case 7:return this.popState(),"acc_title_value";case 8:return this.begin("acc_descr"),32;case 9:return this.popState(),"acc_descr_value";case 10:this.begin("acc_descr_multiline");break;case 11:this.popState();break;case 12:return"acc_descr_multiline_value";case 13:return 8;case 14:break;case 15:return 7;case 16:return 7;case 17:return"EDGE_STATE";case 18:this.begin("callback_name");break;case 19:this.popState();break;case 20:this.popState(),this.begin("callback_args");break;case 21:return 69;case 22:this.popState();break;case 23:return 70;case 24:this.popState();break;case 25:return"STR";case 26:this.begin("string");break;case 27:return this.begin("namespace"),39;case 28:return this.popState(),8;case 29:break;case 30:return this.begin("namespace-body"),36;case 31:return this.popState(),38;case 32:return"EOF_IN_STRUCT";case 33:return 8;case 34:break;case 35:return"EDGE_STATE";case 36:return this.begin("class"),43;case 37:return this.popState(),8;case 38:break;case 39:return this.popState(),this.popState(),38;case 40:return this.begin("class-body"),36;case 41:return this.popState(),38;case 42:return"EOF_IN_STRUCT";case 43:return"EDGE_STATE";case 44:return"OPEN_IN_STRUCT";case 45:break;case 46:return"MEMBER";case 47:return 72;case 48:return 65;case 49:return 66;case 50:return 68;case 51:return 49;case 52:return 51;case 53:return 44;case 54:return 45;case 55:return 71;case 56:this.popState();break;case 57:return"GENERICTYPE";case 58:this.begin("generic");break;case 59:this.popState();break;case 60:return"BQUOTE_STR";case 61:this.begin("bqstring");break;case 62:return 67;case 63:return 67;case 64:return 67;case 65:return 67;case 66:return 59;case 67:return 59;case 68:return 61;case 69:return 61;case 70:return 60;case 71:return 58;case 72:return 62;case 73:return 63;case 74:return 64;case 75:return 21;case 76:return 41;case 77:return 84;case 78:return"DOT";case 79:return"PLUS";case 80:return 81;case 81:return"EQUALS";case 82:return"EQUALS";case 83:return 88;case 84:return 12;case 85:return 14;case 86:return"PUNCTUATION";case 87:return 87;case 88:return 86;case 89:return 83;case 90:return 9}},rules:[/^(?:.*direction\s+TB[^\n]*)/,/^(?:.*direction\s+BT[^\n]*)/,/^(?:.*direction\s+RL[^\n]*)/,/^(?:.*direction\s+LR[^\n]*)/,/^(?:%%(?!\{)*[^\n]*(\r?\n?)+)/,/^(?:%%[^\n]*(\r?\n)*)/,/^(?:accTitle\s*:\s*)/,/^(?:(?!\n||)*[^\n]*)/,/^(?:accDescr\s*:\s*)/,/^(?:(?!\n||)*[^\n]*)/,/^(?:accDescr\s*\{\s*)/,/^(?:[\}])/,/^(?:[^\}]*)/,/^(?:\s*(\r?\n)+)/,/^(?:\s+)/,/^(?:classDiagram-v2\b)/,/^(?:classDiagram\b)/,/^(?:\[\*\])/,/^(?:call[\s]+)/,/^(?:\([\s]*\))/,/^(?:\()/,/^(?:[^(]*)/,/^(?:\))/,/^(?:[^)]*)/,/^(?:["])/,/^(?:[^"]*)/,/^(?:["])/,/^(?:namespace\b)/,/^(?:\s*(\r?\n)+)/,/^(?:\s+)/,/^(?:[{])/,/^(?:[}])/,/^(?:$)/,/^(?:\s*(\r?\n)+)/,/^(?:\s+)/,/^(?:\[\*\])/,/^(?:class\b)/,/^(?:\s*(\r?\n)+)/,/^(?:\s+)/,/^(?:[}])/,/^(?:[{])/,/^(?:[}])/,/^(?:$)/,/^(?:\[\*\])/,/^(?:[{])/,/^(?:[\n])/,/^(?:[^{}\n]*)/,/^(?:cssClass\b)/,/^(?:callback\b)/,/^(?:link\b)/,/^(?:click\b)/,/^(?:note for\b)/,/^(?:note\b)/,/^(?:<<)/,/^(?:>>)/,/^(?:href\b)/,/^(?:[~])/,/^(?:[^~]*)/,/^(?:~)/,/^(?:[`])/,/^(?:[^`]+)/,/^(?:[`])/,/^(?:_self\b)/,/^(?:_blank\b)/,/^(?:_parent\b)/,/^(?:_top\b)/,/^(?:\s*<\|)/,/^(?:\s*\|>)/,/^(?:\s*>)/,/^(?:\s*<)/,/^(?:\s*\*)/,/^(?:\s*o\b)/,/^(?:\s*\(\))/,/^(?:--)/,/^(?:\.\.)/,/^(?::{1}[^:\n;]+)/,/^(?::{3})/,/^(?:-)/,/^(?:\.)/,/^(?:\+)/,/^(?:%)/,/^(?:=)/,/^(?:=)/,/^(?:\w+)/,/^(?:\[)/,/^(?:\])/,/^(?:[!"#$%&'*+,-.`?\\/])/,/^(?:[0-9]+)/,/^(?:[\u00AA\u00B5\u00BA\u00C0-\u00D6\u00D8-\u00F6]|[\u00F8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377]|[\u037A-\u037D\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5]|[\u03F7-\u0481\u048A-\u0527\u0531-\u0556\u0559\u0561-\u0587\u05D0-\u05EA]|[\u05F0-\u05F2\u0620-\u064A\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE]|[\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA]|[\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u08A0]|[\u08A2-\u08AC\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0977]|[\u0979-\u097F\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2]|[\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09F0\u09F1\u0A05-\u0A0A]|[\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39]|[\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8]|[\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0B05-\u0B0C]|[\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C]|[\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99]|[\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0]|[\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C33\u0C35-\u0C39\u0C3D]|[\u0C58\u0C59\u0C60\u0C61\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3]|[\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D05-\u0D0C\u0D0E-\u0D10]|[\u0D12-\u0D3A\u0D3D\u0D4E\u0D60\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1]|[\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E81]|[\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3]|[\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6]|[\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A]|[\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081]|[\u108E\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D]|[\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0]|[\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310]|[\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F4\u1401-\u166C]|[\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u1700-\u170C\u170E-\u1711]|[\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7]|[\u17DC\u1820-\u1877\u1880-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191C]|[\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19C1-\u19C7\u1A00-\u1A16]|[\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-\u1B4B\u1B83-\u1BA0\u1BAE\u1BAF]|[\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\u1CE9-\u1CEC]|[\u1CEE-\u1CF1\u1CF5\u1CF6\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D]|[\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D]|[\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3]|[\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F]|[\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128]|[\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2183\u2184]|[\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3]|[\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6]|[\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE]|[\u2DD0-\u2DD6\u2DD8-\u2DDE\u2E2F\u3005\u3006\u3031-\u3035\u303B\u303C]|[\u3041-\u3096\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D]|[\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FCC]|[\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B]|[\uA640-\uA66E\uA67F-\uA697\uA6A0-\uA6E5\uA717-\uA71F\uA722-\uA788]|[\uA78B-\uA78E\uA790-\uA793\uA7A0-\uA7AA\uA7F8-\uA801\uA803-\uA805]|[\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB]|[\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF\uAA00-\uAA28]|[\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA80-\uAAAF\uAAB1\uAAB5]|[\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4]|[\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E]|[\uABC0-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D]|[\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36]|[\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D]|[\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC]|[\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF]|[\uFFD2-\uFFD7\uFFDA-\uFFDC])/,/^(?:\s)/,/^(?:$)/],conditions:{"namespace-body":{rules:[26,31,32,33,34,35,36,47,48,49,50,51,52,53,54,55,58,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90],inclusive:!1},namespace:{rules:[26,27,28,29,30,47,48,49,50,51,52,53,54,55,58,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90],inclusive:!1},"class-body":{rules:[26,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,58,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90],inclusive:!1},class:{rules:[26,37,38,39,40,47,48,49,50,51,52,53,54,55,58,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90],inclusive:!1},acc_descr_multiline:{rules:[11,12,26,47,48,49,50,51,52,53,54,55,58,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90],inclusive:!1},acc_descr:{rules:[9,26,47,48,49,50,51,52,53,54,55,58,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90],inclusive:!1},acc_title:{rules:[7,26,47,48,49,50,51,52,53,54,55,58,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90],inclusive:!1},callback_args:{rules:[22,23,26,47,48,49,50,51,52,53,54,55,58,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90],inclusive:!1},callback_name:{rules:[19,20,21,26,47,48,49,50,51,52,53,54,55,58,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90],inclusive:!1},href:{rules:[26,47,48,49,50,51,52,53,54,55,58,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90],inclusive:!1},struct:{rules:[26,47,48,49,50,51,52,53,54,55,58,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90],inclusive:!1},generic:{rules:[26,47,48,49,50,51,52,53,54,55,56,57,58,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90],inclusive:!1},bqstring:{rules:[26,47,48,49,50,51,52,53,54,55,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90],inclusive:!1},string:{rules:[24,25,26,47,48,49,50,51,52,53,54,55,58,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90],inclusive:!1},INITIAL:{rules:[0,1,2,3,4,5,6,8,10,13,14,15,16,17,18,26,27,36,47,48,49,50,51,52,53,54,55,58,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90],inclusive:!0}}};return ke}();Ve.lexer=Ye;function ce(){this.yy={}}return ce.prototype=Ve,Ve.Parser=ce,new ce}();Tgt.parser=Tgt;const zRt=Tgt,qRt=["#","+","~","-",""];class HRt{constructor(a,f){this.memberType=f,this.visibility="",this.classifier="";const p=Q1(a,Oe());this.parseMember(p)}getDisplayDetails(){let a=this.visibility+YP(this.id);this.memberType==="method"&&(a+=`(${YP(this.parameters.trim())})`,this.returnType&&(a+=" : "+YP(this.returnType))),a=a.trim();const f=this.parseClassifier();return{displayText:a,cssStyle:f}}parseMember(a){let f="";if(this.memberType==="method"){const p=/([#+~-])?(.+)\((.*)\)([\s$*])?(.*)([$*])?/,w=a.match(p);if(w){const m=w[1]?w[1].trim():"";if(qRt.includes(m)&&(this.visibility=m),this.id=w[2].trim(),this.parameters=w[3]?w[3].trim():"",f=w[4]?w[4].trim():"",this.returnType=w[5]?w[5].trim():"",f===""){const b=this.returnType.substring(this.returnType.length-1);b.match(/[$*]/)&&(f=b,this.returnType=this.returnType.substring(0,this.returnType.length-1))}}}else{const p=a.length,w=a.substring(0,1),m=a.substring(p-1);qRt.includes(w)&&(this.visibility=w),m.match(/[*?]/)&&(f=m),this.id=a.substring(this.visibility===""?0:1,f===""?p:p-1)}this.classifier=f}parseClassifier(){switch(this.classifier){case"*":return"font-style:italic;";case"$":return"text-decoration:underline;";default:return""}}}const $Y="classId-";let Cgt=[],Jl={},zY=[],VRt=0,xk={},_gt=0,WF=[];const AT=i=>Kr.sanitizeText(i,Oe()),wL=function(i){const a=Kr.sanitizeText(i,Oe());let f="",p=a;if(a.indexOf("~")>0){const w=a.split("~");p=AT(w[0]),f=AT(w[1])}return{className:p,type:f}},sGe=function(i,a){const f=Kr.sanitizeText(i,Oe());a&&(a=AT(a));const{className:p}=wL(f);Jl[p].label=a},qY=function(i){const a=Kr.sanitizeText(i,Oe()),{className:f,type:p}=wL(a);if(Object.hasOwn(Jl,f))return;const w=Kr.sanitizeText(f,Oe());Jl[w]={id:w,type:p,label:w,cssClasses:[],methods:[],members:[],annotations:[],domId:$Y+w+"-"+VRt},VRt++},GRt=function(i){const a=Kr.sanitizeText(i,Oe());if(a in Jl)return Jl[a].domId;throw new Error("Class not found: "+a)},aGe=function(){Cgt=[],Jl={},zY=[],WF=[],WF.push(WRt),xk={},_gt=0,hg()},oGe=function(i){return Jl[i]},cGe=function(){return Jl},uGe=function(){return Cgt},lGe=function(){return zY},hGe=function(i){Ut.debug("Adding relation: "+JSON.stringify(i)),qY(i.id1),qY(i.id2),i.id1=wL(i.id1).className,i.id2=wL(i.id2).className,i.relationTitle1=Kr.sanitizeText(i.relationTitle1.trim(),Oe()),i.relationTitle2=Kr.sanitizeText(i.relationTitle2.trim(),Oe()),Cgt.push(i)},fGe=function(i,a){const f=wL(i).className;Jl[f].annotations.push(a)},URt=function(i,a){qY(i);const f=wL(i).className,p=Jl[f];if(typeof a=="string"){const w=a.trim();w.startsWith("<<")&&w.endsWith(">>")?p.annotations.push(AT(w.substring(2,w.length-2))):w.indexOf(")")>0?p.methods.push(new HRt(w,"method")):w&&p.members.push(new HRt(w,"attribute"))}},dGe=function(i,a){Array.isArray(a)&&(a.reverse(),a.forEach(f=>URt(i,f)))},gGe=function(i,a){const f={id:`note${zY.length}`,class:a,text:i};zY.push(f)},pGe=function(i){return i.startsWith(":")&&(i=i.substring(1)),AT(i.trim())},Sgt=function(i,a){i.split(",").forEach(function(f){let p=f;f[0].match(/\d/)&&(p=$Y+p),Jl[p]!==void 0&&Jl[p].cssClasses.push(a)})},bGe=function(i,a){i.split(",").forEach(function(f){a!==void 0&&(Jl[f].tooltip=AT(a))})},wGe=function(i,a){return a?xk[a].classes[i].tooltip:Jl[i].tooltip},vGe=function(i,a,f){const p=Oe();i.split(",").forEach(function(w){let m=w;w[0].match(/\d/)&&(m=$Y+m),Jl[m]!==void 0&&(Jl[m].link=$a.formatUrl(a,p),p.securityLevel==="sandbox"?Jl[m].linkTarget="_top":typeof f=="string"?Jl[m].linkTarget=AT(f):Jl[m].linkTarget="_blank")}),Sgt(i,"clickable")},mGe=function(i,a,f){i.split(",").forEach(function(p){yGe(p,a,f),Jl[p].haveCallback=!0}),Sgt(i,"clickable")},yGe=function(i,a,f){const p=Kr.sanitizeText(i,Oe());if(Oe().securityLevel!=="loose"||a===void 0)return;const m=p;if(Jl[m]!==void 0){const b=GRt(m);let E=[];if(typeof f=="string"){E=f.split(/,(?=(?:(?:[^"]*"){2})*[^"]*$)/);for(let _=0;_")),w.classed("hover",!0)}).on("mouseout",function(){a.transition().duration(500).style("opacity",0),yr(this).classed("hover",!1)})};WF.push(WRt);let YRt="TB";const HY={setAccTitle:E0,getAccTitle:fg,getAccDescription:gg,setAccDescription:dg,getConfig:()=>Oe().class,addClass:qY,bindFunctions:xGe,clear:aGe,getClass:oGe,getClasses:cGe,getNotes:lGe,addAnnotation:fGe,addNote:gGe,getRelations:uGe,addRelation:hGe,getDirection:()=>YRt,setDirection:i=>{YRt=i},addMember:URt,addMembers:dGe,cleanupLabel:pGe,lineType:kGe,relationType:EGe,setClickEvent:mGe,setCssClass:Sgt,setLink:vGe,getTooltip:wGe,setTooltip:bGe,lookUpDomId:GRt,setDiagramTitle:Nb,getDiagramTitle:pg,setClassLabel:sGe,addNamespace:function(i){xk[i]===void 0&&(xk[i]={id:i,classes:{},children:{},domId:$Y+i+"-"+_gt},_gt++)},addClassesToNamespace:function(i,a){xk[i]!==void 0&&a.map(f=>{Jl[f].parent=i,xk[i].classes[f]=Jl[f]})},getNamespace:function(i){return xk[i]},getNamespaces:function(){return xk}},KRt=i=>`g.classGroup text { + fill: ${i.nodeBorder||i.classText}; + stroke: none; + font-family: ${i.fontFamily}; + font-size: 10px; + + .title { + font-weight: bolder; + } + +} + +.nodeLabel, .edgeLabel { + color: ${i.classText}; +} +.edgeLabel .label rect { + fill: ${i.mainBkg}; +} +.label text { + fill: ${i.classText}; +} +.edgeLabel .label span { + background: ${i.mainBkg}; +} + +.classTitle { + font-weight: bolder; +} +.node rect, + .node circle, + .node ellipse, + .node polygon, + .node path { + fill: ${i.mainBkg}; + stroke: ${i.nodeBorder}; + stroke-width: 1px; + } + + +.divider { + stroke: ${i.nodeBorder}; + stroke-width: 1; +} + +g.clickable { + cursor: pointer; +} + +g.classGroup rect { + fill: ${i.mainBkg}; + stroke: ${i.nodeBorder}; +} + +g.classGroup line { + stroke: ${i.nodeBorder}; + stroke-width: 1; +} + +.classLabel .box { + stroke: none; + stroke-width: 0; + fill: ${i.mainBkg}; + opacity: 0.5; +} + +.classLabel .label { + fill: ${i.nodeBorder}; + font-size: 10px; +} + +.relation { + stroke: ${i.lineColor}; + stroke-width: 1; + fill: none; +} + +.dashed-line{ + stroke-dasharray: 3; +} + +.dotted-line{ + stroke-dasharray: 1 2; +} + +#compositionStart, .composition { + fill: ${i.lineColor} !important; + stroke: ${i.lineColor} !important; + stroke-width: 1; +} + +#compositionEnd, .composition { + fill: ${i.lineColor} !important; + stroke: ${i.lineColor} !important; + stroke-width: 1; +} + +#dependencyStart, .dependency { + fill: ${i.lineColor} !important; + stroke: ${i.lineColor} !important; + stroke-width: 1; +} + +#dependencyStart, .dependency { + fill: ${i.lineColor} !important; + stroke: ${i.lineColor} !important; + stroke-width: 1; +} + +#extensionStart, .extension { + fill: transparent !important; + stroke: ${i.lineColor} !important; + stroke-width: 1; +} + +#extensionEnd, .extension { + fill: transparent !important; + stroke: ${i.lineColor} !important; + stroke-width: 1; +} + +#aggregationStart, .aggregation { + fill: transparent !important; + stroke: ${i.lineColor} !important; + stroke-width: 1; +} + +#aggregationEnd, .aggregation { + fill: transparent !important; + stroke: ${i.lineColor} !important; + stroke-width: 1; +} + +#lollipopStart, .lollipop { + fill: ${i.mainBkg} !important; + stroke: ${i.lineColor} !important; + stroke-width: 1; +} + +#lollipopEnd, .lollipop { + fill: ${i.mainBkg} !important; + stroke: ${i.lineColor} !important; + stroke-width: 1; +} + +.edgeTerminals { + font-size: 11px; +} + +.classTitleText { + text-anchor: middle; + font-size: 18px; + fill: ${i.textColor}; +} +`;let XRt=0;const TGe=function(i,a,f,p,w){const m=function(at){switch(at){case w.db.relationType.AGGREGATION:return"aggregation";case w.db.relationType.EXTENSION:return"extension";case w.db.relationType.COMPOSITION:return"composition";case w.db.relationType.DEPENDENCY:return"dependency";case w.db.relationType.LOLLIPOP:return"lollipop"}};a.points=a.points.filter(at=>!Number.isNaN(at.y));const b=a.points,E=E5().x(function(at){return at.x}).y(function(at){return at.y}).curve(HP),_=i.append("path").attr("d",E(b)).attr("id","edge"+XRt).attr("class","relation");let A="";p.arrowMarkerAbsolute&&(A=window.location.protocol+"//"+window.location.host+window.location.pathname+window.location.search,A=A.replace(/\(/g,"\\("),A=A.replace(/\)/g,"\\)")),f.relation.lineType==1&&_.attr("class","relation dashed-line"),f.relation.lineType==10&&_.attr("class","relation dotted-line"),f.relation.type1!=="none"&&_.attr("marker-start","url("+A+"#"+m(f.relation.type1)+"Start)"),f.relation.type2!=="none"&&_.attr("marker-end","url("+A+"#"+m(f.relation.type2)+"End)");let I,B;const N=a.points.length;let R=$a.calcLabelPosition(a.points);I=R.x,B=R.y;let z,W,et,st;if(N%2!==0&&N>1){let at=$a.calcCardinalityPosition(f.relation.type1!=="none",a.points,a.points[0]),bt=$a.calcCardinalityPosition(f.relation.type2!=="none",a.points,a.points[N-1]);Ut.debug("cardinality_1_point "+JSON.stringify(at)),Ut.debug("cardinality_2_point "+JSON.stringify(bt)),z=at.x,W=at.y,et=bt.x,st=bt.y}if(f.title!==void 0){const at=i.append("g").attr("class","classLabel"),bt=at.append("text").attr("class","label").attr("x",I).attr("y",B).attr("fill","red").attr("text-anchor","middle").text(f.title);window.label=bt;const mt=bt.node().getBBox();at.insert("rect",":first-child").attr("class","box").attr("x",mt.x-p.padding/2).attr("y",mt.y-p.padding/2).attr("width",mt.width+p.padding).attr("height",mt.height+p.padding)}Ut.info("Rendering relation "+JSON.stringify(f)),f.relationTitle1!==void 0&&f.relationTitle1!=="none"&&i.append("g").attr("class","cardinality").append("text").attr("class","type1").attr("x",z).attr("y",W).attr("fill","black").attr("font-size","6").text(f.relationTitle1),f.relationTitle2!==void 0&&f.relationTitle2!=="none"&&i.append("g").attr("class","cardinality").append("text").attr("class","type2").attr("x",et).attr("y",st).attr("fill","black").attr("font-size","6").text(f.relationTitle2),XRt++},CGe=function(i,a,f,p){Ut.debug("Rendering class ",a,f);const w=a.id,m={id:w,label:a.id,width:0,height:0},b=i.append("g").attr("id",p.db.lookUpDomId(w)).attr("class","classGroup");let E;a.link?E=b.append("svg:a").attr("xlink:href",a.link).attr("target",a.linkTarget).append("text").attr("y",f.textHeight+f.padding).attr("x",0):E=b.append("text").attr("y",f.textHeight+f.padding).attr("x",0);let _=!0;a.annotations.forEach(function(bt){const mt=E.append("tspan").text("«"+bt+"»");_||mt.attr("dy",f.textHeight),_=!1});let A=QRt(a);const I=E.append("tspan").text(A).attr("class","title");_||I.attr("dy",f.textHeight);const B=E.node().getBBox().height;let N,R,z;if(a.members.length>0){N=b.append("line").attr("x1",0).attr("y1",f.padding+B+f.dividerMargin/2).attr("y2",f.padding+B+f.dividerMargin/2);const bt=b.append("text").attr("x",f.padding).attr("y",B+f.dividerMargin+f.textHeight).attr("fill","white").attr("class","classText");_=!0,a.members.forEach(function(mt){ZRt(bt,mt,_,f),_=!1}),R=bt.node().getBBox()}if(a.methods.length>0){z=b.append("line").attr("x1",0).attr("y1",f.padding+B+f.dividerMargin+R.height).attr("y2",f.padding+B+f.dividerMargin+R.height);const bt=b.append("text").attr("x",f.padding).attr("y",B+2*f.dividerMargin+R.height+f.textHeight).attr("fill","white").attr("class","classText");_=!0,a.methods.forEach(function(mt){ZRt(bt,mt,_,f),_=!1})}const W=b.node().getBBox();var et=" ";a.cssClasses.length>0&&(et=et+a.cssClasses.join(" "));const at=b.insert("rect",":first-child").attr("x",0).attr("y",0).attr("width",W.width+2*f.padding).attr("height",W.height+f.padding+.5*f.dividerMargin).attr("class",et).node().getBBox().width;return E.node().childNodes.forEach(function(bt){bt.setAttribute("x",(at-bt.getBBox().width)/2)}),a.tooltip&&E.insert("title").text(a.tooltip),N&&N.attr("x2",at),z&&z.attr("x2",at),m.width=at,m.height=W.height+f.padding+.5*f.dividerMargin,m},QRt=function(i){let a=i.id;return i.type&&(a+="<"+YP(i.type)+">"),a},_Ge=function(i,a,f,p){Ut.debug("Rendering note ",a,f);const w=a.id,m={id:w,text:a.text,width:0,height:0},b=i.append("g").attr("id",w).attr("class","classGroup");let E=b.append("text").attr("y",f.textHeight+f.padding).attr("x",0);const _=JSON.parse(`"${a.text}"`).split(` +`);_.forEach(function(N){Ut.debug(`Adding line: ${N}`),E.append("tspan").text(N).attr("class","title").attr("dy",f.textHeight)});const A=b.node().getBBox(),B=b.insert("rect",":first-child").attr("x",0).attr("y",0).attr("width",A.width+2*f.padding).attr("height",A.height+_.length*f.textHeight+f.padding+.5*f.dividerMargin).node().getBBox().width;return E.node().childNodes.forEach(function(N){N.setAttribute("x",(B-N.getBBox().width)/2)}),m.width=B,m.height=A.height+_.length*f.textHeight+f.padding+.5*f.dividerMargin,m},ZRt=function(i,a,f,p){const{displayText:w,cssStyle:m}=a.getDisplayDetails(),b=i.append("tspan").attr("x",p.padding).text(w);m!==""&&b.attr("style",a.cssStyle),f||b.attr("dy",p.textHeight)},Agt={getClassTitleString:QRt,drawClass:CGe,drawEdge:TGe,drawNote:_Ge};let VY={};const GY=20,YF=function(i){const a=Object.entries(VY).find(f=>f[1].label===i);if(a)return a[0]},SGe=function(i){i.append("defs").append("marker").attr("id","extensionStart").attr("class","extension").attr("refX",0).attr("refY",7).attr("markerWidth",190).attr("markerHeight",240).attr("orient","auto").append("path").attr("d","M 1,7 L18,13 V 1 Z"),i.append("defs").append("marker").attr("id","extensionEnd").attr("refX",19).attr("refY",7).attr("markerWidth",20).attr("markerHeight",28).attr("orient","auto").append("path").attr("d","M 1,1 V 13 L18,7 Z"),i.append("defs").append("marker").attr("id","compositionStart").attr("class","extension").attr("refX",0).attr("refY",7).attr("markerWidth",190).attr("markerHeight",240).attr("orient","auto").append("path").attr("d","M 18,7 L9,13 L1,7 L9,1 Z"),i.append("defs").append("marker").attr("id","compositionEnd").attr("refX",19).attr("refY",7).attr("markerWidth",20).attr("markerHeight",28).attr("orient","auto").append("path").attr("d","M 18,7 L9,13 L1,7 L9,1 Z"),i.append("defs").append("marker").attr("id","aggregationStart").attr("class","extension").attr("refX",0).attr("refY",7).attr("markerWidth",190).attr("markerHeight",240).attr("orient","auto").append("path").attr("d","M 18,7 L9,13 L1,7 L9,1 Z"),i.append("defs").append("marker").attr("id","aggregationEnd").attr("refX",19).attr("refY",7).attr("markerWidth",20).attr("markerHeight",28).attr("orient","auto").append("path").attr("d","M 18,7 L9,13 L1,7 L9,1 Z"),i.append("defs").append("marker").attr("id","dependencyStart").attr("class","extension").attr("refX",0).attr("refY",7).attr("markerWidth",190).attr("markerHeight",240).attr("orient","auto").append("path").attr("d","M 5,7 L9,13 L1,7 L9,1 Z"),i.append("defs").append("marker").attr("id","dependencyEnd").attr("refX",19).attr("refY",7).attr("markerWidth",20).attr("markerHeight",28).attr("orient","auto").append("path").attr("d","M 18,7 L9,13 L14,7 L9,1 Z")},AGe=Object.freeze(Object.defineProperty({__proto__:null,diagram:{parser:zRt,db:HY,renderer:{draw:function(i,a,f,p){const w=Oe().class;VY={},Ut.info("Rendering diagram "+i);const m=Oe().securityLevel;let b;m==="sandbox"&&(b=yr("#i"+a));const E=yr(m==="sandbox"?b.nodes()[0].contentDocument.body:"body"),_=E.select(`[id='${a}']`);SGe(_);const A=new c1({multigraph:!0});A.setGraph({isMultiGraph:!0}),A.setDefaultEdgeLabel(function(){return{}});const I=p.db.getClasses(),B=Object.keys(I);for(const at of B){const bt=I[at],mt=Agt.drawClass(_,bt,w,p);VY[mt.id]=mt,A.setNode(mt.id,mt),Ut.info("Org height: "+mt.height)}p.db.getRelations().forEach(function(at){Ut.info("tjoho"+YF(at.id1)+YF(at.id2)+JSON.stringify(at)),A.setEdge(YF(at.id1),YF(at.id2),{relation:at},at.title||"DEFAULT")}),p.db.getNotes().forEach(function(at){Ut.debug(`Adding note: ${JSON.stringify(at)}`);const bt=Agt.drawNote(_,at,w,p);VY[bt.id]=bt,A.setNode(bt.id,bt),at.class&&at.class in I&&A.setEdge(at.id,YF(at.class),{relation:{id1:at.id,id2:at.class,relation:{type1:"none",type2:"none",lineType:10}}},"DEFAULT")}),aL(A),A.nodes().forEach(function(at){at!==void 0&&A.node(at)!==void 0&&(Ut.debug("Node "+at+": "+JSON.stringify(A.node(at))),E.select("#"+(p.db.lookUpDomId(at)||at)).attr("transform","translate("+(A.node(at).x-A.node(at).width/2)+","+(A.node(at).y-A.node(at).height/2)+" )"))}),A.edges().forEach(function(at){at!==void 0&&A.edge(at)!==void 0&&(Ut.debug("Edge "+at.v+" -> "+at.w+": "+JSON.stringify(A.edge(at))),Agt.drawEdge(_,A.edge(at),A.edge(at).relation,w,p))});const z=_.node().getBBox(),W=z.width+GY*2,et=z.height+GY*2;k0(_,et,W,w.useMaxWidth);const st=`${z.x-GY} ${z.y-GY} ${W} ${et}`;Ut.debug(`viewBox ${st}`),_.attr("viewBox",st)}},styles:KRt,init:i=>{i.class||(i.class={}),i.class.arrowMarkerAbsolute=i.arrowMarkerAbsolute,HY.clear()}}},Symbol.toStringTag,{value:"Module"})),Lgt=i=>Kr.sanitizeText(i,Oe());let Mgt={dividerMargin:10,padding:5,textHeight:10,curve:void 0};const LGe=function(i,a,f,p){const w=Object.keys(i);Ut.info("keys:",w),Ut.info(i),w.forEach(function(m){var A,I;const b=i[m],_={shape:"rect",id:b.id,domId:b.domId,labelText:Lgt(b.id),labelStyle:"",style:"fill: none; stroke: black",padding:((A=Oe().flowchart)==null?void 0:A.padding)??((I=Oe().class)==null?void 0:I.padding)};a.setNode(b.id,_),JRt(b.classes,a,f,p,b.id),Ut.info("setNode",_)})},JRt=function(i,a,f,p,w){const m=Object.keys(i);Ut.info("keys:",m),Ut.info(i),m.filter(b=>i[b].parent==w).forEach(function(b){var z,W;const E=i[b],_=E.cssClasses.join(" "),A={labelStyle:"",style:""},I=E.label??E.id,B=0,N="class_box",R={labelStyle:A.labelStyle,shape:N,labelText:Lgt(I),classData:E,rx:B,ry:B,class:_,style:A.style,id:E.id,domId:E.domId,tooltip:p.db.getTooltip(E.id,w)||"",haveCallback:E.haveCallback,link:E.link,width:E.type==="group"?500:void 0,type:E.type,padding:((z=Oe().flowchart)==null?void 0:z.padding)??((W=Oe().class)==null?void 0:W.padding)};a.setNode(E.id,R),w&&a.setParent(E.id,w),Ut.info("setNode",R)})},MGe=function(i,a,f,p){Ut.info(i),i.forEach(function(w,m){var W,et;const b=w,E="",_={labelStyle:"",style:""},A=b.text,I=0,B="note",N={labelStyle:_.labelStyle,shape:B,labelText:Lgt(A),noteData:b,rx:I,ry:I,class:E,style:_.style,id:b.id,domId:b.id,tooltip:"",type:"note",padding:((W=Oe().flowchart)==null?void 0:W.padding)??((et=Oe().class)==null?void 0:et.padding)};if(a.setNode(b.id,N),Ut.info("setNode",N),!b.class||!(b.class in p))return;const R=f+m,z={id:`edgeNote${R}`,classes:"relation",pattern:"dotted",arrowhead:"none",startLabelRight:"",endLabelLeft:"",arrowTypeStart:"none",arrowTypeEnd:"none",style:"fill:none",labelStyle:"",curve:ew(Mgt.curve,cg)};a.setEdge(b.id,b.class,z,R)})},DGe=function(i,a){const f=Oe().flowchart;let p=0;i.forEach(function(w){var b;p++;const m={classes:"relation",pattern:w.relation.lineType==1?"dashed":"solid",id:"id"+p,arrowhead:w.type==="arrow_open"?"none":"normal",startLabelRight:w.relationTitle1==="none"?"":w.relationTitle1,endLabelLeft:w.relationTitle2==="none"?"":w.relationTitle2,arrowTypeStart:tjt(w.relation.type1),arrowTypeEnd:tjt(w.relation.type2),style:"fill:none",labelStyle:"",curve:ew(f==null?void 0:f.curve,cg)};if(Ut.info(m,w),w.style!==void 0){const E=im(w.style);m.style=E.style,m.labelStyle=E.labelStyle}w.text=w.title,w.text===void 0?w.style!==void 0&&(m.arrowheadStyle="fill: #333"):(m.arrowheadStyle="fill: #333",m.labelpos="c",((b=Oe().flowchart)==null?void 0:b.htmlLabels)??Oe().htmlLabels?(m.labelType="html",m.label=''+w.text+""):(m.labelType="text",m.label=w.text.replace(Kr.lineBreakRegex,` +`),w.style===void 0&&(m.style=m.style||"stroke: #333; stroke-width: 1.5px;fill:none"),m.labelStyle=m.labelStyle.replace("color:","fill:"))),a.setEdge(w.id1,w.id2,m,p)})},IGe=function(i){Mgt={...Mgt,...i}},OGe=async function(i,a,f,p){Ut.info("Drawing class - ",a);const w=Oe().flowchart??Oe().class,m=Oe().securityLevel;Ut.info("config:",w);const b=(w==null?void 0:w.nodeSpacing)??50,E=(w==null?void 0:w.rankSpacing)??50,_=new c1({multigraph:!0,compound:!0}).setGraph({rankdir:p.db.getDirection(),nodesep:b,ranksep:E,marginx:8,marginy:8}).setDefaultEdgeLabel(function(){return{}}),A=p.db.getNamespaces(),I=p.db.getClasses(),B=p.db.getRelations(),N=p.db.getNotes();Ut.info(B),LGe(A,_,a,p),JRt(I,_,a,p),DGe(B,_),MGe(N,_,B.length+1,I);let R;m==="sandbox"&&(R=yr("#i"+a));const z=yr(m==="sandbox"?R.nodes()[0].contentDocument.body:"body"),W=z.select(`[id="${a}"]`),et=z.select("#"+a+" g");if(await N0t(et,_,["aggregation","extension","composition","dependency","lollipop"],"classDiagram",a),$a.insertTitle(W,"classTitleText",(w==null?void 0:w.titleTopMargin)??5,p.db.getDiagramTitle()),fT(_,W,w==null?void 0:w.diagramPadding,w==null?void 0:w.useMaxWidth),!(w!=null&&w.htmlLabels)){const st=m==="sandbox"?R.nodes()[0].contentDocument:document,at=st.querySelectorAll('[id="'+a+'"] .edgeLabel .label');for(const bt of at){const mt=bt.getBBox(),yt=st.createElementNS("http://www.w3.org/2000/svg","rect");yt.setAttribute("rx",0),yt.setAttribute("ry",0),yt.setAttribute("width",mt.width),yt.setAttribute("height",mt.height),bt.insertBefore(yt,bt.firstChild)}}};function tjt(i){let a;switch(i){case 0:a="aggregation";break;case 1:a="extension";break;case 2:a="composition";break;case 3:a="dependency";break;case 4:a="lollipop";break;default:a="none"}return a}const PGe=Object.freeze(Object.defineProperty({__proto__:null,diagram:{parser:zRt,db:HY,renderer:{setConf:IGe,draw:OGe},styles:KRt,init:i=>{i.class||(i.class={}),i.class.arrowMarkerAbsolute=i.arrowMarkerAbsolute,HY.clear()}}},Symbol.toStringTag,{value:"Module"}));var Dgt=function(){var i=function(Et,Z,Ct,xt){for(Ct=Ct||{},xt=Et.length;xt--;Ct[Et[xt]]=Z);return Ct},a=[1,2],f=[1,3],p=[1,4],w=[2,4],m=[1,9],b=[1,11],E=[1,15],_=[1,16],A=[1,17],I=[1,18],B=[1,30],N=[1,19],R=[1,20],z=[1,21],W=[1,22],et=[1,23],st=[1,25],at=[1,26],bt=[1,27],mt=[1,28],yt=[1,29],ft=[1,32],ut=[1,33],vt=[1,34],X=[1,35],pt=[1,31],U=[1,4,5,15,16,18,20,21,23,24,25,26,27,28,32,34,36,37,41,44,45,46,47,50],Tt=[1,4,5,13,14,15,16,18,20,21,23,24,25,26,27,28,32,34,36,37,41,44,45,46,47,50],nt=[4,5,15,16,18,20,21,23,24,25,26,27,28,32,34,36,37,41,44,45,46,47,50],It={trace:function(){},yy:{},symbols_:{error:2,start:3,SPACE:4,NL:5,SD:6,document:7,line:8,statement:9,classDefStatement:10,cssClassStatement:11,idStatement:12,DESCR:13,"-->":14,HIDE_EMPTY:15,scale:16,WIDTH:17,COMPOSIT_STATE:18,STRUCT_START:19,STRUCT_STOP:20,STATE_DESCR:21,AS:22,ID:23,FORK:24,JOIN:25,CHOICE:26,CONCURRENT:27,note:28,notePosition:29,NOTE_TEXT:30,direction:31,acc_title:32,acc_title_value:33,acc_descr:34,acc_descr_value:35,acc_descr_multiline_value:36,classDef:37,CLASSDEF_ID:38,CLASSDEF_STYLEOPTS:39,DEFAULT:40,class:41,CLASSENTITY_IDS:42,STYLECLASS:43,direction_tb:44,direction_bt:45,direction_rl:46,direction_lr:47,eol:48,";":49,EDGE_STATE:50,STYLE_SEPARATOR:51,left_of:52,right_of:53,$accept:0,$end:1},terminals_:{2:"error",4:"SPACE",5:"NL",6:"SD",13:"DESCR",14:"-->",15:"HIDE_EMPTY",16:"scale",17:"WIDTH",18:"COMPOSIT_STATE",19:"STRUCT_START",20:"STRUCT_STOP",21:"STATE_DESCR",22:"AS",23:"ID",24:"FORK",25:"JOIN",26:"CHOICE",27:"CONCURRENT",28:"note",30:"NOTE_TEXT",32:"acc_title",33:"acc_title_value",34:"acc_descr",35:"acc_descr_value",36:"acc_descr_multiline_value",37:"classDef",38:"CLASSDEF_ID",39:"CLASSDEF_STYLEOPTS",40:"DEFAULT",41:"class",42:"CLASSENTITY_IDS",43:"STYLECLASS",44:"direction_tb",45:"direction_bt",46:"direction_rl",47:"direction_lr",49:";",50:"EDGE_STATE",51:"STYLE_SEPARATOR",52:"left_of",53:"right_of"},productions_:[0,[3,2],[3,2],[3,2],[7,0],[7,2],[8,2],[8,1],[8,1],[9,1],[9,1],[9,1],[9,2],[9,3],[9,4],[9,1],[9,2],[9,1],[9,4],[9,3],[9,6],[9,1],[9,1],[9,1],[9,1],[9,4],[9,4],[9,1],[9,2],[9,2],[9,1],[10,3],[10,3],[11,3],[31,1],[31,1],[31,1],[31,1],[48,1],[48,1],[12,1],[12,1],[12,3],[12,3],[29,1],[29,1]],performAction:function(Z,Ct,xt,Ht,Le,Ft,gn){var Se=Ft.length-1;switch(Le){case 3:return Ht.setRootDoc(Ft[Se]),Ft[Se];case 4:this.$=[];break;case 5:Ft[Se]!="nl"&&(Ft[Se-1].push(Ft[Se]),this.$=Ft[Se-1]);break;case 6:case 7:this.$=Ft[Se];break;case 8:this.$="nl";break;case 11:this.$=Ft[Se];break;case 12:const ce=Ft[Se-1];ce.description=Ht.trimColon(Ft[Se]),this.$=ce;break;case 13:this.$={stmt:"relation",state1:Ft[Se-2],state2:Ft[Se]};break;case 14:const ke=Ht.trimColon(Ft[Se]);this.$={stmt:"relation",state1:Ft[Se-3],state2:Ft[Se-1],description:ke};break;case 18:this.$={stmt:"state",id:Ft[Se-3],type:"default",description:"",doc:Ft[Se-1]};break;case 19:var me=Ft[Se],Ve=Ft[Se-2].trim();if(Ft[Se].match(":")){var Ye=Ft[Se].split(":");me=Ye[0],Ve=[Ve,Ye[1]]}this.$={stmt:"state",id:me,type:"default",description:Ve};break;case 20:this.$={stmt:"state",id:Ft[Se-3],type:"default",description:Ft[Se-5],doc:Ft[Se-1]};break;case 21:this.$={stmt:"state",id:Ft[Se],type:"fork"};break;case 22:this.$={stmt:"state",id:Ft[Se],type:"join"};break;case 23:this.$={stmt:"state",id:Ft[Se],type:"choice"};break;case 24:this.$={stmt:"state",id:Ht.getDividerId(),type:"divider"};break;case 25:this.$={stmt:"state",id:Ft[Se-1].trim(),note:{position:Ft[Se-2].trim(),text:Ft[Se].trim()}};break;case 28:this.$=Ft[Se].trim(),Ht.setAccTitle(this.$);break;case 29:case 30:this.$=Ft[Se].trim(),Ht.setAccDescription(this.$);break;case 31:case 32:this.$={stmt:"classDef",id:Ft[Se-1].trim(),classes:Ft[Se].trim()};break;case 33:this.$={stmt:"applyClass",id:Ft[Se-1].trim(),styleClass:Ft[Se].trim()};break;case 34:Ht.setDirection("TB"),this.$={stmt:"dir",value:"TB"};break;case 35:Ht.setDirection("BT"),this.$={stmt:"dir",value:"BT"};break;case 36:Ht.setDirection("RL"),this.$={stmt:"dir",value:"RL"};break;case 37:Ht.setDirection("LR"),this.$={stmt:"dir",value:"LR"};break;case 40:case 41:this.$={stmt:"state",id:Ft[Se].trim(),type:"default",description:""};break;case 42:this.$={stmt:"state",id:Ft[Se-2].trim(),classes:[Ft[Se].trim()],type:"default",description:""};break;case 43:this.$={stmt:"state",id:Ft[Se-2].trim(),classes:[Ft[Se].trim()],type:"default",description:""};break}},table:[{3:1,4:a,5:f,6:p},{1:[3]},{3:5,4:a,5:f,6:p},{3:6,4:a,5:f,6:p},i([1,4,5,15,16,18,21,23,24,25,26,27,28,32,34,36,37,41,44,45,46,47,50],w,{7:7}),{1:[2,1]},{1:[2,2]},{1:[2,3],4:m,5:b,8:8,9:10,10:12,11:13,12:14,15:E,16:_,18:A,21:I,23:B,24:N,25:R,26:z,27:W,28:et,31:24,32:st,34:at,36:bt,37:mt,41:yt,44:ft,45:ut,46:vt,47:X,50:pt},i(U,[2,5]),{9:36,10:12,11:13,12:14,15:E,16:_,18:A,21:I,23:B,24:N,25:R,26:z,27:W,28:et,31:24,32:st,34:at,36:bt,37:mt,41:yt,44:ft,45:ut,46:vt,47:X,50:pt},i(U,[2,7]),i(U,[2,8]),i(U,[2,9]),i(U,[2,10]),i(U,[2,11],{13:[1,37],14:[1,38]}),i(U,[2,15]),{17:[1,39]},i(U,[2,17],{19:[1,40]}),{22:[1,41]},i(U,[2,21]),i(U,[2,22]),i(U,[2,23]),i(U,[2,24]),{29:42,30:[1,43],52:[1,44],53:[1,45]},i(U,[2,27]),{33:[1,46]},{35:[1,47]},i(U,[2,30]),{38:[1,48],40:[1,49]},{42:[1,50]},i(Tt,[2,40],{51:[1,51]}),i(Tt,[2,41],{51:[1,52]}),i(U,[2,34]),i(U,[2,35]),i(U,[2,36]),i(U,[2,37]),i(U,[2,6]),i(U,[2,12]),{12:53,23:B,50:pt},i(U,[2,16]),i(nt,w,{7:54}),{23:[1,55]},{23:[1,56]},{22:[1,57]},{23:[2,44]},{23:[2,45]},i(U,[2,28]),i(U,[2,29]),{39:[1,58]},{39:[1,59]},{43:[1,60]},{23:[1,61]},{23:[1,62]},i(U,[2,13],{13:[1,63]}),{4:m,5:b,8:8,9:10,10:12,11:13,12:14,15:E,16:_,18:A,20:[1,64],21:I,23:B,24:N,25:R,26:z,27:W,28:et,31:24,32:st,34:at,36:bt,37:mt,41:yt,44:ft,45:ut,46:vt,47:X,50:pt},i(U,[2,19],{19:[1,65]}),{30:[1,66]},{23:[1,67]},i(U,[2,31]),i(U,[2,32]),i(U,[2,33]),i(Tt,[2,42]),i(Tt,[2,43]),i(U,[2,14]),i(U,[2,18]),i(nt,w,{7:68}),i(U,[2,25]),i(U,[2,26]),{4:m,5:b,8:8,9:10,10:12,11:13,12:14,15:E,16:_,18:A,20:[1,69],21:I,23:B,24:N,25:R,26:z,27:W,28:et,31:24,32:st,34:at,36:bt,37:mt,41:yt,44:ft,45:ut,46:vt,47:X,50:pt},i(U,[2,20])],defaultActions:{5:[2,1],6:[2,2],44:[2,44],45:[2,45]},parseError:function(Z,Ct){if(Ct.recoverable)this.trace(Z);else{var xt=new Error(Z);throw xt.hash=Ct,xt}},parse:function(Z){var Ct=this,xt=[0],Ht=[],Le=[null],Ft=[],gn=this.table,Se="",me=0,Ve=0,Ye=2,ce=1,ke=Ft.slice.call(arguments,1),zt=Object.create(this.lexer),re={yy:{}};for(var se in this.yy)Object.prototype.hasOwnProperty.call(this.yy,se)&&(re.yy[se]=this.yy[se]);zt.setInput(Z,re.yy),re.yy.lexer=zt,re.yy.parser=this,typeof zt.yylloc>"u"&&(zt.yylloc={});var Pe=zt.yylloc;Ft.push(Pe);var te=zt.options&&zt.options.ranges;typeof re.yy.parseError=="function"?this.parseError=re.yy.parseError:this.parseError=Object.getPrototypeOf(this).parseError;function Me(){var Ee;return Ee=Ht.pop()||zt.lex()||ce,typeof Ee!="number"&&(Ee instanceof Array&&(Ht=Ee,Ee=Ht.pop()),Ee=Ct.symbols_[Ee]||Ee),Ee}for(var de,on,ni,Ks,ws={},fo,Xi,Er,Xn;;){if(on=xt[xt.length-1],this.defaultActions[on]?ni=this.defaultActions[on]:((de===null||typeof de>"u")&&(de=Me()),ni=gn[on]&&gn[on][de]),typeof ni>"u"||!ni.length||!ni[0]){var di="";Xn=[];for(fo in gn[on])this.terminals_[fo]&&fo>Ye&&Xn.push("'"+this.terminals_[fo]+"'");zt.showPosition?di="Parse error on line "+(me+1)+`: +`+zt.showPosition()+` +Expecting `+Xn.join(", ")+", got '"+(this.terminals_[de]||de)+"'":di="Parse error on line "+(me+1)+": Unexpected "+(de==ce?"end of input":"'"+(this.terminals_[de]||de)+"'"),this.parseError(di,{text:zt.match,token:this.terminals_[de]||de,line:zt.yylineno,loc:Pe,expected:Xn})}if(ni[0]instanceof Array&&ni.length>1)throw new Error("Parse Error: multiple actions possible at state: "+on+", token: "+de);switch(ni[0]){case 1:xt.push(de),Le.push(zt.yytext),Ft.push(zt.yylloc),xt.push(ni[1]),de=null,Ve=zt.yyleng,Se=zt.yytext,me=zt.yylineno,Pe=zt.yylloc;break;case 2:if(Xi=this.productions_[ni[1]][1],ws.$=Le[Le.length-Xi],ws._$={first_line:Ft[Ft.length-(Xi||1)].first_line,last_line:Ft[Ft.length-1].last_line,first_column:Ft[Ft.length-(Xi||1)].first_column,last_column:Ft[Ft.length-1].last_column},te&&(ws._$.range=[Ft[Ft.length-(Xi||1)].range[0],Ft[Ft.length-1].range[1]]),Ks=this.performAction.apply(ws,[Se,Ve,me,re.yy,ni[1],Le,Ft].concat(ke)),typeof Ks<"u")return Ks;Xi&&(xt=xt.slice(0,-1*Xi*2),Le=Le.slice(0,-1*Xi),Ft=Ft.slice(0,-1*Xi)),xt.push(this.productions_[ni[1]][0]),Le.push(ws.$),Ft.push(ws._$),Er=gn[xt[xt.length-2]][xt[xt.length-1]],xt.push(Er);break;case 3:return!0}}return!0}},Ot=function(){var Et={EOF:1,parseError:function(Ct,xt){if(this.yy.parser)this.yy.parser.parseError(Ct,xt);else throw new Error(Ct)},setInput:function(Z,Ct){return this.yy=Ct||this.yy||{},this._input=Z,this._more=this._backtrack=this.done=!1,this.yylineno=this.yyleng=0,this.yytext=this.matched=this.match="",this.conditionStack=["INITIAL"],this.yylloc={first_line:1,first_column:0,last_line:1,last_column:0},this.options.ranges&&(this.yylloc.range=[0,0]),this.offset=0,this},input:function(){var Z=this._input[0];this.yytext+=Z,this.yyleng++,this.offset++,this.match+=Z,this.matched+=Z;var Ct=Z.match(/(?:\r\n?|\n).*/g);return Ct?(this.yylineno++,this.yylloc.last_line++):this.yylloc.last_column++,this.options.ranges&&this.yylloc.range[1]++,this._input=this._input.slice(1),Z},unput:function(Z){var Ct=Z.length,xt=Z.split(/(?:\r\n?|\n)/g);this._input=Z+this._input,this.yytext=this.yytext.substr(0,this.yytext.length-Ct),this.offset-=Ct;var Ht=this.match.split(/(?:\r\n?|\n)/g);this.match=this.match.substr(0,this.match.length-1),this.matched=this.matched.substr(0,this.matched.length-1),xt.length-1&&(this.yylineno-=xt.length-1);var Le=this.yylloc.range;return this.yylloc={first_line:this.yylloc.first_line,last_line:this.yylineno+1,first_column:this.yylloc.first_column,last_column:xt?(xt.length===Ht.length?this.yylloc.first_column:0)+Ht[Ht.length-xt.length].length-xt[0].length:this.yylloc.first_column-Ct},this.options.ranges&&(this.yylloc.range=[Le[0],Le[0]+this.yyleng-Ct]),this.yyleng=this.yytext.length,this},more:function(){return this._more=!0,this},reject:function(){if(this.options.backtrack_lexer)this._backtrack=!0;else return this.parseError("Lexical error on line "+(this.yylineno+1)+`. You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true). +`+this.showPosition(),{text:"",token:null,line:this.yylineno});return this},less:function(Z){this.unput(this.match.slice(Z))},pastInput:function(){var Z=this.matched.substr(0,this.matched.length-this.match.length);return(Z.length>20?"...":"")+Z.substr(-20).replace(/\n/g,"")},upcomingInput:function(){var Z=this.match;return Z.length<20&&(Z+=this._input.substr(0,20-Z.length)),(Z.substr(0,20)+(Z.length>20?"...":"")).replace(/\n/g,"")},showPosition:function(){var Z=this.pastInput(),Ct=new Array(Z.length+1).join("-");return Z+this.upcomingInput()+` +`+Ct+"^"},test_match:function(Z,Ct){var xt,Ht,Le;if(this.options.backtrack_lexer&&(Le={yylineno:this.yylineno,yylloc:{first_line:this.yylloc.first_line,last_line:this.last_line,first_column:this.yylloc.first_column,last_column:this.yylloc.last_column},yytext:this.yytext,match:this.match,matches:this.matches,matched:this.matched,yyleng:this.yyleng,offset:this.offset,_more:this._more,_input:this._input,yy:this.yy,conditionStack:this.conditionStack.slice(0),done:this.done},this.options.ranges&&(Le.yylloc.range=this.yylloc.range.slice(0))),Ht=Z[0].match(/(?:\r\n?|\n).*/g),Ht&&(this.yylineno+=Ht.length),this.yylloc={first_line:this.yylloc.last_line,last_line:this.yylineno+1,first_column:this.yylloc.last_column,last_column:Ht?Ht[Ht.length-1].length-Ht[Ht.length-1].match(/\r?\n?/)[0].length:this.yylloc.last_column+Z[0].length},this.yytext+=Z[0],this.match+=Z[0],this.matches=Z,this.yyleng=this.yytext.length,this.options.ranges&&(this.yylloc.range=[this.offset,this.offset+=this.yyleng]),this._more=!1,this._backtrack=!1,this._input=this._input.slice(Z[0].length),this.matched+=Z[0],xt=this.performAction.call(this,this.yy,this,Ct,this.conditionStack[this.conditionStack.length-1]),this.done&&this._input&&(this.done=!1),xt)return xt;if(this._backtrack){for(var Ft in Le)this[Ft]=Le[Ft];return!1}return!1},next:function(){if(this.done)return this.EOF;this._input||(this.done=!0);var Z,Ct,xt,Ht;this._more||(this.yytext="",this.match="");for(var Le=this._currentRules(),Ft=0;FtCt[0].length)){if(Ct=xt,Ht=Ft,this.options.backtrack_lexer){if(Z=this.test_match(xt,Le[Ft]),Z!==!1)return Z;if(this._backtrack){Ct=!1;continue}else return!1}else if(!this.options.flex)break}return Ct?(Z=this.test_match(Ct,Le[Ht]),Z!==!1?Z:!1):this._input===""?this.EOF:this.parseError("Lexical error on line "+(this.yylineno+1)+`. Unrecognized text. +`+this.showPosition(),{text:"",token:null,line:this.yylineno})},lex:function(){var Ct=this.next();return Ct||this.lex()},begin:function(Ct){this.conditionStack.push(Ct)},popState:function(){var Ct=this.conditionStack.length-1;return Ct>0?this.conditionStack.pop():this.conditionStack[0]},_currentRules:function(){return this.conditionStack.length&&this.conditionStack[this.conditionStack.length-1]?this.conditions[this.conditionStack[this.conditionStack.length-1]].rules:this.conditions.INITIAL.rules},topState:function(Ct){return Ct=this.conditionStack.length-1-Math.abs(Ct||0),Ct>=0?this.conditionStack[Ct]:"INITIAL"},pushState:function(Ct){this.begin(Ct)},stateStackSize:function(){return this.conditionStack.length},options:{"case-insensitive":!0},performAction:function(Ct,xt,Ht,Le){switch(Ht){case 0:return 40;case 1:return 44;case 2:return 45;case 3:return 46;case 4:return 47;case 5:break;case 6:break;case 7:return 5;case 8:break;case 9:break;case 10:break;case 11:break;case 12:return this.pushState("SCALE"),16;case 13:return 17;case 14:this.popState();break;case 15:return this.begin("acc_title"),32;case 16:return this.popState(),"acc_title_value";case 17:return this.begin("acc_descr"),34;case 18:return this.popState(),"acc_descr_value";case 19:this.begin("acc_descr_multiline");break;case 20:this.popState();break;case 21:return"acc_descr_multiline_value";case 22:return this.pushState("CLASSDEF"),37;case 23:return this.popState(),this.pushState("CLASSDEFID"),"DEFAULT_CLASSDEF_ID";case 24:return this.popState(),this.pushState("CLASSDEFID"),38;case 25:return this.popState(),39;case 26:return this.pushState("CLASS"),41;case 27:return this.popState(),this.pushState("CLASS_STYLE"),42;case 28:return this.popState(),43;case 29:return this.pushState("SCALE"),16;case 30:return 17;case 31:this.popState();break;case 32:this.pushState("STATE");break;case 33:return this.popState(),xt.yytext=xt.yytext.slice(0,-8).trim(),24;case 34:return this.popState(),xt.yytext=xt.yytext.slice(0,-8).trim(),25;case 35:return this.popState(),xt.yytext=xt.yytext.slice(0,-10).trim(),26;case 36:return this.popState(),xt.yytext=xt.yytext.slice(0,-8).trim(),24;case 37:return this.popState(),xt.yytext=xt.yytext.slice(0,-8).trim(),25;case 38:return this.popState(),xt.yytext=xt.yytext.slice(0,-10).trim(),26;case 39:return 44;case 40:return 45;case 41:return 46;case 42:return 47;case 43:this.pushState("STATE_STRING");break;case 44:return this.pushState("STATE_ID"),"AS";case 45:return this.popState(),"ID";case 46:this.popState();break;case 47:return"STATE_DESCR";case 48:return 18;case 49:this.popState();break;case 50:return this.popState(),this.pushState("struct"),19;case 51:break;case 52:return this.popState(),20;case 53:break;case 54:return this.begin("NOTE"),28;case 55:return this.popState(),this.pushState("NOTE_ID"),52;case 56:return this.popState(),this.pushState("NOTE_ID"),53;case 57:this.popState(),this.pushState("FLOATING_NOTE");break;case 58:return this.popState(),this.pushState("FLOATING_NOTE_ID"),"AS";case 59:break;case 60:return"NOTE_TEXT";case 61:return this.popState(),"ID";case 62:return this.popState(),this.pushState("NOTE_TEXT"),23;case 63:return this.popState(),xt.yytext=xt.yytext.substr(2).trim(),30;case 64:return this.popState(),xt.yytext=xt.yytext.slice(0,-8).trim(),30;case 65:return 6;case 66:return 6;case 67:return 15;case 68:return 50;case 69:return 23;case 70:return xt.yytext=xt.yytext.trim(),13;case 71:return 14;case 72:return 27;case 73:return 51;case 74:return 5;case 75:return"INVALID"}},rules:[/^(?:default\b)/i,/^(?:.*direction\s+TB[^\n]*)/i,/^(?:.*direction\s+BT[^\n]*)/i,/^(?:.*direction\s+RL[^\n]*)/i,/^(?:.*direction\s+LR[^\n]*)/i,/^(?:%%(?!\{)[^\n]*)/i,/^(?:[^\}]%%[^\n]*)/i,/^(?:[\n]+)/i,/^(?:[\s]+)/i,/^(?:((?!\n)\s)+)/i,/^(?:#[^\n]*)/i,/^(?:%[^\n]*)/i,/^(?:scale\s+)/i,/^(?:\d+)/i,/^(?:\s+width\b)/i,/^(?:accTitle\s*:\s*)/i,/^(?:(?!\n||)*[^\n]*)/i,/^(?:accDescr\s*:\s*)/i,/^(?:(?!\n||)*[^\n]*)/i,/^(?:accDescr\s*\{\s*)/i,/^(?:[\}])/i,/^(?:[^\}]*)/i,/^(?:classDef\s+)/i,/^(?:DEFAULT\s+)/i,/^(?:\w+\s+)/i,/^(?:[^\n]*)/i,/^(?:class\s+)/i,/^(?:(\w+)+((,\s*\w+)*))/i,/^(?:[^\n]*)/i,/^(?:scale\s+)/i,/^(?:\d+)/i,/^(?:\s+width\b)/i,/^(?:state\s+)/i,/^(?:.*<>)/i,/^(?:.*<>)/i,/^(?:.*<>)/i,/^(?:.*\[\[fork\]\])/i,/^(?:.*\[\[join\]\])/i,/^(?:.*\[\[choice\]\])/i,/^(?:.*direction\s+TB[^\n]*)/i,/^(?:.*direction\s+BT[^\n]*)/i,/^(?:.*direction\s+RL[^\n]*)/i,/^(?:.*direction\s+LR[^\n]*)/i,/^(?:["])/i,/^(?:\s*as\s+)/i,/^(?:[^\n\{]*)/i,/^(?:["])/i,/^(?:[^"]*)/i,/^(?:[^\n\s\{]+)/i,/^(?:\n)/i,/^(?:\{)/i,/^(?:%%(?!\{)[^\n]*)/i,/^(?:\})/i,/^(?:[\n])/i,/^(?:note\s+)/i,/^(?:left of\b)/i,/^(?:right of\b)/i,/^(?:")/i,/^(?:\s*as\s*)/i,/^(?:["])/i,/^(?:[^"]*)/i,/^(?:[^\n]*)/i,/^(?:\s*[^:\n\s\-]+)/i,/^(?:\s*:[^:\n;]+)/i,/^(?:[\s\S]*?end note\b)/i,/^(?:stateDiagram\s+)/i,/^(?:stateDiagram-v2\s+)/i,/^(?:hide empty description\b)/i,/^(?:\[\*\])/i,/^(?:[^:\n\s\-\{]+)/i,/^(?:\s*:[^:\n;]+)/i,/^(?:-->)/i,/^(?:--)/i,/^(?::::)/i,/^(?:$)/i,/^(?:.)/i],conditions:{LINE:{rules:[9,10],inclusive:!1},struct:{rules:[9,10,22,26,32,39,40,41,42,51,52,53,54,68,69,70,71,72],inclusive:!1},FLOATING_NOTE_ID:{rules:[61],inclusive:!1},FLOATING_NOTE:{rules:[58,59,60],inclusive:!1},NOTE_TEXT:{rules:[63,64],inclusive:!1},NOTE_ID:{rules:[62],inclusive:!1},NOTE:{rules:[55,56,57],inclusive:!1},CLASS_STYLE:{rules:[28],inclusive:!1},CLASS:{rules:[27],inclusive:!1},CLASSDEFID:{rules:[25],inclusive:!1},CLASSDEF:{rules:[23,24],inclusive:!1},acc_descr_multiline:{rules:[20,21],inclusive:!1},acc_descr:{rules:[18],inclusive:!1},acc_title:{rules:[16],inclusive:!1},SCALE:{rules:[13,14,30,31],inclusive:!1},ALIAS:{rules:[],inclusive:!1},STATE_ID:{rules:[45],inclusive:!1},STATE_STRING:{rules:[46,47],inclusive:!1},FORK_STATE:{rules:[],inclusive:!1},STATE:{rules:[9,10,33,34,35,36,37,38,43,44,48,49,50],inclusive:!1},ID:{rules:[9,10],inclusive:!1},INITIAL:{rules:[0,1,2,3,4,5,6,7,8,10,11,12,15,17,19,22,26,29,32,50,54,65,66,67,68,69,70,71,73,74,75],inclusive:!0}}};return Et}();It.lexer=Ot;function Bt(){this.yy={}}return Bt.prototype=It,It.Parser=Bt,new Bt}();Dgt.parser=Dgt;const ejt=Dgt,FGe="LR",NGe="TB",UY="state",Igt="relation",BGe="classDef",RGe="applyClass",KF="default",njt="divider",Ogt="[*]",rjt="start",ijt=Ogt,sjt="end",ajt="color",ojt="fill",jGe="bgFill",$Ge=",";function cjt(){return{}}let ujt=FGe,WY=[],XF=cjt();const ljt=()=>({relations:[],states:{},documents:{}});let YY={root:ljt()},S0=YY.root,QF=0,hjt=0;const zGe={LINE:0,DOTTED_LINE:1},qGe={AGGREGATION:0,EXTENSION:1,COMPOSITION:2,DEPENDENCY:3},KY=i=>JSON.parse(JSON.stringify(i)),HGe=i=>{Ut.info("Setting root doc",i),WY=i},VGe=()=>WY,XY=(i,a,f)=>{if(a.stmt===Igt)XY(i,a.state1,!0),XY(i,a.state2,!1);else if(a.stmt===UY&&(a.id==="[*]"?(a.id=f?i.id+"_start":i.id+"_end",a.start=f):a.id=a.id.trim()),a.doc){const p=[];let w=[],m;for(m=0;m0&&w.length>0){const b={stmt:UY,id:VIt(),type:"divider",doc:KY(w)};p.push(KY(b)),a.doc=p}a.doc.forEach(b=>XY(a,b,!0))}},GGe=()=>(XY({id:"root"},{id:"root",doc:WY},!0),{id:"root",doc:WY}),UGe=i=>{let a;i.doc?a=i.doc:a=i,Ut.info(a),fjt(!0),Ut.info("Extract",a),a.forEach(f=>{switch(f.stmt){case UY:LT(f.id.trim(),f.type,f.doc,f.description,f.note,f.classes,f.styles,f.textStyles);break;case Igt:djt(f.state1,f.state2,f.description);break;case BGe:gjt(f.id.trim(),f.classes);break;case RGe:Bgt(f.id.trim(),f.styleClass);break}})},LT=function(i,a=KF,f=null,p=null,w=null,m=null,b=null,E=null){const _=i==null?void 0:i.trim();S0.states[_]===void 0?(Ut.info("Adding state ",_,p),S0.states[_]={id:_,descriptions:[],type:a,doc:f,note:w,classes:[],styles:[],textStyles:[]}):(S0.states[_].doc||(S0.states[_].doc=f),S0.states[_].type||(S0.states[_].type=a)),p&&(Ut.info("Setting state description",_,p),typeof p=="string"&&Ngt(_,p.trim()),typeof p=="object"&&p.forEach(A=>Ngt(_,A.trim()))),w&&(S0.states[_].note=w,S0.states[_].note.text=Kr.sanitizeText(S0.states[_].note.text,Oe())),m&&(Ut.info("Setting state classes",_,m),(typeof m=="string"?[m]:m).forEach(I=>Bgt(_,I.trim()))),b&&(Ut.info("Setting state styles",_,b),(typeof b=="string"?[b]:b).forEach(I=>nUe(_,I.trim()))),E&&(Ut.info("Setting state styles",_,b),(typeof E=="string"?[E]:E).forEach(I=>rUe(_,I.trim())))},fjt=function(i){YY={root:ljt()},S0=YY.root,QF=0,XF=cjt(),i||hg()},ZF=function(i){return S0.states[i]},WGe=function(){return S0.states},YGe=function(){Ut.info("Documents = ",YY)},KGe=function(){return S0.relations};function Pgt(i=""){let a=i;return i===Ogt&&(QF++,a=`${rjt}${QF}`),a}function Fgt(i="",a=KF){return i===Ogt?rjt:a}function XGe(i=""){let a=i;return i===ijt&&(QF++,a=`${sjt}${QF}`),a}function QGe(i="",a=KF){return i===ijt?sjt:a}function ZGe(i,a,f){let p=Pgt(i.id.trim()),w=Fgt(i.id.trim(),i.type),m=Pgt(a.id.trim()),b=Fgt(a.id.trim(),a.type);LT(p,w,i.doc,i.description,i.note,i.classes,i.styles,i.textStyles),LT(m,b,a.doc,a.description,a.note,a.classes,a.styles,a.textStyles),S0.relations.push({id1:p,id2:m,relationTitle:Kr.sanitizeText(f,Oe())})}const djt=function(i,a,f){if(typeof i=="object")ZGe(i,a,f);else{const p=Pgt(i.trim()),w=Fgt(i),m=XGe(a.trim()),b=QGe(a);LT(p,w),LT(m,b),S0.relations.push({id1:p,id2:m,title:Kr.sanitizeText(f,Oe())})}},Ngt=function(i,a){const f=S0.states[i],p=a.startsWith(":")?a.replace(":","").trim():a;f.descriptions.push(Kr.sanitizeText(p,Oe()))},JGe=function(i){return i.substring(0,1)===":"?i.substr(2).trim():i.trim()},tUe=()=>(hjt++,"divider-id-"+hjt),gjt=function(i,a=""){XF[i]===void 0&&(XF[i]={id:i,styles:[],textStyles:[]});const f=XF[i];a!=null&&a.split($Ge).forEach(p=>{const w=p.replace(/([^;]*);/,"$1").trim();if(p.match(ajt)){const b=w.replace(ojt,jGe).replace(ajt,ojt);f.textStyles.push(b)}f.styles.push(w)})},eUe=function(){return XF},Bgt=function(i,a){i.split(",").forEach(function(f){let p=ZF(f);if(p===void 0){const w=f.trim();LT(w),p=ZF(w)}p.classes.push(a)})},nUe=function(i,a){const f=ZF(i);f!==void 0&&f.textStyles.push(a)},rUe=function(i,a){const f=ZF(i);f!==void 0&&f.textStyles.push(a)},$5={getConfig:()=>Oe().state,addState:LT,clear:fjt,getState:ZF,getStates:WGe,getRelations:KGe,getClasses:eUe,getDirection:()=>ujt,addRelation:djt,getDividerId:tUe,setDirection:i=>{ujt=i},cleanupLabel:JGe,lineType:zGe,relationType:qGe,logDocuments:YGe,getRootDoc:VGe,setRootDoc:HGe,getRootDocV2:GGe,extract:UGe,trimColon:i=>i&&i[0]===":"?i.substr(1).trim():i.trim(),getAccTitle:fg,setAccTitle:E0,getAccDescription:gg,setAccDescription:dg,addStyleClass:gjt,setCssClass:Bgt,addDescription:Ngt,setDiagramTitle:Nb,getDiagramTitle:pg},pjt=i=>` +defs #statediagram-barbEnd { + fill: ${i.transitionColor}; + stroke: ${i.transitionColor}; + } +g.stateGroup text { + fill: ${i.nodeBorder}; + stroke: none; + font-size: 10px; +} +g.stateGroup text { + fill: ${i.textColor}; + stroke: none; + font-size: 10px; + +} +g.stateGroup .state-title { + font-weight: bolder; + fill: ${i.stateLabelColor}; +} + +g.stateGroup rect { + fill: ${i.mainBkg}; + stroke: ${i.nodeBorder}; +} + +g.stateGroup line { + stroke: ${i.lineColor}; + stroke-width: 1; +} + +.transition { + stroke: ${i.transitionColor}; + stroke-width: 1; + fill: none; +} + +.stateGroup .composit { + fill: ${i.background}; + border-bottom: 1px +} + +.stateGroup .alt-composit { + fill: #e0e0e0; + border-bottom: 1px +} + +.state-note { + stroke: ${i.noteBorderColor}; + fill: ${i.noteBkgColor}; + + text { + fill: ${i.noteTextColor}; + stroke: none; + font-size: 10px; + } +} + +.stateLabel .box { + stroke: none; + stroke-width: 0; + fill: ${i.mainBkg}; + opacity: 0.5; +} + +.edgeLabel .label rect { + fill: ${i.labelBackgroundColor}; + opacity: 0.5; +} +.edgeLabel .label text { + fill: ${i.transitionLabelColor||i.tertiaryTextColor}; +} +.label div .edgeLabel { + color: ${i.transitionLabelColor||i.tertiaryTextColor}; +} + +.stateLabel text { + fill: ${i.stateLabelColor}; + font-size: 10px; + font-weight: bold; +} + +.node circle.state-start { + fill: ${i.specialStateColor}; + stroke: ${i.specialStateColor}; +} + +.node .fork-join { + fill: ${i.specialStateColor}; + stroke: ${i.specialStateColor}; +} + +.node circle.state-end { + fill: ${i.innerEndBackground}; + stroke: ${i.background}; + stroke-width: 1.5 +} +.end-state-inner { + fill: ${i.compositeBackground||i.background}; + // stroke: ${i.background}; + stroke-width: 1.5 +} + +.node rect { + fill: ${i.stateBkg||i.mainBkg}; + stroke: ${i.stateBorder||i.nodeBorder}; + stroke-width: 1px; +} +.node polygon { + fill: ${i.mainBkg}; + stroke: ${i.stateBorder||i.nodeBorder};; + stroke-width: 1px; +} +#statediagram-barbEnd { + fill: ${i.lineColor}; +} + +.statediagram-cluster rect { + fill: ${i.compositeTitleBackground}; + stroke: ${i.stateBorder||i.nodeBorder}; + stroke-width: 1px; +} + +.cluster-label, .nodeLabel { + color: ${i.stateLabelColor}; +} + +.statediagram-cluster rect.outer { + rx: 5px; + ry: 5px; +} +.statediagram-state .divider { + stroke: ${i.stateBorder||i.nodeBorder}; +} + +.statediagram-state .title-state { + rx: 5px; + ry: 5px; +} +.statediagram-cluster.statediagram-cluster .inner { + fill: ${i.compositeBackground||i.background}; +} +.statediagram-cluster.statediagram-cluster-alt .inner { + fill: ${i.altBackground?i.altBackground:"#efefef"}; +} + +.statediagram-cluster .inner { + rx:0; + ry:0; +} + +.statediagram-state rect.basic { + rx: 5px; + ry: 5px; +} +.statediagram-state rect.divider { + stroke-dasharray: 10,10; + fill: ${i.altBackground?i.altBackground:"#efefef"}; +} + +.note-edge { + stroke-dasharray: 5; +} + +.statediagram-note rect { + fill: ${i.noteBkgColor}; + stroke: ${i.noteBorderColor}; + stroke-width: 1px; + rx: 0; + ry: 0; +} +.statediagram-note rect { + fill: ${i.noteBkgColor}; + stroke: ${i.noteBorderColor}; + stroke-width: 1px; + rx: 0; + ry: 0; +} + +.statediagram-note text { + fill: ${i.noteTextColor}; +} + +.statediagram-note .nodeLabel { + color: ${i.noteTextColor}; +} +.statediagram .edgeLabel { + color: red; // ${i.noteTextColor}; +} + +#dependencyStart, #dependencyEnd { + fill: ${i.lineColor}; + stroke: ${i.lineColor}; + stroke-width: 1; +} + +.statediagramTitleText { + text-anchor: middle; + font-size: 18px; + fill: ${i.textColor}; +} +`,Rgt={},iUe=(i,a)=>{Rgt[i]=a},sUe=i=>Rgt[i],bjt=()=>Object.keys(Rgt),aUe={get:sUe,set:iUe,keys:bjt,size:()=>bjt().length},oUe=i=>i.append("circle").attr("class","start-state").attr("r",Oe().state.sizeUnit).attr("cx",Oe().state.padding+Oe().state.sizeUnit).attr("cy",Oe().state.padding+Oe().state.sizeUnit),cUe=i=>i.append("line").style("stroke","grey").style("stroke-dasharray","3").attr("x1",Oe().state.textHeight).attr("class","divider").attr("x2",Oe().state.textHeight*2).attr("y1",0).attr("y2",0),uUe=(i,a)=>{const f=i.append("text").attr("x",2*Oe().state.padding).attr("y",Oe().state.textHeight+2*Oe().state.padding).attr("font-size",Oe().state.fontSize).attr("class","state-title").text(a.id),p=f.node().getBBox();return i.insert("rect",":first-child").attr("x",Oe().state.padding).attr("y",Oe().state.padding).attr("width",p.width+2*Oe().state.padding).attr("height",p.height+2*Oe().state.padding).attr("rx",Oe().state.radius),f},lUe=(i,a)=>{const f=function(N,R,z){const W=N.append("tspan").attr("x",2*Oe().state.padding).text(R);z||W.attr("dy",Oe().state.textHeight)},w=i.append("text").attr("x",2*Oe().state.padding).attr("y",Oe().state.textHeight+1.3*Oe().state.padding).attr("font-size",Oe().state.fontSize).attr("class","state-title").text(a.descriptions[0]).node().getBBox(),m=w.height,b=i.append("text").attr("x",Oe().state.padding).attr("y",m+Oe().state.padding*.4+Oe().state.dividerMargin+Oe().state.textHeight).attr("class","state-description");let E=!0,_=!0;a.descriptions.forEach(function(N){E||(f(b,N,_),_=!1),E=!1});const A=i.append("line").attr("x1",Oe().state.padding).attr("y1",Oe().state.padding+m+Oe().state.dividerMargin/2).attr("y2",Oe().state.padding+m+Oe().state.dividerMargin/2).attr("class","descr-divider"),I=b.node().getBBox(),B=Math.max(I.width,w.width);return A.attr("x2",B+3*Oe().state.padding),i.insert("rect",":first-child").attr("x",Oe().state.padding).attr("y",Oe().state.padding).attr("width",B+2*Oe().state.padding).attr("height",I.height+m+2*Oe().state.padding).attr("rx",Oe().state.radius),i},hUe=(i,a,f)=>{const p=Oe().state.padding,w=2*Oe().state.padding,m=i.node().getBBox(),b=m.width,E=m.x,_=i.append("text").attr("x",0).attr("y",Oe().state.titleShift).attr("font-size",Oe().state.fontSize).attr("class","state-title").text(a.id),I=_.node().getBBox().width+w;let B=Math.max(I,b);B===b&&(B=B+w);let N;const R=i.node().getBBox();a.doc,N=E-p,I>b&&(N=(b-B)/2+p),Math.abs(E-R.x)b&&(N=E-(I-b)/2);const z=1-Oe().state.textHeight;return i.insert("rect",":first-child").attr("x",N).attr("y",z).attr("class",f?"alt-composit":"composit").attr("width",B).attr("height",R.height+Oe().state.textHeight+Oe().state.titleShift+1).attr("rx","0"),_.attr("x",N+p),I<=b&&_.attr("x",E+(B-w)/2-I/2+p),i.insert("rect",":first-child").attr("x",N).attr("y",Oe().state.titleShift-Oe().state.textHeight-Oe().state.padding).attr("width",B).attr("height",Oe().state.textHeight*3).attr("rx",Oe().state.radius),i.insert("rect",":first-child").attr("x",N).attr("y",Oe().state.titleShift-Oe().state.textHeight-Oe().state.padding).attr("width",B).attr("height",R.height+3+2*Oe().state.textHeight).attr("rx",Oe().state.radius),i},fUe=i=>(i.append("circle").attr("class","end-state-outer").attr("r",Oe().state.sizeUnit+Oe().state.miniPadding).attr("cx",Oe().state.padding+Oe().state.sizeUnit+Oe().state.miniPadding).attr("cy",Oe().state.padding+Oe().state.sizeUnit+Oe().state.miniPadding),i.append("circle").attr("class","end-state-inner").attr("r",Oe().state.sizeUnit).attr("cx",Oe().state.padding+Oe().state.sizeUnit+2).attr("cy",Oe().state.padding+Oe().state.sizeUnit+2)),dUe=(i,a)=>{let f=Oe().state.forkWidth,p=Oe().state.forkHeight;if(a.parentId){let w=f;f=p,p=w}return i.append("rect").style("stroke","black").style("fill","black").attr("width",f).attr("height",p).attr("x",Oe().state.padding).attr("y",Oe().state.padding)},gUe=(i,a,f,p)=>{let w=0;const m=p.append("text");m.style("text-anchor","start"),m.attr("class","noteText");let b=i.replace(/\r\n/g,"
            ");b=b.replace(/\n/g,"
            ");const E=b.split(Kr.lineBreakRegex);let _=1.25*Oe().state.noteMargin;for(const A of E){const I=A.trim();if(I.length>0){const B=m.append("tspan");if(B.text(I),_===0){const N=B.node().getBBox();_+=N.height}w+=_,B.attr("x",a+Oe().state.noteMargin),B.attr("y",f+w+1.25*Oe().state.noteMargin)}}return{textWidth:m.node().getBBox().width,textHeight:w}},pUe=(i,a)=>{a.attr("class","state-note");const f=a.append("rect").attr("x",0).attr("y",Oe().state.padding),p=a.append("g"),{textWidth:w,textHeight:m}=gUe(i,0,0,p);return f.attr("height",m+2*Oe().state.noteMargin),f.attr("width",w+Oe().state.noteMargin*2),f},wjt=function(i,a){const f=a.id,p={id:f,label:a.id,width:0,height:0},w=i.append("g").attr("id",f).attr("class","stateGroup");a.type==="start"&&oUe(w),a.type==="end"&&fUe(w),(a.type==="fork"||a.type==="join")&&dUe(w,a),a.type==="note"&&pUe(a.note.text,w),a.type==="divider"&&cUe(w),a.type==="default"&&a.descriptions.length===0&&uUe(w,a),a.type==="default"&&a.descriptions.length>0&&lUe(w,a);const m=w.node().getBBox();return p.width=m.width+2*Oe().state.padding,p.height=m.height+2*Oe().state.padding,aUe.set(f,p),p};let vjt=0;const bUe=function(i,a,f){const p=function(_){switch(_){case $5.relationType.AGGREGATION:return"aggregation";case $5.relationType.EXTENSION:return"extension";case $5.relationType.COMPOSITION:return"composition";case $5.relationType.DEPENDENCY:return"dependency"}};a.points=a.points.filter(_=>!Number.isNaN(_.y));const w=a.points,m=E5().x(function(_){return _.x}).y(function(_){return _.y}).curve(HP),b=i.append("path").attr("d",m(w)).attr("id","edge"+vjt).attr("class","transition");let E="";if(Oe().state.arrowMarkerAbsolute&&(E=window.location.protocol+"//"+window.location.host+window.location.pathname+window.location.search,E=E.replace(/\(/g,"\\("),E=E.replace(/\)/g,"\\)")),b.attr("marker-end","url("+E+"#"+p($5.relationType.DEPENDENCY)+"End)"),f.title!==void 0){const _=i.append("g").attr("class","stateLabel"),{x:A,y:I}=$a.calcLabelPosition(a.points),B=Kr.getRows(f.title);let N=0;const R=[];let z=0,W=0;for(let at=0;at<=B.length;at++){const bt=_.append("text").attr("text-anchor","middle").text(B[at]).attr("x",A).attr("y",I+N),mt=bt.node().getBBox();z=Math.max(z,mt.width),W=Math.min(W,mt.x),Ut.info(mt.x,A,I+N),N===0&&(N=bt.node().getBBox().height,Ut.info("Title height",N,I)),R.push(bt)}let et=N*B.length;if(B.length>1){const at=(B.length-1)*N*.5;R.forEach((bt,mt)=>bt.attr("y",I+mt*N-at)),et=N*B.length}const st=_.node().getBBox();_.insert("rect",":first-child").attr("class","box").attr("x",A-z/2-Oe().state.padding/2).attr("y",I-et/2-Oe().state.padding/2-3.5).attr("width",z+Oe().state.padding).attr("height",et+Oe().state.padding),Ut.info(st)}vjt++};let qb;const jgt={},wUe=function(){},vUe=function(i){i.append("defs").append("marker").attr("id","dependencyEnd").attr("refX",19).attr("refY",7).attr("markerWidth",20).attr("markerHeight",28).attr("orient","auto").append("path").attr("d","M 19,7 L9,13 L14,7 L9,1 Z")},mUe=function(i,a,f,p){qb=Oe().state;const w=Oe().securityLevel;let m;w==="sandbox"&&(m=yr("#i"+a));const b=yr(w==="sandbox"?m.nodes()[0].contentDocument.body:"body"),E=w==="sandbox"?m.nodes()[0].contentDocument:document;Ut.debug("Rendering diagram "+i);const _=b.select(`[id='${a}']`);vUe(_);const A=p.db.getRootDoc();mjt(A,_,void 0,!1,b,E,p);const I=qb.padding,B=_.node().getBBox(),N=B.width+I*2,R=B.height+I*2,z=N*1.75;k0(_,R,z,qb.useMaxWidth),_.attr("viewBox",`${B.x-qb.padding} ${B.y-qb.padding} `+N+" "+R)},yUe=i=>i?i.length*qb.fontSizeFactor:1,mjt=(i,a,f,p,w,m,b)=>{const E=new c1({compound:!0,multigraph:!0});let _,A=!0;for(_=0;_{const mt=bt.parentElement;let yt=0,ft=0;mt&&(mt.parentElement&&(yt=mt.parentElement.getBBox().width),ft=parseInt(mt.getAttribute("data-x-shift"),10),Number.isNaN(ft)&&(ft=0)),bt.setAttribute("x1",0-ft+8),bt.setAttribute("x2",yt-ft-8)})):Ut.debug("No Node "+st+": "+JSON.stringify(E.node(st)))});let W=z.getBBox();E.edges().forEach(function(st){st!==void 0&&E.edge(st)!==void 0&&(Ut.debug("Edge "+st.v+" -> "+st.w+": "+JSON.stringify(E.edge(st))),bUe(a,E.edge(st),E.edge(st).relation))}),W=z.getBBox();const et={id:f||"root",label:f||"root",width:0,height:0};return et.width=W.width+2*qb.padding,et.height=W.height+2*qb.padding,Ut.debug("Doc rendered",et,E),et},xUe=Object.freeze(Object.defineProperty({__proto__:null,diagram:{parser:ejt,db:$5,renderer:{setConf:wUe,draw:mUe},styles:pjt,init:i=>{i.state||(i.state={}),i.state.arrowMarkerAbsolute=i.arrowMarkerAbsolute,$5.clear()}}},Symbol.toStringTag,{value:"Module"})),QY="rect",$gt="rectWithTitle",kUe="start",EUe="end",TUe="divider",CUe="roundedWithTitle",_Ue="note",SUe="noteGroup",vL="statediagram",AUe=`${vL}-state`,yjt="transition",LUe="note",MUe=`${yjt} note-edge`,DUe=`${vL}-${LUe}`,IUe=`${vL}-cluster`,OUe=`${vL}-cluster-alt`,xjt="parent",kjt="note",PUe="state",zgt="----",FUe=`${zgt}${kjt}`,Ejt=`${zgt}${xjt}`,Tjt="fill:none",Cjt="fill: #333",_jt="c",Sjt="text",Ajt="normal";let ZY={},kk=0;const NUe=function(i){const a=Object.keys(i);for(const f of a)i[f]},BUe=function(i,a){return a.db.extract(a.db.getRootDocV2()),a.db.getClasses()};function RUe(i){return i==null?"":i.classes?i.classes.join(" "):""}function qgt(i="",a=0,f="",p=zgt){const w=f!==null&&f.length>0?`${p}${f}`:"";return`${PUe}-${i}${w}-${a}`}const JF=(i,a,f,p,w,m)=>{const b=f.id,E=RUe(p[b]);if(b!=="root"){let _=QY;f.start===!0&&(_=kUe),f.start===!1&&(_=EUe),f.type!==KF&&(_=f.type),ZY[b]||(ZY[b]={id:b,shape:_,description:Kr.sanitizeText(b,Oe()),classes:`${E} ${AUe}`});const A=ZY[b];f.description&&(Array.isArray(A.description)?(A.shape=$gt,A.description.push(f.description)):A.description.length>0?(A.shape=$gt,A.description===b?A.description=[f.description]:A.description=[A.description,f.description]):(A.shape=QY,A.description=f.description),A.description=Kr.sanitizeTextOrArray(A.description,Oe())),A.description.length===1&&A.shape===$gt&&(A.shape=QY),!A.type&&f.doc&&(Ut.info("Setting cluster for ",b,Hgt(f)),A.type="group",A.dir=Hgt(f),A.shape=f.type===njt?TUe:CUe,A.classes=A.classes+" "+IUe+" "+(m?OUe:""));const I={labelStyle:"",shape:A.shape,labelText:A.description,classes:A.classes,style:"",id:b,dir:A.dir,domId:qgt(b,kk),type:A.type,padding:15};if(I.centerLabel=!0,f.note){const B={labelStyle:"",shape:_Ue,labelText:f.note.text,classes:DUe,style:"",id:b+FUe+"-"+kk,domId:qgt(b,kk,kjt),type:A.type,padding:15},N={labelStyle:"",shape:SUe,labelText:f.note.text,classes:A.classes,style:"",id:b+Ejt,domId:qgt(b,kk,xjt),type:"group",padding:0};kk++;const R=b+Ejt;i.setNode(R,N),i.setNode(B.id,B),i.setNode(b,I),i.setParent(b,R),i.setParent(B.id,R);let z=b,W=B.id;f.note.position==="left of"&&(z=B.id,W=b),i.setEdge(z,W,{arrowhead:"none",arrowType:"",style:Tjt,labelStyle:"",classes:MUe,arrowheadStyle:Cjt,labelpos:_jt,labelType:Sjt,thickness:Ajt})}else i.setNode(b,I)}a&&a.id!=="root"&&(Ut.trace("Setting node ",b," to be child of its parent ",a.id),i.setParent(b,a.id)),f.doc&&(Ut.trace("Adding nodes children "),jUe(i,f,f.doc,p,w,!m))},jUe=(i,a,f,p,w,m)=>{Ut.trace("items",f),f.forEach(b=>{switch(b.stmt){case UY:JF(i,a,b,p,w,m);break;case KF:JF(i,a,b,p,w,m);break;case Igt:{JF(i,a,b.state1,p,w,m),JF(i,a,b.state2,p,w,m);const E={id:"edge"+kk,arrowhead:"normal",arrowTypeEnd:"arrow_barb",style:Tjt,labelStyle:"",label:Kr.sanitizeText(b.description,Oe()),arrowheadStyle:Cjt,labelpos:_jt,labelType:Sjt,thickness:Ajt,classes:yjt};i.setEdge(b.state1.id,b.state2.id,E,kk),kk++}break}})},Hgt=(i,a=NGe)=>{let f=a;if(i.doc)for(let p=0;p{i.state||(i.state={}),i.state.arrowMarkerAbsolute=i.arrowMarkerAbsolute,$5.clear()}}},Symbol.toStringTag,{value:"Module"}));var Vgt=function(){var i=function(B,N,R,z){for(R=R||{},z=B.length;z--;R[B[z]]=N);return R},a=[6,8,10,11,12,14,16,17,18],f=[1,9],p=[1,10],w=[1,11],m=[1,12],b=[1,13],E=[1,14],_={trace:function(){},yy:{},symbols_:{error:2,start:3,journey:4,document:5,EOF:6,line:7,SPACE:8,statement:9,NEWLINE:10,title:11,acc_title:12,acc_title_value:13,acc_descr:14,acc_descr_value:15,acc_descr_multiline_value:16,section:17,taskName:18,taskData:19,$accept:0,$end:1},terminals_:{2:"error",4:"journey",6:"EOF",8:"SPACE",10:"NEWLINE",11:"title",12:"acc_title",13:"acc_title_value",14:"acc_descr",15:"acc_descr_value",16:"acc_descr_multiline_value",17:"section",18:"taskName",19:"taskData"},productions_:[0,[3,3],[5,0],[5,2],[7,2],[7,1],[7,1],[7,1],[9,1],[9,2],[9,2],[9,1],[9,1],[9,2]],performAction:function(N,R,z,W,et,st,at){var bt=st.length-1;switch(et){case 1:return st[bt-1];case 2:this.$=[];break;case 3:st[bt-1].push(st[bt]),this.$=st[bt-1];break;case 4:case 5:this.$=st[bt];break;case 6:case 7:this.$=[];break;case 8:W.setDiagramTitle(st[bt].substr(6)),this.$=st[bt].substr(6);break;case 9:this.$=st[bt].trim(),W.setAccTitle(this.$);break;case 10:case 11:this.$=st[bt].trim(),W.setAccDescription(this.$);break;case 12:W.addSection(st[bt].substr(8)),this.$=st[bt].substr(8);break;case 13:W.addTask(st[bt-1],st[bt]),this.$="task";break}},table:[{3:1,4:[1,2]},{1:[3]},i(a,[2,2],{5:3}),{6:[1,4],7:5,8:[1,6],9:7,10:[1,8],11:f,12:p,14:w,16:m,17:b,18:E},i(a,[2,7],{1:[2,1]}),i(a,[2,3]),{9:15,11:f,12:p,14:w,16:m,17:b,18:E},i(a,[2,5]),i(a,[2,6]),i(a,[2,8]),{13:[1,16]},{15:[1,17]},i(a,[2,11]),i(a,[2,12]),{19:[1,18]},i(a,[2,4]),i(a,[2,9]),i(a,[2,10]),i(a,[2,13])],defaultActions:{},parseError:function(N,R){if(R.recoverable)this.trace(N);else{var z=new Error(N);throw z.hash=R,z}},parse:function(N){var R=this,z=[0],W=[],et=[null],st=[],at=this.table,bt="",mt=0,yt=0,ft=2,ut=1,vt=st.slice.call(arguments,1),X=Object.create(this.lexer),pt={yy:{}};for(var U in this.yy)Object.prototype.hasOwnProperty.call(this.yy,U)&&(pt.yy[U]=this.yy[U]);X.setInput(N,pt.yy),pt.yy.lexer=X,pt.yy.parser=this,typeof X.yylloc>"u"&&(X.yylloc={});var Tt=X.yylloc;st.push(Tt);var nt=X.options&&X.options.ranges;typeof pt.yy.parseError=="function"?this.parseError=pt.yy.parseError:this.parseError=Object.getPrototypeOf(this).parseError;function It(){var Se;return Se=W.pop()||X.lex()||ut,typeof Se!="number"&&(Se instanceof Array&&(W=Se,Se=W.pop()),Se=R.symbols_[Se]||Se),Se}for(var Ot,Bt,Et,Z,Ct={},xt,Ht,Le,Ft;;){if(Bt=z[z.length-1],this.defaultActions[Bt]?Et=this.defaultActions[Bt]:((Ot===null||typeof Ot>"u")&&(Ot=It()),Et=at[Bt]&&at[Bt][Ot]),typeof Et>"u"||!Et.length||!Et[0]){var gn="";Ft=[];for(xt in at[Bt])this.terminals_[xt]&&xt>ft&&Ft.push("'"+this.terminals_[xt]+"'");X.showPosition?gn="Parse error on line "+(mt+1)+`: +`+X.showPosition()+` +Expecting `+Ft.join(", ")+", got '"+(this.terminals_[Ot]||Ot)+"'":gn="Parse error on line "+(mt+1)+": Unexpected "+(Ot==ut?"end of input":"'"+(this.terminals_[Ot]||Ot)+"'"),this.parseError(gn,{text:X.match,token:this.terminals_[Ot]||Ot,line:X.yylineno,loc:Tt,expected:Ft})}if(Et[0]instanceof Array&&Et.length>1)throw new Error("Parse Error: multiple actions possible at state: "+Bt+", token: "+Ot);switch(Et[0]){case 1:z.push(Ot),et.push(X.yytext),st.push(X.yylloc),z.push(Et[1]),Ot=null,yt=X.yyleng,bt=X.yytext,mt=X.yylineno,Tt=X.yylloc;break;case 2:if(Ht=this.productions_[Et[1]][1],Ct.$=et[et.length-Ht],Ct._$={first_line:st[st.length-(Ht||1)].first_line,last_line:st[st.length-1].last_line,first_column:st[st.length-(Ht||1)].first_column,last_column:st[st.length-1].last_column},nt&&(Ct._$.range=[st[st.length-(Ht||1)].range[0],st[st.length-1].range[1]]),Z=this.performAction.apply(Ct,[bt,yt,mt,pt.yy,Et[1],et,st].concat(vt)),typeof Z<"u")return Z;Ht&&(z=z.slice(0,-1*Ht*2),et=et.slice(0,-1*Ht),st=st.slice(0,-1*Ht)),z.push(this.productions_[Et[1]][0]),et.push(Ct.$),st.push(Ct._$),Le=at[z[z.length-2]][z[z.length-1]],z.push(Le);break;case 3:return!0}}return!0}},A=function(){var B={EOF:1,parseError:function(R,z){if(this.yy.parser)this.yy.parser.parseError(R,z);else throw new Error(R)},setInput:function(N,R){return this.yy=R||this.yy||{},this._input=N,this._more=this._backtrack=this.done=!1,this.yylineno=this.yyleng=0,this.yytext=this.matched=this.match="",this.conditionStack=["INITIAL"],this.yylloc={first_line:1,first_column:0,last_line:1,last_column:0},this.options.ranges&&(this.yylloc.range=[0,0]),this.offset=0,this},input:function(){var N=this._input[0];this.yytext+=N,this.yyleng++,this.offset++,this.match+=N,this.matched+=N;var R=N.match(/(?:\r\n?|\n).*/g);return R?(this.yylineno++,this.yylloc.last_line++):this.yylloc.last_column++,this.options.ranges&&this.yylloc.range[1]++,this._input=this._input.slice(1),N},unput:function(N){var R=N.length,z=N.split(/(?:\r\n?|\n)/g);this._input=N+this._input,this.yytext=this.yytext.substr(0,this.yytext.length-R),this.offset-=R;var W=this.match.split(/(?:\r\n?|\n)/g);this.match=this.match.substr(0,this.match.length-1),this.matched=this.matched.substr(0,this.matched.length-1),z.length-1&&(this.yylineno-=z.length-1);var et=this.yylloc.range;return this.yylloc={first_line:this.yylloc.first_line,last_line:this.yylineno+1,first_column:this.yylloc.first_column,last_column:z?(z.length===W.length?this.yylloc.first_column:0)+W[W.length-z.length].length-z[0].length:this.yylloc.first_column-R},this.options.ranges&&(this.yylloc.range=[et[0],et[0]+this.yyleng-R]),this.yyleng=this.yytext.length,this},more:function(){return this._more=!0,this},reject:function(){if(this.options.backtrack_lexer)this._backtrack=!0;else return this.parseError("Lexical error on line "+(this.yylineno+1)+`. You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true). +`+this.showPosition(),{text:"",token:null,line:this.yylineno});return this},less:function(N){this.unput(this.match.slice(N))},pastInput:function(){var N=this.matched.substr(0,this.matched.length-this.match.length);return(N.length>20?"...":"")+N.substr(-20).replace(/\n/g,"")},upcomingInput:function(){var N=this.match;return N.length<20&&(N+=this._input.substr(0,20-N.length)),(N.substr(0,20)+(N.length>20?"...":"")).replace(/\n/g,"")},showPosition:function(){var N=this.pastInput(),R=new Array(N.length+1).join("-");return N+this.upcomingInput()+` +`+R+"^"},test_match:function(N,R){var z,W,et;if(this.options.backtrack_lexer&&(et={yylineno:this.yylineno,yylloc:{first_line:this.yylloc.first_line,last_line:this.last_line,first_column:this.yylloc.first_column,last_column:this.yylloc.last_column},yytext:this.yytext,match:this.match,matches:this.matches,matched:this.matched,yyleng:this.yyleng,offset:this.offset,_more:this._more,_input:this._input,yy:this.yy,conditionStack:this.conditionStack.slice(0),done:this.done},this.options.ranges&&(et.yylloc.range=this.yylloc.range.slice(0))),W=N[0].match(/(?:\r\n?|\n).*/g),W&&(this.yylineno+=W.length),this.yylloc={first_line:this.yylloc.last_line,last_line:this.yylineno+1,first_column:this.yylloc.last_column,last_column:W?W[W.length-1].length-W[W.length-1].match(/\r?\n?/)[0].length:this.yylloc.last_column+N[0].length},this.yytext+=N[0],this.match+=N[0],this.matches=N,this.yyleng=this.yytext.length,this.options.ranges&&(this.yylloc.range=[this.offset,this.offset+=this.yyleng]),this._more=!1,this._backtrack=!1,this._input=this._input.slice(N[0].length),this.matched+=N[0],z=this.performAction.call(this,this.yy,this,R,this.conditionStack[this.conditionStack.length-1]),this.done&&this._input&&(this.done=!1),z)return z;if(this._backtrack){for(var st in et)this[st]=et[st];return!1}return!1},next:function(){if(this.done)return this.EOF;this._input||(this.done=!0);var N,R,z,W;this._more||(this.yytext="",this.match="");for(var et=this._currentRules(),st=0;stR[0].length)){if(R=z,W=st,this.options.backtrack_lexer){if(N=this.test_match(z,et[st]),N!==!1)return N;if(this._backtrack){R=!1;continue}else return!1}else if(!this.options.flex)break}return R?(N=this.test_match(R,et[W]),N!==!1?N:!1):this._input===""?this.EOF:this.parseError("Lexical error on line "+(this.yylineno+1)+`. Unrecognized text. +`+this.showPosition(),{text:"",token:null,line:this.yylineno})},lex:function(){var R=this.next();return R||this.lex()},begin:function(R){this.conditionStack.push(R)},popState:function(){var R=this.conditionStack.length-1;return R>0?this.conditionStack.pop():this.conditionStack[0]},_currentRules:function(){return this.conditionStack.length&&this.conditionStack[this.conditionStack.length-1]?this.conditions[this.conditionStack[this.conditionStack.length-1]].rules:this.conditions.INITIAL.rules},topState:function(R){return R=this.conditionStack.length-1-Math.abs(R||0),R>=0?this.conditionStack[R]:"INITIAL"},pushState:function(R){this.begin(R)},stateStackSize:function(){return this.conditionStack.length},options:{"case-insensitive":!0},performAction:function(R,z,W,et){switch(W){case 0:break;case 1:break;case 2:return 10;case 3:break;case 4:break;case 5:return 4;case 6:return 11;case 7:return this.begin("acc_title"),12;case 8:return this.popState(),"acc_title_value";case 9:return this.begin("acc_descr"),14;case 10:return this.popState(),"acc_descr_value";case 11:this.begin("acc_descr_multiline");break;case 12:this.popState();break;case 13:return"acc_descr_multiline_value";case 14:return 17;case 15:return 18;case 16:return 19;case 17:return":";case 18:return 6;case 19:return"INVALID"}},rules:[/^(?:%(?!\{)[^\n]*)/i,/^(?:[^\}]%%[^\n]*)/i,/^(?:[\n]+)/i,/^(?:\s+)/i,/^(?:#[^\n]*)/i,/^(?:journey\b)/i,/^(?:title\s[^#\n;]+)/i,/^(?:accTitle\s*:\s*)/i,/^(?:(?!\n||)*[^\n]*)/i,/^(?:accDescr\s*:\s*)/i,/^(?:(?!\n||)*[^\n]*)/i,/^(?:accDescr\s*\{\s*)/i,/^(?:[\}])/i,/^(?:[^\}]*)/i,/^(?:section\s[^#:\n;]+)/i,/^(?:[^#:\n;]+)/i,/^(?::[^#\n;]+)/i,/^(?::)/i,/^(?:$)/i,/^(?:.)/i],conditions:{acc_descr_multiline:{rules:[12,13],inclusive:!1},acc_descr:{rules:[10],inclusive:!1},acc_title:{rules:[8],inclusive:!1},INITIAL:{rules:[0,1,2,3,4,5,6,7,9,11,14,15,16,17,18,19],inclusive:!0}}};return B}();_.lexer=A;function I(){this.yy={}}return I.prototype=_,_.Parser=I,new I}();Vgt.parser=Vgt;const zUe=Vgt;let mL="";const Ggt=[],tN=[],eN=[],qUe=function(){Ggt.length=0,tN.length=0,mL="",eN.length=0,hg()},HUe=function(i){mL=i,Ggt.push(i)},VUe=function(){return Ggt},GUe=function(){let i=Ljt();const a=100;let f=0;for(;!i&&f{f.people&&i.push(...f.people)}),[...new Set(i)].sort()},WUe=function(i,a){const f=a.substr(1).split(":");let p=0,w=[];f.length===1?(p=Number(f[0]),w=[]):(p=Number(f[0]),w=f[1].split(","));const m=w.map(E=>E.trim()),b={section:mL,type:mL,people:m,task:i,score:p};eN.push(b)},YUe=function(i){const a={section:mL,type:mL,description:i,task:i,classes:[]};tN.push(a)},Ljt=function(){const i=function(f){return eN[f].processed};let a=!0;for(const[f,p]of eN.entries())i(f),a=a&&p.processed;return a},Mjt={getConfig:()=>Oe().journey,clear:qUe,setDiagramTitle:Nb,getDiagramTitle:pg,setAccTitle:E0,getAccTitle:fg,setAccDescription:dg,getAccDescription:gg,addSection:HUe,getSections:VUe,getTasks:GUe,addTask:WUe,addTaskOrg:YUe,getActors:function(){return UUe()}},KUe=i=>`.label { + font-family: 'trebuchet ms', verdana, arial, sans-serif; + font-family: var(--mermaid-font-family); + color: ${i.textColor}; + } + .mouth { + stroke: #666; + } + + line { + stroke: ${i.textColor} + } + + .legend { + fill: ${i.textColor}; + } + + .label text { + fill: #333; + } + .label { + color: ${i.textColor} + } + + .face { + ${i.faceColor?`fill: ${i.faceColor}`:"fill: #FFF8DC"}; + stroke: #999; + } + + .node rect, + .node circle, + .node ellipse, + .node polygon, + .node path { + fill: ${i.mainBkg}; + stroke: ${i.nodeBorder}; + stroke-width: 1px; + } + + .node .label { + text-align: center; + } + .node.clickable { + cursor: pointer; + } + + .arrowheadPath { + fill: ${i.arrowheadColor}; + } + + .edgePath .path { + stroke: ${i.lineColor}; + stroke-width: 1.5px; + } + + .flowchart-link { + stroke: ${i.lineColor}; + fill: none; + } + + .edgeLabel { + background-color: ${i.edgeLabelBackground}; + rect { + opacity: 0.5; + } + text-align: center; + } + + .cluster rect { + } + + .cluster text { + fill: ${i.titleColor}; + } + + div.mermaidTooltip { + position: absolute; + text-align: center; + max-width: 200px; + padding: 2px; + font-family: 'trebuchet ms', verdana, arial, sans-serif; + font-family: var(--mermaid-font-family); + font-size: 12px; + background: ${i.tertiaryColor}; + border: 1px solid ${i.border2}; + border-radius: 2px; + pointer-events: none; + z-index: 100; + } + + .task-type-0, .section-type-0 { + ${i.fillType0?`fill: ${i.fillType0}`:""}; + } + .task-type-1, .section-type-1 { + ${i.fillType0?`fill: ${i.fillType1}`:""}; + } + .task-type-2, .section-type-2 { + ${i.fillType0?`fill: ${i.fillType2}`:""}; + } + .task-type-3, .section-type-3 { + ${i.fillType0?`fill: ${i.fillType3}`:""}; + } + .task-type-4, .section-type-4 { + ${i.fillType0?`fill: ${i.fillType4}`:""}; + } + .task-type-5, .section-type-5 { + ${i.fillType0?`fill: ${i.fillType5}`:""}; + } + .task-type-6, .section-type-6 { + ${i.fillType0?`fill: ${i.fillType6}`:""}; + } + .task-type-7, .section-type-7 { + ${i.fillType0?`fill: ${i.fillType7}`:""}; + } + + .actor-0 { + ${i.actor0?`fill: ${i.actor0}`:""}; + } + .actor-1 { + ${i.actor1?`fill: ${i.actor1}`:""}; + } + .actor-2 { + ${i.actor2?`fill: ${i.actor2}`:""}; + } + .actor-3 { + ${i.actor3?`fill: ${i.actor3}`:""}; + } + .actor-4 { + ${i.actor4?`fill: ${i.actor4}`:""}; + } + .actor-5 { + ${i.actor5?`fill: ${i.actor5}`:""}; + } +`,Ugt=function(i,a){return JW(i,a)},XUe=function(i,a){const p=i.append("circle").attr("cx",a.cx).attr("cy",a.cy).attr("class","face").attr("r",15).attr("stroke-width",2).attr("overflow","visible"),w=i.append("g");w.append("circle").attr("cx",a.cx-15/3).attr("cy",a.cy-15/3).attr("r",1.5).attr("stroke-width",2).attr("fill","#666").attr("stroke","#666"),w.append("circle").attr("cx",a.cx+15/3).attr("cy",a.cy-15/3).attr("r",1.5).attr("stroke-width",2).attr("fill","#666").attr("stroke","#666");function m(_){const A=OA().startAngle(Math.PI/2).endAngle(3*(Math.PI/2)).innerRadius(7.5).outerRadius(6.8181818181818175);_.append("path").attr("class","mouth").attr("d",A).attr("transform","translate("+a.cx+","+(a.cy+2)+")")}function b(_){const A=OA().startAngle(3*Math.PI/2).endAngle(5*(Math.PI/2)).innerRadius(7.5).outerRadius(6.8181818181818175);_.append("path").attr("class","mouth").attr("d",A).attr("transform","translate("+a.cx+","+(a.cy+7)+")")}function E(_){_.append("line").attr("class","mouth").attr("stroke",2).attr("x1",a.cx-5).attr("y1",a.cy+7).attr("x2",a.cx+5).attr("y2",a.cy+7).attr("class","mouth").attr("stroke-width","1px").attr("stroke","#666")}return a.score>3?m(w):a.score<3?b(w):E(w),p},Djt=function(i,a){const f=i.append("circle");return f.attr("cx",a.cx),f.attr("cy",a.cy),f.attr("class","actor-"+a.pos),f.attr("fill",a.fill),f.attr("stroke",a.stroke),f.attr("r",a.r),f.class!==void 0&&f.attr("class",f.class),a.title!==void 0&&f.append("title").text(a.title),f},Ijt=function(i,a){return RDe(i,a)},QUe=function(i,a){function f(w,m,b,E,_){return w+","+m+" "+(w+b)+","+m+" "+(w+b)+","+(m+E-_)+" "+(w+b-_*1.2)+","+(m+E)+" "+w+","+(m+E)}const p=i.append("polygon");p.attr("points",f(a.x,a.y,50,20,7)),p.attr("class","labelBox"),a.y=a.y+a.labelMargin,a.x=a.x+.5*a.labelMargin,Ijt(i,a)},ZUe=function(i,a,f){const p=i.append("g"),w=bT();w.x=a.x,w.y=a.y,w.fill=a.fill,w.width=f.width*a.taskCount+f.diagramMarginX*(a.taskCount-1),w.height=f.height,w.class="journey-section section-type-"+a.num,w.rx=3,w.ry=3,Ugt(p,w),Pjt(f)(a.text,p,w.x,w.y,w.width,w.height,{class:"journey-section section-type-"+a.num},f,a.colour)};let Ojt=-1;const JUe=function(i,a,f){const p=a.x+f.width/2,w=i.append("g");Ojt++;const m=300+5*30;w.append("line").attr("id","task"+Ojt).attr("x1",p).attr("y1",a.y).attr("x2",p).attr("y2",m).attr("class","task-line").attr("stroke-width","1px").attr("stroke-dasharray","4 2").attr("stroke","#666"),XUe(w,{cx:p,cy:300+(5-a.score)*30,score:a.score});const b=bT();b.x=a.x,b.y=a.y,b.fill=a.fill,b.width=f.width,b.height=f.height,b.class="task task-type-"+a.num,b.rx=3,b.ry=3,Ugt(w,b);let E=a.x+14;a.people.forEach(_=>{const A=a.actors[_].color,I={cx:E,cy:a.y,r:7,fill:A,stroke:"#000",title:_,pos:a.actors[_].position};Djt(w,I),E+=10}),Pjt(f)(a.task,w,b.x,b.y,b.width,b.height,{class:"task"},f,a.colour)},tWe=function(i,a){mPt(i,a)},Pjt=function(){function i(w,m,b,E,_,A,I,B){const N=m.append("text").attr("x",b+_/2).attr("y",E+A/2+5).style("font-color",B).style("text-anchor","middle").text(w);p(N,I)}function a(w,m,b,E,_,A,I,B,N){const{taskFontSize:R,taskFontFamily:z}=B,W=w.split(//gi);for(let et=0;et{const w=z5[p].color,m={cx:20,cy:f,r:7,fill:w,stroke:"#000",pos:z5[p].position};nN.drawCircle(i,m);const b={x:40,y:f+7,fill:"#666",text:p,textMargin:a.boxTextMargin|5};nN.drawText(i,b),f+=20})}const JY=Oe().journey,MT=JY.leftMargin,rWe=function(i,a,f,p){const w=Oe().journey,m=Oe().securityLevel;let b;m==="sandbox"&&(b=yr("#i"+a));const E=yr(m==="sandbox"?b.nodes()[0].contentDocument.body:"body");aw.init();const _=E.select("#"+a);nN.initGraphics(_);const A=p.db.getTasks(),I=p.db.getDiagramTitle(),B=p.db.getActors();for(const st in z5)delete z5[st];let N=0;B.forEach(st=>{z5[st]={color:w.actorColours[N%w.actorColours.length],position:N},N++}),nWe(_),aw.insert(0,0,MT,Object.keys(z5).length*50),iWe(_,A,0);const R=aw.getBounds();I&&_.append("text").text(I).attr("x",MT).attr("font-size","4ex").attr("font-weight","bold").attr("y",25);const z=R.stopy-R.starty+2*w.diagramMarginY,W=MT+R.stopx+2*w.diagramMarginX;k0(_,z,W,w.useMaxWidth),_.append("line").attr("x1",MT).attr("y1",w.height*4).attr("x2",W-MT-4).attr("y2",w.height*4).attr("stroke-width",4).attr("stroke","black").attr("marker-end","url(#arrowhead)");const et=I?70:0;_.attr("viewBox",`${R.startx} -25 ${W} ${z+et}`),_.attr("preserveAspectRatio","xMinYMin meet"),_.attr("height",z+et+25)},aw={data:{startx:void 0,stopx:void 0,starty:void 0,stopy:void 0},verticalPos:0,sequenceItems:[],init:function(){this.sequenceItems=[],this.data={startx:void 0,stopx:void 0,starty:void 0,stopy:void 0},this.verticalPos=0},updateVal:function(i,a,f,p){i[a]===void 0?i[a]=f:i[a]=p(f,i[a])},updateBounds:function(i,a,f,p){const w=Oe().journey,m=this;let b=0;function E(_){return function(I){b++;const B=m.sequenceItems.length-b+1;m.updateVal(I,"starty",a-B*w.boxMargin,Math.min),m.updateVal(I,"stopy",p+B*w.boxMargin,Math.max),m.updateVal(aw.data,"startx",i-B*w.boxMargin,Math.min),m.updateVal(aw.data,"stopx",f+B*w.boxMargin,Math.max),_!=="activation"&&(m.updateVal(I,"startx",i-B*w.boxMargin,Math.min),m.updateVal(I,"stopx",f+B*w.boxMargin,Math.max),m.updateVal(aw.data,"starty",a-B*w.boxMargin,Math.min),m.updateVal(aw.data,"stopy",p+B*w.boxMargin,Math.max))}}this.sequenceItems.forEach(E())},insert:function(i,a,f,p){const w=Math.min(i,f),m=Math.max(i,f),b=Math.min(a,p),E=Math.max(a,p);this.updateVal(aw.data,"startx",w,Math.min),this.updateVal(aw.data,"starty",b,Math.min),this.updateVal(aw.data,"stopx",m,Math.max),this.updateVal(aw.data,"stopy",E,Math.max),this.updateBounds(w,b,m,E)},bumpVerticalPos:function(i){this.verticalPos=this.verticalPos+i,this.data.stopy=this.verticalPos},getVerticalPos:function(){return this.verticalPos},getBounds:function(){return this.data}},Wgt=JY.sectionFills,Fjt=JY.sectionColours,iWe=function(i,a,f){const p=Oe().journey;let w="";const m=p.height*2+p.diagramMarginY,b=f+m;let E=0,_="#CCC",A="black",I=0;for(const[B,N]of a.entries()){if(w!==N.section){_=Wgt[E%Wgt.length],I=E%Wgt.length,A=Fjt[E%Fjt.length];let z=0;const W=N.section;for(let st=B;st(z5[W]&&(z[W]=z5[W]),z),{});N.x=B*p.taskMargin+B*p.width+MT,N.y=b,N.width=p.diagramMarginX,N.height=p.diagramMarginY,N.colour=A,N.fill=_,N.num=I,N.actors=R,nN.drawTask(i,N,p),aw.insert(N.x,N.y,N.x+N.width+p.taskMargin,300+5*30)}},Njt={setConf:eWe,draw:rWe},sWe=Object.freeze(Object.defineProperty({__proto__:null,diagram:{parser:zUe,db:Mjt,renderer:Njt,styles:KUe,init:i=>{Njt.setConf(i.journey),Mjt.clear()}}},Symbol.toStringTag,{value:"Module"})),aWe=(i,a,f)=>{const{parentById:p}=f,w=new Set;let m=i;for(;m;){if(w.add(m),m===a)return m;m=p[m]}for(m=a;m;){if(w.has(m))return m;m=p[m]}return"root"};function tK(i){throw new Error('Could not dynamically require "'+i+'". Please configure the dynamicRequireTargets or/and ignoreDynamicRequires option of @rollup/plugin-commonjs appropriately for this require call to work.')}var Bjt={exports:{}};(function(i,a){(function(f){i.exports=f()})(function(){return function(){function f(p,w,m){function b(A,I){if(!w[A]){if(!p[A]){var B=typeof tK=="function"&&tK;if(!I&&B)return B(A,!0);if(E)return E(A,!0);var N=new Error("Cannot find module '"+A+"'");throw N.code="MODULE_NOT_FOUND",N}var R=w[A]={exports:{}};p[A][0].call(R.exports,function(z){var W=p[A][1][z];return b(W||z)},R,R.exports,f,p,w,m)}return w[A].exports}for(var E=typeof tK=="function"&&tK,_=0;_0&&arguments[0]!==void 0?arguments[0]:{},N=B.defaultLayoutOptions,R=N===void 0?{}:N,z=B.algorithms,W=z===void 0?["layered","stress","mrtree","radial","force","disco","sporeOverlap","sporeCompaction","rectpacking"]:z,et=B.workerFactory,st=B.workerUrl;if(b(this,A),this.defaultLayoutOptions=R,this.initialized=!1,typeof st>"u"&&typeof et>"u")throw new Error("Cannot construct an ELK without both 'workerUrl' and 'workerFactory'.");var at=et;typeof st<"u"&&typeof et>"u"&&(at=function(yt){return new Worker(yt)});var bt=at(st);if(typeof bt.postMessage!="function")throw new TypeError("Created worker does not provide the required 'postMessage' function.");this.worker=new _(bt),this.worker.postMessage({cmd:"register",algorithms:W}).then(function(mt){return I.initialized=!0}).catch(console.err)}return m(A,[{key:"layout",value:function(B){var N=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{},R=N.layoutOptions,z=R===void 0?this.defaultLayoutOptions:R,W=N.logging,et=W===void 0?!1:W,st=N.measureExecutionTime,at=st===void 0?!1:st;return B?this.worker.postMessage({cmd:"layout",graph:B,layoutOptions:z,options:{logging:et,measureExecutionTime:at}}):Promise.reject(new Error("Missing mandatory parameter 'graph'."))}},{key:"knownLayoutAlgorithms",value:function(){return this.worker.postMessage({cmd:"algorithms"})}},{key:"knownLayoutOptions",value:function(){return this.worker.postMessage({cmd:"options"})}},{key:"knownLayoutCategories",value:function(){return this.worker.postMessage({cmd:"categories"})}},{key:"terminateWorker",value:function(){this.worker.terminate()}}]),A}();w.default=E;var _=function(){function A(I){var B=this;if(b(this,A),I===void 0)throw new Error("Missing mandatory parameter 'worker'.");this.resolvers={},this.worker=I,this.worker.onmessage=function(N){setTimeout(function(){B.receive(B,N)},0)}}return m(A,[{key:"postMessage",value:function(B){var N=this.id||0;this.id=N+1,B.id=N;var R=this;return new Promise(function(z,W){R.resolvers[N]=function(et,st){et?(R.convertGwtStyleError(et),W(et)):z(st)},R.worker.postMessage(B)})}},{key:"receive",value:function(B,N){var R=N.data,z=B.resolvers[R.id];z&&(delete B.resolvers[R.id],R.error?z(R.error):z(null,R.data))}},{key:"terminate",value:function(){this.worker.terminate&&this.worker.terminate()}},{key:"convertGwtStyleError",value:function(B){if(B){var N=B.__java$exception;N&&(N.cause&&N.cause.backingJsObject&&(B.cause=N.cause.backingJsObject,this.convertGwtStyleError(B.cause)),delete B.__java$exception)}}}]),A}()},{}],2:[function(f,p,w){(function(m){(function(){var b;typeof window<"u"?b=window:typeof m<"u"?b=m:typeof self<"u"&&(b=self);var E;function _(){}function A(){}function I(){}function B(){}function N(){}function R(){}function z(){}function W(){}function et(){}function st(){}function at(){}function bt(){}function mt(){}function yt(){}function ft(){}function ut(){}function vt(){}function X(){}function pt(){}function U(){}function Tt(){}function nt(){}function It(){}function Ot(){}function Bt(){}function Et(){}function Z(){}function Ct(){}function xt(){}function Ht(){}function Le(){}function Ft(){}function gn(){}function Se(){}function me(){}function Ve(){}function Ye(){}function ce(){}function ke(){}function zt(){}function re(){}function se(){}function Pe(){}function te(){}function Me(){}function de(){}function on(){}function ni(){}function Ks(){}function ws(){}function fo(){}function Xi(){}function Er(){}function Xn(){}function di(){}function Ee(){}function Kn(){}function He(){}function Ti(){}function pn(){}function Es(){}function qa(){}function Ma(){}function Gs(){}function Po(){}function vs(){}function ru(){}function zs(){}function Du(){}function pm(){}function uw(){}function Wu(){}function th(){}function Fa(){}function Ml(){}function ha(){}function bc(){}function Cc(){}function pa(){}function Da(){}function Ha(){}function Dl(){}function _c(){}function lw(){}function eh(){}function ed(){}function jd(){}function nd(){}function $d(){}function A0(){}function Bi(){}function cn(){}function kr(){}function Ei(){}function Jo(){}function wc(){}function rf(){}function Oc(){}function sf(){}function af(){}function Qi(){}function Ts(){}function ka(){}function xi(){}function Yc(){}function Ce(){}function vp(){}function Be(){}function Bf(){}function yg(){}function bm(){}function Ek(){}function E3(){}function Il(){}function L0(){}function hw(){}function H5(){}function Hb(){}function V5(){}function f1(){}function rd(){}function id(){}function G5(){}function fw(){}function U5(){}function mp(){}function W5(){}function T3(){}function wm(){}function xg(){}function EL(){}function vl(){}function iN(){}function Sc(){}function cK(){}function Vb(){}function uK(){}function PT(){}function lK(){}function sN(){}function Rf(){}function vm(){}function TL(){}function aN(){}function yp(){}function mm(){}function hK(){}function Gb(){}function fK(){}function dK(){}function Y5(){}function FT(){}function oN(){}function Tk(){}function gK(){}function Ck(){}function pK(){}function bK(){}function wK(){}function vK(){}function mK(){}function yK(){}function xK(){}function kK(){}function EK(){}function TK(){}function CK(){}function CL(){}function _K(){}function SK(){}function NT(){}function cN(){}function K5(){}function AK(){}function LK(){}function MK(){}function DK(){}function IK(){}function BT(){}function _L(){}function uN(){}function C3(){}function _3(){}function OK(){}function of(){}function X5(){}function PK(){}function _k(){}function zd(){}function FK(){}function NK(){}function BK(){}function RK(){}function RT(){}function SL(){}function lN(){}function AL(){}function Q5(){}function jK(){}function hN(){}function fN(){}function $K(){}function zK(){}function qK(){}function HK(){}function VK(){}function GK(){}function qd(){}function dw(){}function UK(){}function dN(){}function gN(){}function WK(){}function S3(){}function Sk(){}function LL(){}function ym(){}function Ak(){}function YK(){}function jT(){}function sd(){}function pN(){}function ML(){}function Lk(){}function DL(){}function bN(){}function KK(){}function IL(){}function XK(){}function QK(){}function wN(){}function Z5(){}function vN(){}function J5(){}function ZK(){}function OL(){}function JK(){}function tX(){}function eX(){}function nX(){}function mN(){}function rX(){}function iX(){}function sX(){}function yN(){}function aX(){}function oX(){}function cX(){}function xN(){}function uX(){}function lX(){}function kN(){}function EN(){}function TN(){}function hX(){}function fX(){}function Mk(){}function tx(){}function $T(){}function dX(){}function PL(){}function zT(){}function FL(){}function CN(){}function _N(){}function gX(){}function pX(){}function bX(){}function SN(){}function AN(){}function wX(){}function vX(){}function mX(){}function yX(){}function xX(){}function LN(){}function kX(){}function EX(){}function TX(){}function CX(){}function MN(){}function qT(){}function _X(){}function SX(){}function DN(){}function AX(){}function LX(){}function MX(){}function DX(){}function IX(){}function OX(){}function IN(){}function PX(){}function ON(){}function FX(){}function NX(){}function BX(){}function HT(){}function RX(){}function VT(){}function jX(){}function PN(){}function FN(){}function NN(){}function BN(){}function gw(){}function RN(){}function jN(){}function $N(){}function zN(){}function $X(){}function ex(){}function GT(){}function A3(){}function zX(){}function qX(){}function UT(){}function HX(){}function VX(){}function GX(){}function UX(){}function WX(){}function YX(){}function KX(){}function XX(){}function QX(){}function ZX(){}function JX(){}function NL(){}function qN(){}function tQ(){}function eQ(){}function nQ(){}function HN(){}function rQ(){}function iQ(){}function sQ(){}function aQ(){}function oQ(){}function cQ(){}function VN(){}function GN(){}function uQ(){}function UN(){}function WN(){}function lQ(){}function hQ(){}function fQ(){}function BL(){}function dQ(){}function Dk(){}function gQ(){}function pQ(){}function bQ(){}function YN(){}function wQ(){}function vQ(){}function mQ(){}function yQ(){}function xQ(){}function kQ(){}function EQ(){}function TQ(){}function CQ(){}function _Q(){}function SQ(){}function AQ(){}function nx(){}function KN(){}function LQ(){}function MQ(){}function DQ(){}function XN(){}function IQ(){}function WT(){}function OQ(){}function PQ(){}function FQ(){}function NQ(){}function BQ(){}function RQ(){}function jQ(){}function $Q(){}function zQ(){}function qQ(){}function rx(){}function HQ(){}function VQ(){}function GQ(){}function UQ(){}function WQ(){}function YQ(){}function KQ(){}function XQ(){}function YT(){}function QQ(){}function ZQ(){}function JQ(){}function tZ(){}function eZ(){}function nZ(){}function rZ(){}function iZ(){}function ix(){}function QN(){}function sZ(){}function RL(){}function aZ(){}function oZ(){}function cZ(){}function uZ(){}function lZ(){}function hZ(){}function fZ(){}function ZN(){}function dZ(){}function JN(){}function gZ(){}function tB(){}function eB(){}function nB(){}function pZ(){}function bZ(){}function KT(){}function jL(){}function XT(){}function wZ(){}function vZ(){}function $L(){}function mZ(){}function yZ(){}function rB(){}function xZ(){}function kZ(){}function EZ(){}function TZ(){}function CZ(){}function _Z(){}function SZ(){}function AZ(){}function LZ(){}function MZ(){}function kg(){}function DZ(){}function xm(){}function iB(){}function IZ(){}function OZ(){}function PZ(){}function FZ(){}function NZ(){}function BZ(){}function RZ(){}function jZ(){}function $Z(){}function Ac(){}function zZ(){}function QT(){}function tc(){}function Kc(){}function zi(){}function zL(){}function qZ(){}function HZ(){}function VZ(){}function sx(){}function km(){}function Ue(){}function GZ(){}function UZ(){}function WZ(){}function YZ(){}function KZ(){}function sB(){}function XZ(){}function QZ(){}function qL(){}function ZZ(){}function Yu(){}function Iu(){}function JZ(){}function tJ(){}function eJ(){}function Em(){}function pw(){}function xp(){}function ad(){}function ax(){}function ZT(){}function Ik(){}function aB(){}function nJ(){}function Ok(){}function oB(){}function rJ(){}function JT(){}function ox(){}function cx(){}function kp(){}function cB(){}function Pk(){}function uB(){}function lB(){}function ux(){}function Ub(){}function M0(){}function Ep(){}function L3(){}function Fk(){}function tC(){}function hB(){}function iJ(){}function fB(){}function dB(){}function gB(){}function Nk(){}function pB(){}function bB(){}function sJ(){}function Bk(){}function Rk(){}function Tm(){}function HL(){}function aJ(){}function oJ(){}function cJ(){}function uJ(){}function lJ(){}function hJ(){}function fJ(){}function dJ(){}function wB(){}function gJ(){}function pJ(){}function bJ(){}function vB(){}function jk(){}function eC(){}function mB(){}function wJ(){}function yB(){}function xB(){}function vJ(){}function nC(){}function Cm(){}function kB(){}function EB(){}function mJ(){}function yJ(){}function rC(){}function TB(){}function CB(){}function uc(){}function xJ(){}function _B(){}function iC(){}function kJ(){}function EJ(){}function sC(){}function SB(){}function aC(){}function oC(){}function jf(){}function VL(){}function GL(){}function lx(){}function TJ(){}function CJ(){}function _J(){}function SJ(){}function _m(){}function AB(){}function hx(){}function d1(){}function LB(){}function MB(){}function DB(){}function IB(){}function OB(){}function PB(){}function $f(){}function du(){}function AJ(){}function LJ(){}function MJ(){}function gu(){}function cC(){}function FB(){}function NB(){}function fx(){}function DJ(){}function $k(){}function IJ(){}function BB(){}function OJ(){}function PJ(){}function uC(){}function RB(){}function UL(){}function lC(){}function FJ(){}function NJ(){}function WL(){}function hC(){}function g1(){}function zk(){}function BJ(){}function qk(){}function YL(){}function Wb(){}function fC(){}function KL(){}function zf(){}function dC(){}function p1(){}function b1(){}function RJ(){}function jJ(){}function M3(){}function Hk(){}function Vk(){}function gC(){}function $J(){}function dx(){}function XL(){}function jB(){}function zJ(){}function pC(){PC()}function qJ(){Rit()}function $B(){o_()}function QL(){sq()}function HJ(){q4t()}function bC(){Jf()}function VJ(){J3t()}function GJ(){iI()}function UJ(){EM()}function WJ(){kM()}function YJ(){KM()}function zB(){BVt()}function KJ(){r6()}function XJ(){$R()}function QJ(){YJt()}function qB(){one()}function ZJ(){_te()}function JJ(){HQt()}function wC(){oE()}function ttt(){nb()}function ett(){cne()}function ntt(){NZt()}function rtt(){Fxt()}function itt(){Kse()}function stt(){VQt()}function HB(){Te()}function att(){qQt()}function VB(){une()}function ott(){fre()}function ZL(){UQt()}function ctt(){Dte()}function GB(){RVt()}function utt(){E5t()}function UB(){uy()}function ltt(){Nne()}function WB(){cI()}function YB(){dat()}function KB(){yst()}function JL(){gv()}function D3(){myt()}function vC(){GQt()}function od(){rle()}function XB(){y5t()}function Gk(){sat()}function tM(){V$()}function htt(){fq()}function Tp(){ui()}function QB(){Sz()}function ZB(){S3t()}function JB(){Dq()}function nh(){IYt()}function eM(){kit()}function tR(){oxt()}function Uk(t){On(t)}function mC(t){this.a=t}function Wk(t){this.a=t}function eR(t){this.a=t}function gx(t){this.a=t}function bw(t){this.a=t}function Yk(t){this.a=t}function nR(t){this.a=t}function ftt(t){this.a=t}function nM(t){this.a=t}function I3(t){this.a=t}function rM(t){this.a=t}function yC(t){this.a=t}function dtt(t){this.a=t}function xC(t){this.a=t}function kC(t){this.a=t}function px(t){this.a=t}function iM(t){this.a=t}function sM(t){this.a=t}function gtt(t){this.a=t}function ptt(t){this.a=t}function btt(t){this.a=t}function rR(t){this.b=t}function wtt(t){this.c=t}function vtt(t){this.a=t}function mtt(t){this.a=t}function ytt(t){this.a=t}function xtt(t){this.a=t}function ktt(t){this.a=t}function Ett(t){this.a=t}function Ttt(t){this.a=t}function Ctt(t){this.a=t}function bx(t){this.a=t}function _tt(t){this.a=t}function Kk(t){this.a=t}function Th(t){this.a=t}function Stt(t){this.a=t}function wx(t){this.a=t}function Xk(t){this.a=t}function EC(t){this.a=t}function Qk(t){this.a=t}function Eg(){this.a=[]}function Att(t,e){t.a=e}function cpt(t,e){t.a=e}function upt(t,e){t.b=e}function lpt(t,e){t.b=e}function hpt(t,e){t.b=e}function aM(t,e){t.j=e}function fpt(t,e){t.g=e}function dpt(t,e){t.i=e}function Ltt(t,e){t.c=e}function w1(t,e){t.d=e}function Mtt(t,e){t.d=e}function gpt(t,e){t.c=e}function D0(t,e){t.k=e}function Dtt(t,e){t.c=e}function iR(t,e){t.c=e}function sR(t,e){t.a=e}function Itt(t,e){t.a=e}function ppt(t,e){t.f=e}function bpt(t,e){t.a=e}function ww(t,e){t.b=e}function oM(t,e){t.d=e}function TC(t,e){t.i=e}function aR(t,e){t.o=e}function wpt(t,e){t.r=e}function vpt(t,e){t.a=e}function oR(t,e){t.b=e}function vw(t,e){t.e=e}function Ott(t,e){t.f=e}function CC(t,e){t.g=e}function vx(t,e){t.e=e}function mpt(t,e){t.f=e}function Zk(t,e){t.f=e}function Ptt(t,e){t.n=e}function Tg(t,e){t.a=e}function ypt(t,e){t.a=e}function O3(t,e){t.c=e}function Ftt(t,e){t.c=e}function Ntt(t,e){t.d=e}function cR(t,e){t.e=e}function uR(t,e){t.g=e}function Btt(t,e){t.a=e}function Jk(t,e){t.c=e}function _C(t,e){t.d=e}function xpt(t,e){t.e=e}function Rtt(t,e){t.f=e}function jtt(t,e){t.j=e}function $tt(t,e){t.a=e}function kpt(t,e){t.b=e}function vc(t,e){t.a=e}function lR(t){t.b=t.a}function ztt(t){t.c=t.d.d}function mx(t){this.d=t}function Cg(t){this.a=t}function Sm(t){this.a=t}function cM(t){this.a=t}function v1(t){this.a=t}function yx(t){this.a=t}function qtt(t){this.a=t}function hR(t){this.a=t}function P3(t){this.a=t}function uM(t){this.a=t}function Am(t){this.a=t}function fR(t){this.a=t}function m1(t){this.a=t}function y(t){this.a=t}function g(t){this.a=t}function x(t){this.b=t}function T(t){this.b=t}function L(t){this.b=t}function O(t){this.a=t}function P(t){this.a=t}function $(t){this.a=t}function q(t){this.c=t}function S(t){this.c=t}function V(t){this.c=t}function Y(t){this.a=t}function rt(t){this.a=t}function ot(t){this.a=t}function ht(t){this.a=t}function dt(t){this.a=t}function Lt(t){this.a=t}function kt(t){this.a=t}function Dt(t){this.a=t}function Pt(t){this.a=t}function $t(t){this.a=t}function Zt(t){this.a=t}function Yt(t){this.a=t}function qt(t){this.a=t}function ne(t){this.a=t}function Gt(t){this.a=t}function ge(t){this.a=t}function be(t){this.a=t}function ie(t){this.a=t}function Fe(t){this.a=t}function we(t){this.a=t}function bn(t){this.a=t}function ze(t){this.a=t}function Ge(t){this.a=t}function En(t){this.a=t}function In(t){this.a=t}function Yn(t){this.a=t}function Sn(t){this.a=t}function Wn(t){this.a=t}function rr(t){this.a=t}function wr(t){this.a=t}function ur(t){this.a=t}function er(t){this.a=t}function vn(t){this.a=t}function gr(t){this.a=t}function fr(t){this.a=t}function Jr(t){this.a=t}function vi(t){this.a=t}function Xs(t){this.a=t}function Ea(t){this.a=t}function Ci(t){this.a=t}function hi(t){this.a=t}function gs(t){this.a=t}function qi(t){this.a=t}function Si(t){this.a=t}function Ui(t){this.a=t}function Va(t){this.e=t}function Qs(t){this.a=t}function qs(t){this.a=t}function Tr(t){this.a=t}function Qt(t){this.a=t}function jn(t){this.a=t}function Sr(t){this.a=t}function ir(t){this.a=t}function sr(t){this.a=t}function Ia(t){this.a=t}function $r(t){this.a=t}function Yi(t){this.a=t}function Fo(t){this.a=t}function Pc(t){this.a=t}function Za(t){this.a=t}function mc(t){this.a=t}function Ta(t){this.a=t}function Ja(t){this.a=t}function ml(t){this.a=t}function qf(t){this.a=t}function Cp(t){this.a=t}function _p(t){this.a=t}function Hf(t){this.a=t}function _g(t){this.a=t}function cd(t){this.a=t}function mw(t){this.a=t}function Lm(t){this.a=t}function xx(t){this.a=t}function F3(t){this.a=t}function kx(t){this.a=t}function SC(t){this.a=t}function N3(t){this.a=t}function Hd(t){this.a=t}function y1(t){this.a=t}function Vd(t){this.a=t}function AC(t){this.a=t}function Yb(t){this.a=t}function dR(t){this.a=t}function Htt(t){this.a=t}function Vtt(t){this.a=t}function Gtt(t){this.a=t}function Utt(t){this.a=t}function Wtt(t){this.a=t}function Ytt(t){this.a=t}function Ktt(t){this.a=t}function t8(t){this.a=t}function lM(t){this.a=t}function LC(t){this.a=t}function gR(t){this.a=t}function pR(t){this.a=t}function Xtt(t){this.a=t}function Sp(t){this.a=t}function hM(t){this.a=t}function bR(t){this.a=t}function e8(t){this.c=t}function Ap(t){this.b=t}function Qtt(t){this.a=t}function S$t(t){this.a=t}function A$t(t){this.a=t}function L$t(t){this.a=t}function M$t(t){this.a=t}function D$t(t){this.a=t}function I$t(t){this.a=t}function O$t(t){this.a=t}function P$t(t){this.a=t}function F$t(t){this.a=t}function N$t(t){this.a=t}function B$t(t){this.a=t}function R$t(t){this.a=t}function j$t(t){this.a=t}function $$t(t){this.a=t}function z$t(t){this.a=t}function q$t(t){this.a=t}function H$t(t){this.a=t}function V$t(t){this.a=t}function G$t(t){this.a=t}function U$t(t){this.a=t}function W$t(t){this.a=t}function Y$t(t){this.a=t}function K$t(t){this.a=t}function Lp(t){this.a=t}function Ex(t){this.a=t}function X$t(t){this.a=t}function Q$t(t){this.a=t}function Z$t(t){this.a=t}function J$t(t){this.a=t}function tzt(t){this.a=t}function ezt(t){this.a=t}function nzt(t){this.a=t}function rzt(t){this.a=t}function izt(t){this.a=t}function szt(t){this.a=t}function azt(t){this.a=t}function ozt(t){this.a=t}function czt(t){this.a=t}function uzt(t){this.a=t}function lzt(t){this.a=t}function hzt(t){this.a=t}function wR(t){this.a=t}function fzt(t){this.a=t}function dzt(t){this.a=t}function gzt(t){this.a=t}function pzt(t){this.a=t}function bzt(t){this.a=t}function wzt(t){this.a=t}function vzt(t){this.a=t}function mzt(t){this.a=t}function yzt(t){this.a=t}function xzt(t){this.a=t}function kzt(t){this.a=t}function Ezt(t){this.a=t}function Tzt(t){this.a=t}function Czt(t){this.a=t}function _zt(t){this.a=t}function Szt(t){this.a=t}function Azt(t){this.a=t}function Lzt(t){this.a=t}function Mzt(t){this.a=t}function Dzt(t){this.a=t}function Izt(t){this.a=t}function Ozt(t){this.a=t}function Pzt(t){this.a=t}function Fzt(t){this.a=t}function Nzt(t){this.a=t}function Bzt(t){this.a=t}function Rzt(t){this.a=t}function jzt(t){this.a=t}function Ept(t){this.a=t}function Vi(t){this.b=t}function $zt(t){this.f=t}function Tpt(t){this.a=t}function zzt(t){this.a=t}function qzt(t){this.a=t}function Hzt(t){this.a=t}function Vzt(t){this.a=t}function Gzt(t){this.a=t}function Uzt(t){this.a=t}function Wzt(t){this.a=t}function Yzt(t){this.a=t}function fM(t){this.a=t}function Kzt(t){this.a=t}function Xzt(t){this.b=t}function Cpt(t){this.c=t}function vR(t){this.e=t}function Qzt(t){this.a=t}function mR(t){this.a=t}function yR(t){this.a=t}function Ztt(t){this.a=t}function Zzt(t){this.a=t}function Jzt(t){this.d=t}function _pt(t){this.a=t}function Spt(t){this.a=t}function yw(t){this.e=t}function WYe(){this.a=0}function B3(){IUt(this)}function he(){ant(this)}function _r(){Xu(this)}function Jtt(){NXt(this)}function tqt(){}function xw(){this.c=oLt}function YYe(t,e){e.Wb(t)}function eqt(t,e){t.b+=e}function nqt(t){t.b=new wet}function it(t){return t.e}function KYe(t){return t.a}function XYe(t){return t.a}function QYe(t){return t.a}function ZYe(t){return t.a}function JYe(t){return t.a}function tKe(){return null}function eKe(){return null}function nKe(){dbt(),dxn()}function rKe(t){t.b.tf(t.e)}function MC(t,e){t.b=e-t.b}function DC(t,e){t.a=e-t.a}function rqt(t,e){e.ad(t.a)}function iKe(t,e){Bs(e,t)}function sKe(t,e,n){t.Od(n,e)}function dM(t,e){t.e=e,e.b=t}function Apt(t){gd(),this.a=t}function iqt(t){gd(),this.a=t}function sqt(t){gd(),this.a=t}function Lpt(t){Wm(),this.a=t}function aqt(t){I8(),Out.be(t)}function Kb(){pWt.call(this)}function Mpt(){pWt.call(this)}function Dpt(){Kb.call(this)}function tet(){Kb.call(this)}function oqt(){Kb.call(this)}function gM(){Kb.call(this)}function Ou(){Kb.call(this)}function IC(){Kb.call(this)}function Or(){Kb.call(this)}function rh(){Kb.call(this)}function cqt(){Kb.call(this)}function lc(){Kb.call(this)}function uqt(){Kb.call(this)}function lqt(){this.a=this}function xR(){this.Bb|=256}function hqt(){this.b=new dUt}function Ipt(){Ipt=Z,new _r}function Opt(){Dpt.call(this)}function fqt(t,e){t.length=e}function kR(t,e){le(t.a,e)}function aKe(t,e){V4t(t.c,e)}function oKe(t,e){Fs(t.b,e)}function cKe(t,e){Jz(t.a,e)}function uKe(t,e){Wit(t.a,e)}function n8(t,e){mi(t.e,e)}function Tx(t){pq(t.c,t.b)}function lKe(t,e){t.kc().Nb(e)}function Ppt(t){this.a=chn(t)}function Hs(){this.a=new _r}function dqt(){this.a=new _r}function ER(){this.a=new he}function eet(){this.a=new he}function Fpt(){this.a=new he}function Ch(){this.a=new uw}function Xb(){this.a=new VJt}function Npt(){this.a=new H5}function Bpt(){this.a=new LVt}function gqt(){this.a=new wZt}function Rpt(){this.a=new OQt}function jpt(){this.a=new rYt}function pqt(){this.a=new he}function $pt(){this.a=new he}function bqt(){this.a=new he}function wqt(){this.a=new he}function vqt(){this.d=new he}function mqt(){this.a=new Hs}function yqt(){this.a=new _r}function xqt(){this.b=new _r}function kqt(){this.b=new he}function zpt(){this.e=new he}function Eqt(){this.d=new he}function Tqt(){this.a=new ttt}function Cqt(){he.call(this)}function qpt(){ER.call(this)}function _qt(){Ij.call(this)}function Sqt(){$pt.call(this)}function net(){OC.call(this)}function OC(){tqt.call(this)}function Cx(){tqt.call(this)}function Hpt(){Cx.call(this)}function Aqt(){lQt.call(this)}function Lqt(){lQt.call(this)}function Mqt(){Xpt.call(this)}function Dqt(){Xpt.call(this)}function Iqt(){Xpt.call(this)}function Oqt(){Qpt.call(this)}function Pu(){Zi.call(this)}function Vpt(){Em.call(this)}function Gpt(){Em.call(this)}function Pqt(){Xqt.call(this)}function Fqt(){Xqt.call(this)}function Nqt(){_r.call(this)}function Bqt(){_r.call(this)}function Rqt(){_r.call(this)}function jqt(){Hs.call(this)}function ret(){ine.call(this)}function $qt(){xR.call(this)}function iet(){x2t.call(this)}function set(){x2t.call(this)}function Upt(){_r.call(this)}function aet(){_r.call(this)}function zqt(){_r.call(this)}function Wpt(){Pk.call(this)}function qqt(){Pk.call(this)}function Hqt(){Wpt.call(this)}function Vqt(){XL.call(this)}function Gqt(t){Lee.call(this,t)}function Uqt(t){Lee.call(this,t)}function Ypt(t){nM.call(this,t)}function Kpt(t){mVt.call(this,t)}function hKe(t){Kpt.call(this,t)}function fKe(t){mVt.call(this,t)}function r8(){this.a=new Zi}function Xpt(){this.a=new Hs}function Qpt(){this.a=new _r}function Wqt(){this.a=new he}function Yqt(){this.j=new he}function Zpt(){this.a=new nB}function Kqt(){this.a=new VHt}function Xqt(){this.a=new cB}function oet(){oet=Z,Sut=new gHt}function cet(){cet=Z,_ut=new dHt}function PC(){PC=Z,Cut=new A}function TR(){TR=Z,Mut=new dWt}function dKe(t){Kpt.call(this,t)}function gKe(t){Kpt.call(this,t)}function Qqt(t){$rt.call(this,t)}function Zqt(t){$rt.call(this,t)}function Jqt(t){CYt.call(this,t)}function uet(t){Pgn.call(this,t)}function kw(t){Om.call(this,t)}function FC(t){NR.call(this,t)}function Jpt(t){NR.call(this,t)}function tHt(t){NR.call(this,t)}function Vo(t){jKt.call(this,t)}function eHt(t){Vo.call(this,t)}function _x(){Qk.call(this,{})}function CR(t){w8(),this.a=t}function NC(t){t.b=null,t.c=0}function pKe(t,e){t.e=e,nue(t,e)}function bKe(t,e){t.a=e,ypn(t)}function het(t,e,n){t.a[e.g]=n}function wKe(t,e,n){Ndn(n,t,e)}function vKe(t,e){HZe(e.i,t.n)}function nHt(t,e){Vun(t).td(e)}function mKe(t,e){return t*t/e}function rHt(t,e){return t.g-e.g}function yKe(t){return new EC(t)}function xKe(t){return new Um(t)}function _R(t){Vo.call(this,t)}function yo(t){Vo.call(this,t)}function iHt(t){Vo.call(this,t)}function fet(t){jKt.call(this,t)}function det(t){wyt(),this.a=t}function sHt(t){DYt(),this.a=t}function Mm(t){Vnt(),this.f=t}function get(t){Vnt(),this.f=t}function i8(t){Vo.call(this,t)}function Fn(t){Vo.call(this,t)}function No(t){Vo.call(this,t)}function aHt(t){Vo.call(this,t)}function Sx(t){Vo.call(this,t)}function je(t){return On(t),t}function Xt(t){return On(t),t}function pM(t){return On(t),t}function tbt(t){return On(t),t}function kKe(t){return On(t),t}function BC(t){return t.b==t.c}function Dm(t){return!!t&&t.b}function EKe(t){return!!t&&t.k}function TKe(t){return!!t&&t.j}function yl(t){On(t),this.a=t}function ebt(t){return g2(t),t}function RC(t){dvt(t,t.length)}function Sg(t){Vo.call(this,t)}function ud(t){Vo.call(this,t)}function pet(t){Vo.call(this,t)}function R3(t){Vo.call(this,t)}function jC(t){Vo.call(this,t)}function Nr(t){Vo.call(this,t)}function bet(t){j2t.call(this,t,0)}function wet(){Wvt.call(this,12,3)}function nbt(){nbt=Z,rEt=new pt}function oHt(){oHt=Z,nEt=new _}function SR(){SR=Z,cS=new mt}function cHt(){cHt=Z,Bge=new ft}function uHt(){throw it(new Or)}function rbt(){throw it(new Or)}function lHt(){throw it(new Or)}function CKe(){throw it(new Or)}function _Ke(){throw it(new Or)}function SKe(){throw it(new Or)}function vet(){this.a=Br(Lr(Ya))}function Ax(t){gd(),this.a=Lr(t)}function hHt(t,e){t.Td(e),e.Sd(t)}function AKe(t,e){t.a.ec().Mc(e)}function LKe(t,e,n){t.c.lf(e,n)}function ibt(t){yo.call(this,t)}function ld(t){Fn.call(this,t)}function Ag(){yx.call(this,"")}function $C(){yx.call(this,"")}function Mp(){yx.call(this,"")}function Im(){yx.call(this,"")}function sbt(t){yo.call(this,t)}function s8(t){T.call(this,t)}function met(t){Ej.call(this,t)}function fHt(t){s8.call(this,t)}function dHt(){xC.call(this,null)}function gHt(){xC.call(this,null)}function AR(){AR=Z,I8()}function pHt(){pHt=Z,Wge=u0n()}function bHt(t){return t.a?t.b:0}function MKe(t){return t.a?t.b:0}function DKe(t,e){return t.a-e.a}function IKe(t,e){return t.a-e.a}function OKe(t,e){return t.a-e.a}function LR(t,e){return Bmt(t,e)}function ct(t,e){return NQt(t,e)}function PKe(t,e){return e in t.a}function wHt(t,e){return t.f=e,t}function FKe(t,e){return t.b=e,t}function vHt(t,e){return t.c=e,t}function NKe(t,e){return t.g=e,t}function abt(t,e){return t.a=e,t}function obt(t,e){return t.f=e,t}function BKe(t,e){return t.k=e,t}function cbt(t,e){return t.a=e,t}function RKe(t,e){return t.e=e,t}function ubt(t,e){return t.e=e,t}function jKe(t,e){return t.f=e,t}function $Ke(t,e){t.b=!0,t.d=e}function zKe(t,e){t.b=new xo(e)}function qKe(t,e,n){e.td(t.a[n])}function HKe(t,e,n){e.we(t.a[n])}function VKe(t,e){return t.b-e.b}function GKe(t,e){return t.g-e.g}function UKe(t,e){return t.s-e.s}function WKe(t,e){return t?0:e-1}function mHt(t,e){return t?0:e-1}function YKe(t,e){return t?e-1:0}function KKe(t,e){return e.Yf(t)}function Ew(t,e){return t.b=e,t}function MR(t,e){return t.a=e,t}function Tw(t,e){return t.c=e,t}function Cw(t,e){return t.d=e,t}function _w(t,e){return t.e=e,t}function lbt(t,e){return t.f=e,t}function zC(t,e){return t.a=e,t}function a8(t,e){return t.b=e,t}function o8(t,e){return t.c=e,t}function Ze(t,e){return t.c=e,t}function kn(t,e){return t.b=e,t}function Je(t,e){return t.d=e,t}function tn(t,e){return t.e=e,t}function XKe(t,e){return t.f=e,t}function en(t,e){return t.g=e,t}function nn(t,e){return t.a=e,t}function rn(t,e){return t.i=e,t}function sn(t,e){return t.j=e,t}function yHt(t,e){return t.k=e,t}function QKe(t,e){return t.j=e,t}function ZKe(t,e){nb(),Uo(e,t)}function JKe(t,e,n){Wen(t.a,e,n)}function xHt(t){RXt.call(this,t)}function hbt(t){RXt.call(this,t)}function DR(t){Snt.call(this,t)}function kHt(t){bhn.call(this,t)}function Dp(t){Qw.call(this,t)}function EHt(t){prt.call(this,t)}function THt(t){prt.call(this,t)}function CHt(){b2t.call(this,"")}function Ca(){this.a=0,this.b=0}function _Ht(){this.b=0,this.a=0}function SHt(t,e){t.b=0,ry(t,e)}function tXe(t,e){t.c=e,t.b=!0}function AHt(t,e){return t.c._b(e)}function Vf(t){return t.e&&t.e()}function yet(t){return t?t.d:null}function LHt(t,e){return eie(t.b,e)}function eXe(t){return t?t.g:null}function nXe(t){return t?t.i:null}function Ip(t){return P0(t),t.o}function Sw(){Sw=Z,G4e=ydn()}function MHt(){MHt=Z,na=I0n()}function c8(){c8=Z,aLt=kdn()}function DHt(){DHt=Z,L5e=xdn()}function fbt(){fbt=Z,pc=wpn()}function dbt(){dbt=Z,Ab=K8()}function IHt(){throw it(new Or)}function OHt(){throw it(new Or)}function PHt(){throw it(new Or)}function FHt(){throw it(new Or)}function NHt(){throw it(new Or)}function BHt(){throw it(new Or)}function IR(t){this.a=new Lx(t)}function gbt(t){Ihe(),_xn(this,t)}function Op(t){this.a=new Ynt(t)}function j3(t,e){for(;t.ye(e););}function pbt(t,e){for(;t.sd(e););}function $3(t,e){return t.a+=e,t}function xet(t,e){return t.a+=e,t}function Lg(t,e){return t.a+=e,t}function Aw(t,e){return t.a+=e,t}function qC(t){return Vp(t),t.a}function OR(t){return t.b!=t.d.c}function RHt(t){return t.l|t.m<<22}function bbt(t,e){return t.d[e.p]}function jHt(t,e){return avn(t,e)}function wbt(t,e,n){t.splice(e,n)}function $Ht(t){t.c?Eue(t):Tue(t)}function PR(t){this.a=0,this.b=t}function zHt(){this.a=new vI(m_t)}function qHt(){this.b=new vI(s_t)}function HHt(){this.b=new vI(Zht)}function VHt(){this.b=new vI(Zht)}function GHt(){throw it(new Or)}function UHt(){throw it(new Or)}function WHt(){throw it(new Or)}function YHt(){throw it(new Or)}function KHt(){throw it(new Or)}function XHt(){throw it(new Or)}function QHt(){throw it(new Or)}function ZHt(){throw it(new Or)}function JHt(){throw it(new Or)}function tVt(){throw it(new Or)}function rXe(){throw it(new lc)}function iXe(){throw it(new lc)}function bM(t){this.a=new eVt(t)}function eVt(t){pcn(this,t,p0n())}function wM(t){return!t||kXt(t)}function vM(t){return Y1[t]!=-1}function sXe(){ZH!=0&&(ZH=0),JH=-1}function nVt(){Tut==null&&(Tut=[])}function aXe(t,e){tat(Wt(t.a),e)}function oXe(t,e){tat(Wt(t.a),e)}function mM(t,e){K3.call(this,t,e)}function u8(t,e){mM.call(this,t,e)}function vbt(t,e){this.b=t,this.c=e}function rVt(t,e){this.b=t,this.a=e}function iVt(t,e){this.a=t,this.b=e}function sVt(t,e){this.a=t,this.b=e}function aVt(t,e){this.a=t,this.b=e}function oVt(t,e){this.a=t,this.b=e}function cVt(t,e){this.a=t,this.b=e}function uVt(t,e){this.a=t,this.b=e}function lVt(t,e){this.a=t,this.b=e}function hVt(t,e){this.a=t,this.b=e}function fVt(t,e){this.b=t,this.a=e}function dVt(t,e){this.b=t,this.a=e}function gVt(t,e){this.b=t,this.a=e}function pVt(t,e){this.b=t,this.a=e}function Vr(t,e){this.f=t,this.g=e}function l8(t,e){this.e=t,this.d=e}function Lw(t,e){this.g=t,this.i=e}function ket(t,e){this.a=t,this.b=e}function bVt(t,e){this.a=t,this.f=e}function wVt(t,e){this.b=t,this.c=e}function cXe(t,e){this.a=t,this.b=e}function vVt(t,e){this.a=t,this.b=e}function Eet(t,e){this.a=t,this.b=e}function mVt(t){A2t(t.dc()),this.c=t}function FR(t){this.b=u(Lr(t),83)}function yVt(t){this.a=u(Lr(t),83)}function Om(t){this.a=u(Lr(t),15)}function xVt(t){this.a=u(Lr(t),15)}function NR(t){this.b=u(Lr(t),47)}function BR(){this.q=new b.Date}function Gd(){Gd=Z,vEt=new Ct}function h8(){h8=Z,a7=new Ot}function HC(t){return t.f.c+t.g.c}function yM(t,e){return t.b.Hc(e)}function kVt(t,e){return t.b.Ic(e)}function EVt(t,e){return t.b.Qc(e)}function TVt(t,e){return t.b.Hc(e)}function CVt(t,e){return t.c.uc(e)}function I0(t,e){return t.a._b(e)}function _Vt(t,e){return yi(t.c,e)}function SVt(t,e){return Tl(t.b,e)}function AVt(t,e){return t>e&&e0}function Cet(t,e){return yc(t,e)<0}function KC(t,e){return t.a.get(e)}function xXe(t,e){return e.split(t)}function WVt(t,e){return Tl(t.e,e)}function _bt(t){return On(t),!1}function WR(t){_n.call(this,t,21)}function kXe(t,e){TQt.call(this,t,e)}function YR(t,e){Vr.call(this,t,e)}function _et(t,e){Vr.call(this,t,e)}function Sbt(t){ort(),CYt.call(this,t)}function Abt(t,e){AKt(t,t.length,e)}function CM(t,e){rXt(t,t.length,e)}function EXe(t,e,n){e.ud(t.a.Ge(n))}function TXe(t,e,n){e.we(t.a.Fe(n))}function CXe(t,e,n){e.td(t.a.Kb(n))}function _Xe(t,e,n){t.Mb(n)&&e.td(n)}function XC(t,e,n){t.splice(e,0,n)}function SXe(t,e){return Nu(t.e,e)}function KR(t,e){this.d=t,this.e=e}function YVt(t,e){this.b=t,this.a=e}function KVt(t,e){this.b=t,this.a=e}function Lbt(t,e){this.b=t,this.a=e}function XVt(t,e){this.a=t,this.b=e}function QVt(t,e){this.a=t,this.b=e}function ZVt(t,e){this.a=t,this.b=e}function JVt(t,e){this.a=t,this.b=e}function Dx(t,e){this.a=t,this.b=e}function Mbt(t,e){this.b=t,this.a=e}function Dbt(t,e){this.b=t,this.a=e}function XR(t,e){Vr.call(this,t,e)}function QR(t,e){Vr.call(this,t,e)}function Ibt(t,e){Vr.call(this,t,e)}function Obt(t,e){Vr.call(this,t,e)}function z3(t,e){Vr.call(this,t,e)}function Aet(t,e){Vr.call(this,t,e)}function Let(t,e){Vr.call(this,t,e)}function Met(t,e){Vr.call(this,t,e)}function ZR(t,e){Vr.call(this,t,e)}function Pbt(t,e){Vr.call(this,t,e)}function Det(t,e){Vr.call(this,t,e)}function _M(t,e){Vr.call(this,t,e)}function JR(t,e){Vr.call(this,t,e)}function Iet(t,e){Vr.call(this,t,e)}function QC(t,e){Vr.call(this,t,e)}function Fbt(t,e){Vr.call(this,t,e)}function ms(t,e){Vr.call(this,t,e)}function tj(t,e){Vr.call(this,t,e)}function tGt(t,e){this.a=t,this.b=e}function eGt(t,e){this.a=t,this.b=e}function nGt(t,e){this.a=t,this.b=e}function rGt(t,e){this.a=t,this.b=e}function iGt(t,e){this.a=t,this.b=e}function sGt(t,e){this.a=t,this.b=e}function aGt(t,e){this.a=t,this.b=e}function oGt(t,e){this.a=t,this.b=e}function cGt(t,e){this.a=t,this.b=e}function Nbt(t,e){this.b=t,this.a=e}function uGt(t,e){this.b=t,this.a=e}function lGt(t,e){this.b=t,this.a=e}function hGt(t,e){this.b=t,this.a=e}function g8(t,e){this.c=t,this.d=e}function fGt(t,e){this.e=t,this.d=e}function dGt(t,e){this.a=t,this.b=e}function gGt(t,e){this.b=e,this.c=t}function ej(t,e){Vr.call(this,t,e)}function SM(t,e){Vr.call(this,t,e)}function Oet(t,e){Vr.call(this,t,e)}function ZC(t,e){Vr.call(this,t,e)}function Bbt(t,e){Vr.call(this,t,e)}function Pet(t,e){Vr.call(this,t,e)}function Fet(t,e){Vr.call(this,t,e)}function AM(t,e){Vr.call(this,t,e)}function Rbt(t,e){Vr.call(this,t,e)}function Net(t,e){Vr.call(this,t,e)}function JC(t,e){Vr.call(this,t,e)}function jbt(t,e){Vr.call(this,t,e)}function t9(t,e){Vr.call(this,t,e)}function e9(t,e){Vr.call(this,t,e)}function Fm(t,e){Vr.call(this,t,e)}function Bet(t,e){Vr.call(this,t,e)}function Ret(t,e){Vr.call(this,t,e)}function $bt(t,e){Vr.call(this,t,e)}function n9(t,e){Vr.call(this,t,e)}function jet(t,e){Vr.call(this,t,e)}function nj(t,e){Vr.call(this,t,e)}function LM(t,e){Vr.call(this,t,e)}function MM(t,e){Vr.call(this,t,e)}function Ix(t,e){Vr.call(this,t,e)}function $et(t,e){Vr.call(this,t,e)}function zbt(t,e){Vr.call(this,t,e)}function zet(t,e){Vr.call(this,t,e)}function qet(t,e){Vr.call(this,t,e)}function qbt(t,e){Vr.call(this,t,e)}function Het(t,e){Vr.call(this,t,e)}function Vet(t,e){Vr.call(this,t,e)}function Get(t,e){Vr.call(this,t,e)}function Uet(t,e){Vr.call(this,t,e)}function Hbt(t,e){Vr.call(this,t,e)}function pGt(t,e){this.b=t,this.a=e}function bGt(t,e){this.a=t,this.b=e}function wGt(t,e){this.a=t,this.b=e}function vGt(t,e){this.a=t,this.b=e}function mGt(t,e){this.a=t,this.b=e}function Vbt(t,e){Vr.call(this,t,e)}function Gbt(t,e){Vr.call(this,t,e)}function yGt(t,e){this.b=t,this.d=e}function Ubt(t,e){Vr.call(this,t,e)}function Wbt(t,e){Vr.call(this,t,e)}function xGt(t,e){this.a=t,this.b=e}function kGt(t,e){this.a=t,this.b=e}function rj(t,e){Vr.call(this,t,e)}function r9(t,e){Vr.call(this,t,e)}function Ybt(t,e){Vr.call(this,t,e)}function Kbt(t,e){Vr.call(this,t,e)}function Xbt(t,e){Vr.call(this,t,e)}function Wet(t,e){Vr.call(this,t,e)}function Qbt(t,e){Vr.call(this,t,e)}function Yet(t,e){Vr.call(this,t,e)}function ij(t,e){Vr.call(this,t,e)}function Ket(t,e){Vr.call(this,t,e)}function Xet(t,e){Vr.call(this,t,e)}function DM(t,e){Vr.call(this,t,e)}function Qet(t,e){Vr.call(this,t,e)}function Zbt(t,e){Vr.call(this,t,e)}function IM(t,e){Vr.call(this,t,e)}function Jbt(t,e){Vr.call(this,t,e)}function AXe(t,e){return Nu(t.c,e)}function LXe(t,e){return Nu(e.b,t)}function MXe(t,e){return-t.b.Je(e)}function t2t(t,e){return Nu(t.g,e)}function OM(t,e){Vr.call(this,t,e)}function Ox(t,e){Vr.call(this,t,e)}function EGt(t,e){this.a=t,this.b=e}function TGt(t,e){this.a=t,this.b=e}function $e(t,e){this.a=t,this.b=e}function i9(t,e){Vr.call(this,t,e)}function s9(t,e){Vr.call(this,t,e)}function PM(t,e){Vr.call(this,t,e)}function Zet(t,e){Vr.call(this,t,e)}function sj(t,e){Vr.call(this,t,e)}function a9(t,e){Vr.call(this,t,e)}function Jet(t,e){Vr.call(this,t,e)}function aj(t,e){Vr.call(this,t,e)}function q3(t,e){Vr.call(this,t,e)}function FM(t,e){Vr.call(this,t,e)}function o9(t,e){Vr.call(this,t,e)}function c9(t,e){Vr.call(this,t,e)}function NM(t,e){Vr.call(this,t,e)}function oj(t,e){Vr.call(this,t,e)}function H3(t,e){Vr.call(this,t,e)}function cj(t,e){Vr.call(this,t,e)}function CGt(t,e){this.a=t,this.b=e}function _Gt(t,e){this.a=t,this.b=e}function SGt(t,e){this.a=t,this.b=e}function AGt(t,e){this.a=t,this.b=e}function LGt(t,e){this.a=t,this.b=e}function MGt(t,e){this.a=t,this.b=e}function fa(t,e){this.a=t,this.b=e}function uj(t,e){Vr.call(this,t,e)}function DGt(t,e){this.a=t,this.b=e}function IGt(t,e){this.a=t,this.b=e}function OGt(t,e){this.a=t,this.b=e}function PGt(t,e){this.a=t,this.b=e}function FGt(t,e){this.a=t,this.b=e}function NGt(t,e){this.a=t,this.b=e}function BGt(t,e){this.b=t,this.a=e}function RGt(t,e){this.b=t,this.a=e}function jGt(t,e){this.b=t,this.a=e}function $Gt(t,e){this.b=t,this.a=e}function zGt(t,e){this.a=t,this.b=e}function qGt(t,e){this.a=t,this.b=e}function DXe(t,e){own(t.a,u(e,56))}function HGt(t,e){mon(t.a,u(e,11))}function IXe(t,e){return k8(),e!=t}function VGt(){return pHt(),new Wge}function GGt(){_rt(),this.b=new Hs}function UGt(){kq(),this.a=new Hs}function WGt(){Uvt(),evt.call(this)}function Px(t,e){Vr.call(this,t,e)}function YGt(t,e){this.a=t,this.b=e}function KGt(t,e){this.a=t,this.b=e}function lj(t,e){this.a=t,this.b=e}function XGt(t,e){this.a=t,this.b=e}function QGt(t,e){this.a=t,this.b=e}function ZGt(t,e){this.a=t,this.b=e}function JGt(t,e){this.d=t,this.b=e}function e2t(t,e){this.d=t,this.e=e}function tUt(t,e){this.f=t,this.c=e}function BM(t,e){this.b=t,this.c=e}function n2t(t,e){this.i=t,this.g=e}function eUt(t,e){this.e=t,this.a=e}function nUt(t,e){this.a=t,this.b=e}function r2t(t,e){t.i=null,fz(t,e)}function OXe(t,e){t&&ki(dP,t,e)}function rUt(t,e){return ist(t.a,e)}function hj(t){return XD(t.c,t.b)}function ec(t){return t?t.dd():null}function Vt(t){return t??null}function Nm(t){return typeof t===b6}function Bm(t){return typeof t===Nxt}function ra(t){return typeof t===Vat}function Np(t,e){return t.Hd().Xb(e)}function fj(t,e){return Kcn(t.Kc(),e)}function Dw(t,e){return yc(t,e)==0}function PXe(t,e){return yc(t,e)>=0}function u9(t,e){return yc(t,e)!=0}function FXe(t){return""+(On(t),t)}function RM(t,e){return t.substr(e)}function iUt(t){return cl(t),t.d.gc()}function tnt(t){return Dbn(t,t.c),t}function dj(t){return k9(t==null),t}function l9(t,e){return t.a+=""+e,t}function go(t,e){return t.a+=""+e,t}function h9(t,e){return t.a+=""+e,t}function hc(t,e){return t.a+=""+e,t}function Gr(t,e){return t.a+=""+e,t}function i2t(t,e){return t.a+=""+e,t}function sUt(t,e){fs(t,e,t.a,t.a.a)}function Zb(t,e){fs(t,e,t.c.b,t.c)}function NXe(t,e,n){gae(e,Wst(t,n))}function BXe(t,e,n){gae(e,Wst(t,n))}function RXe(t,e){Mon(new nr(t),e)}function aUt(t,e){t.q.setTime(Yw(e))}function oUt(t,e){lvt.call(this,t,e)}function cUt(t,e){lvt.call(this,t,e)}function ent(t,e){lvt.call(this,t,e)}function uUt(t){Xu(this),Y9(this,t)}function s2t(t){return An(t,0),null}function Gf(t){return t.a=0,t.b=0,t}function lUt(t,e){return t.a=e.g+1,t}function jXe(t,e){return t.j[e.p]==2}function a2t(t){return xnn(u(t,79))}function hUt(){hUt=Z,zpe=Wr(lst())}function fUt(){fUt=Z,i2e=Wr(Yce())}function dUt(){this.b=new Lx(ty(12))}function gUt(){this.b=0,this.a=!1}function pUt(){this.b=0,this.a=!1}function f9(t){this.a=t,pC.call(this)}function bUt(t){this.a=t,pC.call(this)}function mn(t,e){Ps.call(this,t,e)}function nnt(t,e){qm.call(this,t,e)}function V3(t,e){n2t.call(this,t,e)}function rnt(t,e){tE.call(this,t,e)}function wUt(t,e){jM.call(this,t,e)}function ii(t,e){GR(),ki(dU,t,e)}function int(t,e){return Pl(t.a,0,e)}function vUt(t,e){return t.a.a.a.cc(e)}function mUt(t,e){return Vt(t)===Vt(e)}function $Xe(t,e){return Ms(t.a,e.a)}function zXe(t,e){return pu(t.a,e.a)}function qXe(t,e){return tXt(t.a,e.a)}function hd(t,e){return t.indexOf(e)}function Iw(t,e){return t==e?0:t?1:-1}function gj(t){return t<10?"0"+t:""+t}function HXe(t){return Lr(t),new f9(t)}function yUt(t){return iu(t.l,t.m,t.h)}function p8(t){return ps((On(t),t))}function VXe(t){return ps((On(t),t))}function xUt(t,e){return pu(t.g,e.g)}function Bo(t){return typeof t===Nxt}function GXe(t){return t==Lv||t==Fy}function UXe(t){return t==Lv||t==Py}function o2t(t){return Ro(t.b.b,t,0)}function kUt(t){this.a=VGt(),this.b=t}function EUt(t){this.a=VGt(),this.b=t}function WXe(t,e){return le(t.a,e),e}function YXe(t,e){return le(t.c,e),t}function TUt(t,e){return $l(t.a,e),t}function KXe(t,e){return df(),e.a+=t}function XXe(t,e){return df(),e.a+=t}function QXe(t,e){return df(),e.c+=t}function c2t(t,e){$8(t,0,t.length,e)}function O0(){kt.call(this,new a2)}function CUt(){Wj.call(this,0,0,0,0)}function Fx(){ah.call(this,0,0,0,0)}function xo(t){this.a=t.a,this.b=t.b}function Bp(t){return t==zh||t==Cf}function b8(t){return t==rg||t==ng}function _Ut(t){return t==n5||t==e5}function G3(t){return t!=G1&&t!=Tb}function xl(t){return t.Lg()&&t.Mg()}function SUt(t){return u$(u(t,118))}function pj(t){return $l(new Vs,t)}function AUt(t,e){return new tE(e,t)}function ZXe(t,e){return new tE(e,t)}function u2t(t,e,n){iz(t,e),sz(t,n)}function bj(t,e,n){tv(t,e),Jw(t,n)}function x1(t,e,n){ku(t,e),Eu(t,n)}function wj(t,e,n){V8(t,e),U8(t,n)}function vj(t,e,n){G8(t,e),W8(t,n)}function snt(t,e){aE(t,e),Y8(t,t.D)}function l2t(t){tUt.call(this,t,!0)}function LUt(t,e,n){J2t.call(this,t,e,n)}function Rp(t){rb(),Jcn.call(this,t)}function MUt(){YR.call(this,"Head",1)}function DUt(){YR.call(this,"Tail",3)}function ant(t){t.c=Nt(Qn,De,1,0,5,1)}function IUt(t){t.a=Nt(Qn,De,1,8,5,1)}function OUt(t){xu(t.xf(),new ur(t))}function U3(t){return t!=null?Hi(t):0}function JXe(t,e){return ey(e,T1(t))}function tQe(t,e){return ey(e,T1(t))}function eQe(t,e){return t[t.length]=e}function nQe(t,e){return t[t.length]=e}function h2t(t){return een(t.b.Kc(),t.a)}function rQe(t,e){return hz(srt(t.d),e)}function iQe(t,e){return hz(srt(t.g),e)}function sQe(t,e){return hz(srt(t.j),e)}function eo(t,e){Ps.call(this,t.b,e)}function Ow(t){Wj.call(this,t,t,t,t)}function f2t(t){return t.b&&Sat(t),t.a}function d2t(t){return t.b&&Sat(t),t.c}function aQe(t,e){$1||(t.b=e)}function ont(t,e,n){return ts(t,e,n),n}function PUt(t,e,n){ts(t.c[e.g],e.g,n)}function oQe(t,e,n){u(t.c,69).Xh(e,n)}function cQe(t,e,n){x1(n,n.i+t,n.j+e)}function uQe(t,e){Dr(Lc(t.a),YQt(e))}function lQe(t,e){Dr(al(t.a),KQt(e))}function d9(t){gi(),yw.call(this,t)}function hQe(t){return t==null?0:Hi(t)}function FUt(){FUt=Z,Dht=new i_(_ft)}function Pr(){Pr=Z,new NUt,new he}function NUt(){new _r,new _r,new _r}function g2t(){g2t=Z,Ipt(),iEt=new _r}function k1(){k1=Z,b.Math.log(2)}function ih(){ih=Z,p0=(qVt(),Q4e)}function fQe(){throw it(new Sg(kge))}function dQe(){throw it(new Sg(kge))}function gQe(){throw it(new Sg(Ege))}function pQe(){throw it(new Sg(Ege))}function BUt(t){this.a=t,Iwt.call(this,t)}function cnt(t){this.a=t,FR.call(this,t)}function unt(t){this.a=t,FR.call(this,t)}function Zs(t,e){$nt(t.c,t.c.length,e)}function Go(t){return t.ae?1:0}function jUt(t,e){return yc(t,e)>0?t:e}function iu(t,e,n){return{l:t,m:e,h:n}}function bQe(t,e){t.a!=null&&HGt(e,t.a)}function $Ut(t){t.a=new xt,t.c=new xt}function mj(t){this.b=t,this.a=new he}function zUt(t){this.b=new Ce,this.a=t}function b2t(t){cwt.call(this),this.a=t}function qUt(){YR.call(this,"Range",2)}function HUt(){l4t(),this.a=new vI(I7t)}function wQe(t,e){Lr(e),Q3(t).Jc(new st)}function vQe(t,e){return Fl(),e.n.b+=t}function mQe(t,e,n){return ki(t.g,n,e)}function yQe(t,e,n){return ki(t.k,n,e)}function xQe(t,e){return ki(t.a,e.a,e)}function W3(t,e,n){return M3t(e,n,t.c)}function w2t(t){return new $e(t.c,t.d)}function kQe(t){return new $e(t.c,t.d)}function nc(t){return new $e(t.a,t.b)}function VUt(t,e){return G4n(t.a,e,null)}function EQe(t){Oa(t,null),oa(t,null)}function GUt(t){Art(t,null),Lrt(t,null)}function UUt(){jM.call(this,null,null)}function WUt(){Sj.call(this,null,null)}function v2t(t){this.a=t,_r.call(this)}function TQe(t){this.b=(wn(),new q(t))}function yj(t){t.j=Nt(wEt,ee,310,0,0,1)}function CQe(t,e,n){t.c.Vc(e,u(n,133))}function _Qe(t,e,n){t.c.ji(e,u(n,133))}function YUt(t,e){xr(t),t.Gc(u(e,15))}function g9(t,e){return o4n(t.c,t.b,e)}function SQe(t,e){return new bWt(t.Kc(),e)}function lnt(t,e){return _un(t.Kc(),e)!=-1}function m2t(t,e){return t.a.Bc(e)!=null}function xj(t){return t.Ob()?t.Pb():null}function KUt(t){return Mh(t,0,t.length)}function _t(t,e){return t!=null&&gst(t,e)}function AQe(t,e){t.q.setHours(e),E_(t,e)}function XUt(t,e){t.c&&(Hwt(e),kQt(e))}function LQe(t,e,n){u(t.Kb(n),164).Nb(e)}function MQe(t,e,n){return R4n(t,e,n),n}function QUt(t,e,n){t.a=e^1502,t.b=n^Eot}function hnt(t,e,n){return t.a[e.g][n.g]}function E1(t,e){return t.a[e.c.p][e.p]}function DQe(t,e){return t.e[e.c.p][e.p]}function IQe(t,e){return t.c[e.c.p][e.p]}function OQe(t,e){return t.j[e.p]=q2n(e)}function PQe(t,e){return kmt(t.f,e.tg())}function FQe(t,e){return kmt(t.b,e.tg())}function NQe(t,e){return t.a0?e*e/t:e*e*100}function oZe(t,e){return t>0?e/(t*t):e*100}function cZe(t,e,n){return le(e,yie(t,n))}function uZe(t,e,n){V$(),t.Xe(e)&&n.td(t)}function m8(t,e,n){var r;r=t.Zc(e),r.Rb(n)}function jm(t,e,n){return t.a+=e,t.b+=n,t}function lZe(t,e,n){return t.a*=e,t.b*=n,t}function qM(t,e,n){return t.a-=e,t.b-=n,t}function H2t(t,e){return t.a=e.a,t.b=e.b,t}function Mj(t){return t.a=-t.a,t.b=-t.b,t}function AWt(t){this.c=t,this.a=1,this.b=1}function LWt(t){this.c=t,ku(t,0),Eu(t,0)}function MWt(t){Zi.call(this),V9(this,t)}function DWt(t){qat(),nqt(this),this.mf(t)}function IWt(t,e){YC(),jM.call(this,t,e)}function V2t(t,e){Mg(),Sj.call(this,t,e)}function OWt(t,e){Mg(),Sj.call(this,t,e)}function PWt(t,e){Mg(),V2t.call(this,t,e)}function kl(t,e,n){_l.call(this,t,e,n,2)}function vnt(t,e){ih(),Uj.call(this,t,e)}function FWt(t,e){ih(),vnt.call(this,t,e)}function G2t(t,e){ih(),vnt.call(this,t,e)}function NWt(t,e){ih(),G2t.call(this,t,e)}function U2t(t,e){ih(),Uj.call(this,t,e)}function BWt(t,e){ih(),U2t.call(this,t,e)}function RWt(t,e){ih(),Uj.call(this,t,e)}function hZe(t,e){return t.c.Fc(u(e,133))}function W2t(t,e,n){return Pq(TD(t,e),n)}function fZe(t,e,n){return e.Qk(t.e,t.c,n)}function dZe(t,e,n){return e.Rk(t.e,t.c,n)}function mnt(t,e){return Zp(t.e,u(e,49))}function gZe(t,e,n){n_(al(t.a),e,KQt(n))}function pZe(t,e,n){n_(Lc(t.a),e,YQt(n))}function Y2t(t,e){e.$modCount=t.$modCount}function m9(){m9=Z,HS=new Vi("root")}function y8(){y8=Z,pP=new Pqt,new Fqt}function jWt(){this.a=new Uw,this.b=new Uw}function K2t(){ine.call(this),this.Bb|=Ka}function $Wt(){Vr.call(this,"GROW_TREE",0)}function bZe(t){return t==null?null:P5n(t)}function wZe(t){return t==null?null:qgn(t)}function vZe(t){return t==null?null:$o(t)}function mZe(t){return t==null?null:$o(t)}function P0(t){t.o==null&&b2n(t)}function Re(t){return k9(t==null||Nm(t)),t}function ye(t){return k9(t==null||Bm(t)),t}function Br(t){return k9(t==null||ra(t)),t}function X2t(t){this.q=new b.Date(Yw(t))}function HM(t,e){this.c=t,l8.call(this,t,e)}function Dj(t,e){this.a=t,HM.call(this,t,e)}function yZe(t,e){this.d=t,ztt(this),this.b=e}function Q2t(t,e){Xrt.call(this,t),this.a=e}function Z2t(t,e){Xrt.call(this,t),this.a=e}function xZe(t){C3t.call(this,0,0),this.f=t}function J2t(t,e,n){q$.call(this,t,e,n,null)}function zWt(t,e,n){q$.call(this,t,e,n,null)}function kZe(t,e,n){return t.ue(e,n)<=0?n:e}function EZe(t,e,n){return t.ue(e,n)<=0?e:n}function TZe(t,e){return u(Xw(t.b,e),149)}function CZe(t,e){return u(Xw(t.c,e),229)}function ynt(t){return u(Ne(t.a,t.b),287)}function qWt(t){return new $e(t.c,t.d+t.a)}function HWt(t){return Fl(),_Ut(u(t,197))}function $m(){$m=Z,o7t=un((Al(),K2))}function _Ze(t,e){e.a?hvn(t,e):fnt(t.a,e.b)}function VWt(t,e){$1||le(t.a,e)}function SZe(t,e){return kM(),J8(e.d.i,t)}function AZe(t,e){return r6(),new Uue(e,t)}function dd(t,e){return sD(e,n6t),t.f=e,t}function twt(t,e,n){return n=Hl(t,e,3,n),n}function ewt(t,e,n){return n=Hl(t,e,6,n),n}function nwt(t,e,n){return n=Hl(t,e,9,n),n}function VM(t,e,n){++t.j,t.Ki(),Yrt(t,e,n)}function GWt(t,e,n){++t.j,t.Hi(e,t.oi(e,n))}function UWt(t,e,n){var r;r=t.Zc(e),r.Rb(n)}function WWt(t,e,n){return bxt(t.c,t.b,e,n)}function rwt(t,e){return(e&wi)%t.d.length}function Ps(t,e){Vi.call(this,t),this.a=e}function iwt(t,e){Cpt.call(this,t),this.a=e}function xnt(t,e){Cpt.call(this,t),this.a=e}function YWt(t,e){this.c=t,Qw.call(this,e)}function KWt(t,e){this.a=t,Xzt.call(this,e)}function GM(t,e){this.a=t,Xzt.call(this,e)}function XWt(t){this.a=(jl(t,ky),new Xc(t))}function QWt(t){this.a=(jl(t,ky),new Xc(t))}function UM(t){return!t.a&&(t.a=new at),t.a}function ZWt(t){return t>8?0:t+1}function LZe(t,e){return Nn(),t==e?0:t?1:-1}function swt(t,e,n){return zx(t,u(e,22),n)}function MZe(t,e,n){return t.apply(e,n)}function JWt(t,e,n){return t.a+=Mh(e,0,n),t}function awt(t,e){var n;return n=t.e,t.e=e,n}function DZe(t,e){var n;n=t[kot],n.call(t,e)}function IZe(t,e){var n;n=t[kot],n.call(t,e)}function zm(t,e){t.a.Vc(t.b,e),++t.b,t.c=-1}function tYt(t){Xu(t.e),t.d.b=t.d,t.d.a=t.d}function WM(t){t.b?WM(t.b):t.f.c.zc(t.e,t.d)}function OZe(t,e,n){Qb(),Att(t,e.Ce(t.a,n))}function PZe(t,e){return yet(Nie(t.a,e,!0))}function FZe(t,e){return yet(Bie(t.a,e,!0))}function ff(t,e){return LR(new Array(e),t)}function knt(t){return String.fromCharCode(t)}function NZe(t){return t==null?null:t.message}function eYt(){this.a=new he,this.b=new he}function nYt(){this.a=new H5,this.b=new hqt}function rYt(){this.b=new Ca,this.c=new he}function owt(){this.d=new Ca,this.e=new Ca}function cwt(){this.n=new Ca,this.o=new Ca}function Ij(){this.n=new Cx,this.i=new Fx}function iYt(){this.a=new XJ,this.b=new ZX}function sYt(){this.a=new he,this.d=new he}function aYt(){this.b=new Hs,this.a=new Hs}function oYt(){this.b=new _r,this.a=new _r}function cYt(){this.b=new qHt,this.a=new GQ}function uYt(){Ij.call(this),this.a=new Ca}function y9(t){oun.call(this,t,(U$(),jut))}function uwt(t,e,n,r){Wj.call(this,t,e,n,r)}function BZe(t,e,n){n!=null&&uz(e,Cst(t,n))}function RZe(t,e,n){n!=null&&lz(e,Cst(t,n))}function lwt(t,e,n){return n=Hl(t,e,11,n),n}function Li(t,e){return t.a+=e.a,t.b+=e.b,t}function ia(t,e){return t.a-=e.a,t.b-=e.b,t}function jZe(t,e){return t.n.a=(On(e),e+10)}function $Ze(t,e){return t.n.a=(On(e),e+10)}function zZe(t,e){return e==t||yE(mq(e),t)}function lYt(t,e){return ki(t.a,e,"")==null}function qZe(t,e){return kM(),!J8(e.d.i,t)}function HZe(t,e){Bp(t.f)?a2n(t,e):V0n(t,e)}function VZe(t,e){var n;return n=e.Hh(t.a),n}function qm(t,e){yo.call(this,J_+t+D2+e)}function Rx(t,e,n,r){fe.call(this,t,e,n,r)}function hwt(t,e,n,r){fe.call(this,t,e,n,r)}function hYt(t,e,n,r){hwt.call(this,t,e,n,r)}function fYt(t,e,n,r){r$.call(this,t,e,n,r)}function Ent(t,e,n,r){r$.call(this,t,e,n,r)}function fwt(t,e,n,r){r$.call(this,t,e,n,r)}function dYt(t,e,n,r){Ent.call(this,t,e,n,r)}function dwt(t,e,n,r){Ent.call(this,t,e,n,r)}function Cn(t,e,n,r){fwt.call(this,t,e,n,r)}function gYt(t,e,n,r){dwt.call(this,t,e,n,r)}function pYt(t,e,n,r){hvt.call(this,t,e,n,r)}function bYt(t,e,n){this.a=t,j2t.call(this,e,n)}function wYt(t,e,n){this.c=e,this.b=n,this.a=t}function GZe(t,e,n){return t.d=u(e.Kb(n),164)}function gwt(t,e){return t.Aj().Nh().Kh(t,e)}function pwt(t,e){return t.Aj().Nh().Ih(t,e)}function vYt(t,e){return On(t),Vt(t)===Vt(e)}function hn(t,e){return On(t),Vt(t)===Vt(e)}function Tnt(t,e){return yet(Nie(t.a,e,!1))}function Cnt(t,e){return yet(Bie(t.a,e,!1))}function UZe(t,e){return t.b.sd(new QVt(t,e))}function WZe(t,e){return t.b.sd(new ZVt(t,e))}function mYt(t,e){return t.b.sd(new JVt(t,e))}function bwt(t,e,n){return t.lastIndexOf(e,n)}function YZe(t,e,n){return Ms(t[e.b],t[n.b])}function KZe(t,e){return Jt(e,(Te(),DO),t)}function XZe(t,e){return pu(e.a.d.p,t.a.d.p)}function QZe(t,e){return pu(t.a.d.p,e.a.d.p)}function ZZe(t,e){return Ms(t.c-t.s,e.c-e.s)}function yYt(t){return t.c?Ro(t.c.a,t,0):-1}function JZe(t){return t<100?null:new Dp(t)}function jx(t){return t==Y2||t==g0||t==Gc}function xYt(t,e){return _t(e,15)&&Sue(t.c,e)}function tJe(t,e){$1||e&&(t.d=e)}function _nt(t,e){var n;return n=e,!!jyt(t,n)}function wwt(t,e){this.c=t,Jnt.call(this,t,e)}function kYt(t){this.c=t,ent.call(this,qq,0)}function EYt(t,e){sen.call(this,t,t.length,e)}function eJe(t,e,n){return u(t.c,69).lk(e,n)}function Oj(t,e,n){return u(t.c,69).mk(e,n)}function nJe(t,e,n){return fZe(t,u(e,332),n)}function vwt(t,e,n){return dZe(t,u(e,332),n)}function rJe(t,e,n){return xae(t,u(e,332),n)}function TYt(t,e,n){return egn(t,u(e,332),n)}function x9(t,e){return e==null?null:sy(t.b,e)}function mwt(t){return Bm(t)?(On(t),t):t.ke()}function Pj(t){return!isNaN(t)&&!isFinite(t)}function CYt(t){gd(),this.a=(wn(),new s8(t))}function YM(t){k8(),this.d=t,this.a=new B3}function sh(t,e,n){this.a=t,this.b=e,this.c=n}function _Yt(t,e,n){this.a=t,this.b=e,this.c=n}function SYt(t,e,n){this.d=t,this.b=n,this.a=e}function Snt(t){$Ut(this),Ah(this),Ua(this,t)}function Bu(t){ant(this),Pwt(this.c,0,t.Pc())}function AYt(t){Cl(t.a),Cte(t.c,t.b),t.b=null}function LYt(t){this.a=t,Gd(),Tu(Date.now())}function MYt(){MYt=Z,REt=new _,aV=new _}function Ant(){Ant=Z,LEt=new Ht,Yge=new Le}function DYt(){DYt=Z,n5e=Nt(Qn,De,1,0,5,1)}function IYt(){IYt=Z,y5e=Nt(Qn,De,1,0,5,1)}function ywt(){ywt=Z,x5e=Nt(Qn,De,1,0,5,1)}function gd(){gd=Z,new Apt((wn(),wn(),io))}function iJe(t){return U$(),Ur((Nte(),Qge),t)}function sJe(t){return O1(),Ur((ete(),rpe),t)}function aJe(t){return Gz(),Ur((cJt(),upe),t)}function oJe(t){return Q$(),Ur((uJt(),lpe),t)}function cJe(t){return Cq(),Ur((Kne(),hpe),t)}function uJe(t){return Kf(),Ur((ZJt(),gpe),t)}function lJe(t){return Qu(),Ur((JJt(),bpe),t)}function hJe(t){return yu(),Ur((tte(),vpe),t)}function fJe(t){return $q(),Ur((hUt(),zpe),t)}function dJe(t){return rv(),Ur((Rte(),Hpe),t)}function gJe(t){return u6(),Ur((jte(),Gpe),t)}function pJe(t){return c_(),Ur(($te(),Ype),t)}function bJe(t){return jR(),Ur(($Zt(),Kpe),t)}function wJe(t){return Z$(),Ur((lJt(),fbe),t)}function vJe(t){return q9(),Ur((nte(),Obe),t)}function mJe(t){return Wa(),Ur((bee(),Bbe),t)}function yJe(t){return nE(),Ur((Bte(),qbe),t)}function xJe(t){return iv(),Ur((rte(),Ybe),t)}function xwt(t,e){if(!t)throw it(new Fn(e))}function kJe(t){return Vn(),Ur((Bee(),Zbe),t)}function kwt(t){Wj.call(this,t.d,t.c,t.a,t.b)}function Lnt(t){Wj.call(this,t.d,t.c,t.a,t.b)}function Ewt(t,e,n){this.b=t,this.c=e,this.a=n}function Fj(t,e,n){this.b=t,this.a=e,this.c=n}function OYt(t,e,n){this.a=t,this.b=e,this.c=n}function Twt(t,e,n){this.a=t,this.b=e,this.c=n}function PYt(t,e,n){this.a=t,this.b=e,this.c=n}function Cwt(t,e,n){this.a=t,this.b=e,this.c=n}function FYt(t,e,n){this.b=t,this.a=e,this.c=n}function Nj(t,e,n){this.e=e,this.b=t,this.d=n}function EJe(t,e,n){return Qb(),t.a.Od(e,n),e}function Mnt(t){var e;return e=new Wu,e.e=t,e}function _wt(t){var e;return e=new vqt,e.b=t,e}function KM(){KM=Z,mV=new BK,yV=new RK}function df(){df=Z,f2e=new SX,d2e=new DN}function TJe(t){return Tz(),Ur((qte(),o2e),t)}function CJe(t){return I1(),Ur((Vte(),b2e),t)}function _Je(t){return Eq(),Ur((Rne(),T2e),t)}function SJe(t){return h6(),Ur(($ee(),C2e),t)}function AJe(t){return H$(),Ur((bJt(),_2e),t)}function LJe(t){return n6(),Ur((ite(),S2e),t)}function MJe(t){return b4(),Ur((hee(),v2e),t)}function DJe(t){return nv(),Ur((ote(),E2e),t)}function IJe(t){return oz(),Ur((ste(),A2e),t)}function OJe(t){return x2(),Ur((uee(),L2e),t)}function PJe(t){return LD(),Ur((fJt(),M2e),t)}function FJe(t){return d2(),Ur((ate(),I2e),t)}function NJe(t){return dq(),Ur((Vee(),O2e),t)}function BJe(t){return xD(),Ur((dJt(),P2e),t)}function RJe(t){return oI(),Ur((qee(),F2e),t)}function jJe(t){return kE(),Ur((zee(),N2e),t)}function $Je(t){return oo(),Ur((lre(),B2e),t)}function zJe(t){return eE(),Ur((ute(),R2e),t)}function qJe(t){return q0(),Ur((cte(),$2e),t)}function HJe(t){return I$(),Ur((wJt(),z2e),t)}function VJe(t){return dh(),Ur((fee(),q2e),t)}function GJe(t){return uq(),Ur((Hee(),rme),t)}function UJe(t){return Z9(),Ur((lte(),ime),t)}function WJe(t){return cy(),Ur((Gte(),sme),t)}function YJe(t){return so(),Ur((dte(),hme),t)}function KJe(t){return y4(),Ur((Bne(),ome),t)}function XJe(t){return V0(),Ur((fte(),cme),t)}function QJe(t){return CD(),Ur((pJt(),ume),t)}function ZJe(t){return yz(),Ur((hte(),fme),t)}function JJe(t){return u_(),Ur((lee(),ame),t)}function ttn(t){return pD(),Ur((gJt(),dme),t)}function etn(t){return cE(),Ur((pte(),gme),t)}function ntn(t){return vz(),Ur((bte(),pme),t)}function rtn(t){return Cz(),Ur((gte(),bme),t)}function itn(t){return ev(),Ur((wte(),Lme),t)}function stn(t){return $9(),Ur((mJt(),Pme),t)}function atn(t){return bd(),Ur((yJt(),zme),t)}function otn(t){return C1(),Ur((xJt(),Hme),t)}function ctn(t){return Uf(),Ur((vJt(),iye),t)}function utn(t){return Gw(),Ur((kJt(),hye),t)}function ltn(t){return wE(),Ur((zte(),fye),t)}function htn(t){return p_(),Ur((Gee(),gye),t)}function ftn(t){return T$(),Ur((CJt(),Aye),t)}function dtn(t){return pz(),Ur((TJt(),Pye),t)}function gtn(t){return A$(),Ur((EJt(),Lye),t)}function ptn(t){return Nz(),Ur((vte(),Nye),t)}function btn(t){return G$(),Ur((_Jt(),Bye),t)}function wtn(t){return HD(),Ur((mte(),Rye),t)}function vtn(t){return eq(),Ur((Hte(),Jye),t)}function mtn(t){return mz(),Ur((xte(),t3e),t)}function ytn(t){return Fz(),Ur((yte(),e3e),t)}function xtn(t){return AE(),Ur((pee(),x3e),t)}function ktn(t){return KD(),Ur((kte(),k3e),t)}function Etn(t){return zR(),Ur((RZt(),E3e),t)}function Ttn(t){return qR(),Ur((BZt(),C3e),t)}function Ctn(t){return bD(),Ur((AJt(),_3e),t)}function _tn(t){return uI(),Ur((dee(),S3e),t)}function Stn(t){return UC(),Ur((jZt(),H3e),t)}function Atn(t){return jD(),Ur((SJt(),V3e),t)}function Ltn(t){return Qf(),Ur((gee(),X3e),t)}function Mtn(t){return Ug(),Ur((jne(),Z3e),t)}function Dtn(t){return t0(),Ur((jee(),J3e),t)}function Itn(t){return hy(),Ur((Ree(),s4e),t)}function Otn(t){return ro(),Ur((fUt(),i2e),t)}function Ptn(t){return X8(),Ur((hJt(),r2e),t)}function Ftn(t){return ao(),Ur((wee(),y4e),t)}function Ntn(t){return M1(),Ur((Tte(),x4e),t)}function Btn(t){return W0(),Ur((Yte(),k4e),t)}function Rtn(t){return hq(),Ur((Wee(),E4e),t)}function jtn(t){return G0(),Ur((Ete(),C4e),t)}function $tn(t){return zl(),Ur((Wte(),S4e),t)}function ztn(t){return py(),Ur((Yne(),A4e),t)}function qtn(t){return l4(),Ur((vee(),L4e),t)}function Htn(t){return ua(),Ur((Oee(),M4e),t)}function Vtn(t){return Zu(),Ur((Uee(),D4e),t)}function Gtn(t){return Al(),Ur((Xte(),B4e),t)}function Utn(t){return ll(),Ur((hre(),R4e),t)}function Wtn(t){return ve(),Ur((mee(),I4e),t)}function Ytn(t){return jz(),Ur((Kte(),j4e),t)}function Ktn(t){return Sl(),Ur((Ute(),q4e),t)}function Xtn(t){return CE(),Ur(($ne(),e5e),t)}function Qtn(t,e){return On(t),t+(On(e),e)}function Ztn(t,e){return Gd(),Dr(Wt(t.a),e)}function Jtn(t,e){return Gd(),Dr(Wt(t.a),e)}function Dnt(t,e){this.c=t,this.a=e,this.b=e-t}function NYt(t,e,n){this.a=t,this.b=e,this.c=n}function Swt(t,e,n){this.a=t,this.b=e,this.c=n}function Awt(t,e,n){this.a=t,this.b=e,this.c=n}function BYt(t,e,n){this.a=t,this.b=e,this.c=n}function RYt(t,e,n){this.a=t,this.b=e,this.c=n}function Ig(t,e,n){this.e=t,this.a=e,this.c=n}function jYt(t,e,n){ih(),$vt.call(this,t,e,n)}function Int(t,e,n){ih(),Tvt.call(this,t,e,n)}function Lwt(t,e,n){ih(),Tvt.call(this,t,e,n)}function Mwt(t,e,n){ih(),Tvt.call(this,t,e,n)}function $Yt(t,e,n){ih(),Int.call(this,t,e,n)}function Dwt(t,e,n){ih(),Int.call(this,t,e,n)}function zYt(t,e,n){ih(),Dwt.call(this,t,e,n)}function qYt(t,e,n){ih(),Lwt.call(this,t,e,n)}function HYt(t,e,n){ih(),Mwt.call(this,t,e,n)}function XM(t,e){return Lr(t),Lr(e),new lVt(t,e)}function $x(t,e){return Lr(t),Lr(e),new nKt(t,e)}function ten(t,e){return Lr(t),Lr(e),new rKt(t,e)}function een(t,e){return Lr(t),Lr(e),new fVt(t,e)}function u(t,e){return k9(t==null||gst(t,e)),t}function x8(t){var e;return e=new he,oit(e,t),e}function nen(t){var e;return e=new Hs,oit(e,t),e}function VYt(t){var e;return e=new Bpt,xit(e,t),e}function QM(t){var e;return e=new Zi,xit(e,t),e}function ren(t){return!t.e&&(t.e=new he),t.e}function ien(t){return!t.c&&(t.c=new Tm),t.c}function le(t,e){return t.c[t.c.length]=e,!0}function GYt(t,e){this.c=t,this.b=e,this.a=!1}function Iwt(t){this.d=t,ztt(this),this.b=Xen(t.d)}function UYt(){this.a=";,;",this.b="",this.c=""}function sen(t,e,n){WKt.call(this,e,n),this.a=t}function WYt(t,e,n){this.b=t,oUt.call(this,e,n)}function Owt(t,e,n){this.c=t,KR.call(this,e,n)}function Pwt(t,e,n){n5t(n,0,t,e,n.length,!1)}function Wd(t,e,n,r,s){t.b=e,t.c=n,t.d=r,t.a=s}function aen(t,e){e&&(t.b=e,t.a=(Vp(e),e.a))}function Fwt(t,e,n,r,s){t.d=e,t.c=n,t.a=r,t.b=s}function Nwt(t){var e,n;e=t.b,n=t.c,t.b=n,t.c=e}function Bwt(t){var e,n;n=t.d,e=t.a,t.d=e,t.a=n}function Rwt(t){return Kp(fnn(Bo(t)?Lh(t):t))}function oen(t,e){return pu(uKt(t.d),uKt(e.d))}function cen(t,e){return e==(ve(),Bn)?t.c:t.d}function k8(){k8=Z,r_t=(ve(),Bn),CG=Hn}function YYt(){this.b=Xt(ye(Ie((Jf(),nlt))))}function KYt(t){return Qb(),Nt(Qn,De,1,t,5,1)}function uen(t){return new $e(t.c+t.b,t.d+t.a)}function len(t,e){return $R(),pu(t.d.p,e.d.p)}function Ont(t){return Zn(t.b!=0),lh(t,t.a.a)}function hen(t){return Zn(t.b!=0),lh(t,t.c.b)}function jwt(t,e){if(!t)throw it(new iHt(e))}function Bj(t,e){if(!t)throw it(new Fn(e))}function $wt(t,e,n){g8.call(this,t,e),this.b=n}function ZM(t,e,n){e2t.call(this,t,e),this.c=n}function XYt(t,e,n){See.call(this,e,n),this.d=t}function zwt(t){ywt(),Pk.call(this),this.th(t)}function QYt(t,e,n){this.a=t,V3.call(this,e,n)}function ZYt(t,e,n){this.a=t,V3.call(this,e,n)}function Rj(t,e,n){e2t.call(this,t,e),this.c=n}function JYt(){B8(),Mnn.call(this,(Pp(),Yh))}function tKt(t){return t!=null&&!tst(t,oA,cA)}function fen(t,e){return(uie(t)<<4|uie(e))&ys}function den(t,e){return c$(),kst(t,e),new SXt(t,e)}function Jb(t,e){var n;t.n&&(n=e,le(t.f,n))}function E8(t,e,n){var r;r=new Um(n),Yf(t,e,r)}function gen(t,e){var n;return n=t.c,syt(t,e),n}function qwt(t,e){return e<0?t.g=-1:t.g=e,t}function jj(t,e){return Zon(t),t.a*=e,t.b*=e,t}function eKt(t,e,n,r,s){t.c=e,t.d=n,t.b=r,t.a=s}function ri(t,e){return fs(t,e,t.c.b,t.c),!0}function Hwt(t){t.a.b=t.b,t.b.a=t.a,t.a=t.b=null}function Pnt(t){this.b=t,this.a=Rw(this.b.a).Ed()}function nKt(t,e){this.b=t,this.a=e,pC.call(this)}function rKt(t,e){this.a=t,this.b=e,pC.call(this)}function iKt(t,e){WKt.call(this,e,1040),this.a=t}function JM(t){return t==0||isNaN(t)?t:t<0?-1:1}function pen(t){return Ux(),e0(t)==es(tb(t))}function ben(t){return Ux(),tb(t)==es(e0(t))}function Bw(t,e){return d_(t,new g8(e.a,e.b))}function wen(t){return!Ga(t)&&t.c.i.c==t.d.i.c}function $j(t){var e;return e=t.n,t.a.b+e.d+e.a}function sKt(t){var e;return e=t.n,t.e.b+e.d+e.a}function Vwt(t){var e;return e=t.n,t.e.a+e.b+e.c}function aKt(t){return gi(),new Yd(0,t)}function ven(t){return t.a?t.a:grt(t)}function k9(t){if(!t)throw it(new i8(null))}function oKt(){oKt=Z,$ft=(wn(),new O(put))}function zj(){zj=Z,new z3t((oet(),Sut),(cet(),_ut))}function cKt(){cKt=Z,fEt=Nt(ja,ee,19,256,0,1)}function Fnt(t,e,n,r){b3t.call(this,t,e,n,r,0,0)}function men(t,e,n){return ki(t.b,u(n.b,17),e)}function yen(t,e,n){return ki(t.b,u(n.b,17),e)}function xen(t,e){return le(t,new $e(e.a,e.b))}function ken(t,e){return t.c=e)throw it(new Opt)}function inn(t,e,n){return ts(e,0,Ywt(e[0],n[0])),e}function snn(t,e,n){e.Ye(n,Xt(ye(tr(t.b,n)))*t.a)}function UKt(t,e,n){return k4(),Q8(t,e)&&Q8(t,n)}function S9(t){return Zu(),!t.Hc(sg)&&!t.Hc(Cb)}function e$(t){return new $e(t.c+t.b/2,t.d+t.a/2)}function Wnt(t,e){return e.kh()?Zp(t.b,u(e,49)):e}function lvt(t,e){this.e=t,this.d=e&64?e|md:e}function WKt(t,e){this.c=0,this.d=t,this.b=e|64|md}function n$(t){this.b=new Xc(11),this.a=(Z3(),t)}function Ynt(t){this.b=null,this.a=(Z3(),t||_Et)}function YKt(t){this.a=wse(t.a),this.b=new Bu(t.b)}function KKt(t){this.b=t,Nx.call(this,t),ZUt(this)}function XKt(t){this.b=t,$M.call(this,t),JUt(this)}function Gm(t,e,n){this.a=t,Rx.call(this,e,n,5,6)}function hvt(t,e,n,r){this.b=t,As.call(this,e,n,r)}function Js(t,e,n,r,s){Jrt.call(this,t,e,n,r,s,-1)}function A9(t,e,n,r,s){mD.call(this,t,e,n,r,s,-1)}function fe(t,e,n,r){As.call(this,t,e,n),this.b=r}function r$(t,e,n,r){ZM.call(this,t,e,n),this.b=r}function QKt(t){tUt.call(this,t,!1),this.a=!1}function ZKt(t,e){this.b=t,wtt.call(this,t.b),this.a=e}function JKt(t,e){Wm(),cXe.call(this,t,Dz(new yl(e)))}function i$(t,e){return gi(),new Cvt(t,e,0)}function Knt(t,e){return gi(),new Cvt(6,t,e)}function ann(t,e){return hn(t.substr(0,e.length),e)}function Tl(t,e){return ra(e)?wrt(t,e):!!Lo(t.f,e)}function ba(t,e){for(On(e);t.Ob();)e.td(t.Pb())}function X3(t,e,n){rb(),this.e=t,this.d=e,this.a=n}function Og(t,e,n,r){var s;s=t.i,s.i=e,s.a=n,s.b=r}function fvt(t){var e;for(e=t;e.f;)e=e.f;return e}function Hx(t){var e;return e=Q9(t),Zn(e!=null),e}function onn(t){var e;return e=Uln(t),Zn(e!=null),e}function C8(t,e){var n;return n=t.a.gc(),Emt(e,n),n-e}function dvt(t,e){var n;for(n=0;n0?b.Math.log(t/e):-100}function tXt(t,e){return yc(t,e)<0?-1:yc(t,e)>0?1:0}function vvt(t,e,n){return Gle(t,u(e,46),u(n,167))}function eXt(t,e){return u(cvt(Rw(t.a)).Xb(e),42).cd()}function bnn(t,e){return jon(e,t.length),new iKt(t,e)}function Jnt(t,e){this.d=t,nr.call(this,t),this.e=e}function jw(t){this.d=(On(t),t),this.a=0,this.c=qq}function mvt(t,e){yw.call(this,1),this.a=t,this.b=e}function nXt(t,e){return t.c?nXt(t.c,e):le(t.b,e),t}function wnn(t,e,n){var r;return r=Jm(t,e),Brt(t,e,n),r}function yvt(t,e){var n;return n=t.slice(0,e),Bmt(n,t)}function rXt(t,e,n){var r;for(r=0;r=t.g}function crt(t,e,n){var r;return r=mit(t,e,n),Y5t(t,r)}function Vx(t,e){var n;n=t.a.length,Jm(t,n),Brt(t,n,e)}function vXt(t,e){var n;n=console[t],n.call(console,e)}function mXt(t,e){var n;++t.j,n=t.Vi(),t.Ii(t.oi(n,e))}function Lnn(t,e,n){u(e.b,65),xu(e.a,new Swt(t,n,e))}function Tvt(t,e,n){vR.call(this,e),this.a=t,this.b=n}function Cvt(t,e,n){yw.call(this,t),this.a=e,this.b=n}function _vt(t,e,n){this.a=t,Cpt.call(this,e),this.b=n}function yXt(t,e,n){this.a=t,nmt.call(this,8,e,null,n)}function Mnn(t){this.a=(On(Yr),Yr),this.b=t,new Upt}function xXt(t){this.c=t,this.b=this.c.a,this.a=this.c.e}function Svt(t){this.c=t,this.b=t.a.d.a,Y2t(t.a.e,this)}function Cl(t){Rm(t.c!=-1),t.d.$c(t.c),t.b=t.c,t.c=-1}function D9(t){return b.Math.sqrt(t.a*t.a+t.b*t.b)}function zw(t,e){return T8(e,t.a.c.length),Ne(t.a,e)}function pd(t,e){return Vt(t)===Vt(e)||t!=null&&yi(t,e)}function Dnn(t){return 0>=t?new mbt:wcn(t-1)}function Inn(t){return s3?wrt(s3,t):!1}function kXt(t){return t?t.dc():!t.Kc().Ob()}function Na(t){return!t.a&&t.c?t.c.b:t.a}function Onn(t){return!t.a&&(t.a=new As(_b,t,4)),t.a}function qw(t){return!t.d&&(t.d=new As(ho,t,1)),t.d}function On(t){if(t==null)throw it(new IC);return t}function I9(t){t.c?t.c.He():(t.d=!0,Rwn(t))}function Vp(t){t.c?Vp(t.c):(w2(t),t.d=!0)}function EXt(t){Dvt(t.a),t.b=Nt(Qn,De,1,t.b.length,5,1)}function Pnn(t,e){return pu(e.j.c.length,t.j.c.length)}function Fnn(t,e){t.c<0||t.b.b=0?t.Bh(n):i5t(t,e)}function TXt(t){var e,n;return e=t.c.i.c,n=t.d.i.c,e==n}function Bnn(t){if(t.p!=4)throw it(new Ou);return t.e}function Rnn(t){if(t.p!=3)throw it(new Ou);return t.e}function jnn(t){if(t.p!=6)throw it(new Ou);return t.f}function $nn(t){if(t.p!=6)throw it(new Ou);return t.k}function znn(t){if(t.p!=3)throw it(new Ou);return t.j}function qnn(t){if(t.p!=4)throw it(new Ou);return t.j}function Avt(t){return!t.b&&(t.b=new mR(new aet)),t.b}function Hw(t){return t.c==-2&&Jk(t,agn(t.g,t.b)),t.c}function A8(t,e){var n;return n=rrt("",t),n.n=e,n.i=1,n}function Hnn(t,e){qnt(u(e.b,65),t),xu(e.a,new Jr(t))}function Vnn(t,e){Dr((!t.a&&(t.a=new GM(t,t)),t.a),e)}function CXt(t,e){this.b=t,Jnt.call(this,t,e),ZUt(this)}function _Xt(t,e){this.b=t,wwt.call(this,t,e),JUt(this)}function Lvt(t,e,n,r){Lw.call(this,t,e),this.d=n,this.a=r}function o$(t,e,n,r){Lw.call(this,t,n),this.a=e,this.f=r}function SXt(t,e){TQe.call(this,vcn(Lr(t),Lr(e))),this.a=e}function AXt(){N4t.call(this,O2,(DHt(),L5e)),f4n(this)}function LXt(){N4t.call(this,Bh,(c8(),aLt)),x3n(this)}function MXt(){Vr.call(this,"DELAUNAY_TRIANGULATION",0)}function Gnn(t){return String.fromCharCode.apply(null,t)}function ki(t,e,n){return ra(e)?ko(t,e,n):au(t.f,e,n)}function Mvt(t){return wn(),t?t.ve():(Z3(),Z3(),AEt)}function Unn(t,e,n){return i6(),n.pg(t,u(e.cd(),146))}function DXt(t,e){return zj(),new z3t(new fWt(t),new hWt(e))}function Wnn(t){return jl(t,Yat),J$(Pa(Pa(5,t),t/10|0))}function c$(){c$=Z,Age=new uet(lt(ct(P2,1),Hq,42,0,[]))}function IXt(t){return!t.d&&(t.d=new T(t.c.Cc())),t.d}function L8(t){return!t.a&&(t.a=new fHt(t.c.vc())),t.a}function OXt(t){return!t.b&&(t.b=new s8(t.c.ec())),t.b}function Xd(t,e){for(;e-- >0;)t=t<<1|(t<0?1:0);return t}function Fc(t,e){return Vt(t)===Vt(e)||t!=null&&yi(t,e)}function Ynn(t,e){return Nn(),u(e.b,19).ar&&++r,r}function N0(t){var e,n;return n=(e=new xw,e),H8(n,t),n}function drt(t){var e,n;return n=(e=new xw,e),j4t(n,t),n}function urn(t,e){var n;return n=tr(t.f,e),byt(e,n),null}function grt(t){var e;return e=ycn(t),e||null}function HXt(t){return!t.b&&(t.b=new fe(Ys,t,12,3)),t.b}function lrn(t){return t!=null&&yM(gU,t.toLowerCase())}function hrn(t,e){return Ms(Ru(t)*El(t),Ru(e)*El(e))}function frn(t,e){return Ms(Ru(t)*El(t),Ru(e)*El(e))}function drn(t,e){return Ms(t.d.c+t.d.b/2,e.d.c+e.d.b/2)}function grn(t,e){return Ms(t.g.c+t.g.b/2,e.g.c+e.g.b/2)}function VXt(t,e,n){n.a?Eu(t,e.b-t.f/2):ku(t,e.a-t.g/2)}function GXt(t,e,n,r){this.a=t,this.b=e,this.c=n,this.d=r}function UXt(t,e,n,r){this.a=t,this.b=e,this.c=n,this.d=r}function n2(t,e,n,r){this.e=t,this.a=e,this.c=n,this.d=r}function WXt(t,e,n,r){this.a=t,this.c=e,this.d=n,this.b=r}function YXt(t,e,n,r){ih(),$Jt.call(this,e,n,r),this.a=t}function KXt(t,e,n,r){ih(),$Jt.call(this,e,n,r),this.a=t}function XXt(t,e){this.a=t,yZe.call(this,t,u(t.d,15).Zc(e))}function prt(t){this.f=t,this.c=this.f.e,t.f>0&&cae(this)}function QXt(t,e,n,r){this.b=t,this.c=r,ent.call(this,e,n)}function ZXt(t){return Zn(t.b=0&&hn(t.substr(n,e.length),e)}function Gp(t,e,n,r,s,o,h){return new jrt(t.e,e,n,r,s,o,h)}function pQt(t,e,n,r,s,o){this.a=t,fit.call(this,e,n,r,s,o)}function bQt(t,e,n,r,s,o){this.a=t,fit.call(this,e,n,r,s,o)}function wQt(t,e){this.g=t,this.d=lt(ct(l0,1),Yg,10,0,[e])}function Pg(t,e){this.e=t,this.a=Qn,this.b=$ue(e),this.c=e}function vQt(t,e){Ij.call(this),Gmt(this),this.a=t,this.c=e}function aD(t,e,n,r){ts(t.c[e.g],n.g,r),ts(t.c[n.g],e.g,r)}function yrt(t,e,n,r){ts(t.c[e.g],e.g,n),ts(t.b[e.g],e.g,r)}function Nrn(){return pD(),lt(ct(Y9t,1),oe,376,0,[Sht,BO])}function Brn(){return xD(),lt(ct($Tt,1),oe,479,0,[jTt,WV])}function Rrn(){return LD(),lt(ct(BTt,1),oe,419,0,[GV,NTt])}function jrn(){return H$(),lt(ct(LTt,1),oe,422,0,[ATt,Alt])}function $rn(){return I$(),lt(ct(JTt,1),oe,420,0,[Hlt,ZTt])}function zrn(){return CD(),lt(ct(V9t,1),oe,421,0,[Tht,Cht])}function qrn(){return $9(),lt(ct(Ome,1),oe,523,0,[BS,NS])}function Hrn(){return Uf(),lt(ct(rye,1),oe,520,0,[Ky,mb])}function Vrn(){return bd(),lt(ct($me,1),oe,516,0,[zv,ep])}function Grn(){return C1(),lt(ct(qme,1),oe,515,0,[H2,H1])}function Urn(){return Gw(),lt(ct(lye,1),oe,455,0,[yb,r5])}function Wrn(){return A$(),lt(ct(v_t,1),oe,425,0,[qht,w_t])}function Yrn(){return T$(),lt(ct(b_t,1),oe,480,0,[zht,p_t])}function Krn(){return pz(),lt(ct(m_t,1),oe,495,0,[FG,D7])}function Xrn(){return G$(),lt(ct(x_t,1),oe,426,0,[y_t,Uht])}function Qrn(){return jD(),lt(ct(TSt,1),oe,429,0,[VG,ESt])}function Zrn(){return bD(),lt(ct(nSt,1),oe,430,0,[eft,qG])}function Jrn(){return Gz(),lt(ct(zEt,1),oe,428,0,[qut,$Et])}function tin(){return Q$(),lt(ct(HEt,1),oe,427,0,[qEt,Hut])}function ein(){return Z$(),lt(ct(w7t,1),oe,424,0,[tlt,gV])}function nin(){return X8(),lt(ct(n2e,1),oe,511,0,[yO,dlt])}function m$(t,e,n,r){return n>=0?t.jh(e,n,r):t.Sg(null,n,r)}function xrt(t){return t.b.b==0?t.a.$e():Ont(t.b)}function rin(t){if(t.p!=5)throw it(new Ou);return Ar(t.f)}function iin(t){if(t.p!=5)throw it(new Ou);return Ar(t.k)}function jvt(t){return Vt(t.a)===Vt((kit(),Bft))&&s4n(t),t.a}function mQt(t){this.a=u(Lr(t),271),this.b=(wn(),new I2t(t))}function yQt(t,e){vpt(this,new $e(t.a,t.b)),oR(this,QM(e))}function Gw(){Gw=Z,yb=new Wbt(y6,0),r5=new Wbt(x6,1)}function bd(){bd=Z,zv=new Gbt(x6,0),ep=new Gbt(y6,1)}function Uw(){gKe.call(this,new Lx(ty(12))),A2t(!0),this.a=2}function krt(t,e,n){gi(),yw.call(this,t),this.b=e,this.a=n}function $vt(t,e,n){ih(),vR.call(this,e),this.a=t,this.b=n}function xQt(t){Ij.call(this),Gmt(this),this.a=t,this.c=!0}function kQt(t){var e;e=t.c.d.b,t.b=e,t.a=t.c.d,e.a=t.c.d.b=t}function y$(t){var e;hcn(t.a),OUt(t.a),e=new er(t.a),p3t(e)}function sin(t,e){Due(t,!0),xu(t.e.wf(),new Ewt(t,!0,e))}function x$(t,e){return eJt(e),ccn(t,Nt(Cr,Xr,25,e,15,1),e)}function ain(t,e){return Ux(),t==es(e0(e))||t==es(tb(e))}function Nc(t,e){return e==null?ec(Lo(t.f,null)):KC(t.g,e)}function oin(t){return t.b==0?null:(Zn(t.b!=0),lh(t,t.a.a))}function ps(t){return Math.max(Math.min(t,wi),-2147483648)|0}function cin(t,e){var n=Iut[t.charCodeAt(0)];return n??t}function k$(t,e){return g$(t,"set1"),g$(e,"set2"),new vVt(t,e)}function uin(t,e){var n;return n=rcn(t.f,e),Li(Mj(n),t.f.d)}function P9(t,e){var n,r;return n=e,r=new zt,mhe(t,n,r),r.d}function Ert(t,e,n,r){var s;s=new uYt,e.a[n.g]=s,zx(t.b,r,s)}function zvt(t,e,n){var r;r=t.Yg(e),r>=0?t.sh(r,n):M5t(t,e,n)}function J3(t,e,n){C$(),t&&ki(Pft,t,e),t&&ki(dP,t,n)}function EQt(t,e,n){this.i=new he,this.b=t,this.g=e,this.a=n}function E$(t,e,n){this.c=new he,this.e=t,this.f=e,this.b=n}function qvt(t,e,n){this.a=new he,this.e=t,this.f=e,this.c=n}function TQt(t,e){yj(this),this.f=e,this.g=t,d$(this),this._d()}function oD(t,e){var n;n=t.q.getHours(),t.q.setDate(e),E_(t,n)}function CQt(t,e){var n;for(Lr(e),n=t.a;n;n=n.c)e.Od(n.g,n.i)}function _Qt(t){var e;return e=new IR(ty(t.length)),Oyt(e,t),e}function lin(t){function e(){}return e.prototype=t||{},new e}function hin(t,e){return ere(t,e)?(Jee(t),!0):!1}function B0(t,e){if(e==null)throw it(new IC);return cfn(t,e)}function fin(t){if(t.qe())return null;var e=t.n;return QH[e]}function cD(t){return t.Db>>16!=3?null:u(t.Cb,33)}function T1(t){return t.Db>>16!=9?null:u(t.Cb,33)}function SQt(t){return t.Db>>16!=6?null:u(t.Cb,79)}function AQt(t){return t.Db>>16!=7?null:u(t.Cb,235)}function LQt(t){return t.Db>>16!=7?null:u(t.Cb,160)}function es(t){return t.Db>>16!=11?null:u(t.Cb,33)}function MQt(t,e){var n;return n=t.Yg(e),n>=0?t.lh(n):Zst(t,e)}function DQt(t,e){var n;return n=new Wwt(e),Iae(n,t),new Bu(n)}function Hvt(t){var e;return e=t.d,e=t.si(t.f),Dr(t,e),e.Ob()}function IQt(t,e){return t.b+=e.b,t.c+=e.c,t.d+=e.d,t.a+=e.a,t}function Trt(t,e){return b.Math.abs(t)0}function OQt(){this.a=new O0,this.e=new Hs,this.g=0,this.i=0}function PQt(t){this.a=t,this.b=Nt(Mme,ee,1944,t.e.length,0,2)}function Crt(t,e,n){var r;r=xre(t,e,n),t.b=new gz(r.c.length)}function C1(){C1=Z,H2=new Vbt(Dot,0),H1=new Vbt("UP",1)}function T$(){T$=Z,zht=new Ybt(Y1e,0),p_t=new Ybt("FAN",1)}function C$(){C$=Z,Pft=new _r,dP=new _r,OXe(Uge,new JT)}function gin(t){if(t.p!=0)throw it(new Ou);return u9(t.f,0)}function pin(t){if(t.p!=0)throw it(new Ou);return u9(t.k,0)}function FQt(t){return t.Db>>16!=3?null:u(t.Cb,147)}function O8(t){return t.Db>>16!=6?null:u(t.Cb,235)}function Ym(t){return t.Db>>16!=17?null:u(t.Cb,26)}function NQt(t,e){var n=t.a=t.a||[];return n[e]||(n[e]=t.le(e))}function bin(t,e){var n;return n=t.a.get(e),n??new Array}function win(t,e){var n;n=t.q.getHours(),t.q.setMonth(e),E_(t,n)}function ko(t,e,n){return e==null?au(t.f,null,n):sv(t.g,e,n)}function F9(t,e,n,r,s,o){return new z0(t.e,e,t.aj(),n,r,s,o)}function uD(t,e,n){return t.a=Pl(t.a,0,e)+(""+n)+RM(t.a,e),t}function vin(t,e,n){return le(t.a,(c$(),kst(e,n),new Lw(e,n))),t}function Vvt(t){return M2t(t.c),t.e=t.a=t.c,t.c=t.c.c,++t.d,t.a.f}function BQt(t){return M2t(t.e),t.c=t.a=t.e,t.e=t.e.e,--t.d,t.a.f}function oa(t,e){t.d&&mu(t.d.e,t),t.d=e,t.d&&le(t.d.e,t)}function Oa(t,e){t.c&&mu(t.c.g,t),t.c=e,t.c&&le(t.c.g,t)}function Eo(t,e){t.c&&mu(t.c.a,t),t.c=e,t.c&&le(t.c.a,t)}function Uo(t,e){t.i&&mu(t.i.j,t),t.i=e,t.i&&le(t.i.j,t)}function RQt(t,e,n){this.a=e,this.c=t,this.b=(Lr(n),new Bu(n))}function jQt(t,e,n){this.a=e,this.c=t,this.b=(Lr(n),new Bu(n))}function $Qt(t,e){this.a=t,this.c=nc(this.a),this.b=new v$(e)}function min(t){var e;return w2(t),e=new Hs,Ri(t,new Ge(e))}function Km(t,e){if(t<0||t>e)throw it(new yo(Kxt+t+Xxt+e))}function Gvt(t,e){return MKt(t.a,e)?pvt(t,u(e,22).g,null):null}function yin(t){return qit(),Nn(),u(t.a,81).d.e!=0}function zQt(){zQt=Z,Dge=Wr((TR(),lt(ct(Mge,1),oe,538,0,[Mut])))}function qQt(){qQt=Z,wme=Ku(new Vs,(Wa(),Io),(ro(),xO))}function Uvt(){Uvt=Z,vme=Ku(new Vs,(Wa(),Io),(ro(),xO))}function HQt(){HQt=Z,yme=Ku(new Vs,(Wa(),Io),(ro(),xO))}function VQt(){VQt=Z,Fme=bi(new Vs,(Wa(),Io),(ro(),pS))}function Fl(){Fl=Z,Rme=bi(new Vs,(Wa(),Io),(ro(),pS))}function GQt(){GQt=Z,jme=bi(new Vs,(Wa(),Io),(ro(),pS))}function _rt(){_rt=Z,Vme=bi(new Vs,(Wa(),Io),(ro(),pS))}function UQt(){UQt=Z,Mye=Ku(new Vs,(wE(),jS),(p_(),Iht))}function i2(t,e,n,r){this.c=t,this.d=r,Art(this,e),Lrt(this,n)}function Yx(t){this.c=new Zi,this.b=t.b,this.d=t.c,this.a=t.a}function Srt(t){this.a=b.Math.cos(t),this.b=b.Math.sin(t)}function Art(t,e){t.a&&mu(t.a.k,t),t.a=e,t.a&&le(t.a.k,t)}function Lrt(t,e){t.b&&mu(t.b.f,t),t.b=e,t.b&&le(t.b.f,t)}function WQt(t,e){Lnn(t,t.b,t.c),u(t.b.b,65),e&&u(e.b,65).b}function xin(t,e){c3t(t,e),_t(t.Cb,88)&&gy(sl(u(t.Cb,88)),2)}function Mrt(t,e){_t(t.Cb,88)&&gy(sl(u(t.Cb,88)),4),Qc(t,e)}function _$(t,e){_t(t.Cb,179)&&(u(t.Cb,179).tb=null),Qc(t,e)}function Bc(t,e){return to(),ait(e)?new qj(e,t):new BM(e,t)}function kin(t,e){var n,r;n=e.c,r=n!=null,r&&Vx(t,new Um(e.c))}function YQt(t){var e,n;return n=(c8(),e=new xw,e),H8(n,t),n}function KQt(t){var e,n;return n=(c8(),e=new xw,e),H8(n,t),n}function XQt(t,e){var n;return n=new Sh(t),e.c[e.c.length]=n,n}function QQt(t,e){var n;return n=u(sy(Wx(t.a),e),14),n?n.gc():0}function ZQt(t){var e;return w2(t),e=(Z3(),Z3(),SEt),ez(t,e)}function JQt(t){for(var e;;)if(e=t.Pb(),!t.Ob())return e}function Wvt(t,e){fKe.call(this,new Lx(ty(t))),jl(e,ffe),this.a=e}function Qd(t,e,n){aie(e,n,t.gc()),this.c=t,this.a=e,this.b=n-e}function tZt(t,e,n){var r;aie(e,n,t.c.length),r=n-e,wbt(t.c,e,r)}function Ein(t,e){QUt(t,Ar(Ns($p(e,24),Uq)),Ar(Ns(e,Uq)))}function An(t,e){if(t<0||t>=e)throw it(new yo(Kxt+t+Xxt+e))}function Rr(t,e){if(t<0||t>=e)throw it(new sbt(Kxt+t+Xxt+e))}function _n(t,e){this.b=(On(t),t),this.a=e&Ey?e:e|64|md}function eZt(t){IUt(this),fqt(this.a,Dyt(b.Math.max(8,t))<<1)}function _1(t){return Yo(lt(ct(Ws,1),ee,8,0,[t.i.n,t.n,t.a]))}function Tin(){return O1(),lt(ct(fl,1),oe,132,0,[BEt,Ul,Iy])}function Cin(){return Kf(),lt(ct(Oy,1),oe,232,0,[sc,eu,ac])}function _in(){return Qu(),lt(ct(ppe,1),oe,461,0,[Md,fb,kf])}function Sin(){return yu(),lt(ct(wpe,1),oe,462,0,[n1,db,Ef])}function Ain(){return iv(),lt(ct(F7t,1),oe,423,0,[q4,P7t,llt])}function Lin(){return q9(),lt(ct(D7t,1),oe,379,0,[ilt,rlt,slt])}function Min(){return Z9(),lt(ct(P9t,1),oe,378,0,[vht,O9t,yG])}function Din(){return n6(),lt(ct(DTt,1),oe,314,0,[P6,EO,MTt])}function Iin(){return oz(),lt(ct(OTt,1),oe,337,0,[ITt,VV,Llt])}function Oin(){return d2(),lt(ct(D2e,1),oe,450,0,[Ilt,w7,U4])}function Pin(){return nv(),lt(ct(mlt,1),oe,361,0,[Dv,pb,Mv])}function Fin(){return q0(),lt(ct(j2e,1),oe,303,0,[CO,Y4,F6])}function Nin(){return eE(),lt(ct(qlt,1),oe,292,0,[$lt,zlt,TO])}function Bin(){return so(),lt(ct(lme,1),oe,452,0,[OS,tl,nu])}function Rin(){return V0(),lt(ct(H9t,1),oe,339,0,[vb,q9t,Eht])}function jin(){return yz(),lt(ct(W9t,1),oe,375,0,[G9t,_ht,U9t])}function $in(){return Cz(),lt(ct(t_t,1),oe,377,0,[Mht,L7,Yy])}function zin(){return cE(),lt(ct(X9t,1),oe,336,0,[Aht,K9t,PS])}function qin(){return vz(),lt(ct(J9t,1),oe,338,0,[Z9t,Lht,Q9t])}function Hin(){return ev(),lt(ct(Ame,1),oe,454,0,[RO,FS,TG])}function Vin(){return Nz(),lt(ct(Fye,1),oe,442,0,[Ght,Hht,Vht])}function Gin(){return HD(),lt(ct(T_t,1),oe,380,0,[NG,k_t,E_t])}function Uin(){return Fz(),lt(ct(q_t,1),oe,381,0,[z_t,Qht,$_t])}function Win(){return mz(),lt(ct(R_t,1),oe,293,0,[Xht,B_t,N_t])}function Yin(){return KD(),lt(ct(Zht,1),oe,437,0,[jG,$G,zG])}function Kin(){return G0(),lt(ct(DAt,1),oe,334,0,[tU,sp,ZS])}function Xin(){return M1(),lt(ct(mAt,1),oe,272,0,[P7,Zy,F7])}function Qin(t,e){return v2n(t,e,_t(e,99)&&(u(e,18).Bb&Ka)!=0)}function Zin(t,e,n){var r;return r=__(t,e,!1),r.b<=e&&r.a<=n}function nZt(t,e,n){var r;r=new NQ,r.b=e,r.a=n,++e.b,le(t.d,r)}function Jin(t,e){var n;return n=(On(t),t).g,q2t(!!n),On(e),n(e)}function Yvt(t,e){var n,r;return r=C8(t,e),n=t.a.Zc(r),new wVt(t,n)}function tsn(t){return t.Db>>16!=6?null:u(eat(t),235)}function esn(t){if(t.p!=2)throw it(new Ou);return Ar(t.f)&ys}function nsn(t){if(t.p!=2)throw it(new Ou);return Ar(t.k)&ys}function rsn(t){return t.a==(B8(),vU)&&Btt(t,P2n(t.g,t.b)),t.a}function Kx(t){return t.d==(B8(),vU)&&_C(t,Smn(t.g,t.b)),t.d}function J(t){return Zn(t.ar?1:0}function rZt(t,e){var n,r;return n=eit(e),r=n,u(tr(t.c,r),19).a}function iZt(t,e){var n;for(n=t+"";n.length0&&t.a[--t.d]==0;);t.a[t.d++]==0&&(t.e=0)}function EZt(t){return t.a?t.e.length==0?t.a.a:t.a.a+(""+t.e):t.c}function gsn(t){return!!t.a&&al(t.a.a).i!=0&&!(t.b&&mst(t.b))}function psn(t){return!!t.u&&Lc(t.u.a).i!=0&&!(t.n&&vst(t.n))}function TZt(t){return Bnt(t.e.Hd().gc()*t.c.Hd().gc(),16,new gx(t))}function bsn(t,e){return tXt(Tu(t.q.getTime()),Tu(e.q.getTime()))}function wd(t){return u(P1(t,Nt(hlt,Wot,17,t.c.length,0,1)),474)}function lD(t){return u(P1(t,Nt(l0,Yg,10,t.c.length,0,1)),193)}function wsn(t){return Fl(),!Ga(t)&&!(!Ga(t)&&t.c.i.c==t.d.i.c)}function CZt(t,e,n){var r;r=(Lr(t),new Bu(t)),W1n(new RQt(r,e,n))}function hD(t,e,n){var r;r=(Lr(t),new Bu(t)),Y1n(new jQt(r,e,n))}function _Zt(t,e){var n;return n=1-e,t.a[n]=dz(t.a[n],n),dz(t,e)}function SZt(t,e){var n;t.e=new Zpt,n=wy(e),Zs(n,t.c),yue(t,n,0)}function ca(t,e,n,r){var s;s=new iB,s.a=e,s.b=n,s.c=r,ri(t.a,s)}function xe(t,e,n,r){var s;s=new iB,s.a=e,s.b=n,s.c=r,ri(t.b,s)}function pf(t){var e,n,r;return e=new oXt,n=yat(e,t),n5n(e),r=n,r}function tmt(){var t,e,n;return e=(n=(t=new xw,t),n),le(bLt,e),e}function L$(t){return t.j.c=Nt(Qn,De,1,0,5,1),Dvt(t.c),Qnn(t.a),t}function t4(t){return GC(),_t(t.g,10)?u(t.g,10):null}function vsn(t){return Q3(t).dc()?!1:(wQe(t,new ut),!0)}function msn(t){if(!("stack"in t))try{throw t}catch{}return t}function fD(t,e){if(t<0||t>=e)throw it(new yo(Ipn(t,e)));return t}function AZt(t,e,n){if(t<0||en)throw it(new yo(rpn(t,e,n)))}function Prt(t,e){if(Fs(t.a,e),e.d)throw it(new Vo(Pfe));e.d=t}function Frt(t,e){if(e.$modCount!=t.$modCount)throw it(new rh)}function LZt(t,e){return _t(e,42)?Tst(t.a,u(e,42)):!1}function MZt(t,e){return _t(e,42)?Tst(t.a,u(e,42)):!1}function DZt(t,e){return _t(e,42)?Tst(t.a,u(e,42)):!1}function ysn(t,e){return t.a<=t.b?(e.ud(t.a++),!0):!1}function Yw(t){var e;return Bo(t)?(e=t,e==-0?0:e):Lon(t)}function M$(t){var e;return Vp(t),e=new Ye,j3(t.a,new bn(e)),e}function IZt(t){var e;return Vp(t),e=new Ve,j3(t.a,new we(e)),e}function da(t,e){this.a=t,mx.call(this,t),Km(e,t.gc()),this.b=e}function emt(t){this.e=t,this.b=this.e.a.entries(),this.a=new Array}function xsn(t){return Bnt(t.e.Hd().gc()*t.c.Hd().gc(),273,new eR(t))}function D$(t){return new Xc((jl(t,Yat),J$(Pa(Pa(5,t),t/10|0))))}function OZt(t){return u(P1(t,Nt(Jbe,h1e,11,t.c.length,0,1)),1943)}function ksn(t,e,n){return n.f.c.length>0?vvt(t.a,e,n):vvt(t.b,e,n)}function Esn(t,e,n){t.d&&mu(t.d.e,t),t.d=e,t.d&&Hm(t.d.e,n,t)}function Nrt(t,e){bxn(e,t),Bwt(t.d),Bwt(u(Q(t,(Te(),dG)),207))}function B9(t,e){pxn(e,t),Nwt(t.d),Nwt(u(Q(t,(Te(),dG)),207))}function Kw(t,e){var n,r;return n=B0(t,e),r=null,n&&(r=n.fe()),r}function P8(t,e){var n,r;return n=Jm(t,e),r=null,n&&(r=n.ie()),r}function R9(t,e){var n,r;return n=B0(t,e),r=null,n&&(r=n.ie()),r}function R0(t,e){var n,r;return n=B0(t,e),r=null,n&&(r=U4t(n)),r}function Tsn(t,e,n){var r;return r=pE(n),Aq(t.g,r,e),Aq(t.i,e,n),e}function Csn(t,e,n){var r;r=Jhn();try{return MZe(t,e,n)}finally{Nsn(r)}}function PZt(t){var e;e=t.Wg(),this.a=_t(e,69)?u(e,69).Zh():e.Kc()}function Vs(){Yqt.call(this),this.j.c=Nt(Qn,De,1,0,5,1),this.a=-1}function nmt(t,e,n,r){this.d=t,this.n=e,this.g=n,this.o=r,this.p=-1}function FZt(t,e,n,r){this.e=r,this.d=null,this.c=t,this.a=e,this.b=n}function rmt(t,e,n){this.d=new bR(this),this.e=t,this.i=e,this.f=n}function I$(){I$=Z,Hlt=new $bt(qE,0),ZTt=new $bt("TOP_LEFT",1)}function NZt(){NZt=Z,n_t=DXt(pe(1),pe(4)),e_t=DXt(pe(1),pe(2))}function BZt(){BZt=Z,C3e=Wr((qR(),lt(ct(T3e,1),oe,551,0,[tft])))}function RZt(){RZt=Z,E3e=Wr((zR(),lt(ct(eSt,1),oe,482,0,[Jht])))}function jZt(){jZt=Z,H3e=Wr((UC(),lt(ct(kSt,1),oe,530,0,[VO])))}function $Zt(){$Zt=Z,Kpe=Wr((jR(),lt(ct(l7t,1),oe,481,0,[Kut])))}function _sn(){return rv(),lt(ct(qpe,1),oe,406,0,[hO,lO,Wut,Yut])}function Ssn(){return U$(),lt(ct(sV,1),oe,297,0,[jut,OEt,PEt,FEt])}function Asn(){return c_(),lt(ct(Wpe,1),oe,394,0,[bO,lV,hV,wO])}function Lsn(){return u6(),lt(ct(Vpe,1),oe,323,0,[dO,fO,gO,pO])}function Msn(){return nE(),lt(ct(zbe,1),oe,405,0,[Lv,Fy,Py,z4])}function Dsn(){return Tz(),lt(ct(a2e,1),oe,360,0,[wlt,BV,RV,kO])}function zZt(t,e,n,r){return _t(n,54)?new SWt(t,e,n,r):new ovt(t,e,n,r)}function Isn(){return I1(),lt(ct(p2e,1),oe,411,0,[O6,f7,d7,vlt])}function Osn(t){var e;return t.j==(ve(),mr)&&(e=uce(t),Nu(e,Hn))}function Psn(t,e){var n;n=e.a,Oa(n,e.c.d),oa(n,e.d.d),ny(n.a,t.n)}function qZt(t,e){return u(Nw(Jj(u(Ai(t.k,e),15).Oc(),H4)),113)}function HZt(t,e){return u(Nw(t$(u(Ai(t.k,e),15).Oc(),H4)),113)}function Fsn(t){return new _n(Icn(u(t.a.dd(),14).gc(),t.a.cd()),16)}function F8(t){return _t(t,14)?u(t,14).dc():!t.Kc().Ob()}function Xx(t){return GC(),_t(t.g,145)?u(t.g,145):null}function VZt(t){if(t.e.g!=t.b)throw it(new rh);return!!t.c&&t.d>0}function ti(t){return Zn(t.b!=t.d.c),t.c=t.b,t.b=t.b.a,++t.a,t.c.c}function imt(t,e){On(e),ts(t.a,t.c,e),t.c=t.c+1&t.a.length-1,Gse(t)}function Up(t,e){On(e),t.b=t.b-1&t.a.length-1,ts(t.a,t.b,e),Gse(t)}function GZt(t,e){var n;for(n=t.j.c.length;n0&&Dc(t.g,0,e,0,t.i),e}function KZt(t,e){GR();var n;return n=u(tr(dU,t),55),!n||n.wj(e)}function Ysn(t){if(t.p!=1)throw it(new Ou);return Ar(t.f)<<24>>24}function Ksn(t){if(t.p!=1)throw it(new Ou);return Ar(t.k)<<24>>24}function Xsn(t){if(t.p!=7)throw it(new Ou);return Ar(t.k)<<16>>16}function Qsn(t){if(t.p!=7)throw it(new Ou);return Ar(t.f)<<16>>16}function j0(t){var e;for(e=0;t.Ob();)t.Pb(),e=Pa(e,1);return J$(e)}function XZt(t,e){var n;return n=new Im,t.xd(n),n.a+="..",e.yd(n),n.a}function Zsn(t,e,n){var r;r=u(tr(t.g,n),57),le(t.a.c,new fa(e,r))}function Jsn(t,e,n){return Unt(ye(ec(Lo(t.f,e))),ye(ec(Lo(t.f,n))))}function O$(t,e,n){return Mq(t,e,n,_t(e,99)&&(u(e,18).Bb&Ka)!=0)}function tan(t,e,n){return DE(t,e,n,_t(e,99)&&(u(e,18).Bb&Ka)!=0)}function ean(t,e,n){return T2n(t,e,n,_t(e,99)&&(u(e,18).Bb&Ka)!=0)}function omt(t,e){return t==(Vn(),Os)&&e==Os?4:t==Os||e==Os?8:32}function QZt(t,e){return Vt(e)===Vt(t)?"(this Map)":e==null?_u:$o(e)}function nan(t,e){return u(e==null?ec(Lo(t.f,null)):KC(t.g,e),281)}function ZZt(t,e,n){var r;return r=pE(n),ki(t.b,r,e),ki(t.c,e,n),e}function JZt(t,e){var n;for(n=e;n;)jm(t,n.i,n.j),n=es(n);return t}function cmt(t,e){var n;return n=iD(x8(new nit(t,e))),Vj(new nit(t,e)),n}function Zd(t,e){to();var n;return n=u(t,66).Mj(),Ngn(n,e),n.Ok(e)}function ran(t,e,n,r,s){var o;o=L2n(s,n,r),le(e,Spn(s,o)),vgn(t,s,e)}function tJt(t,e,n){t.i=0,t.e=0,e!=n&&(Cre(t,e,n),Tre(t,e,n))}function umt(t,e){var n;n=t.q.getHours(),t.q.setFullYear(e+ab),E_(t,n)}function ian(t,e,n){if(n){var r=n.ee();t.a[e]=r(n)}else delete t.a[e]}function Brt(t,e,n){if(n){var r=n.ee();n=r(n)}else n=void 0;t.a[e]=n}function eJt(t){if(t<0)throw it(new aHt("Negative array size: "+t))}function Lc(t){return t.n||(sl(t),t.n=new PKt(t,ho,t),Ao(t)),t.n}function j9(t){return Zn(t.a=0&&t.a[n]===e[n];n--);return n<0}function aJt(t,e){oE();var n;return n=t.j.g-e.j.g,n!=0?n:0}function oJt(t,e){return On(e),t.a!=null?Hen(e.Kb(t.a)):iV}function P$(t){var e;return t?new Wwt(t):(e=new O0,xit(e,t),e)}function Bl(t,e){var n;return e.b.Kb(Jte(t,e.c.Ee(),(n=new In(e),n)))}function F$(t){M4t(),QUt(this,Ar(Ns($p(t,24),Uq)),Ar(Ns(t,Uq)))}function cJt(){cJt=Z,upe=Wr((Gz(),lt(ct(zEt,1),oe,428,0,[qut,$Et])))}function uJt(){uJt=Z,lpe=Wr((Q$(),lt(ct(HEt,1),oe,427,0,[qEt,Hut])))}function lJt(){lJt=Z,fbe=Wr((Z$(),lt(ct(w7t,1),oe,424,0,[tlt,gV])))}function hJt(){hJt=Z,r2e=Wr((X8(),lt(ct(n2e,1),oe,511,0,[yO,dlt])))}function fJt(){fJt=Z,M2e=Wr((LD(),lt(ct(BTt,1),oe,419,0,[GV,NTt])))}function dJt(){dJt=Z,P2e=Wr((xD(),lt(ct($Tt,1),oe,479,0,[jTt,WV])))}function gJt(){gJt=Z,dme=Wr((pD(),lt(ct(Y9t,1),oe,376,0,[Sht,BO])))}function pJt(){pJt=Z,ume=Wr((CD(),lt(ct(V9t,1),oe,421,0,[Tht,Cht])))}function bJt(){bJt=Z,_2e=Wr((H$(),lt(ct(LTt,1),oe,422,0,[ATt,Alt])))}function wJt(){wJt=Z,z2e=Wr((I$(),lt(ct(JTt,1),oe,420,0,[Hlt,ZTt])))}function vJt(){vJt=Z,iye=Wr((Uf(),lt(ct(rye,1),oe,520,0,[Ky,mb])))}function mJt(){mJt=Z,Pme=Wr(($9(),lt(ct(Ome,1),oe,523,0,[BS,NS])))}function yJt(){yJt=Z,zme=Wr((bd(),lt(ct($me,1),oe,516,0,[zv,ep])))}function xJt(){xJt=Z,Hme=Wr((C1(),lt(ct(qme,1),oe,515,0,[H2,H1])))}function kJt(){kJt=Z,hye=Wr((Gw(),lt(ct(lye,1),oe,455,0,[yb,r5])))}function EJt(){EJt=Z,Lye=Wr((A$(),lt(ct(v_t,1),oe,425,0,[qht,w_t])))}function TJt(){TJt=Z,Pye=Wr((pz(),lt(ct(m_t,1),oe,495,0,[FG,D7])))}function CJt(){CJt=Z,Aye=Wr((T$(),lt(ct(b_t,1),oe,480,0,[zht,p_t])))}function _Jt(){_Jt=Z,Bye=Wr((G$(),lt(ct(x_t,1),oe,426,0,[y_t,Uht])))}function SJt(){SJt=Z,V3e=Wr((jD(),lt(ct(TSt,1),oe,429,0,[VG,ESt])))}function AJt(){AJt=Z,_3e=Wr((bD(),lt(ct(nSt,1),oe,430,0,[eft,qG])))}function $9(){$9=Z,BS=new Hbt("UPPER",0),NS=new Hbt("LOWER",1)}function can(t,e){var n;n=new _x,r2(n,"x",e.a),r2(n,"y",e.b),Vx(t,n)}function uan(t,e){var n;n=new _x,r2(n,"x",e.a),r2(n,"y",e.b),Vx(t,n)}function lan(t,e){var n,r;r=!1;do n=bre(t,e),r=r|n;while(n);return r}function fmt(t,e){var n,r;for(n=e,r=0;n>0;)r+=t.a[n],n-=n&-n;return r}function LJt(t,e){var n;for(n=e;n;)jm(t,-n.i,-n.j),n=es(n);return t}function va(t,e){var n,r;for(On(e),r=t.Kc();r.Ob();)n=r.Pb(),e.td(n)}function MJt(t,e){var n;return n=e.cd(),new Lw(n,t.e.pc(n,u(e.dd(),14)))}function fs(t,e,n,r){var s;s=new xt,s.c=e,s.b=n,s.a=r,r.b=n.a=s,++t.b}function ch(t,e,n){var r;return r=(An(e,t.c.length),t.c[e]),t.c[e]=n,r}function han(t,e,n){return u(e==null?au(t.f,null,n):sv(t.g,e,n),281)}function zrt(t){return t.c&&t.d?Kvt(t.c)+"->"+Kvt(t.d):"e_"+Pw(t)}function N8(t,e){return(w2(t),qC(new Tn(t,new Nmt(e,t.a)))).sd(o7)}function fan(){return Wa(),lt(ct(I7t,1),oe,356,0,[Dd,gb,cu,qc,Io])}function dan(){return ve(),lt(ct(Xa,1),xc,61,0,[Zo,Pn,Hn,mr,Bn])}function gan(t){return AR(),function(){return Csn(t,this,arguments)}}function pan(){return Date.now?Date.now():new Date().getTime()}function Ga(t){return!t.c||!t.d?!1:!!t.c.i&&t.c.i==t.d.i}function DJt(t){if(!t.c.Sb())throw it(new lc);return t.a=!0,t.c.Ub()}function dD(t){t.i=0,CM(t.b,null),CM(t.c,null),t.a=null,t.e=null,++t.g}function dmt(t){kXe.call(this,t==null?_u:$o(t),_t(t,78)?u(t,78):null)}function IJt(t){rfe(),nqt(this),this.a=new Zi,$yt(this,t),ri(this.a,t)}function OJt(){ant(this),this.b=new $e(as,as),this.a=new $e(Cs,Cs)}function PJt(t,e){this.c=0,this.b=e,cUt.call(this,t,17493),this.a=this.c}function qrt(t){N$(),!$1&&(this.c=t,this.e=!0,this.a=new he)}function N$(){N$=Z,$1=!0,Jge=!1,tpe=!1,npe=!1,epe=!1}function gmt(t,e){return _t(e,149)?hn(t.c,u(e,149).c):!1}function pmt(t,e){var n;return n=0,t&&(n+=t.f.a/2),e&&(n+=e.f.a/2),n}function Hrt(t,e){var n;return n=u(Xw(t.d,e),23),n||u(Xw(t.e,e),23)}function FJt(t){this.b=t,nr.call(this,t),this.a=u(Dn(this.b.a,4),126)}function NJt(t){this.b=t,Bx.call(this,t),this.a=u(Dn(this.b.a,4),126)}function sl(t){return t.t||(t.t=new Uzt(t),n_(new sHt(t),0,t.t)),t.t}function ban(){return ao(),lt(ct(XS,1),oe,103,0,[h0,Cf,zh,ng,rg])}function wan(){return l4(),lt(ct(tA,1),oe,249,0,[Eb,iP,IAt,JS,OAt])}function van(){return Qf(),lt(ct(ip,1),oe,175,0,[qn,ea,Pd,V2,rp])}function man(){return uI(),lt(ct(aSt,1),oe,316,0,[rSt,nft,sSt,rft,iSt])}function yan(){return u_(),lt(ct(N9t,1),oe,315,0,[F9t,xht,kht,DS,IS])}function xan(){return x2(),lt(ct(FTt,1),oe,335,0,[Mlt,PTt,Dlt,vS,wS])}function kan(){return AE(),lt(ct(y3e,1),oe,355,0,[i5,G6,GS,VS,US])}function Ean(){return b4(),lt(ct(w2e,1),oe,363,0,[$V,qV,HV,zV,jV])}function Tan(){return dh(),lt(ct(fCt,1),oe,163,0,[MO,ES,bb,TS,jy])}function B8(){B8=Z;var t,e;wU=(c8(),e=new xR,e),vU=(t=new ret,t)}function BJt(t){var e;return t.c||(e=t.r,_t(e,88)&&(t.c=u(e,26))),t.c}function Can(t){return t.e=3,t.d=t.Yb(),t.e!=2?(t.e=0,!0):!1}function Vrt(t){var e,n,r;return e=t&hl,n=t>>22&hl,r=t<0?Z0:0,iu(e,n,r)}function _an(t){var e,n,r,s;for(n=t,r=0,s=n.length;r0?Fie(t,e):rue(t,-e)}function bmt(t,e){return e==0||t.e==0?t:e>0?rue(t,e):Fie(t,-e)}function Mr(t){if(zr(t))return t.c=t.a,t.a.Pb();throw it(new lc)}function jJt(t){var e,n;return e=t.c.i,n=t.d.i,e.k==(Vn(),ks)&&n.k==ks}function Grt(t){var e;return e=new Vw,Mo(e,t),Jt(e,(Te(),So),null),e}function Urt(t,e,n){var r;return r=t.Yg(e),r>=0?t._g(r,n,!0):dv(t,e,n)}function wmt(t,e,n,r){var s;for(s=0;se)throw it(new yo(J4t(t,e,"index")));return t}function Wrt(t,e,n,r){var s;return s=Nt(Cr,Xr,25,e,15,1),j0n(s,t,e,n,r),s}function Aan(t,e){var n;n=t.q.getHours()+(e/60|0),t.q.setMinutes(e),E_(t,n)}function Lan(t,e){return b.Math.min(Wp(e.a,t.d.d.c),Wp(e.b,t.d.d.c))}function Jx(t,e){return ra(e)?e==null?b5t(t.f,null):Zne(t.g,e):b5t(t.f,e)}function L1(t){this.c=t,this.a=new S(this.c.a),this.b=new S(this.c.b)}function B$(){this.e=new he,this.c=new he,this.d=new he,this.b=new he}function VJt(){this.g=new Fpt,this.b=new Fpt,this.a=new he,this.k=new he}function GJt(t,e,n){this.a=t,this.c=e,this.d=n,le(e.e,this),le(n.b,this)}function UJt(t,e){oUt.call(this,e.rd(),e.qd()&-6),On(t),this.a=t,this.b=e}function WJt(t,e){cUt.call(this,e.rd(),e.qd()&-6),On(t),this.a=t,this.b=e}function Tmt(t,e){ent.call(this,e.rd(),e.qd()&-6),On(t),this.a=t,this.b=e}function R$(t,e,n){this.a=t,this.b=e,this.c=n,le(t.t,this),le(e.i,this)}function j$(){this.b=new Zi,this.a=new Zi,this.b=new Zi,this.a=new Zi}function $$(){$$=Z,WS=new Vi("org.eclipse.elk.labels.labelManager")}function YJt(){YJt=Z,ETt=new Ps("separateLayerConnections",(Tz(),wlt))}function Uf(){Uf=Z,Ky=new Ubt("REGULAR",0),mb=new Ubt("CRITICAL",1)}function pD(){pD=Z,Sht=new qbt("STACKED",0),BO=new qbt("SEQUENCED",1)}function bD(){bD=Z,eft=new Zbt("FIXED",0),qG=new Zbt("CENTER_NODE",1)}function Man(t,e){var n;return n=P4n(t,e),t.b=new gz(n.c.length),U3n(t,n)}function Dan(t,e,n){var r;return++t.e,--t.f,r=u(t.d[e].$c(n),133),r.dd()}function KJt(t){var e;return t.a||(e=t.r,_t(e,148)&&(t.a=u(e,148))),t.a}function Cmt(t){if(t.a){if(t.e)return Cmt(t.e)}else return t;return null}function Ian(t,e){return t.pe.p?-1:0}function z$(t,e){return On(e),t.c=0,"Initial capacity must not be negative")}function ZJt(){ZJt=Z,gpe=Wr((Kf(),lt(ct(Oy,1),oe,232,0,[sc,eu,ac])))}function JJt(){JJt=Z,bpe=Wr((Qu(),lt(ct(ppe,1),oe,461,0,[Md,fb,kf])))}function tte(){tte=Z,vpe=Wr((yu(),lt(ct(wpe,1),oe,462,0,[n1,db,Ef])))}function ete(){ete=Z,rpe=Wr((O1(),lt(ct(fl,1),oe,132,0,[BEt,Ul,Iy])))}function nte(){nte=Z,Obe=Wr((q9(),lt(ct(D7t,1),oe,379,0,[ilt,rlt,slt])))}function rte(){rte=Z,Ybe=Wr((iv(),lt(ct(F7t,1),oe,423,0,[q4,P7t,llt])))}function ite(){ite=Z,S2e=Wr((n6(),lt(ct(DTt,1),oe,314,0,[P6,EO,MTt])))}function ste(){ste=Z,A2e=Wr((oz(),lt(ct(OTt,1),oe,337,0,[ITt,VV,Llt])))}function ate(){ate=Z,I2e=Wr((d2(),lt(ct(D2e,1),oe,450,0,[Ilt,w7,U4])))}function ote(){ote=Z,E2e=Wr((nv(),lt(ct(mlt,1),oe,361,0,[Dv,pb,Mv])))}function cte(){cte=Z,$2e=Wr((q0(),lt(ct(j2e,1),oe,303,0,[CO,Y4,F6])))}function ute(){ute=Z,R2e=Wr((eE(),lt(ct(qlt,1),oe,292,0,[$lt,zlt,TO])))}function lte(){lte=Z,ime=Wr((Z9(),lt(ct(P9t,1),oe,378,0,[vht,O9t,yG])))}function hte(){hte=Z,fme=Wr((yz(),lt(ct(W9t,1),oe,375,0,[G9t,_ht,U9t])))}function fte(){fte=Z,cme=Wr((V0(),lt(ct(H9t,1),oe,339,0,[vb,q9t,Eht])))}function dte(){dte=Z,hme=Wr((so(),lt(ct(lme,1),oe,452,0,[OS,tl,nu])))}function gte(){gte=Z,bme=Wr((Cz(),lt(ct(t_t,1),oe,377,0,[Mht,L7,Yy])))}function pte(){pte=Z,gme=Wr((cE(),lt(ct(X9t,1),oe,336,0,[Aht,K9t,PS])))}function bte(){bte=Z,pme=Wr((vz(),lt(ct(J9t,1),oe,338,0,[Z9t,Lht,Q9t])))}function wte(){wte=Z,Lme=Wr((ev(),lt(ct(Ame,1),oe,454,0,[RO,FS,TG])))}function vte(){vte=Z,Nye=Wr((Nz(),lt(ct(Fye,1),oe,442,0,[Ght,Hht,Vht])))}function mte(){mte=Z,Rye=Wr((HD(),lt(ct(T_t,1),oe,380,0,[NG,k_t,E_t])))}function yte(){yte=Z,e3e=Wr((Fz(),lt(ct(q_t,1),oe,381,0,[z_t,Qht,$_t])))}function xte(){xte=Z,t3e=Wr((mz(),lt(ct(R_t,1),oe,293,0,[Xht,B_t,N_t])))}function kte(){kte=Z,k3e=Wr((KD(),lt(ct(Zht,1),oe,437,0,[jG,$G,zG])))}function Ete(){Ete=Z,C4e=Wr((G0(),lt(ct(DAt,1),oe,334,0,[tU,sp,ZS])))}function Tte(){Tte=Z,x4e=Wr((M1(),lt(ct(mAt,1),oe,272,0,[P7,Zy,F7])))}function jan(){return ua(),lt(ct(PAt,1),oe,98,0,[Tb,G1,B7,Y2,g0,Gc])}function o2(t,e){return!t.o&&(t.o=new _l((Jc(),Sb),Hv,t,0)),ist(t.o,e)}function $an(t){return!t.g&&(t.g=new Ik),!t.g.d&&(t.g.d=new Hzt(t)),t.g.d}function zan(t){return!t.g&&(t.g=new Ik),!t.g.a&&(t.g.a=new Vzt(t)),t.g.a}function qan(t){return!t.g&&(t.g=new Ik),!t.g.b&&(t.g.b=new qzt(t)),t.g.b}function wD(t){return!t.g&&(t.g=new Ik),!t.g.c&&(t.g.c=new Gzt(t)),t.g.c}function Han(t,e,n){var r,s;for(s=new tE(e,t),r=0;rn||e=0?t._g(n,!0,!0):dv(t,e,!0)}function aon(t,e){return Ms(Xt(ye(Q(t,(ae(),Fv)))),Xt(ye(Q(e,Fv))))}function Dte(){Dte=Z,Dye=uv(uv(VR(new Vs,(wE(),RS)),(p_(),LG)),Oht)}function oon(t,e,n){var r;return r=xre(t,e,n),t.b=new gz(r.c.length),z5t(t,r)}function con(t){if(t.b<=0)throw it(new lc);return--t.b,t.a-=t.c.c,pe(t.a)}function uon(t){var e;if(!t.a)throw it(new FXt);return e=t.a,t.a=es(t.a),e}function lon(t){for(;!t.a;)if(!mYt(t.c,new ze(t)))return!1;return!0}function e6(t){var e;return Lr(t),_t(t,198)?(e=u(t,198),e):new btt(t)}function hon(t){V$(),u(t.We((ui(),Qy)),174).Fc((Zu(),sP)),t.Ye(kft,null)}function V$(){V$=Z,W3e=new LZ,K3e=new MZ,Y3e=Kun((ui(),kft),W3e,xb,K3e)}function G$(){G$=Z,y_t=new Qbt("LEAF_NUMBER",0),Uht=new Qbt("NODE_SIZE",1)}function fon(t,e,n){t.a=e,t.c=n,t.b.a.$b(),Ah(t.d),t.e.a.c=Nt(Qn,De,1,0,5,1)}function tit(t){t.a=Nt(Cr,Xr,25,t.b+1,15,1),t.c=Nt(Cr,Xr,25,t.b,15,1),t.d=0}function don(t,e){t.a.ue(e.d,t.b)>0&&(le(t.c,new $wt(e.c,e.d,t.d)),t.b=e.d)}function Fmt(t,e){if(t.g==null||e>=t.i)throw it(new nnt(e,t.i));return t.g[e]}function Ite(t,e,n){if(sE(t,n),n!=null&&!t.wj(n))throw it(new tet);return n}function Ote(t){var e;if(t.Ek())for(e=t.i-1;e>=0;--e)At(t,e);return amt(t)}function gon(t){var e,n;if(!t.b)return null;for(n=t.b;e=n.a[0];)n=e;return n}function pon(t,e){var n,r;return eJt(e),n=(r=t.slice(0,e),Bmt(r,t)),n.length=e,n}function $8(t,e,n,r){var s;r=(Z3(),r||_Et),s=t.slice(e,n),t5t(s,t,e,n,-e,r)}function uh(t,e,n,r,s){return e<0?dv(t,n,r):u(n,66).Nj().Pj(t,t.yh(),e,r,s)}function bon(t){return _t(t,172)?""+u(t,172).a:t==null?null:$o(t)}function won(t){return _t(t,172)?""+u(t,172).a:t==null?null:$o(t)}function Pte(t,e){if(e.a)throw it(new Vo(Pfe));Fs(t.a,e),e.a=t,!t.j&&(t.j=e)}function Nmt(t,e){ent.call(this,e.rd(),e.qd()&-16449),On(t),this.a=t,this.c=e}function Fte(t,e){var n,r;return r=e/t.c.Hd().gc()|0,n=e%t.c.Hd().gc(),t6(t,r,n)}function Qu(){Qu=Z,Md=new Let(y6,0),fb=new Let(qE,1),kf=new Let(x6,2)}function U$(){U$=Z,jut=new YR("All",0),OEt=new MUt,PEt=new qUt,FEt=new DUt}function Nte(){Nte=Z,Qge=Wr((U$(),lt(ct(sV,1),oe,297,0,[jut,OEt,PEt,FEt])))}function Bte(){Bte=Z,qbe=Wr((nE(),lt(ct(zbe,1),oe,405,0,[Lv,Fy,Py,z4])))}function Rte(){Rte=Z,Hpe=Wr((rv(),lt(ct(qpe,1),oe,406,0,[hO,lO,Wut,Yut])))}function jte(){jte=Z,Gpe=Wr((u6(),lt(ct(Vpe,1),oe,323,0,[dO,fO,gO,pO])))}function $te(){$te=Z,Ype=Wr((c_(),lt(ct(Wpe,1),oe,394,0,[bO,lV,hV,wO])))}function zte(){zte=Z,fye=Wr((wE(),lt(ct(s_t,1),oe,393,0,[AG,RS,$O,jS])))}function qte(){qte=Z,o2e=Wr((Tz(),lt(ct(a2e,1),oe,360,0,[wlt,BV,RV,kO])))}function Hte(){Hte=Z,Jye=Wr((eq(),lt(ct(F_t,1),oe,340,0,[Kht,O_t,P_t,I_t])))}function Vte(){Vte=Z,b2e=Wr((I1(),lt(ct(p2e,1),oe,411,0,[O6,f7,d7,vlt])))}function Gte(){Gte=Z,sme=Wr((cy(),lt(ct(yht,1),oe,197,0,[xG,mht,n5,e5])))}function Ute(){Ute=Z,q4e=Wr((Sl(),lt(ct(z4e,1),oe,396,0,[Ql,qAt,zAt,HAt])))}function Wte(){Wte=Z,S4e=Wr((zl(),lt(ct(_4e,1),oe,285,0,[rP,f0,kb,nP])))}function Yte(){Yte=Z,k4e=Wr((W0(),lt(ct(_ft,1),oe,218,0,[Cft,eP,N7,X6])))}function Kte(){Kte=Z,j4e=Wr((jz(),lt(ct($At,1),oe,311,0,[Lft,BAt,jAt,RAt])))}function Xte(){Xte=Z,B4e=Wr((Al(),lt(ct(rA,1),oe,374,0,[oP,K2,aP,Jy])))}function Qte(){Qte=Z,Dq(),TLt=as,V5e=Cs,CLt=new P3(as),G5e=new P3(Cs)}function xD(){xD=Z,jTt=new jbt(J0,0),WV=new jbt("IMPROVE_STRAIGHTNESS",1)}function von(t,e){return k8(),le(t,new fa(e,pe(e.e.c.length+e.g.c.length)))}function mon(t,e){return k8(),le(t,new fa(e,pe(e.e.c.length+e.g.c.length)))}function Bmt(t,e){return _D(e)!=10&<(ol(e),e.hm,e.__elementTypeId$,_D(e),t),t}function mu(t,e){var n;return n=Ro(t,e,0),n==-1?!1:(Fg(t,n),!0)}function Zte(t,e){var n;return n=u(Jx(t.e,e),387),n?(Hwt(n),n.e):null}function z8(t){var e;return Bo(t)&&(e=0-t,!isNaN(e))?e:Kp(rE(t))}function Ro(t,e,n){for(;n=0?Xz(t,n,!0,!0):dv(t,e,!0)}function qmt(t,e){GC();var n,r;return n=Xx(t),r=Xx(e),!!n&&!!r&&!gse(n.k,r.k)}function kon(t,e){ku(t,e==null||Pj((On(e),e))||isNaN((On(e),e))?0:(On(e),e))}function Eon(t,e){Eu(t,e==null||Pj((On(e),e))||isNaN((On(e),e))?0:(On(e),e))}function Ton(t,e){tv(t,e==null||Pj((On(e),e))||isNaN((On(e),e))?0:(On(e),e))}function Con(t,e){Jw(t,e==null||Pj((On(e),e))||isNaN((On(e),e))?0:(On(e),e))}function ree(t){(this.q?this.q:(wn(),wn(),u0)).Ac(t.q?t.q:(wn(),wn(),u0))}function _on(t,e){return _t(e,99)&&u(e,18).Bb&Ka?new rnt(e,t):new tE(e,t)}function Son(t,e){return _t(e,99)&&u(e,18).Bb&Ka?new rnt(e,t):new tE(e,t)}function iee(t,e){c7t=new vp,Upe=e,hS=t,u(hS.b,65),Amt(hS,c7t,null),Qle(hS)}function sit(t,e,n){var r;return r=t.g[e],p9(t,e,t.oi(e,n)),t.gi(e,n,r),t.ci(),r}function X$(t,e){var n;return n=t.Xc(e),n>=0?(t.$c(n),!0):!1}function ait(t){var e;return t.d!=t.r&&(e=Dh(t),t.e=!!e&&e.Cj()==j0e,t.d=e),t.e}function oit(t,e){var n;for(Lr(t),Lr(e),n=!1;e.Ob();)n=n|t.Fc(e.Pb());return n}function Xw(t,e){var n;return n=u(tr(t.e,e),387),n?(XUt(t,n),n.e):null}function see(t){var e,n;return e=t/60|0,n=t%60,n==0?""+e:""+e+":"+(""+n)}function Wo(t,e){var n,r;return w2(t),r=new Tmt(e,t.a),n=new kYt(r),new Tn(t,n)}function Jm(t,e){var n=t.a[e],r=(_it(),Put)[typeof n];return r?r(n):Uyt(typeof n)}function Aon(t){switch(t.g){case 0:return wi;case 1:return-1;default:return 0}}function Lon(t){return u4t(t,(q8(),oEt))<0?-GQe(rE(t)):t.l+t.m*m6+t.h*C2}function _D(t){return t.__elementTypeCategory$==null?10:t.__elementTypeCategory$}function cit(t){var e;return e=t.b.c.length==0?null:Ne(t.b,0),e!=null&&vit(t,0),e}function aee(t,e){for(;e[0]=0;)++e[0]}function SD(t,e){this.e=e,this.a=Jne(t),this.a<54?this.f=Yw(t):this.c=JD(t)}function oee(t,e,n,r){gi(),yw.call(this,26),this.c=t,this.a=e,this.d=n,this.b=r}function Jd(t,e,n){var r,s;for(r=10,s=0;st.a[r]&&(r=n);return r}function Fon(t,e){var n;return n=av(t.e.c,e.e.c),n==0?Ms(t.e.d,e.e.d):n}function e4(t,e){return e.e==0||t.e==0?s7:(TE(),uat(t,e))}function Non(t,e){if(!t)throw it(new Fn(jwn("Enum constant undefined: %s",e)))}function H9(){H9=Z,Gbe=new xg,Ube=new T3,Hbe=new cK,Vbe=new Vb,Wbe=new uK}function Q$(){Q$=Z,qEt=new Obt("BY_SIZE",0),Hut=new Obt("BY_SIZE_AND_SHAPE",1)}function Z$(){Z$=Z,tlt=new Pbt("EADES",0),gV=new Pbt("FRUCHTERMAN_REINGOLD",1)}function LD(){LD=Z,GV=new Rbt("READING_DIRECTION",0),NTt=new Rbt("ROTATION",1)}function uee(){uee=Z,L2e=Wr((x2(),lt(ct(FTt,1),oe,335,0,[Mlt,PTt,Dlt,vS,wS])))}function lee(){lee=Z,ame=Wr((u_(),lt(ct(N9t,1),oe,315,0,[F9t,xht,kht,DS,IS])))}function hee(){hee=Z,v2e=Wr((b4(),lt(ct(w2e,1),oe,363,0,[$V,qV,HV,zV,jV])))}function fee(){fee=Z,q2e=Wr((dh(),lt(ct(fCt,1),oe,163,0,[MO,ES,bb,TS,jy])))}function dee(){dee=Z,S3e=Wr((uI(),lt(ct(aSt,1),oe,316,0,[rSt,nft,sSt,rft,iSt])))}function gee(){gee=Z,X3e=Wr((Qf(),lt(ct(ip,1),oe,175,0,[qn,ea,Pd,V2,rp])))}function pee(){pee=Z,x3e=Wr((AE(),lt(ct(y3e,1),oe,355,0,[i5,G6,GS,VS,US])))}function bee(){bee=Z,Bbe=Wr((Wa(),lt(ct(I7t,1),oe,356,0,[Dd,gb,cu,qc,Io])))}function wee(){wee=Z,y4e=Wr((ao(),lt(ct(XS,1),oe,103,0,[h0,Cf,zh,ng,rg])))}function vee(){vee=Z,L4e=Wr((l4(),lt(ct(tA,1),oe,249,0,[Eb,iP,IAt,JS,OAt])))}function mee(){mee=Z,I4e=Wr((ve(),lt(ct(Xa,1),xc,61,0,[Zo,Pn,Hn,mr,Bn])))}function uit(t,e){var n;return n=u(tr(t.a,e),134),n||(n=new ka,ki(t.a,e,n)),n}function yee(t){var e;return e=u(Q(t,(ae(),Iv)),305),e?e.a==t:!1}function xee(t){var e;return e=u(Q(t,(ae(),Iv)),305),e?e.i==t:!1}function kee(t,e){return On(e),uvt(t),t.d.Ob()?(e.td(t.d.Pb()),!0):!1}function J$(t){return yc(t,wi)>0?wi:yc(t,Sa)<0?Sa:Ar(t)}function ty(t){return t<3?(jl(t,bfe),t+1):t=0&&e=-.01&&t.a<=B1&&(t.a=0),t.b>=-.01&&t.b<=B1&&(t.b=0),t}function Tee(t,e){return e==(Ant(),Ant(),Yge)?t.toLocaleLowerCase():t.toLowerCase()}function Vmt(t){return(t.i&2?"interface ":t.i&1?"":"class ")+(P0(t),t.o)}function Co(t){var e,n;n=(e=new iet,e),Dr((!t.q&&(t.q=new fe(Wh,t,11,10)),t.q),n)}function Bon(t,e){var n;return n=e>0?e-1:e,yHt(QKe(Kee(qwt(new r8,n),t.n),t.j),t.k)}function Ron(t,e,n,r){var s;t.j=-1,d5t(t,W4t(t,e,n),(to(),s=u(e,66).Mj(),s.Ok(r)))}function Cee(t){this.g=t,this.f=new he,this.a=b.Math.min(this.g.c.c,this.g.d.c)}function _ee(t){this.b=new he,this.a=new he,this.c=new he,this.d=new he,this.e=t}function See(t,e){this.a=new _r,this.e=new _r,this.b=(Z9(),yG),this.c=t,this.b=e}function Aee(t,e,n){Ij.call(this),Gmt(this),this.a=t,this.c=n,this.b=e.d,this.f=e.e}function Lee(t){this.d=t,this.c=t.c.vc().Kc(),this.b=null,this.a=null,this.e=(TR(),Mut)}function Qw(t){if(t<0)throw it(new Fn("Illegal Capacity: "+t));this.g=this.ri(t)}function jon(t,e){if(0>t||t>e)throw it(new ibt("fromIndex: 0, toIndex: "+t+Uxt+e))}function $on(t){var e;if(t.a==t.b.a)throw it(new lc);return e=t.a,t.c=e,t.a=t.a.e,e}function tz(t){var e;Rm(!!t.c),e=t.c.a,lh(t.d,t.c),t.b==t.c?t.b=e:--t.a,t.c=null}function ez(t,e){var n;return w2(t),n=new QXt(t,t.a.rd(),t.a.qd()|4,e),new Tn(t,n)}function zon(t,e){var n,r;return n=u(sy(t.d,e),14),n?(r=e,t.e.pc(r,n)):null}function nz(t,e){var n,r;for(r=t.Kc();r.Ob();)n=u(r.Pb(),70),Jt(n,(ae(),j6),e)}function qon(t){var e;return e=Xt(ye(Q(t,(Te(),Jg)))),e<0&&(e=0,Jt(t,Jg,e)),e}function Hon(t,e,n){var r;r=b.Math.max(0,t.b/2-.5),h_(n,r,1),le(e,new eGt(n,r))}function Von(t,e,n){var r;return r=t.a.e[u(e.a,10).p]-t.a.e[u(n.a,10).p],ps(JM(r))}function Mee(t,e,n,r,s,o){var h;h=Grt(r),Oa(h,s),oa(h,o),ln(t.a,r,new Fj(h,e,n.f))}function Dee(t,e){var n;if(n=mI(t.Tg(),e),!n)throw it(new Fn(lb+e+Wct));return n}function ey(t,e){var n;for(n=t;es(n);)if(n=es(n),n==e)return!0;return!1}function Gon(t,e){var n,r,s;for(r=e.a.cd(),n=u(e.a.dd(),14).gc(),s=0;s0&&(t.a/=e,t.b/=e),t}function Rl(t){var e;return t.w?t.w:(e=tsn(t),e&&!e.kh()&&(t.w=e),e)}function Jon(t){var e;return t==null?null:(e=u(t,190),tgn(e,e.length))}function At(t,e){if(t.g==null||e>=t.i)throw it(new nnt(e,t.i));return t.li(e,t.g[e])}function tcn(t){var e,n;for(e=t.a.d.j,n=t.c.d.j;e!=n;)vf(t.b,e),e=Oz(e);vf(t.b,e)}function ecn(t){var e;for(e=0;e=14&&e<=16))),t}function Fee(t,e,n){var r=function(){return t.apply(r,arguments)};return e.apply(r,n),r}function Nee(t,e,n){var r,s;r=e;do s=Xt(t.p[r.p])+n,t.p[r.p]=s,r=t.a[r.p];while(r!=e)}function H8(t,e){var n,r;r=t.a,n=Fln(t,e,null),r!=e&&!t.e&&(n=PE(t,e,n)),n&&n.Fi()}function Umt(t,e){return k1(),wf(sb),b.Math.abs(t-e)<=sb||t==e||isNaN(t)&&isNaN(e)}function Wmt(t,e){return k1(),wf(sb),b.Math.abs(t-e)<=sb||t==e||isNaN(t)&&isNaN(e)}function icn(t,e){return nb(),pu(t.b.c.length-t.e.c.length,e.b.c.length-e.e.c.length)}function n4(t,e){return nXe(U9(t,e,Ar(_a(i0,Xd(Ar(_a(e==null?0:Hi(e),s0)),15)))))}function Bee(){Bee=Z,Zbe=Wr((Vn(),lt(ct(flt,1),oe,267,0,[Os,ta,ks,Hc,Ll,z1])))}function Ree(){Ree=Z,s4e=Wr((hy(),lt(ct(dft,1),oe,291,0,[fft,XO,KO,hft,WO,YO])))}function jee(){jee=Z,J3e=Wr((t0(),lt(ct(LSt,1),oe,248,0,[uft,GO,UO,WG,GG,UG])))}function $ee(){$ee=Z,C2e=Wr((h6(),lt(ct(b7,1),oe,227,0,[p7,bS,g7,Ny,G4,V4])))}function zee(){zee=Z,N2e=Wr((kE(),lt(ct(QTt,1),oe,275,0,[mS,WTt,XTt,KTt,YTt,UTt])))}function qee(){qee=Z,F2e=Wr((oI(),lt(ct(GTt,1),oe,274,0,[YV,qTt,VTt,zTt,HTt,Rlt])))}function Hee(){Hee=Z,rme=Wr((uq(),lt(ct(I9t,1),oe,313,0,[wht,M9t,bht,L9t,D9t,mG])))}function Vee(){Vee=Z,O2e=Wr((dq(),lt(ct(RTt,1),oe,276,0,[Plt,Olt,Nlt,Flt,Blt,UV])))}function Gee(){Gee=Z,gye=Wr((p_(),lt(ct(dye,1),oe,327,0,[LG,Oht,Fht,Pht,Nht,Iht])))}function Uee(){Uee=Z,D4e=Wr((Zu(),lt(ct(eU,1),oe,273,0,[Cb,sg,sP,nA,eA,Q6])))}function Wee(){Wee=Z,E4e=Wr((hq(),lt(ct(CAt,1),oe,312,0,[Sft,kAt,TAt,yAt,EAt,xAt])))}function scn(){return py(),lt(ct(lo,1),oe,93,0,[_f,ig,Sf,Lf,d0,Hh,Yl,Af,qh])}function iz(t,e){var n;n=t.a,t.a=e,t.Db&4&&!(t.Db&1)&&mi(t,new Qm(t,0,n,t.a))}function sz(t,e){var n;n=t.b,t.b=e,t.Db&4&&!(t.Db&1)&&mi(t,new Qm(t,1,n,t.b))}function V8(t,e){var n;n=t.b,t.b=e,t.Db&4&&!(t.Db&1)&&mi(t,new Qm(t,3,n,t.b))}function Jw(t,e){var n;n=t.f,t.f=e,t.Db&4&&!(t.Db&1)&&mi(t,new Qm(t,3,n,t.f))}function tv(t,e){var n;n=t.g,t.g=e,t.Db&4&&!(t.Db&1)&&mi(t,new Qm(t,4,n,t.g))}function ku(t,e){var n;n=t.i,t.i=e,t.Db&4&&!(t.Db&1)&&mi(t,new Qm(t,5,n,t.i))}function Eu(t,e){var n;n=t.j,t.j=e,t.Db&4&&!(t.Db&1)&&mi(t,new Qm(t,6,n,t.j))}function G8(t,e){var n;n=t.j,t.j=e,t.Db&4&&!(t.Db&1)&&mi(t,new Qm(t,1,n,t.j))}function U8(t,e){var n;n=t.c,t.c=e,t.Db&4&&!(t.Db&1)&&mi(t,new Qm(t,4,n,t.c))}function W8(t,e){var n;n=t.k,t.k=e,t.Db&4&&!(t.Db&1)&&mi(t,new Qm(t,2,n,t.k))}function hit(t,e){var n;n=t.d,t.d=e,t.Db&4&&!(t.Db&1)&&mi(t,new Rrt(t,2,n,t.d))}function Rg(t,e){var n;n=t.s,t.s=e,t.Db&4&&!(t.Db&1)&&mi(t,new Rrt(t,4,n,t.s))}function ry(t,e){var n;n=t.t,t.t=e,t.Db&4&&!(t.Db&1)&&mi(t,new Rrt(t,5,n,t.t))}function Y8(t,e){var n;n=t.F,t.F=e,t.Db&4&&!(t.Db&1)&&mi(t,new Js(t,1,5,n,e))}function MD(t,e){var n;return n=u(tr((GR(),dU),t),55),n?n.xj(e):Nt(Qn,De,1,e,5,1)}function H0(t,e){var n,r;return n=e in t.a,n&&(r=B0(t,e).he(),r)?r.a:null}function acn(t,e){var n,r,s;return n=(r=(Sw(),s=new ZT,s),e&&F5t(r,e),r),nyt(n,t),n}function Yee(t,e,n){if(sE(t,n),!t.Bk()&&n!=null&&!t.wj(n))throw it(new tet);return n}function Kee(t,e){return t.n=e,t.n?(t.f=new he,t.e=new he):(t.f=null,t.e=null),t}function jr(t,e,n,r,s,o){var h;return h=rrt(t,e),Qee(n,h),h.i=s?8:0,h.f=r,h.e=s,h.g=o,h}function Ymt(t,e,n,r,s){this.d=e,this.k=r,this.f=s,this.o=-1,this.p=1,this.c=t,this.a=n}function Kmt(t,e,n,r,s){this.d=e,this.k=r,this.f=s,this.o=-1,this.p=2,this.c=t,this.a=n}function Xmt(t,e,n,r,s){this.d=e,this.k=r,this.f=s,this.o=-1,this.p=6,this.c=t,this.a=n}function Qmt(t,e,n,r,s){this.d=e,this.k=r,this.f=s,this.o=-1,this.p=7,this.c=t,this.a=n}function Zmt(t,e,n,r,s){this.d=e,this.j=r,this.e=s,this.o=-1,this.p=4,this.c=t,this.a=n}function Xee(t,e){var n,r,s,o;for(r=e,s=0,o=r.length;s=0),afn(t.d,t.c)<0&&(t.a=t.a-1&t.d.a.length-1,t.b=t.d.c),t.c=-1}function Jmt(t){return t.a<54?t.f<0?-1:t.f>0?1:0:(!t.c&&(t.c=VD(t.f)),t.c).e}function wf(t){if(!(t>=0))throw it(new Fn("tolerance ("+t+") must be >= 0"));return t}function K8(){return oft||(oft=new jue,o4(oft,lt(ct($4,1),De,130,0,[new Tp]))),oft}function so(){so=Z,OS=new zet(N_,0),tl=new zet("INPUT",1),nu=new zet("OUTPUT",2)}function oz(){oz=Z,ITt=new Fet("ARD",0),VV=new Fet("MSD",1),Llt=new Fet("MANUAL",2)}function ev(){ev=Z,RO=new Uet("BARYCENTER",0),FS=new Uet(E1e,1),TG=new Uet(T1e,2)}function DD(t,e){var n;if(n=t.gc(),e<0||e>n)throw it(new qm(e,n));return new wwt(t,e)}function tne(t,e){var n;return _t(e,42)?t.c.Mc(e):(n=ist(t,e),qz(t,e),n)}function bo(t,e,n){return b2(t,e),Qc(t,n),Rg(t,0),ry(t,1),qg(t,!0),zg(t,!0),t}function jl(t,e){if(t<0)throw it(new Fn(e+" cannot be negative but was: "+t));return t}function ene(t,e){var n,r;for(n=0,r=t.gc();n0?u(Ne(n.a,r-1),10):null}function G9(t,e){var n;n=t.k,t.k=e,t.Db&4&&!(t.Db&1)&&mi(t,new Js(t,1,2,n,t.k))}function uz(t,e){var n;n=t.f,t.f=e,t.Db&4&&!(t.Db&1)&&mi(t,new Js(t,1,8,n,t.f))}function lz(t,e){var n;n=t.i,t.i=e,t.Db&4&&!(t.Db&1)&&mi(t,new Js(t,1,7,n,t.i))}function nyt(t,e){var n;n=t.a,t.a=e,t.Db&4&&!(t.Db&1)&&mi(t,new Js(t,1,8,n,t.a))}function ryt(t,e){var n;n=t.b,t.b=e,t.Db&4&&!(t.Db&1)&&mi(t,new Js(t,1,0,n,t.b))}function iyt(t,e){var n;n=t.b,t.b=e,t.Db&4&&!(t.Db&1)&&mi(t,new Js(t,1,0,n,t.b))}function syt(t,e){var n;n=t.c,t.c=e,t.Db&4&&!(t.Db&1)&&mi(t,new Js(t,1,1,n,t.c))}function ayt(t,e){var n;n=t.c,t.c=e,t.Db&4&&!(t.Db&1)&&mi(t,new Js(t,1,1,n,t.c))}function dit(t,e){var n;n=t.c,t.c=e,t.Db&4&&!(t.Db&1)&&mi(t,new Js(t,1,4,n,t.c))}function oyt(t,e){var n;n=t.d,t.d=e,t.Db&4&&!(t.Db&1)&&mi(t,new Js(t,1,1,n,t.d))}function git(t,e){var n;n=t.D,t.D=e,t.Db&4&&!(t.Db&1)&&mi(t,new Js(t,1,2,n,t.D))}function pit(t,e){t.r>0&&t.c0&&t.g!=0&&pit(t.i,e/t.r*t.i.d))}function pcn(t,e,n){var r;t.b=e,t.a=n,r=(t.a&512)==512?new Vqt:new XL,t.c=Dvn(r,t.b,t.a)}function lne(t,e){return X0(t.e,e)?(to(),ait(e)?new qj(e,t):new BM(e,t)):new nUt(e,t)}function hz(t,e){return eXe(W9(t.a,e,Ar(_a(i0,Xd(Ar(_a(e==null?0:Hi(e),s0)),15)))))}function bcn(t,e,n){return Zm(t,new ge(e),new Kn,new be(n),lt(ct(fl,1),oe,132,0,[]))}function wcn(t){var e,n;return 0>t?new mbt:(e=t+1,n=new PJt(e,t),new Z2t(null,n))}function vcn(t,e){wn();var n;return n=new Lx(1),ra(t)?ko(n,t,e):au(n.f,t,e),new q(n)}function mcn(t,e){var n,r;return n=t.o+t.p,r=e.o+e.p,ne?(e<<=1,e>0?e:D_):e}function bit(t){switch(L2t(t.e!=3),t.e){case 2:return!1;case 0:return!0}return Can(t)}function fne(t,e){var n;return _t(e,8)?(n=u(e,8),t.a==n.a&&t.b==n.b):!1}function wit(t,e,n){var r,s,o;return o=e>>5,s=e&31,r=Ns(Vm(t.n[n][o],Ar(F0(s,1))),3),r}function xcn(t,e){var n,r;for(r=e.vc().Kc();r.Ob();)n=u(r.Pb(),42),aq(t,n.cd(),n.dd())}function kcn(t,e){var n;n=new vp,u(e.b,65),u(e.b,65),u(e.b,65),xu(e.a,new Awt(t,n,e))}function cyt(t,e){var n;n=t.b,t.b=e,t.Db&4&&!(t.Db&1)&&mi(t,new Js(t,1,21,n,t.b))}function uyt(t,e){var n;n=t.d,t.d=e,t.Db&4&&!(t.Db&1)&&mi(t,new Js(t,1,11,n,t.d))}function fz(t,e){var n;n=t.j,t.j=e,t.Db&4&&!(t.Db&1)&&mi(t,new Js(t,1,13,n,t.j))}function dne(t,e,n){var r,s,o;for(o=t.a.length-1,s=t.b,r=0;r>>31;r!=0&&(t[n]=r)}function Icn(t,e){wn();var n,r;for(r=new he,n=0;n0&&(this.g=this.ri(this.i+(this.i/8|0)+1),t.Qc(this.g))}function ss(t,e){Rj.call(this,E5e,t,e),this.b=this,this.a=ou(t.Tg(),yn(this.e.Tg(),this.c))}function Y9(t,e){var n,r;for(On(e),r=e.vc().Kc();r.Ob();)n=u(r.Pb(),42),t.zc(n.cd(),n.dd())}function qcn(t,e,n){var r;for(r=n.Kc();r.Ob();)if(!O$(t,e,r.Pb()))return!1;return!0}function Hcn(t,e,n,r,s){var o;return n&&(o=Gi(e.Tg(),t.c),s=n.gh(e,-1-(o==-1?r:o),null,s)),s}function Vcn(t,e,n,r,s){var o;return n&&(o=Gi(e.Tg(),t.c),s=n.ih(e,-1-(o==-1?r:o),null,s)),s}function Ine(t){var e;if(t.b==-2){if(t.e==0)e=-1;else for(e=0;t.a[e]==0;e++);t.b=e}return t.b}function One(t){switch(t.g){case 2:return ve(),Bn;case 4:return ve(),Hn;default:return t}}function Pne(t){switch(t.g){case 1:return ve(),mr;case 3:return ve(),Pn;default:return t}}function Gcn(t){var e,n,r;return t.j==(ve(),Pn)&&(e=uce(t),n=Nu(e,Hn),r=Nu(e,Bn),r||r&&n)}function Ucn(t){var e,n;return e=u(t.e&&t.e(),9),n=u(yvt(e,e.length),9),new sh(e,n,e.length)}function Wcn(t,e){vr(e,k1e,1),p3t(dXe(new er((VC(),new hrt(t,!1,!1,new aN))))),or(e)}function ID(t,e){return Nn(),ra(t)?kmt(t,Br(e)):Bm(t)?Unt(t,ye(e)):Nm(t)?Qen(t,Re(e)):t.wd(e)}function pyt(t,e){e.q=t,t.d=b.Math.max(t.d,e.r),t.b+=e.d+(t.a.c.length==0?0:t.c),le(t.a,e)}function Q8(t,e){var n,r,s,o;return s=t.c,n=t.c+t.b,o=t.d,r=t.d+t.a,e.a>s&&e.ao&&e.b1||t.Ob())return++t.a,t.g=0,e=t.i,t.Ob(),e;throw it(new lc)}function sun(t){FUt();var e;return GVt(Dht,t)||(e=new RQ,e.a=t,swt(Dht,t,e)),u(po(Dht,t),635)}function Lh(t){var e,n,r,s;return s=t,r=0,s<0&&(s+=C2,r=Z0),n=ps(s/m6),e=ps(s-n*m6),iu(e,n,r)}function OD(t){var e,n,r;for(r=0,n=new Mx(t.a);n.a>22),s=t.h+e.h+(r>>22),iu(n&hl,r&hl,s&Z0)}function tre(t,e){var n,r,s;return n=t.l-e.l,r=t.m-e.m+(n>>22),s=t.h-e.h+(r>>22),iu(n&hl,r&hl,s&Z0)}function BD(t){var e;return t<128?(e=(pKt(),hEt)[t],!e&&(e=hEt[t]=new hR(t)),e):new hR(t)}function Wi(t){var e;return _t(t,78)?t:(e=t&&t.__java$exception,e||(e=new Hre(t),aqt(e)),e)}function RD(t){if(_t(t,186))return u(t,118);if(t)return null;throw it(new Sx(Kde))}function ere(t,e){if(e==null)return!1;for(;t.a!=t.b;)if(yi(e,Mz(t)))return!0;return!1}function xyt(t){return t.a.Ob()?!0:t.a!=t.d?!1:(t.a=new emt(t.e.f),t.a.Ob())}function Ls(t,e){var n,r;return n=e.Pc(),r=n.length,r==0?!1:(Pwt(t.c,t.c.length,n),!0)}function yun(t,e,n){var r,s;for(s=e.vc().Kc();s.Ob();)r=u(s.Pb(),42),t.yc(r.cd(),r.dd(),n);return t}function nre(t,e){var n,r;for(r=new S(t.b);r.a=0,"Negative initial capacity"),Bj(e>=0,"Non-positive load factor"),Xu(this)}function Sit(t,e,n){return t>=128?!1:t<64?u9(Ns(F0(1,t),n),0):u9(Ns(F0(1,t-64),e),0)}function Lun(t,e){return!t||!e||t==e?!1:av(t.b.c,e.b.c+e.b.b)<0&&av(e.b.c,t.b.c+t.b.b)<0}function gre(t){var e,n,r;return n=t.n,r=t.o,e=t.d,new ah(n.a-e.b,n.b-e.d,r.a+(e.b+e.c),r.b+(e.d+e.a))}function Mun(t){var e,n,r,s;for(n=t.a,r=0,s=n.length;rr)throw it(new qm(e,r));return t.hi()&&(n=DQt(t,n)),t.Vh(e,n)}function zD(t,e,n){return n==null?(!t.q&&(t.q=new _r),Jx(t.q,e)):(!t.q&&(t.q=new _r),ki(t.q,e,n)),t}function Jt(t,e,n){return n==null?(!t.q&&(t.q=new _r),Jx(t.q,e)):(!t.q&&(t.q=new _r),ki(t.q,e,n)),t}function pre(t){var e,n;return n=new B$,Mo(n,t),Jt(n,(Yp(),I6),t),e=new _r,Pyn(t,n,e),a5n(t,n,e),n}function Oun(t){k4();var e,n,r;for(n=Nt(Ws,ee,8,2,0,1),r=0,e=0;e<2;e++)r+=.5,n[e]=g1n(r,t);return n}function bre(t,e){var n,r,s,o;for(n=!1,r=t.a[e].length,o=0;o>=1);return e}function vre(t){var e,n;return n=pI(t.h),n==32?(e=pI(t.m),e==32?pI(t.l)+32:e+20-10):n-12}function Q9(t){var e;return e=t.a[t.b],e==null?null:(ts(t.a,t.b,null),t.b=t.b+1&t.a.length-1,e)}function mre(t){var e,n;return e=t.t-t.k[t.o.p]*t.d+t.j[t.o.p]>t.f,n=t.u+t.e[t.o.p]*t.d>t.f*t.s*t.d,e||n}function _z(t,e,n){var r,s;return r=new Qrt(e,n),s=new zt,t.b=lue(t,t.b,r,s),s.b||++t.c,t.b.b=!1,s.d}function yre(t,e,n){var r,s,o,h;for(h=t_(e,n),o=0,s=h.Kc();s.Ob();)r=u(s.Pb(),11),ki(t.c,r,pe(o++))}function Xp(t){var e,n;for(n=new S(t.a.b);n.an&&(n=t[e]);return n}function xre(t,e,n){var r;return r=new he,R5t(t,e,r,(ve(),Hn),!0,!1),R5t(t,n,r,Bn,!1,!1),r}function Lit(t,e,n){var r,s,o,h;return o=null,h=e,s=Kw(h,"labels"),r=new zGt(t,n),o=(Zbn(r.a,r.b,s),s),o}function Fun(t,e,n,r){var s;return s=C5t(t,e,n,r),!s&&(s=Nln(t,n,r),s&&!C4(t,e,s))?null:s}function Nun(t,e,n,r){var s;return s=_5t(t,e,n,r),!s&&(s=Uit(t,n,r),s&&!C4(t,e,s))?null:s}function kre(t,e){var n;for(n=0;n1||e>=0&&t.b<3)}function qD(t){var e,n,r;for(e=new Pu,r=ei(t,0);r.b!=r.d.c;)n=u(ti(r),8),m8(e,0,new xo(n));return e}function g2(t){var e,n;for(n=new S(t.a.b);n.ar?1:0}function $yt(t,e){return Uce(t,e)?(ln(t.b,u(Q(e,(ae(),By)),21),e),ri(t.a,e),!0):!1}function Yun(t){var e,n;e=u(Q(t,(ae(),Ju)),10),e&&(n=e.c,mu(n.a,e),n.a.c.length==0&&mu(Na(e).b,n))}function Are(t){return $1?Nt(Zge,Mfe,572,0,0,1):u(P1(t.a,Nt(Zge,Mfe,572,t.a.c.length,0,1)),842)}function Kun(t,e,n,r){return c$(),new uet(lt(ct(P2,1),Hq,42,0,[(kst(t,e),new Lw(t,e)),(kst(n,r),new Lw(n,r))]))}function a4(t,e,n){var r,s;return s=(r=new iet,r),bo(s,e,n),Dr((!t.q&&(t.q=new fe(Wh,t,11,10)),t.q),s),s}function Oit(t){var e,n,r,s;for(s=xXe(Z4e,t),n=s.length,r=Nt(Ae,ee,2,n,6,1),e=0;e=t.b.c.length||(zyt(t,2*e+1),n=2*e+2,n=0&&t[r]===e[r];r--);return r<0?0:Cet(Ns(t[r],co),Ns(e[r],co))?-1:1}function Xun(t,e){var n,r;for(r=ei(t,0);r.b!=r.d.c;)n=u(ti(r),214),n.e.length>0&&(e.td(n),n.i&&Vln(n))}function Fit(t,e){var n,r;return r=u(Dn(t.a,4),126),n=Nt(Fft,lut,415,e,0,1),r!=null&&Dc(r,0,n,0,r.length),n}function Mre(t,e){var n;return n=new fat((t.f&256)!=0,t.i,t.a,t.d,(t.f&16)!=0,t.j,t.g,e),t.e!=null||(n.c=t),n}function Qun(t,e){var n,r;for(r=t.Zb().Cc().Kc();r.Ob();)if(n=u(r.Pb(),14),n.Hc(e))return!0;return!1}function Nit(t,e,n,r,s){var o,h;for(h=n;h<=s;h++)for(o=e;o<=r;o++)if(f4(t,o,h))return!0;return!1}function Dre(t,e,n){var r,s,o,h;for(On(n),h=!1,o=t.Zc(e),s=n.Kc();s.Ob();)r=s.Pb(),o.Rb(r),h=!0;return h}function Zun(t,e){var n;return t===e?!0:_t(e,83)?(n=u(e,83),H4t(Rw(t),n.vc())):!1}function Ire(t,e,n){var r,s;for(s=n.Kc();s.Ob();)if(r=u(s.Pb(),42),t.re(e,r.dd()))return!0;return!1}function Ore(t,e,n){return t.d[e.p][n.p]||(Yfn(t,e,n),t.d[e.p][n.p]=!0,t.d[n.p][e.p]=!0),t.a[e.p][n.p]}function sE(t,e){if(!t.ai()&&e==null)throw it(new Fn("The 'no null' constraint is violated"));return e}function aE(t,e){t.D==null&&t.B!=null&&(t.D=t.B,t.B=null),git(t,e==null?null:(On(e),e)),t.C&&t.yk(null)}function Jun(t,e){var n;return!t||t==e||!Us(e,(ae(),Pv))?!1:(n=u(Q(e,(ae(),Pv)),10),n!=t)}function Bit(t){switch(t.i){case 2:return!0;case 1:return!1;case-1:++t.c;default:return t.pl()}}function Pre(t){switch(t.i){case-2:return!0;case-1:return!1;case 1:--t.c;default:return t.ql()}}function Fre(t){TQt.call(this,"The given string does not match the expected format for individual spacings.",t)}function Sl(){Sl=Z,Ql=new uj("ELK",0),qAt=new uj("JSON",1),zAt=new uj("DOT",2),HAt=new uj("SVG",3)}function HD(){HD=Z,NG=new Yet(J0,0),k_t=new Yet("RADIAL_COMPACTION",1),E_t=new Yet("WEDGE_COMPACTION",2)}function O1(){O1=Z,BEt=new _et("CONCURRENT",0),Ul=new _et("IDENTITY_FINISH",1),Iy=new _et("UNORDERED",2)}function Rit(){Rit=Z,f7t=(jR(),Kut),h7t=new mn(o6t,f7t),Xpe=new Vi(c6t),Qpe=new Vi(u6t),Zpe=new Vi(l6t)}function oE(){oE=Z,CTt=new J5,_Tt=new ZK,l2e=new OL,u2e=new JK,c2e=new tX,TTt=(On(c2e),new gn)}function cE(){cE=Z,Aht=new Het("CONSERVATIVE",0),K9t=new Het("CONSERVATIVE_SOFT",1),PS=new Het("SLOPPY",2)}function Sz(){Sz=Z,MAt=new Ow(15),T4e=new eo((ui(),U2),MAt),QS=Y6,_At=o4e,SAt=G2,LAt=c5,AAt=XG}function jit(t,e,n){var r,s,o;for(r=new Zi,o=ei(n,0);o.b!=o.d.c;)s=u(ti(o),8),ri(r,new xo(s));Dre(t,e,r)}function tln(t){var e,n,r;for(e=0,r=Nt(Ws,ee,8,t.b,0,1),n=ei(t,0);n.b!=n.d.c;)r[e++]=u(ti(n),8);return r}function Hyt(t){var e;return e=(!t.a&&(t.a=new fe(ag,t,9,5)),t.a),e.i!=0?vXe(u(At(e,0),678)):null}function eln(t,e){var n;return n=Pa(t,e),Cet(Drt(t,e),0)|PXe(Drt(t,n),0)?n:Pa(qq,Drt(Vm(n,63),1))}function nln(t,e){var n;n=Ie((nst(),vG))!=null&&e.wg()!=null?Xt(ye(e.wg()))/Xt(ye(Ie(vG))):1,ki(t.b,e,n)}function rln(t,e){var n,r;return n=u(t.d.Bc(e),14),n?(r=t.e.hc(),r.Gc(n),t.e.d-=n.gc(),n.$b(),r):null}function Vyt(t,e){var n,r;if(r=t.c[e],r!=0)for(t.c[e]=0,t.d-=r,n=e+1;n0)return T8(e-1,t.a.c.length),Fg(t.a,e-1);throw it(new cqt)}function iln(t,e,n){if(e<0)throw it(new yo(sde+e));ee)throw it(new Fn(Wq+t+Dfe+e));if(t<0||e>n)throw it(new ibt(Wq+t+Yxt+e+Uxt+n))}function Rre(t){if(!t.a||!(t.a.i&8))throw it(new No("Enumeration class expected for layout option "+t.f))}function iy(t){var e;++t.j,t.i==0?t.g=null:t.ikH?t-n>kH:n-t>kH}function zit(t,e){return!t||e&&!t.j||_t(t,124)&&u(t,124).a.b==0?0:t.Re()}function Lz(t,e){return!t||e&&!t.k||_t(t,124)&&u(t,124).a.a==0?0:t.Se()}function VD(t){return rb(),t<0?t!=-1?new j3t(-1,-t):But:t<=10?CEt[ps(t)]:new j3t(1,t)}function Uyt(t){throw _it(),it(new eHt("Unexpected typeof result '"+t+"'; please report this bug to the GWT team"))}function Hre(t){oHt(),yj(this),d$(this),this.e=t,nue(this,t),this.g=t==null?_u:$o(t),this.a="",this.b=t,this.a=""}function Wyt(){this.a=new vZ,this.f=new X$t(this),this.b=new Q$t(this),this.i=new Z$t(this),this.e=new J$t(this)}function Vre(){dKe.call(this,new Mmt(ty(16))),jl(2,ffe),this.b=2,this.a=new Lvt(null,null,0,null),dM(this.a,this.a)}function Z9(){Z9=Z,vht=new jet("DUMMY_NODE_OVER",0),O9t=new jet("DUMMY_NODE_UNDER",1),yG=new jet("EQUAL",2)}function qit(){qit=Z,olt=_Qt(lt(ct(XS,1),oe,103,0,[(ao(),zh),Cf])),clt=_Qt(lt(ct(XS,1),oe,103,0,[rg,ng]))}function Hit(t){return(ve(),Au).Hc(t.j)?Xt(ye(Q(t,(ae(),k7)))):Yo(lt(ct(Ws,1),ee,8,0,[t.i.n,t.n,t.a])).b}function uln(t){var e,n,r,s;for(r=t.b.a,n=r.a.ec().Kc();n.Ob();)e=u(n.Pb(),561),s=new Nce(e,t.e,t.f),le(t.g,s)}function b2(t,e){var n,r,s;r=t.nk(e,null),s=null,e&&(s=(c8(),n=new xw,n),H8(s,t.r)),r=F1(t,s,r),r&&r.Fi()}function lln(t,e){var n,r;for(r=ul(t.d,1)!=0,n=!0;n;)n=!1,n=e.c.Tf(e.e,r),n=n|yI(t,e,r,!1),r=!r;hyt(t)}function Yyt(t,e){var n,r,s;return r=!1,n=e.q.d,e.ds&&(bae(e.q,s),r=n!=e.q.d)),r}function Gre(t,e){var n,r,s,o,h,d,v,k;return v=e.i,k=e.j,r=t.f,s=r.i,o=r.j,h=v-s,d=k-o,n=b.Math.sqrt(h*h+d*d),n}function Kyt(t,e){var n,r;return r=Hz(t),r||(n=(Fat(),woe(e)),r=new Jzt(n),Dr(r.Vk(),t)),r}function GD(t,e){var n,r;return n=u(t.c.Bc(e),14),n?(r=t.hc(),r.Gc(n),t.d-=n.gc(),n.$b(),t.mc(r)):t.jc()}function Ure(t,e){var n;for(n=0;n=t.c.b:t.a<=t.c.b))throw it(new lc);return e=t.a,t.a+=t.c.c,++t.b,pe(e)}function dln(t){var e;return e=new Cee(t),hD(t.a,Wbe,new yl(lt(ct(mO,1),De,369,0,[e]))),e.d&&le(e.f,e.d),e.f}function Vit(t){var e;return e=new b2t(t.a),Mo(e,t),Jt(e,(ae(),_i),t),e.o.a=t.g,e.o.b=t.f,e.n.a=t.i,e.n.b=t.j,e}function gln(t,e,n,r){var s,o;for(o=t.Kc();o.Ob();)s=u(o.Pb(),70),s.n.a=e.a+(r.a-s.o.a)/2,s.n.b=e.b,e.b+=s.o.b+n}function pln(t,e,n){var r,s;for(s=e.a.a.ec().Kc();s.Ob();)if(r=u(s.Pb(),57),sQt(t,r,n))return!0;return!1}function bln(t){var e,n;for(n=new S(t.r);n.a=0?e:-e;r>0;)r%2==0?(n*=n,r=r/2|0):(s*=n,r-=1);return e<0?1/s:s}function yln(t,e){var n,r,s;for(s=1,n=t,r=e>=0?e:-e;r>0;)r%2==0?(n*=n,r=r/2|0):(s*=n,r-=1);return e<0?1/s:s}function Jre(t){var e,n;if(t!=null)for(n=0;n0&&(n=u(Ne(t.a,t.a.c.length-1),570),$yt(n,e))||le(t.a,new IJt(e))}function Cln(t){df();var e,n;e=t.d.c-t.e.c,n=u(t.g,145),xu(n.b,new AC(e)),xu(n.c,new Yb(e)),va(n.i,new dR(e))}function rie(t){var e;return e=new Mp,e.a+="VerticalSegment ",hc(e,t.e),e.a+=" ",Gr(e,_2t(new vet,new S(t.k))),e.a}function _ln(t){var e;return e=u(Xw(t.c.c,""),229),e||(e=new Yx(o8(a8(new xm,""),"Other")),m2(t.c.c,"",e)),e}function J9(t){var e;return t.Db&64?mf(t):(e=new _h(mf(t)),e.a+=" (name: ",go(e,t.zb),e.a+=")",e.a)}function t3t(t,e,n){var r,s;return s=t.sb,t.sb=e,t.Db&4&&!(t.Db&1)&&(r=new Js(t,1,4,s,e),n?n.Ei(r):n=r),n}function Git(t,e){var n,r,s;for(n=0,s=Ko(t,e).Kc();s.Ob();)r=u(s.Pb(),11),n+=Q(r,(ae(),Ju))!=null?1:0;return n}function c4(t,e,n){var r,s,o;for(r=0,o=ei(t,0);o.b!=o.d.c&&(s=Xt(ye(ti(o))),!(s>n));)s>=e&&++r;return r}function Sln(t,e,n){var r,s;return r=new z0(t.e,3,13,null,(s=e.c,s||(dn(),W1)),Hg(t,e),!1),n?n.Ei(r):n=r,n}function Aln(t,e,n){var r,s;return r=new z0(t.e,4,13,(s=e.c,s||(dn(),W1)),null,Hg(t,e),!1),n?n.Ei(r):n=r,n}function e3t(t,e,n){var r,s;return s=t.r,t.r=e,t.Db&4&&!(t.Db&1)&&(r=new Js(t,1,8,s,t.r),n?n.Ei(r):n=r),n}function $g(t,e){var n,r;return n=u(e,676),r=n.vk(),!r&&n.wk(r=_t(e,88)?new JGt(t,u(e,26)):new yZt(t,u(e,148))),r}function UD(t,e,n){var r;t.qi(t.i+1),r=t.oi(e,n),e!=t.i&&Dc(t.g,e,t.g,e+1,t.i-e),ts(t.g,e,r),++t.i,t.bi(e,n),t.ci()}function Lln(t,e){var n;return e.a&&(n=e.a.a.length,t.a?Gr(t.a,t.b):t.a=new Ol(t.d),kZt(t.a,e.a,e.d.length,n)),t}function Mln(t,e){var n,r,s,o;if(e.vi(t.a),o=u(Dn(t.a,8),1936),o!=null)for(n=o,r=0,s=n.length;rn)throw it(new yo(Wq+t+Yxt+e+", size: "+n));if(t>e)throw it(new Fn(Wq+t+Dfe+e))}function fh(t,e,n){if(e<0)i5t(t,n);else{if(!n.Ij())throw it(new Fn(lb+n.ne()+X_));u(n,66).Nj().Vj(t,t.yh(),e)}}function Oln(t,e,n,r,s,o,h,d){var v;for(v=n;o=r||e=65&&t<=70?t-65+10:t>=97&&t<=102?t-97+10:t>=48&&t<=57?t-48:0}function lie(t){var e;return t.Db&64?mf(t):(e=new _h(mf(t)),e.a+=" (source: ",go(e,t.d),e.a+=")",e.a)}function Fln(t,e,n){var r,s;return s=t.a,t.a=e,t.Db&4&&!(t.Db&1)&&(r=new Js(t,1,5,s,t.a),n?T4t(n,r):n=r),n}function zg(t,e){var n;n=(t.Bb&256)!=0,e?t.Bb|=256:t.Bb&=-257,t.Db&4&&!(t.Db&1)&&mi(t,new bf(t,1,2,n,e))}function r3t(t,e){var n;n=(t.Bb&256)!=0,e?t.Bb|=256:t.Bb&=-257,t.Db&4&&!(t.Db&1)&&mi(t,new bf(t,1,8,n,e))}function Iz(t,e){var n;n=(t.Bb&256)!=0,e?t.Bb|=256:t.Bb&=-257,t.Db&4&&!(t.Db&1)&&mi(t,new bf(t,1,8,n,e))}function qg(t,e){var n;n=(t.Bb&512)!=0,e?t.Bb|=512:t.Bb&=-513,t.Db&4&&!(t.Db&1)&&mi(t,new bf(t,1,3,n,e))}function i3t(t,e){var n;n=(t.Bb&512)!=0,e?t.Bb|=512:t.Bb&=-513,t.Db&4&&!(t.Db&1)&&mi(t,new bf(t,1,9,n,e))}function e_(t,e){var n;return t.b==-1&&t.a&&(n=t.a.Gj(),t.b=n?t.c.Xg(t.a.aj(),n):Gi(t.c.Tg(),t.a)),t.c.Og(t.b,e)}function pe(t){var e,n;return t>-129&&t<128?(e=t+128,n=(cKt(),fEt)[e],!n&&(n=fEt[e]=new uM(t)),n):new uM(t)}function uE(t){var e,n;return t>-129&&t<128?(e=t+128,n=(gKt(),bEt)[e],!n&&(n=bEt[e]=new fR(t)),n):new fR(t)}function s3t(t){var e,n;return e=t.k,e==(Vn(),ks)?(n=u(Q(t,(ae(),oc)),61),n==(ve(),Pn)||n==mr):!1}function Nln(t,e,n){var r,s,o;return o=(s=_E(t.b,e),s),o&&(r=u(Pq(TD(t,o),""),26),r)?C5t(t,r,e,n):null}function Uit(t,e,n){var r,s,o;return o=(s=_E(t.b,e),s),o&&(r=u(Pq(TD(t,o),""),26),r)?_5t(t,r,e,n):null}function hie(t,e){var n,r;for(r=new nr(t);r.e!=r.i.gc();)if(n=u(dr(r),138),Vt(e)===Vt(n))return!0;return!1}function n_(t,e,n){var r;if(r=t.gc(),e>r)throw it(new qm(e,r));if(t.hi()&&t.Hc(n))throw it(new Fn(eO));t.Xh(e,n)}function Bln(t,e){var n;if(n=n4(t.i,e),n==null)throw it(new ud("Node did not exist in input."));return byt(e,n),null}function Rln(t,e){var n;if(n=mI(t,e),_t(n,322))return u(n,34);throw it(new Fn(lb+e+"' is not a valid attribute"))}function jln(t,e,n){var r,s;for(s=_t(e,99)&&u(e,18).Bb&Ka?new rnt(e,t):new tE(e,t),r=0;re?1:t==e?t==0?Ms(1/t,1/e):0:isNaN(t)?isNaN(e)?0:1:-1}function Yln(t,e){vr(e,"Sort end labels",1),ls(Ri(Wo(new Tn(null,new _n(t.b,16)),new cN),new K5),new AK),or(e)}function r_(t,e,n){var r,s;return t.ej()?(s=t.fj(),r=Jst(t,e,n),t.$i(t.Zi(7,pe(n),r,e,s)),r):Jst(t,e,n)}function Wit(t,e){var n,r,s;t.d==null?(++t.e,--t.f):(s=e.cd(),n=e.Sh(),r=(n&wi)%t.d.length,Dan(t,r,Lce(t,r,n,s)))}function lE(t,e){var n;n=(t.Bb&xf)!=0,e?t.Bb|=xf:t.Bb&=-1025,t.Db&4&&!(t.Db&1)&&mi(t,new bf(t,1,10,n,e))}function hE(t,e){var n;n=(t.Bb&Ey)!=0,e?t.Bb|=Ey:t.Bb&=-4097,t.Db&4&&!(t.Db&1)&&mi(t,new bf(t,1,12,n,e))}function fE(t,e){var n;n=(t.Bb&Hu)!=0,e?t.Bb|=Hu:t.Bb&=-8193,t.Db&4&&!(t.Db&1)&&mi(t,new bf(t,1,15,n,e))}function dE(t,e){var n;n=(t.Bb&Dy)!=0,e?t.Bb|=Dy:t.Bb&=-2049,t.Db&4&&!(t.Db&1)&&mi(t,new bf(t,1,11,n,e))}function Kln(t,e){var n;return n=Ms(t.b.c,e.b.c),n!=0||(n=Ms(t.a.a,e.a.a),n!=0)?n:Ms(t.a.b,e.a.b)}function Xln(t,e){var n;if(n=tr(t.k,e),n==null)throw it(new ud("Port did not exist in input."));return byt(e,n),null}function Qln(t){var e,n;for(n=Pce(Rl(t)).Kc();n.Ob();)if(e=Br(n.Pb()),k_(t,e))return san((HVt(),l5e),e);return null}function Zln(t,e){var n,r,s,o,h;for(h=ou(t.e.Tg(),e),o=0,n=u(t.g,119),s=0;s>10)+RI&ys,e[1]=(t&1023)+56320&ys,Mh(e,0,e.length)}function Pz(t){var e,n;return n=u(Q(t,(Te(),Wl)),103),n==(ao(),h0)?(e=Xt(ye(Q(t,rG))),e>=1?Cf:ng):n}function ehn(t){switch(u(Q(t,(Te(),eg)),218).g){case 1:return new YX;case 3:return new JX;default:return new WX}}function w2(t){if(t.c)w2(t.c);else if(t.d)throw it(new No("Stream already terminated, can't be modified or used"))}function Xit(t){var e;return t.Db&64?mf(t):(e=new _h(mf(t)),e.a+=" (identifier: ",go(e,t.k),e.a+=")",e.a)}function pie(t,e,n){var r,s;return r=(Sw(),s=new xp,s),iz(r,e),sz(r,n),t&&Dr((!t.a&&(t.a=new As(Gh,t,5)),t.a),r),r}function Qit(t,e,n,r){var s,o;return On(r),On(n),s=t.xc(e),o=s==null?n:MVt(u(s,15),u(n,14)),o==null?t.Bc(e):t.zc(e,o),o}function un(t){var e,n,r,s;return n=(e=u(Vf((r=t.gm,s=r.f,s==Hr?r:s)),9),new sh(e,u(ff(e,e.length),9),0)),vf(n,t),n}function nhn(t,e,n){var r,s;for(s=t.a.ec().Kc();s.Ob();)if(r=u(s.Pb(),10),ND(n,u(Ne(e,r.p),14)))return r;return null}function rhn(t,e,n){var r;try{Bun(t,e,n)}catch(s){throw s=Wi(s),_t(s,597)?(r=s,it(new dmt(r))):it(s)}return e}function Jp(t,e){var n;return Bo(t)&&Bo(e)&&(n=t-e,BI>1,t.k=n-1>>1}function Zit(){M4t();var t,e,n;n=Jxn+++Date.now(),t=ps(b.Math.floor(n*$I))&Uq,e=ps(n-t*Gxt),this.a=t^1502,this.b=e^Eot}function U0(t){var e,n,r;for(e=new he,r=new S(t.j);r.a34028234663852886e22?as:e<-34028234663852886e22?Cs:e}function bie(t){return t-=t>>1&1431655765,t=(t>>2&858993459)+(t&858993459),t=(t>>4)+t&252645135,t+=t>>8,t+=t>>16,t&63}function wie(t){var e,n,r,s;for(e=new QWt(t.Hd().gc()),s=0,r=e6(t.Hd().Kc());r.Ob();)n=r.Pb(),vin(e,n,pe(s++));return Hgn(e.a)}function uhn(t,e){var n,r,s;for(s=new _r,r=e.vc().Kc();r.Ob();)n=u(r.Pb(),42),ki(s,n.cd(),tun(t,u(n.dd(),15)));return s}function h3t(t,e){t.n.c.length==0&&le(t.n,new E$(t.s,t.t,t.i)),le(t.b,e),W3t(u(Ne(t.n,t.n.c.length-1),211),e),Sle(t,e)}function u4(t){return(t.c!=t.b.b||t.i!=t.g.b)&&(t.a.c=Nt(Qn,De,1,0,5,1),Ls(t.a,t.b),Ls(t.a,t.g),t.c=t.b.b,t.i=t.g.b),t.a}function Jit(t,e){var n,r,s;for(s=0,r=u(e.Kb(t),20).Kc();r.Ob();)n=u(r.Pb(),17),je(Re(Q(n,(ae(),q1))))||++s;return s}function lhn(t,e){var n,r,s;r=t4(e),s=Xt(ye(oy(r,(Te(),Tf)))),n=b.Math.max(0,s/2-.5),h_(e,n,1),le(t,new uGt(e,n))}function dh(){dh=Z,MO=new MM(J0,0),ES=new MM("FIRST",1),bb=new MM(C1e,2),TS=new MM("LAST",3),jy=new MM(_1e,4)}function W0(){W0=Z,Cft=new sj(N_,0),eP=new sj("POLYLINE",1),N7=new sj("ORTHOGONAL",2),X6=new sj("SPLINES",3)}function Fz(){Fz=Z,z_t=new Xet("ASPECT_RATIO_DRIVEN",0),Qht=new Xet("MAX_SCALE_DRIVEN",1),$_t=new Xet("AREA_DRIVEN",2)}function KD(){KD=Z,jG=new Qet("P1_STRUCTURE",0),$G=new Qet("P2_PROCESSING_ORDER",1),zG=new Qet("P3_EXECUTION",2)}function Nz(){Nz=Z,Ght=new Wet("OVERLAP_REMOVAL",0),Hht=new Wet("COMPACTION",1),Vht=new Wet("GRAPH_SIZE_CALCULATION",2)}function av(t,e){return k1(),wf(sb),b.Math.abs(t-e)<=sb||t==e||isNaN(t)&&isNaN(e)?0:te?1:Iw(isNaN(t),isNaN(e))}function vie(t,e){var n,r;for(n=ei(t,0);n.b!=n.d.c;){if(r=pM(ye(ti(n))),r==e)return;if(r>e){Ort(n);break}}eD(n,e)}function an(t,e){var n,r,s,o,h;if(n=e.f,m2(t.c.d,n,e),e.g!=null)for(s=e.g,o=0,h=s.length;oe&&r.ue(t[o-1],t[o])>0;--o)h=t[o],ts(t,o,t[o-1]),ts(t,o-1,h)}function gh(t,e,n,r){if(e<0)M5t(t,n,r);else{if(!n.Ij())throw it(new Fn(lb+n.ne()+X_));u(n,66).Nj().Tj(t,t.yh(),e,r)}}function Bz(t,e){if(e==t.d)return t.e;if(e==t.e)return t.d;throw it(new Fn("Node "+e+" not part of edge "+t))}function fhn(t,e){switch(e.g){case 2:return t.b;case 1:return t.c;case 4:return t.d;case 3:return t.a;default:return!1}}function mie(t,e){switch(e.g){case 2:return t.b;case 1:return t.c;case 4:return t.d;case 3:return t.a;default:return!1}}function f3t(t,e,n,r){switch(e){case 3:return t.f;case 4:return t.g;case 5:return t.i;case 6:return t.j}return n3t(t,e,n,r)}function dhn(t){return t.k!=(Vn(),Os)?!1:N8(new Tn(null,new jw(new ar(lr(Ds(t).a.Kc(),new z)))),new $N)}function ghn(t){return t.e==null?t:(!t.c&&(t.c=new fat((t.f&256)!=0,t.i,t.a,t.d,(t.f&16)!=0,t.j,t.g,null)),t.c)}function phn(t,e){return t.h==NI&&t.m==0&&t.l==0?(e&&(hb=iu(0,0,0)),yUt((q8(),aEt))):(e&&(hb=iu(t.l,t.m,t.h)),iu(0,0,0))}function $o(t){var e;return Array.isArray(t)&&t.im===Et?Ip(ol(t))+"@"+(e=Hi(t)>>>0,e.toString(16)):t.toString()}function i_(t){var e;this.a=(e=u(t.e&&t.e(),9),new sh(e,u(ff(e,e.length),9),0)),this.b=Nt(Qn,De,1,this.a.a.length,5,1)}function bhn(t){var e,n,r;for(this.a=new O0,r=new S(t);r.a0&&(Rr(e-1,t.length),t.charCodeAt(e-1)==58)&&!tst(t,oA,cA))}function tst(t,e,n){var r,s;for(r=0,s=t.length;r=s)return e.c+n;return e.c+e.b.gc()}function xhn(t,e){y8();var n,r,s,o;for(r=Ote(t),s=e,$8(r,0,r.length,s),n=0;n0&&(r+=s,++n);return n>1&&(r+=t.d*(n-1)),r}function g3t(t){var e,n,r;for(r=new Ag,r.a+="[",e=0,n=t.gc();e0&&this.b>0&&Kwt(this.c,this.b,this.a)}function w3t(t){nst(),this.c=A1(lt(ct(w6n,1),De,831,0,[eme])),this.b=new _r,this.a=t,ki(this.b,vG,1),xu(nme,new czt(this))}function yie(t,e){var n;return t.d?Tl(t.b,e)?u(tr(t.b,e),51):(n=e.Kf(),ki(t.b,e,n),n):e.Kf()}function v3t(t,e){var n;return Vt(t)===Vt(e)?!0:_t(e,91)?(n=u(e,91),t.e==n.e&&t.d==n.d&&oan(t,n.a)):!1}function a6(t){switch(ve(),t.g){case 4:return Pn;case 1:return Hn;case 3:return mr;case 2:return Bn;default:return Zo}}function m3t(t,e){switch(e){case 3:return t.f!=0;case 4:return t.g!=0;case 5:return t.i!=0;case 6:return t.j!=0}return vyt(t,e)}function Shn(t){switch(t.g){case 0:return new gZ;case 1:return new tB;default:throw it(new Fn(Ict+(t.f!=null?t.f:""+t.g)))}}function xie(t){switch(t.g){case 0:return new JN;case 1:return new eB;default:throw it(new Fn(Yot+(t.f!=null?t.f:""+t.g)))}}function kie(t){switch(t.g){case 0:return new Qpt;case 1:return new Oqt;default:throw it(new Fn(_H+(t.f!=null?t.f:""+t.g)))}}function Ahn(t){switch(t.g){case 1:return new uZ;case 2:return new jWt;default:throw it(new Fn(Ict+(t.f!=null?t.f:""+t.g)))}}function Lhn(t){var e,n;if(t.b)return t.b;for(n=$1?null:t.d;n;){if(e=$1?null:n.b,e)return e;n=$1?null:n.d}return d8(),NEt}function Mhn(t){var e,n,r;return t.e==0?0:(e=t.d<<5,n=t.a[t.d-1],t.e<0&&(r=Ine(t),r==t.d-1&&(--n,n=n|0)),e-=pI(n),e)}function Dhn(t){var e,n,r;return t>5,e=t&31,r=Nt(Cr,Xr,25,n+1,15,1),r[n]=1<3;)s*=10,--o;t=(t+(s>>1))/s|0}return r.i=t,!0}function Ohn(t){return qit(),Nn(),!!(mie(u(t.a,81).j,u(t.b,103))||u(t.a,81).d.e!=0&&mie(u(t.a,81).j,u(t.b,103)))}function Phn(t){V$(),u(t.We((ui(),xb)),174).Hc((ll(),iU))&&(u(t.We(Qy),174).Fc((Zu(),Q6)),u(t.We(xb),174).Mc(iU))}function Tie(t,e){var n,r;if(e){for(n=0;n=0;--r)for(e=n[r],s=0;s>1,this.k=e-1>>1}function $hn(t,e){vr(e,"End label post-processing",1),ls(Ri(Wo(new Tn(null,new _n(t.b,16)),new kK),new EK),new TK),or(e)}function zhn(t,e,n){var r,s;return r=Xt(t.p[e.i.p])+Xt(t.d[e.i.p])+e.n.b+e.a.b,s=Xt(t.p[n.i.p])+Xt(t.d[n.i.p])+n.n.b+n.a.b,s-r}function qhn(t,e,n){var r,s;for(r=Ns(n,co),s=0;yc(r,0)!=0&&s0&&(Rr(0,e.length),e.charCodeAt(0)==43)?e.substr(1):e))}function Vhn(t){var e;return t==null?null:new Rp((e=$c(t,!0),e.length>0&&(Rr(0,e.length),e.charCodeAt(0)==43)?e.substr(1):e))}function _3t(t,e){var n;return t.i>0&&(e.lengtht.i&&ts(e,t.i,null),e}function Zc(t,e,n){var r,s,o;return t.ej()?(r=t.i,o=t.fj(),UD(t,r,e),s=t.Zi(3,null,e,r,o),n?n.Ei(s):n=s):UD(t,t.i,e),n}function Ghn(t,e,n){var r,s;return r=new z0(t.e,4,10,(s=e.c,_t(s,88)?u(s,26):(dn(),Kh)),null,Hg(t,e),!1),n?n.Ei(r):n=r,n}function Uhn(t,e,n){var r,s;return r=new z0(t.e,3,10,null,(s=e.c,_t(s,88)?u(s,26):(dn(),Kh)),Hg(t,e),!1),n?n.Ei(r):n=r,n}function Sie(t){$m();var e;return e=new xo(u(t.e.We((ui(),c5)),8)),t.B.Hc((ll(),R7))&&(e.a<=0&&(e.a=20),e.b<=0&&(e.b=20)),e}function Aie(t){cy();var e;return(t.q?t.q:(wn(),wn(),u0))._b((Te(),Bv))?e=u(Q(t,Bv),197):e=u(Q(Na(t),AS),197),e}function oy(t,e){var n,r;return r=null,Us(t,(Te(),bG))&&(n=u(Q(t,bG),94),n.Xe(e)&&(r=n.We(e))),r==null&&(r=Q(Na(t),e)),r}function Lie(t,e){var n,r,s;return _t(e,42)?(n=u(e,42),r=n.cd(),s=sy(t.Rc(),r),pd(s,n.dd())&&(s!=null||t.Rc()._b(r))):!1}function ist(t,e){var n,r,s;return t.f>0?(t.qj(),r=e==null?0:Hi(e),s=(r&wi)%t.d.length,n=Lce(t,s,r,e),n!=-1):!1}function Xf(t,e){var n,r,s;return t.f>0&&(t.qj(),r=e==null?0:Hi(e),s=(r&wi)%t.d.length,n=l5t(t,s,r,e),n)?n.dd():null}function XD(t,e){var n,r,s,o;for(o=ou(t.e.Tg(),e),n=u(t.g,119),s=0;s1?S1(F0(e.a[1],32),Ns(e.a[0],co)):Ns(e.a[0],co),Yw(_a(e.e,n))))}function QD(t,e){var n;return Bo(t)&&Bo(e)&&(n=t%e,BI>5,e&=31,s=t.d+n+(e==0?0:1),r=Nt(Cr,Xr,25,s,15,1),W0n(r,t.a,n,e),o=new X3(t.e,s,r),N9(o),o}function A3t(t,e,n){var r,s;r=u(Nc(z7,e),117),s=u(Nc(gA,e),117),n?(ko(z7,t,r),ko(gA,t,s)):(ko(gA,t,r),ko(z7,t,s))}function Nie(t,e,n){var r,s,o;for(s=null,o=t.b;o;){if(r=t.a.ue(e,o.d),n&&r==0)return o;r>=0?o=o.a[1]:(s=o,o=o.a[0])}return s}function Bie(t,e,n){var r,s,o;for(s=null,o=t.b;o;){if(r=t.a.ue(e,o.d),n&&r==0)return o;r<=0?o=o.a[0]:(s=o,o=o.a[1])}return s}function Qhn(t,e,n,r){var s,o,h;return s=!1,I4n(t.f,n,r)&&(kfn(t.f,t.a[e][n],t.a[e][r]),o=t.a[e],h=o[r],o[r]=o[n],o[n]=h,s=!0),s}function L3t(t,e,n,r,s){var o,h,d;for(h=s;e.b!=e.c;)o=u(Hx(e),10),d=u(Ko(o,r).Xb(0),11),t.d[d.p]=h++,n.c[n.c.length]=d;return h}function M3t(t,e,n){var r,s,o,h,d;return h=t.k,d=e.k,r=n[h.g][d.g],s=ye(oy(t,r)),o=ye(oy(e,r)),b.Math.max((On(s),s),(On(o),o))}function Zhn(t,e,n){var r,s,o,h;for(r=n/t.c.length,s=0,h=new S(t);h.a2e3&&(Pge=t,JH=b.setTimeout(sXe,10))),ZH++==0?(Oon((nbt(),rEt)),!0):!1}function tfn(t,e){var n,r,s;for(r=new ar(lr(Ds(t).a.Kc(),new z));zr(r);)if(n=u(Mr(r),17),s=n.d.i,s.c==e)return!1;return!0}function D3t(t,e){var n,r;if(_t(e,245)){r=u(e,245);try{return n=t.vd(r),n==0}catch(s){if(s=Wi(s),!_t(s,205))throw it(s)}}return!1}function efn(){return Error.stackTraceLimit>0?(b.Error.stackTraceLimit=Error.stackTraceLimit=64,!0):"stack"in new Error}function nfn(t,e){return k1(),k1(),wf(sb),(b.Math.abs(t-e)<=sb||t==e||isNaN(t)&&isNaN(e)?0:te?1:Iw(isNaN(t),isNaN(e)))>0}function I3t(t,e){return k1(),k1(),wf(sb),(b.Math.abs(t-e)<=sb||t==e||isNaN(t)&&isNaN(e)?0:te?1:Iw(isNaN(t),isNaN(e)))<0}function $ie(t,e){return k1(),k1(),wf(sb),(b.Math.abs(t-e)<=sb||t==e||isNaN(t)&&isNaN(e)?0:te?1:Iw(isNaN(t),isNaN(e)))<=0}function ast(t,e){for(var n=0;!e[n]||e[n]=="";)n++;for(var r=e[n++];nvot)return n.fh();if(r=n.Zg(),r||n==t)break}return r}function O3t(t){return C$(),_t(t,156)?u(tr(dP,Uge),288).vg(t):Tl(dP,ol(t))?u(tr(dP,ol(t)),288).vg(t):null}function ifn(t){if(Vz(XE,t))return Nn(),r7;if(Vz(Vct,t))return Nn(),F2;throw it(new Fn("Expecting true or false"))}function sfn(t,e){if(e.c==t)return e.d;if(e.d==t)return e.c;throw it(new Fn("Input edge is not connected to the input port."))}function Uie(t,e){return t.e>e.e?1:t.ee.d?t.e:t.d=48&&t<48+b.Math.min(10,10)?t-48:t>=97&&t<97?t-97+10:t>=65&&t<65?t-65+10:-1}function Yie(t,e){var n;return Vt(e)===Vt(t)?!0:!_t(e,21)||(n=u(e,21),n.gc()!=t.gc())?!1:t.Ic(n)}function afn(t,e){var n,r,s,o;return r=t.a.length-1,n=e-t.b&r,o=t.c-e&r,s=t.c-t.b&r,TWt(n=o?(sln(t,e),-1):(aln(t,e),1)}function ofn(t,e){var n,r;for(n=(Rr(e,t.length),t.charCodeAt(e)),r=e+1;re.e?1:t.fe.f?1:Hi(t)-Hi(e)}function Vz(t,e){return On(t),e==null?!1:hn(t,e)?!0:t.length==e.length&&hn(t.toLowerCase(),e.toLowerCase())}function bfn(t,e){var n,r,s,o;for(r=0,s=e.gc();r0&&yc(t,128)<0?(e=Ar(t)+128,n=(dKt(),dEt)[e],!n&&(n=dEt[e]=new Am(t)),n):new Am(t)}function Xie(t,e){var n,r;return n=e.Hh(t.a),n&&(r=Br(Xf((!n.b&&(n.b=new kl((dn(),Qa),cc,n)),n.b),ci)),r!=null)?r:e.ne()}function wfn(t,e){var n,r;return n=e.Hh(t.a),n&&(r=Br(Xf((!n.b&&(n.b=new kl((dn(),Qa),cc,n)),n.b),ci)),r!=null)?r:e.ne()}function vfn(t,e){_rt();var n,r;for(r=new ar(lr(U0(t).a.Kc(),new z));zr(r);)if(n=u(Mr(r),17),n.d.i==e||n.c.i==e)return n;return null}function N3t(t,e,n){this.c=t,this.f=new he,this.e=new Ca,this.j=new Gwt,this.n=new Gwt,this.b=e,this.g=new ah(e.c,e.d,e.b,e.a),this.a=n}function ost(t){var e,n,r,s;for(this.a=new O0,this.d=new Hs,this.e=0,n=t,r=0,s=n.length;r0):!1}function Jie(t){var e;Vt(qe(t,(ui(),s5)))===Vt((G0(),tU))&&(es(t)?(e=u(qe(es(t),s5),334),wo(t,s5,e)):wo(t,s5,ZS))}function kfn(t,e,n){var r,s;qst(t.e,e,n,(ve(),Bn)),qst(t.i,e,n,Hn),t.a&&(s=u(Q(e,(ae(),_i)),11),r=u(Q(n,_i),11),Irt(t.g,s,r))}function tse(t,e,n){var r,s,o;r=e.c.p,o=e.p,t.b[r][o]=new wQt(t,e),n&&(t.a[r][o]=new e8(e),s=u(Q(e,(ae(),Pv)),10),s&&ln(t.d,s,e))}function ese(t,e){var n,r,s;if(le(dV,t),e.Fc(t),n=u(tr(Jut,t),21),n)for(s=n.Kc();s.Ob();)r=u(s.Pb(),33),Ro(dV,r,0)!=-1||ese(r,e)}function Efn(t,e,n){var r;(Jge?(Lhn(t),!0):tpe||npe?(d8(),!0):epe&&(d8(),!1))&&(r=new LYt(e),r.b=n,_gn(t,r))}function cst(t,e){var n;n=!t.A.Hc((Al(),K2))||t.q==(ua(),Gc),t.u.Hc((Zu(),sg))?n?G5n(t,e):Dhe(t,e):t.u.Hc(Cb)&&(n?l5n(t,e):Ghe(t,e))}function bE(t,e){var n,r;if(++t.j,e!=null&&(n=(r=t.a.Cb,_t(r,97)?u(r,97).Jg():null),vbn(e,n))){o6(t.a,4,n);return}o6(t.a,4,u(e,126))}function nse(t,e,n){return new ah(b.Math.min(t.a,e.a)-n/2,b.Math.min(t.b,e.b)-n/2,b.Math.abs(t.a-e.a)+n,b.Math.abs(t.b-e.b)+n)}function Tfn(t,e){var n,r;return n=pu(t.a.c.p,e.a.c.p),n!=0?n:(r=pu(t.a.d.i.p,e.a.d.i.p),r!=0?r:pu(e.a.d.p,t.a.d.p))}function Cfn(t,e,n){var r,s,o,h;return o=e.j,h=n.j,o!=h?o.g-h.g:(r=t.f[e.p],s=t.f[n.p],r==0&&s==0?0:r==0?-1:s==0?1:Ms(r,s))}function rse(t,e,n){var r,s,o;if(!n[e.d])for(n[e.d]=!0,s=new S(u4(e));s.a=s)return s;for(e=e>0?e:0;er&&ts(e,r,null),e}function sse(t,e){var n,r;for(r=t.a.length,e.lengthr&&ts(e,r,null),e}function m2(t,e,n){var r,s,o;return s=u(tr(t.e,e),387),s?(o=awt(s,n),XUt(t,s),o):(r=new Owt(t,e,n),ki(t.e,e,r),kQt(r),null)}function Afn(t){var e;if(t==null)return null;if(e=k2n($c(t,!0)),e==null)throw it(new pet("Invalid hexBinary value: '"+t+"'"));return e}function JD(t){return rb(),yc(t,0)<0?yc(t,-1)!=0?new x4t(-1,z8(t)):But:yc(t,10)<=0?CEt[Ar(t)]:new x4t(1,t)}function lst(){return $q(),lt(ct($pe,1),oe,159,0,[Rpe,Bpe,jpe,Lpe,Ape,Mpe,Ope,Ipe,Dpe,Npe,Fpe,Ppe,_pe,Cpe,Spe,Epe,kpe,Tpe,ype,mpe,xpe,Uut])}function ase(t){var e;this.d=new he,this.j=new Ca,this.g=new Ca,e=t.g.b,this.f=u(Q(Na(e),(Te(),Wl)),103),this.e=Xt(ye(Wz(e,Wy)))}function ose(t){this.b=new he,this.e=new he,this.d=t,this.a=!qC(Ri(new Tn(null,new jw(new L1(t.b))),new Zt(new zN))).sd((Qb(),o7))}function Qf(){Qf=Z,qn=new OM("PARENTS",0),ea=new OM("NODES",1),Pd=new OM("EDGES",2),V2=new OM("PORTS",3),rp=new OM("LABELS",4)}function l4(){l4=Z,Eb=new FM("DISTRIBUTED",0),iP=new FM("JUSTIFIED",1),IAt=new FM("BEGIN",2),JS=new FM(qE,3),OAt=new FM("END",4)}function Lfn(t){var e;switch(e=t.yi(null),e){case 10:return 0;case 15:return 1;case 14:return 2;case 11:return 3;case 21:return 4}return-1}function hst(t){switch(t.g){case 1:return ao(),rg;case 4:return ao(),zh;case 2:return ao(),Cf;case 3:return ao(),ng}return ao(),h0}function Mfn(t,e,n){var r;switch(r=n.q.getFullYear()-ab+ab,r<0&&(r=-r),e){case 1:t.a+=r;break;case 2:Jd(t,r%100,2);break;default:Jd(t,r,e)}}function ei(t,e){var n,r;if(Km(e,t.b),e>=t.b>>1)for(r=t.c,n=t.b;n>e;--n)r=r.b;else for(r=t.a.a,n=0;n=64&&e<128&&(s=S1(s,F0(1,e-64)));return s}function Wz(t,e){var n,r;return r=null,Us(t,(ui(),K6))&&(n=u(Q(t,K6),94),n.Xe(e)&&(r=n.We(e))),r==null&&Na(t)&&(r=Q(Na(t),e)),r}function lse(t,e){var n,r,s;s=e.d.i,r=s.k,!(r==(Vn(),Os)||r==z1)&&(n=new ar(lr(Ds(s).a.Kc(),new z)),zr(n)&&ki(t.k,e,u(Mr(n),17)))}function fst(t,e){var n,r,s;return r=yn(t.Tg(),e),n=e-t.Ah(),n<0?(s=t.Yg(r),s>=0?t.lh(s):Zst(t,r)):n<0?Zst(t,r):u(r,66).Nj().Sj(t,t.yh(),n)}function Ie(t){var e;if(_t(t.a,4)){if(e=O3t(t.a),e==null)throw it(new No(ode+t.b+"'. "+ade+(P0(gP),gP.k)+d8t));return e}else return t.a}function Ofn(t){var e;if(t==null)return null;if(e=J5n($c(t,!0)),e==null)throw it(new pet("Invalid base64Binary value: '"+t+"'"));return e}function dr(t){var e;try{return e=t.i.Xb(t.e),t.mj(),t.g=t.e++,e}catch(n){throw n=Wi(n),_t(n,73)?(t.mj(),it(new lc)):it(n)}}function dst(t){var e;try{return e=t.c.ki(t.e),t.mj(),t.g=t.e++,e}catch(n){throw n=Wi(n),_t(n,73)?(t.mj(),it(new lc)):it(n)}}function o_(){o_=Z,p7t=(ui(),hAt),Qut=HSt,Jpe=W6,g7t=U2,rbe=(sq(),WEt),nbe=GEt,ibe=KEt,ebe=VEt,tbe=(Rit(),h7t),Xut=Xpe,d7t=Qpe,fV=Zpe}function Yz(t){switch(kbt(),this.c=new he,this.d=t,t.g){case 0:case 2:this.a=Mvt(O7t),this.b=as;break;case 3:case 1:this.a=O7t,this.b=Cs}}function hse(t,e,n){var r,s;if(t.c)ku(t.c,t.c.i+e),Eu(t.c,t.c.j+n);else for(s=new S(t.b);s.a0&&(le(t.b,new GYt(e.a,n)),r=e.a.length,0r&&(e.a+=KUt(Nt(xh,yd,25,-r,15,1))))}function fse(t,e){var n,r,s;for(n=t.o,s=u(u(Ai(t.r,e),21),84).Kc();s.Ob();)r=u(s.Pb(),111),r.e.a=N1n(r,n.a),r.e.b=n.b*Xt(ye(r.b.We(uV)))}function Ffn(t,e){var n,r,s,o;return s=t.k,n=Xt(ye(Q(t,(ae(),Fv)))),o=e.k,r=Xt(ye(Q(e,Fv))),o!=(Vn(),ks)?-1:s!=ks?1:n==r?0:n=0?t.hh(e,n,r):(t.eh()&&(r=(s=t.Vg(),s>=0?t.Qg(r):t.eh().ih(t,-1-s,null,r))),t.Sg(e,n,r))}function R3t(t,e){switch(e){case 7:!t.e&&(t.e=new Cn(Ys,t,7,4)),xr(t.e);return;case 8:!t.d&&(t.d=new Cn(Ys,t,8,5)),xr(t.d);return}T3t(t,e)}function Zf(t,e){var n;n=t.Zc(e);try{return n.Pb()}catch(r){throw r=Wi(r),_t(r,109)?it(new yo("Can't get element "+e)):it(r)}}function j3t(t,e){this.e=t,e=0&&(n.d=t.t);break;case 3:t.t>=0&&(n.a=t.t)}t.C&&(n.b=t.C.b,n.c=t.C.c)}function u6(){u6=Z,dO=new QR(Kq,0),fO=new QR(Iot,1),gO=new QR(Oot,2),pO=new QR(Pot,3),dO.a=!1,fO.a=!0,gO.a=!1,pO.a=!0}function c_(){c_=Z,bO=new XR(Kq,0),lV=new XR(Iot,1),hV=new XR(Oot,2),wO=new XR(Pot,3),bO.a=!1,lV.a=!0,hV.a=!1,wO.a=!0}function $fn(t){var e;e=t.a;do e=u(Mr(new ar(lr(jo(e).a.Kc(),new z))),17).c.i,e.k==(Vn(),ta)&&t.b.Fc(e);while(e.k==(Vn(),ta));t.b=l2(t.b)}function zfn(t){var e,n,r;for(r=t.c.a,t.p=(Lr(r),new Bu(r)),n=new S(r);n.an.b)return!0}return!1}function gst(t,e){return ra(t)?!!Sge[e]:t.hm?!!t.hm[e]:Bm(t)?!!_ge[e]:Nm(t)?!!Cge[e]:!1}function wo(t,e,n){return n==null?(!t.o&&(t.o=new _l((Jc(),Sb),Hv,t,0)),qz(t.o,e)):(!t.o&&(t.o=new _l((Jc(),Sb),Hv,t,0)),aq(t.o,e,n)),t}function Gfn(t,e,n,r){var s,o;o=e.Xe((ui(),o5))?u(e.We(o5),21):t.j,s=Pln(o),s!=($q(),Uut)&&(n&&!P3t(s)||V4t(E2n(t,s,r),e))}function Xz(t,e,n,r){var s,o,h;return o=yn(t.Tg(),e),s=e-t.Ah(),s<0?(h=t.Yg(o),h>=0?t._g(h,n,!0):dv(t,o,n)):u(o,66).Nj().Pj(t,t.yh(),s,n,r)}function Ufn(t,e,n,r){var s,o,h;n.mh(e)&&(to(),ait(e)?(s=u(n.ah(e),153),bfn(t,s)):(o=(h=e,h?u(r,49).xh(h):null),o&&YYe(n.ah(e),o)))}function Wfn(t){switch(t.g){case 1:return rv(),hO;case 3:return rv(),lO;case 2:return rv(),Yut;case 4:return rv(),Wut;default:return null}}function $3t(t){switch(typeof t){case Vat:return Vg(t);case Nxt:return ps(t);case b6:return Nn(),t?1231:1237;default:return t==null?0:Pw(t)}}function Yfn(t,e,n){if(t.e)switch(t.b){case 1:Ern(t.c,e,n);break;case 0:Trn(t.c,e,n)}else tJt(t.c,e,n);t.a[e.p][n.p]=t.c.i,t.a[n.p][e.p]=t.c.e}function wse(t){var e,n;if(t==null)return null;for(n=Nt(l0,ee,193,t.length,0,2),e=0;e=0)return s;if(t.Fk()){for(r=0;r=s)throw it(new qm(e,s));if(t.hi()&&(r=t.Xc(n),r>=0&&r!=e))throw it(new Fn(eO));return t.mi(e,n)}function z3t(t,e){if(this.a=u(Lr(t),245),this.b=u(Lr(e),245),t.vd(e)>0||t==(cet(),_ut)||e==(oet(),Sut))throw it(new Fn("Invalid range: "+XZt(t,e)))}function vse(t){var e,n;for(this.b=new he,this.c=t,this.a=!1,n=new S(t.a);n.a0),(e&-e)==e)return ps(e*ul(t,31)*4656612873077393e-25);do n=ul(t,31),r=n%e;while(n-r+(e-1)<0);return ps(r)}function Vg(t){MYt();var e,n,r;return n=":"+t,r=aV[n],r!=null?ps((On(r),r)):(r=REt[n],e=r==null?$wn(t):ps((On(r),r)),prn(),aV[n]=e,e)}function yse(t,e,n){vr(n,"Compound graph preprocessor",1),t.a=new Uw,_he(t,e,null),S3n(t,e),uwn(t),Jt(e,(ae(),rCt),t.a),t.a=null,Xu(t.b),or(n)}function Qfn(t,e,n){switch(n.g){case 1:t.a=e.a/2,t.b=0;break;case 2:t.a=e.a,t.b=e.b/2;break;case 3:t.a=e.a/2,t.b=e.b;break;case 4:t.a=0,t.b=e.b/2}}function Zfn(t){var e,n,r;for(r=u(Ai(t.a,(b4(),qV)),15).Kc();r.Ob();)n=u(r.Pb(),101),e=t4t(n),_8(t,n,e[0],(nv(),Mv),0),_8(t,n,e[1],Dv,1)}function Jfn(t){var e,n,r;for(r=u(Ai(t.a,(b4(),HV)),15).Kc();r.Ob();)n=u(r.Pb(),101),e=t4t(n),_8(t,n,e[0],(nv(),Mv),0),_8(t,n,e[1],Dv,1)}function pst(t){switch(t.g){case 0:return null;case 1:return new yne;case 2:return new Zpt;default:throw it(new Fn(Ict+(t.f!=null?t.f:""+t.g)))}}function tI(t,e,n){var r,s;for(xun(t,e-t.s,n-t.t),s=new S(t.n);s.a1&&(o=Xfn(t,e)),o}function bst(t){var e;return t.f&&t.f.kh()&&(e=u(t.f,49),t.f=u(Zp(t,e),82),t.f!=e&&t.Db&4&&!(t.Db&1)&&mi(t,new Js(t,9,8,e,t.f))),t.f}function wst(t){var e;return t.i&&t.i.kh()&&(e=u(t.i,49),t.i=u(Zp(t,e),82),t.i!=e&&t.Db&4&&!(t.Db&1)&&mi(t,new Js(t,9,7,e,t.i))),t.i}function no(t){var e;return t.b&&t.b.Db&64&&(e=t.b,t.b=u(Zp(t,e),18),t.b!=e&&t.Db&4&&!(t.Db&1)&&mi(t,new Js(t,9,21,e,t.b))),t.b}function Jz(t,e){var n,r,s;t.d==null?(++t.e,++t.f):(r=e.Sh(),bwn(t,t.f+1),s=(r&wi)%t.d.length,n=t.d[s],!n&&(n=t.d[s]=t.uj()),n.Fc(e),++t.f)}function V3t(t,e,n){var r;return e.Kj()?!1:e.Zj()!=-2?(r=e.zj(),r==null?n==null:yi(r,n)):e.Hj()==t.e.Tg()&&n==null}function tq(){var t;jl(16,bfe),t=hne(16),this.b=Nt(Lut,PI,317,t,0,1),this.c=Nt(Lut,PI,317,t,0,1),this.a=null,this.e=null,this.i=0,this.f=t-1,this.g=0}function Y0(t){cwt.call(this),this.k=(Vn(),Os),this.j=(jl(6,ky),new Xc(6)),this.b=(jl(2,ky),new Xc(2)),this.d=new net,this.f=new Hpt,this.a=t}function e1n(t){var e,n;t.c.length<=1||(e=vue(t,(ve(),mr)),aoe(t,u(e.a,19).a,u(e.b,19).a),n=vue(t,Bn),aoe(t,u(n.a,19).a,u(n.b,19).a))}function u_(){u_=Z,F9t=new LM("SIMPLE",0),xht=new LM(Xot,1),kht=new LM("LINEAR_SEGMENTS",2),DS=new LM("BRANDES_KOEPF",3),IS=new LM(q1e,4)}function G3t(t,e,n){jx(u(Q(e,(Te(),cs)),98))||(jmt(t,e,Gg(e,n)),jmt(t,e,Gg(e,(ve(),mr))),jmt(t,e,Gg(e,Pn)),wn(),Zs(e.j,new hM(t)))}function xse(t,e,n,r){var s,o,h;for(s=u(Ai(r?t.a:t.b,e),21),h=s.Kc();h.Ob();)if(o=u(h.Pb(),33),Tq(t,n,o))return!0;return!1}function vst(t){var e,n;for(n=new nr(t);n.e!=n.i.gc();)if(e=u(dr(n),87),e.e||(!e.d&&(e.d=new As(ho,e,1)),e.d).i!=0)return!0;return!1}function mst(t){var e,n;for(n=new nr(t);n.e!=n.i.gc();)if(e=u(dr(n),87),e.e||(!e.d&&(e.d=new As(ho,e,1)),e.d).i!=0)return!0;return!1}function n1n(t){var e,n,r;for(e=0,r=new S(t.c.a);r.a102?-1:t<=57?t-48:t<65?-1:t<=70?t-65+10:t<97?-1:t-97+10}function kst(t,e){if(t==null)throw it(new Sx("null key in entry: null="+e));if(e==null)throw it(new Sx("null value in entry: "+t+"=null"))}function r1n(t,e){for(var n,r;t.Ob();)if(!e.Ob()||(n=t.Pb(),r=e.Pb(),!(Vt(n)===Vt(r)||n!=null&&yi(n,r))))return!1;return!e.Ob()}function Ese(t,e){var n;return n=lt(ct(aa,1),vo,25,15,[zit(t.a[0],e),zit(t.a[1],e),zit(t.a[2],e)]),t.d&&(n[0]=b.Math.max(n[0],n[2]),n[2]=n[0]),n}function Tse(t,e){var n;return n=lt(ct(aa,1),vo,25,15,[Lz(t.a[0],e),Lz(t.a[1],e),Lz(t.a[2],e)]),t.d&&(n[0]=b.Math.max(n[0],n[2]),n[2]=n[0]),n}function x2(){x2=Z,Mlt=new AM("GREEDY",0),PTt=new AM(A1e,1),Dlt=new AM(Xot,2),vS=new AM("MODEL_ORDER",3),wS=new AM("GREEDY_MODEL_ORDER",4)}function Cse(t,e){var n,r,s;for(t.b[e.g]=1,r=ei(e.d,0);r.b!=r.d.c;)n=u(ti(r),188),s=n.c,t.b[s.g]==1?ri(t.a,n):t.b[s.g]==2?t.b[s.g]=1:Cse(t,s)}function i1n(t,e){var n,r,s;for(s=new Xc(e.gc()),r=e.Kc();r.Ob();)n=u(r.Pb(),286),n.c==n.f?EE(t,n,n.c):npn(t,n)||(s.c[s.c.length]=n);return s}function s1n(t,e,n){var r,s,o,h,d;for(d=t.r+e,t.r+=e,t.d+=n,r=n/t.n.c.length,s=0,h=new S(t.n);h.ao&&ts(e,o,null),e}function m1n(t,e){var n,r;if(r=t.gc(),e==null){for(n=0;n0&&(v+=s),k[C]=h,h+=d*(v+r)}function Ose(t){var e,n,r;for(r=t.f,t.n=Nt(aa,vo,25,r,15,1),t.d=Nt(aa,vo,25,r,15,1),e=0;e0?t.c:0),++s;t.b=r,t.d=o}function _1n(t,e){var n,r,s,o,h;for(r=0,s=0,n=0,h=new S(e);h.a0?t.g:0),++n;t.c=s,t.d=r}function Rse(t,e){var n;return n=lt(ct(aa,1),vo,25,15,[H3t(t,(Kf(),sc),e),H3t(t,eu,e),H3t(t,ac,e)]),t.f&&(n[0]=b.Math.max(n[0],n[2]),n[2]=n[0]),n}function S1n(t,e,n){var r;try{Sq(t,e+t.j,n+t.k,!1,!0)}catch(s){throw s=Wi(s),_t(s,73)?(r=s,it(new yo(r.g+Qq+e+Ya+n+")."))):it(s)}}function A1n(t,e,n){var r;try{Sq(t,e+t.j,n+t.k,!0,!1)}catch(s){throw s=Wi(s),_t(s,73)?(r=s,it(new yo(r.g+Qq+e+Ya+n+")."))):it(s)}}function jse(t){var e;Us(t,(Te(),Nv))&&(e=u(Q(t,Nv),21),e.Hc((py(),_f))?(e.Mc(_f),e.Fc(Sf)):e.Hc(Sf)&&(e.Mc(Sf),e.Fc(_f)))}function $se(t){var e;Us(t,(Te(),Nv))&&(e=u(Q(t,Nv),21),e.Hc((py(),Lf))?(e.Mc(Lf),e.Fc(Hh)):e.Hc(Hh)&&(e.Mc(Hh),e.Fc(Lf)))}function L1n(t,e,n){vr(n,"Self-Loop ordering",1),ls(wu(Ri(Ri(Wo(new Tn(null,new _n(e.b,16)),new mN),new rX),new iX),new sX),new Lm(t)),or(n)}function nI(t,e,n,r){var s,o;for(s=e;s0&&(s.b+=e),s}function rq(t,e){var n,r,s;for(s=new Ca,r=t.Kc();r.Ob();)n=u(r.Pb(),37),x_(n,0,s.b),s.b+=n.f.b+e,s.a=b.Math.max(s.a,n.f.a);return s.a>0&&(s.a+=e),s}function qse(t){var e,n,r;for(r=wi,n=new S(t.a);n.a>16==6?t.Cb.ih(t,5,i1,e):(r=no(u(yn((n=u(Dn(t,16),26),n||t.zh()),t.Db>>16),18)),t.Cb.ih(t,r.n,r.f,e))}function P1n(t){I8();var e=t.e;if(e&&e.stack){var n=e.stack,r=e+` +`;return n.substring(0,r.length)==r&&(n=n.substring(r.length)),n.split(` +`)}return[]}function F1n(t){var e;return e=(sne(),jge),e[t>>>28]|e[t>>24&15]<<4|e[t>>20&15]<<8|e[t>>16&15]<<12|e[t>>12&15]<<16|e[t>>8&15]<<20|e[t>>4&15]<<24|e[t&15]<<28}function Gse(t){var e,n,r;t.b==t.c&&(r=t.a.length,n=Dyt(b.Math.max(8,r))<<1,t.b!=0?(e=ff(t.a,n),dne(t,e,r),t.a=e,t.b=0):fqt(t.a,n),t.c=r)}function N1n(t,e){var n;return n=t.b,n.Xe((ui(),dl))?n.Hf()==(ve(),Bn)?-n.rf().a-Xt(ye(n.We(dl))):e+Xt(ye(n.We(dl))):n.Hf()==(ve(),Bn)?-n.rf().a:e}function rI(t){var e;return t.b.c.length!=0&&u(Ne(t.b,0),70).a?u(Ne(t.b,0),70).a:(e=grt(t),e??""+(t.c?Ro(t.c.a,t,0):-1))}function iq(t){var e;return t.f.c.length!=0&&u(Ne(t.f,0),70).a?u(Ne(t.f,0),70).a:(e=grt(t),e??""+(t.i?Ro(t.i.j,t,0):-1))}function B1n(t,e){var n,r;if(e<0||e>=t.gc())return null;for(n=e;n0?t.c:0),s=b.Math.max(s,e.d),++r;t.e=o,t.b=s}function j1n(t){var e,n;if(!t.b)for(t.b=D$(u(t.f,118).Ag().i),n=new nr(u(t.f,118).Ag());n.e!=n.i.gc();)e=u(dr(n),137),le(t.b,new get(e));return t.b}function $1n(t,e){var n,r,s;if(e.dc())return y8(),y8(),pP;for(n=new YWt(t,e.gc()),s=new nr(t);s.e!=s.i.gc();)r=dr(s),e.Hc(r)&&Dr(n,r);return n}function Z3t(t,e,n,r){return e==0?r?(!t.o&&(t.o=new _l((Jc(),Sb),Hv,t,0)),t.o):(!t.o&&(t.o=new _l((Jc(),Sb),Hv,t,0)),wD(t.o)):Xz(t,e,n,r)}function Mst(t){var e,n;if(t.rb)for(e=0,n=t.rb.i;e>22),s+=r>>22,s<0)?!1:(t.l=n&hl,t.m=r&hl,t.h=s&Z0,!0)}function V1n(t,e,n,r,s,o,h){var d,v;return!(e.Ae()&&(v=t.a.ue(n,r),v<0||!s&&v==0)||e.Be()&&(d=t.a.ue(n,o),d>0||!h&&d==0))}function G1n(t,e){oE();var n;if(n=t.j.g-e.j.g,n!=0)return 0;switch(t.j.g){case 2:return Jit(e,_Tt)-Jit(t,_Tt);case 4:return Jit(t,CTt)-Jit(e,CTt)}return 0}function U1n(t){switch(t.g){case 0:return Olt;case 1:return Plt;case 2:return Flt;case 3:return Nlt;case 4:return UV;case 5:return Blt;default:return null}}function _o(t,e,n){var r,s;return r=(s=new set,b2(s,e),Qc(s,n),Dr((!t.c&&(t.c=new fe(Vv,t,12,10)),t.c),s),s),Rg(r,0),ry(r,1),qg(r,!0),zg(r,!0),r}function l6(t,e){var n,r;if(e>=t.i)throw it(new nnt(e,t.i));return++t.j,n=t.g[e],r=t.i-e-1,r>0&&Dc(t.g,e+1,t.g,e,r),ts(t.g,--t.i,null),t.fi(e,n),t.ci(),n}function Use(t,e){var n,r;return t.Db>>16==17?t.Cb.ih(t,21,Uh,e):(r=no(u(yn((n=u(Dn(t,16),26),n||t.zh()),t.Db>>16),18)),t.Cb.ih(t,r.n,r.f,e))}function W1n(t){var e,n,r,s;for(wn(),Zs(t.c,t.a),s=new S(t.c);s.an.a.c.length))throw it(new Fn("index must be >= 0 and <= layer node count"));t.c&&mu(t.c.a,t),t.c=n,n&&Hm(n.a,e,t)}function Qse(t,e){var n,r,s;for(r=new ar(lr(U0(t).a.Kc(),new z));zr(r);)return n=u(Mr(r),17),s=u(e.Kb(n),10),new Wk(Lr(s.n.b+s.o.b/2));return PC(),PC(),Cut}function Zse(t,e){this.c=new _r,this.a=t,this.b=e,this.d=u(Q(t,(ae(),Q4)),304),Vt(Q(t,(Te(),h9t)))===Vt((xD(),WV))?this.e=new Lqt:this.e=new Aqt}function J1n(t,e){var n,r,s,o;for(o=0,r=new S(t);r.a>16==6?t.Cb.ih(t,6,Ys,e):(r=no(u(yn((n=u(Dn(t,16),26),n||(Jc(),aU)),t.Db>>16),18)),t.Cb.ih(t,r.n,r.f,e))}function i4t(t,e){var n,r;return t.Db>>16==7?t.Cb.ih(t,1,lP,e):(r=no(u(yn((n=u(Dn(t,16),26),n||(Jc(),GAt)),t.Db>>16),18)),t.Cb.ih(t,r.n,r.f,e))}function s4t(t,e){var n,r;return t.Db>>16==9?t.Cb.ih(t,9,rs,e):(r=no(u(yn((n=u(Dn(t,16),26),n||(Jc(),WAt)),t.Db>>16),18)),t.Cb.ih(t,r.n,r.f,e))}function tae(t,e){var n,r;return t.Db>>16==5?t.Cb.ih(t,9,pU,e):(r=no(u(yn((n=u(Dn(t,16),26),n||(dn(),op)),t.Db>>16),18)),t.Cb.ih(t,r.n,r.f,e))}function a4t(t,e){var n,r;return t.Db>>16==3?t.Cb.ih(t,0,fP,e):(r=no(u(yn((n=u(Dn(t,16),26),n||(dn(),ap)),t.Db>>16),18)),t.Cb.ih(t,r.n,r.f,e))}function eae(t,e){var n,r;return t.Db>>16==7?t.Cb.ih(t,6,i1,e):(r=no(u(yn((n=u(Dn(t,16),26),n||(dn(),up)),t.Db>>16),18)),t.Cb.ih(t,r.n,r.f,e))}function nae(){this.a=new oB,this.g=new tq,this.j=new tq,this.b=new _r,this.d=new tq,this.i=new tq,this.k=new _r,this.c=new _r,this.e=new _r,this.f=new _r}function rdn(t,e,n){var r,s,o;for(n<0&&(n=0),o=t.i,s=n;svot)return vE(t,r);if(r==t)return!0}}return!1}function sdn(t){switch(Cj(),t.q.g){case 5:$oe(t,(ve(),Pn)),$oe(t,mr);break;case 4:Fce(t,(ve(),Pn)),Fce(t,mr);break;default:Fhe(t,(ve(),Pn)),Fhe(t,mr)}}function adn(t){switch(Cj(),t.q.g){case 5:ece(t,(ve(),Hn)),ece(t,Bn);break;case 4:fse(t,(ve(),Hn)),fse(t,Bn);break;default:Nhe(t,(ve(),Hn)),Nhe(t,Bn)}}function odn(t){var e,n;e=u(Q(t,(Jf(),ybe)),19),e?(n=e.a,n==0?Jt(t,(Yp(),wV),new Zit):Jt(t,(Yp(),wV),new F$(n))):Jt(t,(Yp(),wV),new F$(1))}function cdn(t,e){var n;switch(n=t.i,e.g){case 1:return-(t.n.b+t.o.b);case 2:return t.n.a-n.o.a;case 3:return t.n.b-n.o.b;case 4:return-(t.n.a+t.o.a)}return 0}function udn(t,e){switch(t.g){case 0:return e==(dh(),bb)?BV:RV;case 1:return e==(dh(),bb)?BV:kO;case 2:return e==(dh(),bb)?kO:RV;default:return kO}}function sI(t,e){var n,r,s;for(mu(t.a,e),t.e-=e.r+(t.a.c.length==0?0:t.c),s=Ukt,r=new S(t.a);r.a>16==3?t.Cb.ih(t,12,rs,e):(r=no(u(yn((n=u(Dn(t,16),26),n||(Jc(),VAt)),t.Db>>16),18)),t.Cb.ih(t,r.n,r.f,e))}function c4t(t,e){var n,r;return t.Db>>16==11?t.Cb.ih(t,10,rs,e):(r=no(u(yn((n=u(Dn(t,16),26),n||(Jc(),UAt)),t.Db>>16),18)),t.Cb.ih(t,r.n,r.f,e))}function rae(t,e){var n,r;return t.Db>>16==10?t.Cb.ih(t,11,Uh,e):(r=no(u(yn((n=u(Dn(t,16),26),n||(dn(),cp)),t.Db>>16),18)),t.Cb.ih(t,r.n,r.f,e))}function iae(t,e){var n,r;return t.Db>>16==10?t.Cb.ih(t,12,Wh,e):(r=no(u(yn((n=u(Dn(t,16),26),n||(dn(),i3)),t.Db>>16),18)),t.Cb.ih(t,r.n,r.f,e))}function Dh(t){var e;return!(t.Bb&1)&&t.r&&t.r.kh()&&(e=u(t.r,49),t.r=u(Zp(t,e),138),t.r!=e&&t.Db&4&&!(t.Db&1)&&mi(t,new Js(t,9,8,e,t.r))),t.r}function Ist(t,e,n){var r;return r=lt(ct(aa,1),vo,25,15,[O4t(t,(Kf(),sc),e,n),O4t(t,eu,e,n),O4t(t,ac,e,n)]),t.f&&(r[0]=b.Math.max(r[0],r[2]),r[2]=r[0]),r}function ldn(t,e){var n,r,s;if(s=i1n(t,e),s.c.length!=0)for(Zs(s,new WK),n=s.c.length,r=0;r>19,k=e.h>>19,v!=k?k-v:(s=t.h,d=e.h,s!=d?s-d:(r=t.m,h=e.m,r!=h?r-h:(n=t.l,o=e.l,n-o)))}function sq(){sq=Z,XEt=(Cq(),Vut),KEt=new mn(Qxt,XEt),YEt=(Q$(),Hut),WEt=new mn(Zxt,YEt),UEt=(Gz(),qut),GEt=new mn(Jxt,UEt),VEt=new mn(t6t,(Nn(),!0))}function h_(t,e,n){var r,s;r=e*n,_t(t.g,145)?(s=Xx(t),s.f.d?s.f.a||(t.d.a+=r+B1):(t.d.d-=r+B1,t.d.a+=r+B1)):_t(t.g,10)&&(t.d.d-=r,t.d.a+=2*r)}function sae(t,e,n){var r,s,o,h,d;for(s=t[n.g],d=new S(e.d);d.a0?t.g:0),++n;e.b=r,e.e=s}function aae(t){var e,n,r;if(r=t.b,AVt(t.i,r.length)){for(n=r.length*2,t.b=Nt(Lut,PI,317,n,0,1),t.c=Nt(Lut,PI,317,n,0,1),t.f=n-1,t.i=0,e=t.a;e;e=e.c)fI(t,e,e);++t.g}}function vdn(t,e,n,r){var s,o,h,d;for(s=0;sh&&(d=h/r),s>o&&(v=o/s),fd(t,b.Math.min(d,v)),t}function ydn(){Dq();var t,e;try{if(e=u(m4t((Pp(),Yh),ZE),2014),e)return e}catch(n){if(n=Wi(n),_t(n,102))t=n,avt((Pr(),t));else throw it(n)}return new ax}function xdn(){Qte();var t,e;try{if(e=u(m4t((Pp(),Yh),O2),2024),e)return e}catch(n){if(n=Wi(n),_t(n,102))t=n,avt((Pr(),t));else throw it(n)}return new _m}function kdn(){Dq();var t,e;try{if(e=u(m4t((Pp(),Yh),Bh),1941),e)return e}catch(n){if(n=Wi(n),_t(n,102))t=n,avt((Pr(),t));else throw it(n)}return new aJ}function Edn(t,e,n){var r,s;return s=t.e,t.e=e,t.Db&4&&!(t.Db&1)&&(r=new Js(t,1,4,s,e),n?n.Ei(r):n=r),s!=e&&(e?n=PE(t,vq(t,e),n):n=PE(t,t.a,n)),n}function oae(){BR.call(this),this.e=-1,this.a=!1,this.p=Sa,this.k=-1,this.c=-1,this.b=-1,this.g=!1,this.f=-1,this.j=-1,this.n=-1,this.i=-1,this.d=-1,this.o=Sa}function Tdn(t,e){var n,r,s;if(r=t.b.d.d,t.a||(r+=t.b.d.a),s=e.b.d.d,e.a||(s+=e.b.d.a),n=Ms(r,s),n==0){if(!t.a&&e.a)return-1;if(!e.a&&t.a)return 1}return n}function Cdn(t,e){var n,r,s;if(r=t.b.b.d,t.a||(r+=t.b.b.a),s=e.b.b.d,e.a||(s+=e.b.b.a),n=Ms(r,s),n==0){if(!t.a&&e.a)return-1;if(!e.a&&t.a)return 1}return n}function _dn(t,e){var n,r,s;if(r=t.b.g.d,t.a||(r+=t.b.g.a),s=e.b.g.d,e.a||(s+=e.b.g.a),n=Ms(r,s),n==0){if(!t.a&&e.a)return-1;if(!e.a&&t.a)return 1}return n}function l4t(){l4t=Z,Pbe=Ku(bi(bi(bi(new Vs,(Wa(),qc),(ro(),hTt)),qc,fTt),Io,dTt),Io,tTt),Nbe=bi(bi(new Vs,qc,W7t),qc,eTt),Fbe=Ku(new Vs,Io,rTt)}function Sdn(t){var e,n,r,s,o;for(e=u(Q(t,(ae(),kS)),83),o=t.n,r=e.Cc().Kc();r.Ob();)n=u(r.Pb(),306),s=n.i,s.c+=o.a,s.d+=o.b,n.c?Eue(n):Tue(n);Jt(t,kS,null)}function Adn(t,e,n){var r,s;switch(s=t.b,r=s.d,e.g){case 1:return-r.d-n;case 2:return s.o.a+r.c+n;case 3:return s.o.b+r.a+n;case 4:return-r.b-n;default:return-1}}function Ldn(t){var e,n,r,s,o;if(r=0,s=VE,t.b)for(e=0;e<360;e++)n=e*.017453292519943295,txt(t,t.d,0,0,O4,n),o=t.b.ig(t.d),o0&&(h=(o&wi)%t.d.length,s=l5t(t,h,o,e),s)?(d=s.ed(n),d):(r=t.tj(o,e,n),t.c.Fc(r),null)}function d4t(t,e){var n,r,s,o;switch($g(t,e)._k()){case 3:case 2:{for(n=T4(e),s=0,o=n.i;s=0;r--)if(hn(t[r].d,e)||hn(t[r].d,n)){t.length>=r+1&&t.splice(0,r+1);break}return t}function aI(t,e){var n;return Bo(t)&&Bo(e)&&(n=t/e,BI0&&(t.b+=2,t.a+=r):(t.b+=1,t.a+=b.Math.min(r,s))}function gae(t,e){var n,r;if(r=!1,ra(e)&&(r=!0,Vx(t,new Um(Br(e)))),r||_t(e,236)&&(r=!0,Vx(t,(n=mwt(u(e,236)),new EC(n)))),!r)throw it(new fet(A8t))}function Wdn(t,e,n,r){var s,o,h;return s=new z0(t.e,1,10,(h=e.c,_t(h,88)?u(h,26):(dn(),Kh)),(o=n.c,_t(o,88)?u(o,26):(dn(),Kh)),Hg(t,e),!1),r?r.Ei(s):r=s,r}function b4t(t){var e,n;switch(u(Q(Na(t),(Te(),r9t)),420).g){case 0:return e=t.n,n=t.o,new $e(e.a+n.a/2,e.b+n.b/2);case 1:return new xo(t.n);default:return null}}function oI(){oI=Z,YV=new t9(J0,0),qTt=new t9("LEFTUP",1),VTt=new t9("RIGHTUP",2),zTt=new t9("LEFTDOWN",3),HTt=new t9("RIGHTDOWN",4),Rlt=new t9("BALANCED",5)}function Ydn(t,e,n){var r,s,o;if(r=Ms(t.a[e.p],t.a[n.p]),r==0){if(s=u(Q(e,(ae(),R6)),15),o=u(Q(n,R6),15),s.Hc(n))return-1;if(o.Hc(e))return 1}return r}function Kdn(t){switch(t.g){case 1:return new hZ;case 2:return new fZ;case 3:return new lZ;case 0:return null;default:throw it(new Fn(Ict+(t.f!=null?t.f:""+t.g)))}}function w4t(t,e,n){switch(e){case 1:!t.n&&(t.n=new fe(qo,t,1,7)),xr(t.n),!t.n&&(t.n=new fe(qo,t,1,7)),is(t.n,u(n,14));return;case 2:G9(t,Br(n));return}Byt(t,e,n)}function v4t(t,e,n){switch(e){case 3:Jw(t,Xt(ye(n)));return;case 4:tv(t,Xt(ye(n)));return;case 5:ku(t,Xt(ye(n)));return;case 6:Eu(t,Xt(ye(n)));return}w4t(t,e,n)}function oq(t,e,n){var r,s,o;o=(r=new set,r),s=F1(o,e,null),s&&s.Fi(),Qc(o,n),Dr((!t.c&&(t.c=new fe(Vv,t,12,10)),t.c),o),Rg(o,0),ry(o,1),qg(o,!0),zg(o,!0)}function m4t(t,e){var n,r,s;return n=KC(t.g,e),_t(n,235)?(s=u(n,235),s.Qh()==null,s.Nh()):_t(n,498)?(r=u(n,1938),s=r.b,s):null}function Xdn(t,e,n,r){var s,o;return Lr(e),Lr(n),o=u(x9(t.d,e),19),nee(!!o,"Row %s not in %s",e,t.e),s=u(x9(t.b,n),19),nee(!!s,"Column %s not in %s",n,t.c),ore(t,o.a,s.a,r)}function pae(t,e,n,r,s,o,h){var d,v,k,C,M;if(C=s[o],k=o==h-1,d=k?r:0,M=Nse(d,C),r!=10&<(ct(t,h-o),e[o],n[o],d,M),!k)for(++o,v=0;v1||d==-1?(o=u(v,15),s.Wb(rfn(t,o))):s.Wb(yat(t,u(v,56)))))}function r0n(t,e,n,r){nVt();var s=Tut;function o(){for(var h=0;hLct)return n;s>-1e-6&&++n}return n}function k4t(t,e){var n;e!=t.b?(n=null,t.b&&(n=m$(t.b,t,-4,n)),e&&(n=c6(e,t,-4,n)),n=Qre(t,e,n),n&&n.Fi()):t.Db&4&&!(t.Db&1)&&mi(t,new Js(t,1,3,e,e))}function vae(t,e){var n;e!=t.f?(n=null,t.f&&(n=m$(t.f,t,-1,n)),e&&(n=c6(e,t,-1,n)),n=Zre(t,e,n),n&&n.Fi()):t.Db&4&&!(t.Db&1)&&mi(t,new Js(t,1,0,e,e))}function mae(t){var e,n,r;if(t==null)return null;if(n=u(t,15),n.dc())return"";for(r=new Ag,e=n.Kc();e.Ob();)go(r,(Ii(),Br(e.Pb()))),r.a+=" ";return int(r,r.a.length-1)}function yae(t){var e,n,r;if(t==null)return null;if(n=u(t,15),n.dc())return"";for(r=new Ag,e=n.Kc();e.Ob();)go(r,(Ii(),Br(e.Pb()))),r.a+=" ";return int(r,r.a.length-1)}function h0n(t,e,n){var r,s;return r=t.c[e.c.p][e.p],s=t.c[n.c.p][n.p],r.a!=null&&s.a!=null?Unt(r.a,s.a):r.a!=null?-1:s.a!=null?1:0}function f0n(t,e){var n,r,s,o,h,d;if(e)for(o=e.a.length,n=new e2(o),d=(n.b-n.a)*n.c<0?(Fp(),Ib):new jp(n);d.Ob();)h=u(d.Pb(),19),s=P8(e,h.a),r=new xzt(t),ern(r.a,s)}function d0n(t,e){var n,r,s,o,h,d;if(e)for(o=e.a.length,n=new e2(o),d=(n.b-n.a)*n.c<0?(Fp(),Ib):new jp(n);d.Ob();)h=u(d.Pb(),19),s=P8(e,h.a),r=new fzt(t),trn(r.a,s)}function g0n(t){var e;if(t!=null&&t.length>0&&wa(t,t.length-1)==33)try{return e=woe(Pl(t,0,t.length-1)),e.e==null}catch(n){if(n=Wi(n),!_t(n,32))throw it(n)}return!1}function xae(t,e,n){var r,s,o;return r=e.ak(),o=e.dd(),s=r.$j()?Gp(t,3,r,null,o,DE(t,r,o,_t(r,99)&&(u(r,18).Bb&Ka)!=0),!0):Gp(t,1,r,r.zj(),o,-1,!0),n?n.Ei(s):n=s,n}function p0n(){var t,e,n;for(e=0,t=0;t<1;t++){if(n=g5t((Rr(t,1),"X".charCodeAt(t))),n==0)throw it(new Nr("Unknown Option: "+"X".substr(t)));e|=n}return e}function b0n(t,e,n){var r,s,o;switch(r=Na(e),s=Pz(r),o=new Mc,Uo(o,e),n.g){case 1:Bs(o,YD(a6(s)));break;case 2:Bs(o,a6(s))}return Jt(o,(Te(),Vy),ye(Q(t,Vy))),o}function E4t(t){var e,n;return e=u(Mr(new ar(lr(jo(t.a).a.Kc(),new z))),17),n=u(Mr(new ar(lr(Ds(t.a).a.Kc(),new z))),17),je(Re(Q(e,(ae(),q1))))||je(Re(Q(n,q1)))}function b4(){b4=Z,$V=new SM("ONE_SIDE",0),qV=new SM("TWO_SIDES_CORNER",1),HV=new SM("TWO_SIDES_OPPOSING",2),zV=new SM("THREE_SIDES",3),jV=new SM("FOUR_SIDES",4)}function Nst(t,e,n,r,s){var o,h;o=u(Bl(Ri(e.Oc(),new VX),c2(new ke,new ce,new Xn,lt(ct(fl,1),oe,132,0,[(O1(),Ul)]))),15),h=u(h2(t.b,n,r),15),s==0?h.Wc(0,o):h.Gc(o)}function w0n(t,e){var n,r,s,o,h;for(o=new S(e.a);o.a0&&Wse(this,this.c-1,(ve(),Hn)),this.c0&&t[0].length>0&&(this.c=je(Re(Q(Na(t[0][0]),(ae(),sCt))))),this.a=Nt(Tme,ee,2018,t.length,0,2),this.b=Nt(Cme,ee,2019,t.length,0,2),this.d=new Vre}function k0n(t){return t.c.length==0?!1:(An(0,t.c.length),u(t.c[0],17)).c.i.k==(Vn(),ta)?!0:N8(wu(new Tn(null,new _n(t,16)),new mQ),new yQ)}function E0n(t,e,n){return vr(n,"Tree layout",1),L$(t.b),Kd(t.b,(wE(),AG),AG),Kd(t.b,RS,RS),Kd(t.b,$O,$O),Kd(t.b,jS,jS),t.a=Fq(t.b,e),Zwn(t,e,Rc(n,1)),or(n),e}function Eae(t,e){var n,r,s,o,h,d,v;for(d=wy(e),o=e.f,v=e.g,h=b.Math.sqrt(o*o+v*v),s=0,r=new S(d);r.a=0?(n=aI(t,Gq),r=QD(t,Gq)):(e=Vm(t,1),n=aI(e,5e8),r=QD(e,5e8),r=Pa(F0(r,1),Ns(t,1))),S1(F0(r,32),Ns(n,co))}function _ae(t,e,n){var r,s;switch(r=(Zn(e.b!=0),u(lh(e,e.a.a),8)),n.g){case 0:r.b=0;break;case 2:r.b=t.f;break;case 3:r.a=0;break;default:r.a=t.g}return s=ei(e,0),eD(s,r),e}function Sae(t,e,n,r){var s,o,h,d,v;switch(v=t.b,o=e.d,h=o.j,d=B3t(h,v.d[h.g],n),s=Li(nc(o.n),o.a),o.j.g){case 1:case 3:d.a+=s.a;break;case 2:case 4:d.b+=s.b}fs(r,d,r.c.b,r.c)}function F0n(t,e,n){var r,s,o,h;for(h=Ro(t.e,e,0),o=new zpt,o.b=n,r=new da(t.e,h);r.b1;e>>=1)e&1&&(r=e4(r,n)),n.d==1?n=e4(n,n):n=new Qie(ale(n.a,n.d,Nt(Cr,Xr,25,n.d<<1,15,1)));return r=e4(r,n),r}function M4t(){M4t=Z;var t,e,n,r;for(DEt=Nt(aa,vo,25,25,15,1),IEt=Nt(aa,vo,25,33,15,1),r=152587890625e-16,e=32;e>=0;e--)IEt[e]=r,r*=.5;for(n=1,t=24;t>=0;t--)DEt[t]=n,n*=.5}function z0n(t){var e,n;if(je(Re(qe(t,(Te(),Hy))))){for(n=new ar(lr(K0(t).a.Kc(),new z));zr(n);)if(e=u(Mr(n),79),fv(e)&&je(Re(qe(e,j2))))return!0}return!1}function Aae(t,e){var n,r,s;Fs(t.f,e)&&(e.b=t,r=e.c,Ro(t.j,r,0)!=-1||le(t.j,r),s=e.d,Ro(t.j,s,0)!=-1||le(t.j,s),n=e.a.b,n.c.length!=0&&(!t.i&&(t.i=new ase(t)),run(t.i,n)))}function q0n(t){var e,n,r,s,o;return n=t.c.d,r=n.j,s=t.d.d,o=s.j,r==o?n.p=0&&hn(t.substr(e,3),"GMT")||e>=0&&hn(t.substr(e,3),"UTC"))&&(n[0]=e+3),rxt(t,n,r)}function V0n(t,e){var n,r,s,o,h;for(o=t.g.a,h=t.g.b,r=new S(t.d);r.an;o--)t[o]|=e[o-n-1]>>>h,t[o-1]=e[o-n-1]<=t.f)break;o.c[o.c.length]=n}return o}function I4t(t){var e,n,r,s;for(e=null,s=new S(t.wf());s.a0&&Dc(t.g,e,t.g,e+r,d),h=n.Kc(),t.i+=r,s=0;so&&ann(k,Tee(n[d],LEt))&&(s=d,o=v);return s>=0&&(r[0]=e+o),s}function Q0n(t,e){var n;if(n=xUt(t.b.Hf(),e.b.Hf()),n!=0)return n;switch(t.b.Hf().g){case 1:case 2:return pu(t.b.sf(),e.b.sf());case 3:case 4:return pu(e.b.sf(),t.b.sf())}return 0}function Z0n(t){var e,n,r;for(r=t.e.c.length,t.a=t2(Cr,[ee,Xr],[48,25],15,[r,r],2),n=new S(t.c);n.a>4&15,o=t[r]&15,h[s++]=YAt[n],h[s++]=YAt[o];return Mh(h,0,h.length)}function egn(t,e,n){var r,s,o;return r=e.ak(),o=e.dd(),s=r.$j()?Gp(t,4,r,o,null,DE(t,r,o,_t(r,99)&&(u(r,18).Bb&Ka)!=0),!0):Gp(t,r.Kj()?2:1,r,o,r.zj(),-1,!0),n?n.Ei(s):n=s,n}function Cu(t){var e,n;return t>=Ka?(e=RI+(t-Ka>>10&1023)&ys,n=56320+(t-Ka&1023)&ys,String.fromCharCode(e)+(""+String.fromCharCode(n))):String.fromCharCode(t&ys)}function ngn(t,e){$m();var n,r,s,o;return s=u(u(Ai(t.r,e),21),84),s.gc()>=2?(r=u(s.Kc().Pb(),111),n=t.u.Hc((Zu(),nA)),o=t.u.Hc(Q6),!r.a&&!n&&(s.gc()==2||o)):!1}function Dae(t,e,n,r,s){var o,h,d;for(o=gue(t,e,n,r,s),d=!1;!o;)bq(t,s,!0),d=!0,o=gue(t,e,n,r,s);d&&bq(t,s,!1),h=Cit(s),h.c.length!=0&&(t.d&&t.d.lg(h),Dae(t,s,n,r,h))}function hq(){hq=Z,Sft=new a9(J0,0),kAt=new a9("DIRECTED",1),TAt=new a9("UNDIRECTED",2),yAt=new a9("ASSOCIATION",3),EAt=new a9("GENERALIZATION",4),xAt=new a9("DEPENDENCY",5)}function rgn(t,e){var n;if(!T1(t))throw it(new No(_de));switch(n=T1(t),e.g){case 1:return-(t.j+t.f);case 2:return t.i-n.g;case 3:return t.j-n.f;case 4:return-(t.i+t.g)}return 0}function xE(t,e){var n,r;for(On(e),r=t.b.c.length,le(t.b,e);r>0;){if(n=r,r=(r-1)/2|0,t.a.ue(Ne(t.b,r),e)<=0)return ch(t.b,n,e),!0;ch(t.b,n,Ne(t.b,r))}return ch(t.b,r,e),!0}function O4t(t,e,n,r){var s,o;if(s=0,n)s=Lz(t.a[n.g][e.g],r);else for(o=0;o=d)}function P4t(t,e,n,r){var s;if(s=!1,ra(r)&&(s=!0,E8(e,n,Br(r))),s||Nm(r)&&(s=!0,P4t(t,e,n,r)),s||_t(r,236)&&(s=!0,r2(e,n,u(r,236))),!s)throw it(new fet(A8t))}function sgn(t,e){var n,r,s;if(n=e.Hh(t.a),n&&(s=Xf((!n.b&&(n.b=new kl((dn(),Qa),cc,n)),n.b),Nh),s!=null)){for(r=1;r<($u(),vLt).length;++r)if(hn(vLt[r],s))return r}return 0}function agn(t,e){var n,r,s;if(n=e.Hh(t.a),n&&(s=Xf((!n.b&&(n.b=new kl((dn(),Qa),cc,n)),n.b),Nh),s!=null)){for(r=1;r<($u(),mLt).length;++r)if(hn(mLt[r],s))return r}return 0}function Iae(t,e){var n,r,s,o;if(On(e),o=t.a.gc(),o0?1:0;o.a[s]!=n;)o=o.a[s],s=t.a.ue(n.d,o.d)>0?1:0;o.a[s]=r,r.b=n.b,r.a[0]=n.a[0],r.a[1]=n.a[1],n.a[0]=null,n.a[1]=null}function ugn(t){Zu();var e,n;return e=ji(sg,lt(ct(eU,1),oe,273,0,[Cb])),!(OD(k$(e,t))>1||(n=ji(nA,lt(ct(eU,1),oe,273,0,[eA,Q6])),OD(k$(n,t))>1))}function N4t(t,e){var n;n=Nc((Pp(),Yh),t),_t(n,498)?ko(Yh,t,new QGt(this,e)):ko(Yh,t,this),Hst(this,e),e==(c8(),aLt)?(this.wb=u(this,1939),u(e,1941)):this.wb=(Hp(),Ln)}function lgn(t){var e,n,r;if(t==null)return null;for(e=null,n=0;n=Wg?"error":r>=900?"warn":r>=800?"info":"log"),vXt(n,t.a),t.b&&N5t(e,n,t.b,"Exception: ",!0))}function Q(t,e){var n,r;return r=(!t.q&&(t.q=new _r),tr(t.q,e)),r??(n=e.wg(),_t(n,4)&&(n==null?(!t.q&&(t.q=new _r),Jx(t.q,e)):(!t.q&&(t.q=new _r),ki(t.q,e,n))),n)}function Wa(){Wa=Z,Dd=new _M("P1_CYCLE_BREAKING",0),gb=new _M("P2_LAYERING",1),cu=new _M("P3_NODE_ORDERING",2),qc=new _M("P4_NODE_PLACEMENT",3),Io=new _M("P5_EDGE_ROUTING",4)}function Nae(t,e){var n,r,s,o,h;for(s=e==1?clt:olt,r=s.a.ec().Kc();r.Ob();)for(n=u(r.Pb(),103),h=u(Ai(t.f.c,n),21).Kc();h.Ob();)o=u(h.Pb(),46),mu(t.b.b,o.b),mu(t.b.a,u(o.b,81).d)}function hgn(t,e){H9();var n;if(t.c==e.c){if(t.b==e.b||Ncn(t.b,e.b)){if(n=GXe(t.b)?1:-1,t.a&&!e.a)return n;if(!t.a&&e.a)return-n}return pu(t.b.g,e.b.g)}else return Ms(t.c,e.c)}function fgn(t,e){var n;vr(e,"Hierarchical port position processing",1),n=t.b,n.c.length>0&&ele((An(0,n.c.length),u(n.c[0],29)),t),n.c.length>1&&ele(u(Ne(n,n.c.length-1),29),t),or(e)}function Bae(t,e){var n,r,s;if(R4t(t,e))return!0;for(r=new S(e);r.a=s||e<0)throw it(new yo(iut+e+D2+s));if(n>=s||n<0)throw it(new yo(sut+n+D2+s));return e!=n?r=(o=t.Ti(n),t.Hi(e,o),o):r=t.Oi(n),r}function $ae(t){var e,n,r;if(r=t,t)for(e=0,n=t.Ug();n;n=n.Ug()){if(++e>vot)return $ae(n);if(r=n,n==t)throw it(new No("There is a cycle in the containment hierarchy of "+t))}return r}function eb(t){var e,n,r;for(r=new f2(Ya,"[","]"),n=t.Kc();n.Ob();)e=n.Pb(),$0(r,Vt(e)===Vt(t)?"(this Collection)":e==null?_u:$o(e));return r.a?r.e.length==0?r.a.a:r.a.a+(""+r.e):r.c}function R4t(t,e){var n,r;if(r=!1,e.gc()<2)return!1;for(n=0;nr&&(Rr(e-1,t.length),t.charCodeAt(e-1)<=32);)--e;return r>0||e1&&(t.j.b+=t.e)):(t.j.a+=n.a,t.j.b=b.Math.max(t.j.b,n.b),t.d.c.length>1&&(t.j.a+=t.e))}function nb(){nb=Z,y2e=lt(ct(Xa,1),xc,61,0,[(ve(),Pn),Hn,mr]),m2e=lt(ct(Xa,1),xc,61,0,[Hn,mr,Bn]),x2e=lt(ct(Xa,1),xc,61,0,[mr,Bn,Pn]),k2e=lt(ct(Xa,1),xc,61,0,[Bn,Pn,Hn])}function ggn(t,e,n,r){var s,o,h,d,v,k,C;if(h=t.c.d,d=t.d.d,h.j!=d.j)for(C=t.b,s=h.j,v=null;s!=d.j;)v=e==0?Oz(s):o3t(s),o=B3t(s,C.d[s.g],n),k=B3t(v,C.d[v.g],n),ri(r,Li(o,k)),s=v}function pgn(t,e,n,r){var s,o,h,d,v;return h=Yse(t.a,e,n),d=u(h.a,19).a,o=u(h.b,19).a,r&&(v=u(Q(e,(ae(),Ju)),10),s=u(Q(n,Ju),10),v&&s&&(tJt(t.b,v,s),d+=t.b.i,o+=t.b.e)),d>o}function qae(t){var e,n,r,s,o,h,d,v,k;for(this.a=wse(t),this.b=new he,n=t,r=0,s=n.length;rynt(t.d).c?(t.i+=t.g.c,sst(t.d)):ynt(t.d).c>ynt(t.g).c?(t.e+=t.d.c,sst(t.g)):(t.i+=mKt(t.g),t.e+=mKt(t.d),sst(t.g),sst(t.d))}function vgn(t,e,n){var r,s,o,h;for(o=e.q,h=e.r,new i2((Uf(),mb),e,o,1),new i2(mb,o,h,1),s=new S(n);s.ad&&(v=d/r),s>o&&(k=o/s),h=b.Math.min(v,k),t.a+=h*(e.a-t.a),t.b+=h*(e.b-t.b)}function kgn(t,e,n,r,s){var o,h;for(h=!1,o=u(Ne(n.b,0),33);Byn(t,e,o,r,s)&&(h=!0,e0n(n,o),n.b.c.length!=0);)o=u(Ne(n.b,0),33);return n.b.c.length==0&&sI(n.j,n),h&&nq(e.q),h}function Egn(t,e){k4();var n,r,s,o;if(e.b<2)return!1;for(o=ei(e,0),n=u(ti(o),8),r=n;o.b!=o.d.c;){if(s=u(ti(o),8),cat(t,r,s))return!0;r=s}return!!cat(t,r,n)}function $4t(t,e,n,r){var s,o;return n==0?(!t.o&&(t.o=new _l((Jc(),Sb),Hv,t,0)),Oj(t.o,e,r)):(o=u(yn((s=u(Dn(t,16),26),s||t.zh()),n),66),o.Nj().Rj(t,su(t),n-Jn(t.zh()),e,r))}function Hst(t,e){var n;e!=t.sb?(n=null,t.sb&&(n=u(t.sb,49).ih(t,1,sA,n)),e&&(n=u(e,49).gh(t,1,sA,n)),n=t3t(t,e,n),n&&n.Fi()):t.Db&4&&!(t.Db&1)&&mi(t,new Js(t,1,4,e,e))}function Tgn(t,e){var n,r,s,o;if(e)s=H0(e,"x"),n=new vzt(t),V8(n.a,(On(s),s)),o=H0(e,"y"),r=new mzt(t),U8(r.a,(On(o),o));else throw it(new ud("All edge sections need an end point."))}function Cgn(t,e){var n,r,s,o;if(e)s=H0(e,"x"),n=new pzt(t),G8(n.a,(On(s),s)),o=H0(e,"y"),r=new bzt(t),W8(r.a,(On(o),o));else throw it(new ud("All edge sections need a start point."))}function _gn(t,e){var n,r,s,o,h,d,v;for(r=Are(t),o=0,d=r.length;o>22-e,s=t.h<>22-e):e<44?(n=0,r=t.l<>44-e):(n=0,r=0,s=t.l<t)throw it(new Fn("k must be smaller than n"));return e==0||e==t?1:t==0?0:g4t(t)/(g4t(e)*g4t(t-e))}function z4t(t,e){var n,r,s,o;for(n=new l2t(t);n.g==null&&!n.c?Hvt(n):n.g==null||n.i!=0&&u(n.g[n.i-1],47).Ob();)if(o=u(wq(n),56),_t(o,160))for(r=u(o,160),s=0;s>4],e[n*2+1]=yU[o&15];return Mh(e,0,e.length)}function Hgn(t){c$();var e,n,r;switch(r=t.c.length,r){case 0:return Age;case 1:return e=u(Ioe(new S(t)),42),den(e.cd(),e.dd());default:return n=u(P1(t,Nt(P2,Hq,42,t.c.length,0,1)),165),new uet(n)}}function Vgn(t){var e,n,r,s,o,h;for(e=new B3,n=new B3,Up(e,t),Up(n,t);n.b!=n.c;)for(s=u(Hx(n),37),h=new S(s.a);h.a0&&kI(t,n,e),s):_bn(t,e,n)}function Xae(t,e,n){var r,s,o,h;if(e.b!=0){for(r=new Zi,h=ei(e,0);h.b!=h.d.c;)o=u(ti(h),86),Ua(r,Eyt(o)),s=o.e,s.a=u(Q(o,(fc(),$ht)),19).a,s.b=u(Q(o,o_t),19).a;Xae(t,r,Rc(n,r.b/t.a|0))}}function Qae(t,e){var n,r,s,o,h;if(t.e<=e||Zin(t,t.g,e))return t.g;for(o=t.r,r=t.g,h=t.r,s=(o-r)/2+r;r+11&&(t.e.b+=t.a)):(t.e.a+=n.a,t.e.b=b.Math.max(t.e.b,n.b),t.d.c.length>1&&(t.e.a+=t.a))}function Kgn(t){var e,n,r,s;switch(s=t.i,e=s.b,r=s.j,n=s.g,s.a.g){case 0:n.a=(t.g.b.o.a-r.a)/2;break;case 1:n.a=e.d.n.a+e.d.a.a;break;case 2:n.a=e.d.n.a+e.d.a.a-r.a;break;case 3:n.b=e.d.n.b+e.d.a.b}}function Zae(t,e,n,r,s){if(rr&&(t.a=r),t.bs&&(t.b=s),t}function Xgn(t){if(_t(t,149))return Cwn(u(t,149));if(_t(t,229))return khn(u(t,229));if(_t(t,23))return Lgn(u(t,23));throw it(new Fn(L8t+eb(new yl(lt(ct(Qn,1),De,1,5,[t])))))}function Qgn(t,e,n,r,s){var o,h,d;for(o=!0,h=0;h>>s|n[h+r+1]<>>s,++h}return o}function G4t(t,e,n,r){var s,o,h;if(e.k==(Vn(),ta)){for(o=new ar(lr(jo(e).a.Kc(),new z));zr(o);)if(s=u(Mr(o),17),h=s.c.i.k,h==ta&&t.c.a[s.c.i.c.p]==r&&t.c.a[e.c.p]==n)return!0}return!1}function Zgn(t,e){var n,r,s,o;return e&=63,n=t.h&Z0,e<22?(o=n>>>e,s=t.m>>e|n<<22-e,r=t.l>>e|t.m<<22-e):e<44?(o=0,s=n>>>e-22,r=t.m>>e-22|t.h<<44-e):(o=0,s=0,r=n>>>e-44),iu(r&hl,s&hl,o&Z0)}function Jae(t,e,n,r){var s;this.b=r,this.e=t==(ev(),FS),s=e[n],this.d=t2(pl,[ee,o0],[177,25],16,[s.length,s.length],2),this.a=t2(Cr,[ee,Xr],[48,25],15,[s.length,s.length],2),this.c=new S4t(e,n)}function Jgn(t){var e,n,r;for(t.k=new Wvt((ve(),lt(ct(Xa,1),xc,61,0,[Zo,Pn,Hn,mr,Bn])).length,t.j.c.length),r=new S(t.j);r.a=n)return EE(t,e,r.p),!0;return!1}function eoe(t){var e;return t.Db&64?Vst(t):(e=new Ol(v8t),!t.a||Gr(Gr((e.a+=' "',e),t.a),'"'),Gr(Aw(Gr(Aw(Gr(Aw(Gr(Aw((e.a+=" (",e),t.i),","),t.j)," | "),t.g),","),t.f),")"),e.a)}function noe(t,e,n){var r,s,o,h,d;for(d=ou(t.e.Tg(),e),s=u(t.g,119),r=0,h=0;hn?J4t(t,n,"start index"):e<0||e>n?J4t(e,n,"end index"):y_("end index (%s) must not be less than start index (%s)",lt(ct(Qn,1),De,1,5,[pe(e),pe(t)]))}function ioe(t,e){var n,r,s,o;for(r=0,s=t.length;r0&&soe(t,o,n));e.p=0}function Xe(t){var e;this.c=new Zi,this.f=t.e,this.e=t.d,this.i=t.g,this.d=t.c,this.b=t.b,this.k=t.j,this.a=t.a,t.i?this.j=t.i:this.j=(e=u(Vf(ip),9),new sh(e,u(ff(e,e.length),9),0)),this.g=t.f}function spn(t){var e,n,r,s;for(e=qp(Gr(new Ol("Predicates."),"and"),40),n=!0,s=new mx(t);s.b0?d[h-1]:Nt(l0,Yg,10,0,0,1),s=d[h],k=h=0?t.Bh(s):i5t(t,r);else throw it(new Fn(lb+r.ne()+X_));else throw it(new Fn(Bde+e+Rde));else fh(t,n,r)}function U4t(t){var e,n;if(n=null,e=!1,_t(t,204)&&(e=!0,n=u(t,204).a),e||_t(t,258)&&(e=!0,n=""+u(t,258).a),e||_t(t,483)&&(e=!0,n=""+u(t,483).a),!e)throw it(new fet(A8t));return n}function uoe(t,e){var n,r;if(t.f){for(;e.Ob();)if(n=u(e.Pb(),72),r=n.ak(),_t(r,99)&&u(r,18).Bb&dc&&(!t.e||r.Gj()!=j7||r.aj()!=0)&&n.dd()!=null)return e.Ub(),!0;return!1}else return e.Ob()}function loe(t,e){var n,r;if(t.f){for(;e.Sb();)if(n=u(e.Ub(),72),r=n.ak(),_t(r,99)&&u(r,18).Bb&dc&&(!t.e||r.Gj()!=j7||r.aj()!=0)&&n.dd()!=null)return e.Pb(),!0;return!1}else return e.Sb()}function W4t(t,e,n){var r,s,o,h,d,v;for(v=ou(t.e.Tg(),e),r=0,d=t.i,s=u(t.g,119),h=0;h1&&(e.c[e.c.length]=o))}function upn(t){var e,n,r,s;for(n=new Zi,Ua(n,t.o),r=new qpt;n.b!=0;)e=u(n.b==0?null:(Zn(n.b!=0),lh(n,n.a.a)),508),s=Hhe(t,e,!0),s&&le(r.a,e);for(;r.a.c.length!=0;)e=u(Nre(r),508),Hhe(t,e,!1)}function Ug(){Ug=Z,_St=new Ox(N_,0),La=new Ox("BOOLEAN",1),gc=new Ox("INT",2),I7=new Ox("STRING",3),Oo=new Ox("DOUBLE",4),us=new Ox("ENUM",5),U6=new Ox("ENUMSET",6),V1=new Ox("OBJECT",7)}function g_(t,e){var n,r,s,o,h;r=b.Math.min(t.c,e.c),o=b.Math.min(t.d,e.d),s=b.Math.max(t.c+t.b,e.c+e.b),h=b.Math.max(t.d+t.a,e.d+e.a),s=(s/2|0))for(this.e=r?r.c:null,this.d=s;n++0;)Vvt(this);this.b=e,this.a=null}function fpn(t,e){var n,r;e.a?Fwn(t,e):(n=u(Cnt(t.b,e.b),57),n&&n==t.a[e.b.f]&&n.a&&n.a!=e.b.a&&n.c.Fc(e.b),r=u(Tnt(t.b,e.b),57),r&&t.a[r.f]==e.b&&r.a&&r.a!=e.b.a&&e.b.c.Fc(r),fnt(t.b,e.b))}function foe(t,e){var n,r;if(n=u(po(t.b,e),124),u(u(Ai(t.r,e),21),84).dc()){n.n.b=0,n.n.c=0;return}n.n.b=t.C.b,n.n.c=t.C.c,t.A.Hc((Al(),K2))&&Nue(t,e),r=qfn(t,e),lat(t,e)==(l4(),Eb)&&(r+=2*t.w),n.a.a=r}function doe(t,e){var n,r;if(n=u(po(t.b,e),124),u(u(Ai(t.r,e),21),84).dc()){n.n.d=0,n.n.a=0;return}n.n.d=t.C.d,n.n.a=t.C.a,t.A.Hc((Al(),K2))&&Bue(t,e),r=Hfn(t,e),lat(t,e)==(l4(),Eb)&&(r+=2*t.w),n.a.b=r}function dpn(t,e){var n,r,s,o;for(o=new he,r=new S(e);r.an.a&&(r.Hc((hy(),WO))?s=(e.a-n.a)/2:r.Hc(YO)&&(s=e.a-n.a)),e.b>n.b&&(r.Hc((hy(),XO))?o=(e.b-n.b)/2:r.Hc(KO)&&(o=e.b-n.b)),F4t(t,s,o)}function xoe(t,e,n,r,s,o,h,d,v,k,C,M,j){_t(t.Cb,88)&&gy(sl(u(t.Cb,88)),4),Qc(t,n),t.f=h,hE(t,d),dE(t,v),lE(t,k),fE(t,C),qg(t,M),gE(t,j),zg(t,!0),Rg(t,s),t.ok(o),b2(t,e),r!=null&&(t.i=null,fz(t,r))}function koe(t){var e,n;if(t.f){for(;t.n>0;){if(e=u(t.k.Xb(t.n-1),72),n=e.ak(),_t(n,99)&&u(n,18).Bb&dc&&(!t.e||n.Gj()!=j7||n.aj()!=0)&&e.dd()!=null)return!0;--t.n}return!1}else return t.n>0}function J4t(t,e,n){if(t<0)return y_(afe,lt(ct(Qn,1),De,1,5,[n,pe(t)]));if(e<0)throw it(new Fn(ofe+e));return y_("%s (%s) must not be greater than size (%s)",lt(ct(Qn,1),De,1,5,[n,pe(t),pe(e)]))}function t5t(t,e,n,r,s,o){var h,d,v,k;if(h=r-n,h<7){hhn(e,n,r,o);return}if(v=n+s,d=r+s,k=v+(d-v>>1),t5t(e,t,v,k,-s,o),t5t(e,t,k,d,-s,o),o.ue(t[k-1],t[k])<=0){for(;n=0?t.sh(o,n):M5t(t,s,n);else throw it(new Fn(lb+s.ne()+X_));else throw it(new Fn(Bde+e+Rde));else gh(t,r,s,n)}function Eoe(t){var e,n,r,s;if(n=u(t,49).qh(),n)try{if(r=null,e=_E((Pp(),Yh),sle(ghn(n))),e&&(s=e.rh(),s&&(r=s.Wk(kKe(n.e)))),r&&r!=t)return Eoe(r)}catch(o){if(o=Wi(o),!_t(o,60))throw it(o)}return t}function au(t,e,n){var r,s,o,h;if(h=e==null?0:t.b.se(e),s=(r=t.a.get(h),r??new Array),s.length==0)t.a.set(h,s);else if(o=jre(t,e,s),o)return o.ed(n);return ts(s,s.length,new KR(e,n)),++t.c,w$(t.b),null}function Toe(t,e){var n,r;return L$(t.a),Kd(t.a,(pz(),FG),FG),Kd(t.a,D7,D7),r=new Vs,bi(r,D7,(Nz(),Ght)),Vt(qe(e,(uy(),Yht)))!==Vt((HD(),NG))&&bi(r,D7,Hht),bi(r,D7,Vht),TUt(t.a,r),n=Fq(t.a,e),n}function Coe(t){if(!t)return cHt(),Bge;var e=t.valueOf?t.valueOf():t;if(e!==t){var n=Put[typeof e];return n?n(e):Uyt(typeof e)}else return t instanceof Array||t instanceof b.Array?new wx(t):new Qk(t)}function _oe(t,e,n){var r,s,o;switch(o=t.o,r=u(po(t.p,n),244),s=r.i,s.b=gI(r),s.a=dI(r),s.b=b.Math.max(s.b,o.a),s.b>o.a&&!e&&(s.b=o.a),s.c=-(s.b-o.a)/2,n.g){case 1:s.d=-s.a;break;case 3:s.d=o.b}Eat(r),Tat(r)}function Soe(t,e,n){var r,s,o;switch(o=t.o,r=u(po(t.p,n),244),s=r.i,s.b=gI(r),s.a=dI(r),s.a=b.Math.max(s.a,o.b),s.a>o.b&&!e&&(s.a=o.b),s.d=-(s.a-o.b)/2,n.g){case 4:s.c=-s.b;break;case 2:s.c=o.a}Eat(r),Tat(r)}function Apn(t,e){var n,r,s,o,h;if(!e.dc()){if(s=u(e.Xb(0),128),e.gc()==1){tue(t,s,s,1,0,e);return}for(n=1;n0)try{s=ql(e,Sa,wi)}catch(o){throw o=Wi(o),_t(o,127)?(r=o,it(new W$(r))):it(o)}return n=(!t.a&&(t.a=new Ztt(t)),t.a),s=0?u(At(n,s),56):null}function Ipn(t,e){if(t<0)return y_(afe,lt(ct(Qn,1),De,1,5,["index",pe(t)]));if(e<0)throw it(new Fn(ofe+e));return y_("%s (%s) must be less than size (%s)",lt(ct(Qn,1),De,1,5,["index",pe(t),pe(e)]))}function Opn(t){var e,n,r,s,o;if(t==null)return _u;for(o=new f2(Ya,"[","]"),n=t,r=0,s=n.length;r0)for(h=t.c.d,d=t.d.d,s=fd(ia(new $e(d.a,d.b),h),1/(r+1)),o=new $e(h.a,h.b),n=new S(t.a);n.a=0?t._g(n,!0,!0):dv(t,s,!0),153)),u(r,215).ol(e);else throw it(new Fn(lb+e.ne()+X_))}function s5t(t){var e,n;return t>-0x800000000000&&t<0x800000000000?t==0?0:(e=t<0,e&&(t=-t),n=ps(b.Math.floor(b.Math.log(t)/.6931471805599453)),(!e||t!=b.Math.pow(2,n))&&++n,n):Jne(Tu(t))}function Upn(t){var e,n,r,s,o,h,d;for(o=new O0,n=new S(t);n.a2&&d.e.b+d.j.b<=2&&(s=d,r=h),o.a.zc(s,o),s.q=r);return o}function Foe(t,e){var n,r,s;return r=new Y0(t),Mo(r,e),Jt(r,(ae(),eG),e),Jt(r,(Te(),cs),(ua(),Gc)),Jt(r,Id,(t0(),UG)),D0(r,(Vn(),ks)),n=new Mc,Uo(n,r),Bs(n,(ve(),Bn)),s=new Mc,Uo(s,r),Bs(s,Hn),r}function Noe(t){switch(t.g){case 0:return new det((ev(),RO));case 1:return new VB;case 2:return new ltt;default:throw it(new Fn("No implementation is available for the crossing minimizer "+(t.f!=null?t.f:""+t.g)))}}function Boe(t,e){var n,r,s,o,h;for(t.c[e.p]=!0,le(t.a,e),h=new S(e.j);h.a=o)h.$b();else for(s=h.Kc(),r=0;r0?rbt():h<0&&zoe(t,e,-h),!0):!1}function dI(t){var e,n,r,s,o,h,d;if(d=0,t.b==0){for(h=Ese(t,!0),e=0,r=h,s=0,o=r.length;s0&&(d+=n,++e);e>1&&(d+=t.c*(e-1))}else d=bHt(Sne(l$(Ri(Qnt(t.a),new Ml),new ha)));return d>0?d+t.n.d+t.n.a:0}function gI(t){var e,n,r,s,o,h,d;if(d=0,t.b==0)d=bHt(Sne(l$(Ri(Qnt(t.a),new th),new Fa)));else{for(h=Tse(t,!0),e=0,r=h,s=0,o=r.length;s0&&(d+=n,++e);e>1&&(d+=t.c*(e-1))}return d>0?d+t.n.b+t.n.c:0}function tbn(t,e){var n,r,s,o;for(o=u(po(t.b,e),124),n=o.a,s=u(u(Ai(t.r,e),21),84).Kc();s.Ob();)r=u(s.Pb(),111),r.c&&(n.a=b.Math.max(n.a,Vwt(r.c)));if(n.a>0)switch(e.g){case 2:o.n.c=t.s;break;case 4:o.n.b=t.s}}function ebn(t,e){var n,r,s;return n=u(Q(e,(Jf(),c7)),19).a-u(Q(t,c7),19).a,n==0?(r=ia(nc(u(Q(t,(Yp(),vO)),8)),u(Q(t,dS),8)),s=ia(nc(u(Q(e,vO),8)),u(Q(e,dS),8)),Ms(r.a*r.b,s.a*s.b)):n}function nbn(t,e){var n,r,s;return n=u(Q(e,(gv(),PG)),19).a-u(Q(t,PG),19).a,n==0?(r=ia(nc(u(Q(t,(fc(),zO)),8)),u(Q(t,$S),8)),s=ia(nc(u(Q(e,zO),8)),u(Q(e,$S),8)),Ms(r.a*r.b,s.a*s.b)):n}function qoe(t){var e,n;return n=new Mp,n.a+="e_",e=hun(t),e!=null&&(n.a+=""+e),t.c&&t.d&&(Gr((n.a+=" ",n),iq(t.c)),Gr(hc((n.a+="[",n),t.c.i),"]"),Gr((n.a+=Uot,n),iq(t.d)),Gr(hc((n.a+="[",n),t.d.i),"]")),n.a}function Hoe(t){switch(t.g){case 0:return new ZL;case 1:return new ctt;case 2:return new ott;case 3:return new GB;default:throw it(new Fn("No implementation is available for the layout phase "+(t.f!=null?t.f:""+t.g)))}}function o5t(t,e,n,r,s){var o;switch(o=0,s.g){case 1:o=b.Math.max(0,e.b+t.b-(n.b+r));break;case 3:o=b.Math.max(0,-t.b-r);break;case 2:o=b.Math.max(0,-t.a-r);break;case 4:o=b.Math.max(0,e.a+t.a-(n.a+r))}return o}function rbn(t,e,n){var r,s,o,h,d;if(n)for(s=n.a.length,r=new e2(s),d=(r.b-r.a)*r.c<0?(Fp(),Ib):new jp(r);d.Ob();)h=u(d.Pb(),19),o=P8(n,h.a),k8t in o.a||nut in o.a?gmn(t,o,e):yxn(t,o,e),zQe(u(tr(t.b,pE(o)),79))}function c5t(t){var e,n;switch(t.b){case-1:return!0;case 0:return n=t.t,n>1||n==-1?(t.b=-1,!0):(e=Dh(t),e&&(to(),e.Cj()==j0e)?(t.b=-1,!0):(t.b=1,!1));default:case 1:return!1}}function ibn(t,e){var n,r,s,o,h;for(r=(!e.s&&(e.s=new fe(Mu,e,21,17)),e.s),o=null,s=0,h=r.i;s=0&&r=0?t._g(n,!0,!0):dv(t,s,!0),153)),u(r,215).ll(e);throw it(new Fn(lb+e.ne()+Wct))}function ubn(){Tbt();var t;return T5e?u(_E((Pp(),Yh),Bh),1939):(ii(P2,new jf),V4n(),t=u(_t(Nc((Pp(),Yh),Bh),547)?Nc(Yh,Bh):new LXt,547),T5e=!0,$xn(t),Gxn(t),ki((Ebt(),sLt),t,new oJ),ko(Yh,Bh,t),t)}function lbn(t,e){var n,r,s,o;t.j=-1,xl(t.e)?(n=t.i,o=t.i!=0,gD(t,e),r=new z0(t.e,3,t.c,null,e,n,o),s=e.Qk(t.e,t.c,null),s=xae(t,e,s),s?(s.Ei(r),s.Fi()):mi(t.e,r)):(gD(t,e),s=e.Qk(t.e,t.c,null),s&&s.Fi())}function gq(t,e){var n,r,s;if(s=0,r=e[0],r>=t.length)return-1;for(n=(Rr(r,t.length),t.charCodeAt(r));n>=48&&n<=57&&(s=s*10+(n-48),++r,!(r>=t.length));)n=(Rr(r,t.length),t.charCodeAt(r));return r>e[0]?e[0]=r:s=-1,s}function hbn(t){var e,n,r,s,o;return s=u(t.a,19).a,o=u(t.b,19).a,n=s,r=o,e=b.Math.max(b.Math.abs(s),b.Math.abs(o)),s<=0&&s==o?(n=0,r=o-1):s==-e&&o!=e?(n=o,r=s,o>=0&&++n):(n=-o,r=s),new fa(pe(n),pe(r))}function fbn(t,e,n,r){var s,o,h,d,v,k;for(s=0;s=0&&k>=0&&v=t.i)throw it(new yo(iut+e+D2+t.i));if(n>=t.i)throw it(new yo(sut+n+D2+t.i));return r=t.g[n],e!=n&&(e>16),e=r>>16&16,n=16-e,t=t>>e,r=t-256,e=r>>16&8,n+=e,t<<=e,r=t-Ey,e=r>>16&4,n+=e,t<<=e,r=t-md,e=r>>16&2,n+=e,t<<=e,r=t>>14,e=r&~(r>>1),n+2-e)}function gbn(t){Ux();var e,n,r,s;for(dV=new he,Jut=new _r,Zut=new he,e=(!t.a&&(t.a=new fe(rs,t,10,11)),t.a),U5n(e),s=new nr(e);s.e!=s.i.gc();)r=u(dr(s),33),Ro(dV,r,0)==-1&&(n=new he,le(Zut,n),ese(r,n));return Zut}function pbn(t,e,n){var r,s,o,h;t.a=n.b.d,_t(e,352)?(s=x4(u(e,79),!1,!1),o=lI(s),r=new Ea(t),va(o,r),CI(o,s),e.We((ui(),a5))!=null&&va(u(e.We(a5),74),r)):(h=u(e,470),h.Hg(h.Dg()+t.a.a),h.Ig(h.Eg()+t.a.b))}function Goe(t,e){var n,r,s,o,h,d,v,k;for(k=Xt(ye(Q(e,(Te(),LS)))),v=t[0].n.a+t[0].o.a+t[0].d.c+k,d=1;d=0?n:(d=D9(ia(new $e(h.c+h.b/2,h.d+h.a/2),new $e(o.c+o.b/2,o.d+o.a/2))),-(dle(o,h)-1)*d)}function wbn(t,e,n){var r;ls(new Tn(null,(!n.a&&(n.a=new fe(Ji,n,6,6)),new _n(n.a,16))),new LGt(t,e)),ls(new Tn(null,(!n.n&&(n.n=new fe(qo,n,1,7)),new _n(n.n,16))),new MGt(t,e)),r=u(qe(n,(ui(),a5)),74),r&&dyt(r,t,e)}function dv(t,e,n){var r,s,o;if(o=C4(($u(),ya),t.Tg(),e),o)return to(),u(o,66).Oj()||(o=Kx(To(ya,o))),s=(r=t.Yg(o),u(r>=0?t._g(r,!0,!0):dv(t,o,!0),153)),u(s,215).hl(e,n);throw it(new Fn(lb+e.ne()+Wct))}function l5t(t,e,n,r){var s,o,h,d,v;if(s=t.d[e],s){if(o=s.g,v=s.i,r!=null){for(d=0;d=n&&(r=e,k=(v.c+v.a)/2,h=k-n,v.c<=k-n&&(s=new Dnt(v.c,h),Hm(t,r++,s)),d=k+n,d<=v.a&&(o=new Dnt(d,v.a),Km(r,t.c.length),XC(t.c,r,o)))}function h5t(t){var e;if(!t.c&&t.g==null)t.d=t.si(t.f),Dr(t,t.d),e=t.d;else{if(t.g==null)return!0;if(t.i==0)return!1;e=u(t.g[t.i-1],47)}return e==t.b&&null.km>=null.jm()?(wq(t),h5t(t)):e.Ob()}function xbn(t,e,n){var r,s,o,h,d;if(d=n,!d&&(d=qwt(new r8,0)),vr(d,c1e,1),dhe(t.c,e),h=F4n(t.a,e),h.gc()==1)Kle(u(h.Xb(0),37),d);else for(o=1/h.gc(),s=h.Kc();s.Ob();)r=u(s.Pb(),37),Kle(r,Rc(d,o));LKe(t.a,h,e),Fvn(e),or(d)}function Yoe(t){if(this.a=t,t.c.i.k==(Vn(),ks))this.c=t.c,this.d=u(Q(t.c.i,(ae(),oc)),61);else if(t.d.i.k==ks)this.c=t.d,this.d=u(Q(t.d.i,(ae(),oc)),61);else throw it(new Fn("Edge "+t+" is not an external edge."))}function Koe(t,e){var n,r,s;s=t.b,t.b=e,t.Db&4&&!(t.Db&1)&&mi(t,new Js(t,1,3,s,t.b)),e?e!=t&&(Qc(t,e.zb),hit(t,e.d),n=(r=e.c,r??e.zb),dit(t,n==null||hn(n,e.zb)?null:n)):(Qc(t,null),hit(t,0),dit(t,null))}function Xoe(t){var e,n;if(t.f){for(;t.n=h)throw it(new qm(e,h));return s=n[e],h==1?r=null:(r=Nt(Fft,lut,415,h-1,0,1),Dc(n,0,r,0,e),o=h-e-1,o>0&&Dc(n,e+1,r,e,o)),bE(t,r),moe(t,e,s),s}function d6(){d6=Z,tk=u(At(Wt((fbt(),pc).qb),6),34),J6=u(At(Wt(pc.qb),3),34),zft=u(At(Wt(pc.qb),4),34),qft=u(At(Wt(pc.qb),5),18),cq(tk),cq(J6),cq(zft),cq(qft),A5e=new yl(lt(ct(Mu,1),B4,170,0,[tk,J6]))}function tce(t,e){var n;this.d=new OC,this.b=e,this.e=new xo(e.qf()),n=t.u.Hc((Zu(),sP)),t.u.Hc(sg)?t.D?this.a=n&&!e.If():this.a=!0:t.u.Hc(Cb)?n?this.a=!(e.zf().Kc().Ob()||e.Bf().Kc().Ob()):this.a=!1:this.a=!1}function ece(t,e){var n,r,s,o;for(n=t.o.a,o=u(u(Ai(t.r,e),21),84).Kc();o.Ob();)s=u(o.Pb(),111),s.e.a=(r=s.b,r.Xe((ui(),dl))?r.Hf()==(ve(),Bn)?-r.rf().a-Xt(ye(r.We(dl))):n+Xt(ye(r.We(dl))):r.Hf()==(ve(),Bn)?-r.rf().a:n)}function nce(t,e){var n,r,s,o;n=u(Q(t,(Te(),Wl)),103),o=u(qe(e,C7),61),s=u(Q(t,cs),98),s!=(ua(),G1)&&s!=Tb?o==(ve(),Zo)&&(o=uxt(e,n),o==Zo&&(o=a6(n))):(r=Yle(e),r>0?o=a6(n):o=YD(a6(n))),wo(e,C7,o)}function Cbn(t,e){var n,r,s,o,h;for(h=t.j,e.a!=e.b&&Zs(h,new ex),s=h.c.length/2|0,r=0;r0&&kI(t,n,e),o):r.a!=null?(kI(t,e,n),-1):s.a!=null?(kI(t,n,e),1):0}function rce(t,e){var n,r,s,o;t.ej()?(n=t.Vi(),o=t.fj(),++t.j,t.Hi(n,t.oi(n,e)),r=t.Zi(3,null,e,n,o),t.bj()?(s=t.cj(e,null),s?(s.Ei(r),s.Fi()):t.$i(r)):t.$i(r)):(mXt(t,e),t.bj()&&(s=t.cj(e,null),s&&s.Fi()))}function pq(t,e){var n,r,s,o,h;for(h=ou(t.e.Tg(),e),s=new ox,n=u(t.g,119),o=t.i;--o>=0;)r=n[o],h.rl(r.ak())&&Dr(s,r);!Uhe(t,s)&&xl(t.e)&&n8(t,e.$j()?Gp(t,6,e,(wn(),io),null,-1,!1):Gp(t,e.Kj()?2:1,e,null,null,-1,!1))}function TE(){TE=Z;var t,e;for(D6=Nt(j4,ee,91,32,0,1),lS=Nt(j4,ee,91,32,0,1),t=1,e=0;e<=18;e++)D6[e]=JD(t),lS[e]=JD(F0(t,e)),t=_a(t,5);for(;eh)||e.q&&(r=e.C,h=r.c.c.a-r.o.a/2,s=r.n.a-n,s>h)))}function Abn(t,e){var n;vr(e,"Partition preprocessing",1),n=u(Bl(Ri(Wo(Ri(new Tn(null,new _n(t.a,16)),new QK),new wN),new Z5),c2(new ke,new ce,new Xn,lt(ct(fl,1),oe,132,0,[(O1(),Ul)]))),15),ls(n.Oc(),new vN),or(e)}function ice(t){_rt();var e,n,r,s,o,h,d;for(n=new a2,s=new S(t.e.b);s.a1?t.e*=Xt(t.a):t.f/=Xt(t.a),uln(t),gfn(t),Xvn(t),Jt(t.b,(o_(),fV),t.g)}function cce(t,e,n){var r,s,o,h,d,v;for(r=0,v=n,e||(r=n*(t.c.length-1),v*=-1),o=new S(t);o.a=0?(e||(e=new $C,r>0&&go(e,t.substr(0,r))),e.a+="\\",S8(e,n&ys)):e&&S8(e,n&ys);return e?e.a:t}function Bbn(t){var e;if(!t.a)throw it(new No("IDataType class expected for layout option "+t.f));if(e=Gsn(t.a),e==null)throw it(new No("Couldn't create new instance of property '"+t.f+"'. "+ade+(P0(gP),gP.k)+d8t));return u(e,414)}function eat(t){var e,n,r,s,o;return o=t.eh(),o&&o.kh()&&(s=Zp(t,o),s!=o)?(n=t.Vg(),r=(e=t.Vg(),e>=0?t.Qg(null):t.eh().ih(t,-1-e,null,null)),t.Rg(u(s,49),n),r&&r.Fi(),t.Lg()&&t.Mg()&&n>-1&&mi(t,new Js(t,9,n,o,s)),s):o}function dce(t){var e,n,r,s,o,h,d,v;for(h=0,o=t.f.e,r=0;r>5,s>=t.d)return t.e<0;if(n=t.a[s],e=1<<(e&31),t.e<0){if(r=Ine(t),s>16)),15).Xc(o),d0&&(!(Bp(t.a.c)&&e.n.d)&&!(b8(t.a.c)&&e.n.b)&&(e.g.d+=b.Math.max(0,r/2-.5)),!(Bp(t.a.c)&&e.n.a)&&!(b8(t.a.c)&&e.n.c)&&(e.g.a-=r-1))}function bce(t){var e,n,r,s,o;if(s=new he,o=ule(t,s),e=u(Q(t,(ae(),Ju)),10),e)for(r=new S(e.j);r.a>e,o=t.m>>e|n<<22-e,s=t.l>>e|t.m<<22-e):e<44?(h=r?Z0:0,o=n>>e-22,s=t.m>>e-22|n<<44-e):(h=r?Z0:0,o=r?hl:0,s=n>>e-44),iu(s&hl,o&hl,h&Z0)}function nat(t){var e,n,r,s,o,h;for(this.c=new he,this.d=t,r=as,s=as,e=Cs,n=Cs,h=ei(t,0);h.b!=h.d.c;)o=u(ti(h),8),r=b.Math.min(r,o.a),s=b.Math.min(s,o.b),e=b.Math.max(e,o.a),n=b.Math.max(n,o.b);this.a=new ah(r,s,e-r,n-s)}function mce(t,e){var n,r,s,o,h,d;for(o=new S(t.b);o.a0&&_t(e,42)&&(t.a.qj(),k=u(e,42),v=k.cd(),o=v==null?0:Hi(v),h=rwt(t.a,o),n=t.a.d[h],n)){for(r=u(n.g,367),C=n.i,d=0;d=2)for(n=s.Kc(),e=ye(n.Pb());n.Ob();)o=e,e=ye(n.Pb()),r=b.Math.min(r,(On(e),e-(On(o),o)));return r}function Ybn(t,e){var n,r,s,o,h;r=new Zi,fs(r,e,r.c.b,r.c);do for(n=(Zn(r.b!=0),u(lh(r,r.a.a),86)),t.b[n.g]=1,o=ei(n.d,0);o.b!=o.d.c;)s=u(ti(o),188),h=s.c,t.b[h.g]==1?ri(t.a,s):t.b[h.g]==2?t.b[h.g]=1:fs(r,h,r.c.b,r.c);while(r.b!=0)}function Kbn(t,e){var n,r,s;if(Vt(e)===Vt(Lr(t)))return!0;if(!_t(e,15)||(r=u(e,15),s=t.gc(),s!=r.gc()))return!1;if(_t(r,54)){for(n=0;n0&&(s=n),h=new S(t.f.e);h.a0?(e-=1,n-=1):r>=0&&s<0?(e+=1,n+=1):r>0&&s>=0?(e-=1,n+=1):(e+=1,n-=1),new fa(pe(e),pe(n))}function d2n(t,e){return t.ce.c?1:t.be.b?1:t.a!=e.a?Hi(t.a)-Hi(e.a):t.d==($9(),BS)&&e.d==NS?-1:t.d==NS&&e.d==BS?1:0}function _ce(t,e){var n,r,s,o,h;return o=e.a,o.c.i==e.b?h=o.d:h=o.c,o.c.i==e.b?r=o.c:r=o.d,s=zhn(t.a,h,r),s>0&&s0):s<0&&-s0):!1}function g2n(t,e,n,r){var s,o,h,d,v,k,C,M;for(s=(e-t.d)/t.c.c.length,o=0,t.a+=n,t.d=e,M=new S(t.c);M.a>24;return h}function b2n(t){if(t.pe()){var e=t.c;e.qe()?t.o="["+e.n:e.pe()?t.o="["+e.ne():t.o="[L"+e.ne()+";",t.b=e.me()+"[]",t.k=e.oe()+"[]";return}var n=t.j,r=t.d;r=r.split("/"),t.o=ast(".",[n,ast("$",r)]),t.b=ast(".",[n,ast(".",r)]),t.k=r[r.length-1]}function w2n(t,e){var n,r,s,o,h;for(h=null,o=new S(t.e.a);o.a=0;e-=2)for(n=0;n<=e;n+=2)(t.b[n]>t.b[n+2]||t.b[n]===t.b[n+2]&&t.b[n+1]>t.b[n+3])&&(r=t.b[n+2],t.b[n+2]=t.b[n],t.b[n]=r,r=t.b[n+3],t.b[n+3]=t.b[n+1],t.b[n+1]=r);t.c=!0}}function Sce(t,e){var n,r,s,o,h,d,v,k;for(h=e==1?clt:olt,o=h.a.ec().Kc();o.Ob();)for(s=u(o.Pb(),103),v=u(Ai(t.f.c,s),21).Kc();v.Ob();)switch(d=u(v.Pb(),46),r=u(d.b,81),k=u(d.a,189),n=k.c,s.g){case 2:case 1:r.g.d+=n;break;case 4:case 3:r.g.c+=n}}function y2n(t,e){var n,r,s,o,h,d,v,k,C;for(k=-1,C=0,h=t,d=0,v=h.length;d0&&++C;++k}return C}function mf(t){var e,n;return n=new Ol(Ip(t.gm)),n.a+="@",Gr(n,(e=Hi(t)>>>0,e.toString(16))),t.kh()?(n.a+=" (eProxyURI: ",hc(n,t.qh()),t.$g()&&(n.a+=" eClass: ",hc(n,t.$g())),n.a+=")"):t.$g()&&(n.a+=" (eClass: ",hc(n,t.$g()),n.a+=")"),n.a}function v_(t){var e,n,r,s;if(t.e)throw it(new No((P0(zut),Sot+zut.k+Aot)));for(t.d==(ao(),h0)&&Bq(t,zh),n=new S(t.a.a);n.a>24}return n}function E2n(t,e,n){var r,s,o;if(s=u(po(t.i,e),306),!s)if(s=new Aee(t.d,e,n),zx(t.i,e,s),P3t(e))jQe(t.a,e.c,e.b,s);else switch(o=lpn(e),r=u(po(t.p,o),244),o.g){case 1:case 3:s.j=!0,het(r,e.b,s);break;case 4:case 2:s.k=!0,het(r,e.c,s)}return s}function T2n(t,e,n,r){var s,o,h,d,v,k;if(d=new ox,v=ou(t.e.Tg(),e),s=u(t.g,119),to(),u(e,66).Oj())for(h=0;h=0)return s;for(o=1,d=new S(e.j);d.a0&&e.ue((An(s-1,t.c.length),u(t.c[s-1],10)),o)>0;)ch(t,s,(An(s-1,t.c.length),u(t.c[s-1],10))),--s;An(s,t.c.length),t.c[s]=o}n.a=new _r,n.b=new _r}function C2n(t,e,n){var r,s,o,h,d,v,k,C;for(C=(r=u(e.e&&e.e(),9),new sh(r,u(ff(r,r.length),9),0)),v=vy(n,"[\\[\\]\\s,]+"),o=v,h=0,d=o.length;h0&&(!(Bp(t.a.c)&&e.n.d)&&!(b8(t.a.c)&&e.n.b)&&(e.g.d-=b.Math.max(0,r/2-.5)),!(Bp(t.a.c)&&e.n.a)&&!(b8(t.a.c)&&e.n.c)&&(e.g.a+=b.Math.max(0,r-1)))}function Ice(t,e,n){var r,s;if((t.c-t.b&t.a.length-1)==2)e==(ve(),Pn)||e==Hn?(nz(u(Q9(t),15),(zl(),f0)),nz(u(Q9(t),15),kb)):(nz(u(Q9(t),15),(zl(),kb)),nz(u(Q9(t),15),f0));else for(s=new O9(t);s.a!=s.b;)r=u(Mz(s),15),nz(r,n)}function S2n(t,e){var n,r,s,o,h,d,v;for(s=x8(new Tpt(t)),d=new da(s,s.c.length),o=x8(new Tpt(e)),v=new da(o,o.c.length),h=null;d.b>0&&v.b>0&&(n=(Zn(d.b>0),u(d.a.Xb(d.c=--d.b),33)),r=(Zn(v.b>0),u(v.a.Xb(v.c=--v.b),33)),n==r);)h=n;return h}function ul(t,e){var n,r,s,o,h,d;return o=t.a*Eot+t.b*1502,d=t.b*Eot+11,n=b.Math.floor(d*$I),o+=n,d-=n*Gxt,o%=Gxt,t.a=o,t.b=d,e<=24?b.Math.floor(t.a*DEt[e]):(s=t.a*(1<=2147483648&&(r-=mot),r)}function Oce(t,e,n){var r,s,o,h;rZt(t,e)>rZt(t,n)?(r=Ko(n,(ve(),Hn)),t.d=r.dc()?0:Nnt(u(r.Xb(0),11)),h=Ko(e,Bn),t.b=h.dc()?0:Nnt(u(h.Xb(0),11))):(s=Ko(n,(ve(),Bn)),t.d=s.dc()?0:Nnt(u(s.Xb(0),11)),o=Ko(e,Hn),t.b=o.dc()?0:Nnt(u(o.Xb(0),11)))}function Pce(t){var e,n,r,s,o,h,d;if(t&&(e=t.Hh(Bh),e&&(h=Br(Xf((!e.b&&(e.b=new kl((dn(),Qa),cc,e)),e.b),"conversionDelegates")),h!=null))){for(d=new he,r=vy(h,"\\w+"),s=0,o=r.length;st.c));h++)s.a>=t.s&&(o<0&&(o=h),d=h);return v=(t.s+t.c)/2,o>=0&&(r=lmn(t,e,o,d),v=mXe((An(r,e.c.length),u(e.c[r],329))),ybn(e,r,n)),v}function sat(){sat=Z,l3e=new eo((ui(),W6),1.3),G_t=GSt,Z_t=new Ow(15),w3e=new eo(U2,Z_t),m3e=new eo(W2,15),h3e=YG,g3e=G2,p3e=c5,b3e=xb,d3e=o5,K_t=tP,v3e=Qy,Q_t=(y5t(),o3e),Y_t=s3e,X_t=a3e,J_t=c3e,U_t=i3e,W_t=KG,f3e=WSt,HO=r3e,V_t=n3e,tSt=u3e}function Ir(t,e,n){var r,s,o,h,d,v,k;for(h=(o=new lB,o),oyt(h,(On(e),e)),k=(!h.b&&(h.b=new kl((dn(),Qa),cc,h)),h.b),v=1;v0&&r4n(this,s)}function S5t(t,e,n,r,s,o){var h,d,v;if(!s[e.b]){for(s[e.b]=!0,h=r,!h&&(h=new B$),le(h.e,e),v=o[e.b].Kc();v.Ob();)d=u(v.Pb(),282),!(d.d==n||d.c==n)&&(d.c!=e&&S5t(t,d.c,e,h,s,o),d.d!=e&&S5t(t,d.d,e,h,s,o),le(h.c,d),Ls(h.d,d.b));return h}return null}function M2n(t){var e,n,r,s,o,h,d;for(e=0,s=new S(t.e);s.a=2}function D2n(t,e){var n,r,s,o;for(vr(e,"Self-Loop pre-processing",1),r=new S(t.a);r.a1||(e=ji(_f,lt(ct(lo,1),oe,93,0,[ig,Sf])),OD(k$(e,t))>1)||(r=ji(Lf,lt(ct(lo,1),oe,93,0,[d0,Hh])),OD(k$(r,t))>1))}function P2n(t,e){var n,r,s;return n=e.Hh(t.a),n&&(s=Br(Xf((!n.b&&(n.b=new kl((dn(),Qa),cc,n)),n.b),"affiliation")),s!=null)?(r=Tj(s,Cu(35)),r==-1?Uit(t,C9(t,Rl(e.Hj())),s):r==0?Uit(t,null,s.substr(1)):Uit(t,s.substr(0,r),s.substr(r+1))):null}function F2n(t){var e,n,r;try{return t==null?_u:$o(t)}catch(s){if(s=Wi(s),_t(s,102))return e=s,r=Ip(ol(t))+"@"+(n=(Gd(),$3t(t)>>>0),n.toString(16)),Efn(kun(),(d8(),"Exception during lenientFormat for "+r),e),"<"+r+" threw "+Ip(e.gm)+">";throw it(s)}}function Bce(t){switch(t.g){case 0:return new ett;case 1:return new qB;case 2:return new jVt;case 3:return new BL;case 4:return new aYt;case 5:return new ntt;default:throw it(new Fn("No implementation is available for the layerer "+(t.f!=null?t.f:""+t.g)))}}function A5t(t,e,n){var r,s,o;for(o=new S(t.t);o.a0&&(r.b.n-=r.c,r.b.n<=0&&r.b.u>0&&ri(e,r.b));for(s=new S(t.i);s.a0&&(r.a.u-=r.c,r.a.u<=0&&r.a.n>0&&ri(n,r.a))}function wq(t){var e,n,r,s,o;if(t.g==null&&(t.d=t.si(t.f),Dr(t,t.d),t.c))return o=t.f,o;if(e=u(t.g[t.i-1],47),s=e.Pb(),t.e=e,n=t.si(s),n.Ob())t.d=n,Dr(t,n);else for(t.d=null;!e.Ob()&&(ts(t.g,--t.i,null),t.i!=0);)r=u(t.g[t.i-1],47),e=r;return s}function N2n(t,e){var n,r,s,o,h,d;if(r=e,s=r.ak(),X0(t.e,s)){if(s.hi()&&O$(t,s,r.dd()))return!1}else for(d=ou(t.e.Tg(),s),n=u(t.g,119),o=0;o1||n>1)return 2;return e+n==1?2:0}function jce(t,e,n){var r,s,o,h,d;for(vr(n,"ELK Force",1),je(Re(qe(e,(Jf(),y7t))))||y$((r=new rr((Pm(),new Mm(e))),r)),d=pre(e),odn(d),$un(t,u(Q(d,m7t),424)),h=Ale(t.a,d),o=h.Kc();o.Ob();)s=u(o.Pb(),231),kmn(t.b,s,Rc(n,1/h.gc()));d=zhe(h),Rhe(d),or(n)}function H2n(t,e){var n,r,s,o,h;if(vr(e,"Breaking Point Processor",1),u5n(t),je(Re(Q(t,(Te(),S9t))))){for(s=new S(t.b);s.a=0?t._g(r,!0,!0):dv(t,o,!0),153)),u(s,215).ml(e,n)}else throw it(new Fn(lb+e.ne()+X_))}function W2n(t,e){var n,r,s,o,h;for(n=new he,s=Wo(new Tn(null,new _n(t,16)),new ZQ),o=Wo(new Tn(null,new _n(t,16)),new JQ),h=yon(Fan(l$(_wn(lt(ct(n6n,1),De,833,0,[s,o])),new tZ))),r=1;r=2*e&&le(n,new Dnt(h[r-1]+e,h[r]-e));return n}function Y2n(t,e,n){vr(n,"Eades radial",1),n.n&&e&&gf(n,pf(e),(Sl(),Ql)),t.d=u(qe(e,(m9(),HS)),33),t.c=Xt(ye(qe(e,(uy(),RG)))),t.e=pst(u(qe(e,qO),293)),t.a=Shn(u(qe(e,D_t),426)),t.b=Kdn(u(qe(e,M_t),340)),Ldn(t),n.n&&e&&gf(n,pf(e),(Sl(),Ql))}function K2n(t,e,n){var r,s,o,h,d,v,k,C;if(n)for(o=n.a.length,r=new e2(o),d=(r.b-r.a)*r.c<0?(Fp(),Ib):new jp(r);d.Ob();)h=u(d.Pb(),19),s=P8(n,h.a),s&&(v=Wsn(t,(k=(Sw(),C=new Gpt,C),e&&D5t(k,e),k),s),G9(v,R0(s,Ad)),lq(s,v),e5t(s,v),Lit(t,s,v))}function mq(t){var e,n,r,s,o,h;if(!t.j){if(h=new tC,e=uA,o=e.a.zc(t,e),o==null){for(r=new nr(Ao(t));r.e!=r.i.gc();)n=u(dr(r),26),s=mq(n),is(h,s),Dr(h,n);e.a.Bc(t)!=null}iy(h),t.j=new V3((u(At(Wt((Hp(),Ln).o),11),18),h.i),h.g),sl(t).b&=-33}return t.j}function X2n(t){var e,n,r,s;if(t==null)return null;if(r=$c(t,!0),s=oO.length,hn(r.substr(r.length-s,s),oO)){if(n=r.length,n==4){if(e=(Rr(0,r.length),r.charCodeAt(0)),e==43)return CLt;if(e==45)return G5e}else if(n==3)return CLt}return new Ppt(r)}function Q2n(t){var e,n,r;return n=t.l,n&n-1||(r=t.m,r&r-1)||(e=t.h,e&e-1)||e==0&&r==0&&n==0?-1:e==0&&r==0&&n!=0?tyt(n):e==0&&r!=0&&n==0?tyt(r)+22:e!=0&&r==0&&n==0?tyt(e)+44:-1}function Z2n(t,e){var n,r,s,o,h;for(vr(e,"Edge joining",1),n=je(Re(Q(t,(Te(),dht)))),s=new S(t.b);s.a1)for(s=new S(t.a);s.a0),o.a.Xb(o.c=--o.b),zm(o,s),Zn(o.b3&&Jd(t,0,e-3))}function nwn(t){var e,n,r,s;return Vt(Q(t,(Te(),qy)))===Vt((G0(),sp))?!t.e&&Vt(Q(t,DO))!==Vt((eE(),TO)):(r=u(Q(t,eht),292),s=je(Re(Q(t,nht)))||Vt(Q(t,_S))===Vt((n6(),EO)),e=u(Q(t,VCt),19).a,n=t.a.c.length,!s&&r!=(eE(),TO)&&(e==0||e>n))}function rwn(t){var e,n;for(n=0;n0);n++);if(n>0&&n0);e++);return e>0&&n>16!=6&&e){if(vE(t,e))throw it(new Fn(Q_+sce(t)));r=null,t.Cb&&(r=(n=t.Db>>16,n>=0?r4t(t,r):t.Cb.ih(t,-1-n,null,r))),e&&(r=c6(e,t,6,r)),r=ewt(t,e,r),r&&r.Fi()}else t.Db&4&&!(t.Db&1)&&mi(t,new Js(t,1,6,e,e))}function D5t(t,e){var n,r;if(e!=t.Cb||t.Db>>16!=9&&e){if(vE(t,e))throw it(new Fn(Q_+zue(t)));r=null,t.Cb&&(r=(n=t.Db>>16,n>=0?s4t(t,r):t.Cb.ih(t,-1-n,null,r))),e&&(r=c6(e,t,9,r)),r=nwt(t,e,r),r&&r.Fi()}else t.Db&4&&!(t.Db&1)&&mi(t,new Js(t,1,9,e,e))}function oat(t,e){var n,r;if(e!=t.Cb||t.Db>>16!=3&&e){if(vE(t,e))throw it(new Fn(Q_+$le(t)));r=null,t.Cb&&(r=(n=t.Db>>16,n>=0?o4t(t,r):t.Cb.ih(t,-1-n,null,r))),e&&(r=c6(e,t,12,r)),r=twt(t,e,r),r&&r.Fi()}else t.Db&4&&!(t.Db&1)&&mi(t,new Js(t,1,3,e,e))}function SE(t){var e,n,r,s,o;if(r=Dh(t),o=t.j,o==null&&r)return t.$j()?null:r.zj();if(_t(r,148)){if(n=r.Aj(),n&&(s=n.Nh(),s!=t.i)){if(e=u(r,148),e.Ej())try{t.g=s.Kh(e,o)}catch(h){if(h=Wi(h),_t(h,78))t.g=null;else throw it(h)}t.i=s}return t.g}return null}function qce(t){var e;return e=new he,le(e,new Dx(new $e(t.c,t.d),new $e(t.c+t.b,t.d))),le(e,new Dx(new $e(t.c,t.d),new $e(t.c,t.d+t.a))),le(e,new Dx(new $e(t.c+t.b,t.d+t.a),new $e(t.c+t.b,t.d))),le(e,new Dx(new $e(t.c+t.b,t.d+t.a),new $e(t.c,t.d+t.a))),e}function Hce(t,e,n,r){var s,o,h;if(h=p4t(e,n),r.c[r.c.length]=e,t.j[h.p]==-1||t.j[h.p]==2||t.a[e.p])return r;for(t.j[h.p]=-1,o=new ar(lr(U0(h).a.Kc(),new z));zr(o);)if(s=u(Mr(o),17),!(!(!Ga(s)&&!(!Ga(s)&&s.c.i.c==s.d.i.c))||s==e))return Hce(t,s,h,r);return r}function iwn(t,e,n){var r,s,o;for(o=e.a.ec().Kc();o.Ob();)s=u(o.Pb(),79),r=u(tr(t.b,s),266),!r&&(es(e0(s))==es(tb(s))?mvn(t,s,n):e0(s)==es(tb(s))?tr(t.c,s)==null&&tr(t.b,tb(s))!=null&&khe(t,s,n,!1):tr(t.d,s)==null&&tr(t.b,e0(s))!=null&&khe(t,s,n,!0))}function swn(t,e){var n,r,s,o,h,d,v;for(s=t.Kc();s.Ob();)for(r=u(s.Pb(),10),d=new Mc,Uo(d,r),Bs(d,(ve(),Hn)),Jt(d,(ae(),nG),(Nn(),!0)),h=e.Kc();h.Ob();)o=u(h.Pb(),10),v=new Mc,Uo(v,o),Bs(v,Bn),Jt(v,nG,!0),n=new Vw,Jt(n,nG,!0),Oa(n,d),oa(n,v)}function awn(t,e,n,r){var s,o,h,d;s=Rie(t,e,n),o=Rie(t,n,e),h=u(tr(t.c,e),112),d=u(tr(t.c,n),112),sr.b.g&&(o.c[o.c.length]=r);return o}function AE(){AE=Z,i5=new DM("CANDIDATE_POSITION_LAST_PLACED_RIGHT",0),G6=new DM("CANDIDATE_POSITION_LAST_PLACED_BELOW",1),GS=new DM("CANDIDATE_POSITION_WHOLE_DRAWING_RIGHT",2),VS=new DM("CANDIDATE_POSITION_WHOLE_DRAWING_BELOW",3),US=new DM("WHOLE_DRAWING",4)}function own(t,e){if(_t(e,239))return Bln(t,u(e,33));if(_t(e,186))return Xln(t,u(e,118));if(_t(e,354))return urn(t,u(e,137));if(_t(e,352))return Oyn(t,u(e,79));if(e)return null;throw it(new Fn(L8t+eb(new yl(lt(ct(Qn,1),De,1,5,[e])))))}function cwn(t){var e,n,r,s,o,h,d;for(o=new Zi,s=new S(t.d.a);s.a1)for(e=Fw((n=new Xb,++t.b,n),t.d),d=ei(o,0);d.b!=d.d.c;)h=u(ti(d),121),yf(lf(uf(hf(cf(new Ch,1),0),e),h))}function I5t(t,e){var n,r;if(e!=t.Cb||t.Db>>16!=11&&e){if(vE(t,e))throw it(new Fn(Q_+X5t(t)));r=null,t.Cb&&(r=(n=t.Db>>16,n>=0?c4t(t,r):t.Cb.ih(t,-1-n,null,r))),e&&(r=c6(e,t,10,r)),r=lwt(t,e,r),r&&r.Fi()}else t.Db&4&&!(t.Db&1)&&mi(t,new Js(t,1,11,e,e))}function uwn(t){var e,n,r,s;for(r=new p2(new Cg(t.b).a);r.b;)n=Zw(r),s=u(n.cd(),11),e=u(n.dd(),10),Jt(e,(ae(),_i),s),Jt(s,Ju,e),Jt(s,SO,(Nn(),!0)),Bs(s,u(Q(e,oc),61)),Q(e,oc),Jt(s.i,(Te(),cs),(ua(),B7)),u(Q(Na(s.i),Vc),21).Fc((oo(),y7))}function lwn(t,e,n){var r,s,o,h,d,v;if(o=0,h=0,t.c)for(v=new S(t.d.i.j);v.ao.a?-1:s.av){for(C=t.d,t.d=Nt(XAt,R8t,63,2*v+4,0,1),o=0;o=9223372036854776e3?(q8(),sEt):(s=!1,t<0&&(s=!0,t=-t),r=0,t>=C2&&(r=ps(t/C2),t-=r*C2),n=0,t>=m6&&(n=ps(t/m6),t-=n*m6),e=ps(t),o=iu(e,n,r),s&&Ait(o),o)}function ywn(t,e){var n,r,s,o;for(n=!e||!t.u.Hc((Zu(),sg)),o=0,s=new S(t.e.Cf());s.a=-e&&r==e?new fa(pe(n-1),pe(r)):new fa(pe(n),pe(r-1))}function Yce(){return ro(),lt(ct(l6n,1),oe,77,0,[J7t,X7t,gS,glt,vTt,CV,FV,h7,bTt,oTt,gTt,l7,wTt,iTt,mTt,V7t,LV,plt,EV,IV,xTt,DV,G7t,pTt,kTt,OV,yTt,TV,eTt,fTt,hTt,NV,Y7t,kV,SV,W7t,u7,uTt,sTt,dTt,pS,Q7t,K7t,lTt,aTt,AV,PV,U7t,MV,cTt,_V,nTt,tTt,xO,xV,rTt,Z7t])}function Twn(t,e,n){t.d=0,t.b=0,e.k==(Vn(),Hc)&&n.k==Hc&&u(Q(e,(ae(),_i)),10)==u(Q(n,_i),10)&&(eit(e).j==(ve(),Pn)?Oce(t,e,n):Oce(t,n,e)),e.k==Hc&&n.k==ta?eit(e).j==(ve(),Pn)?t.d=1:t.b=1:n.k==Hc&&e.k==ta&&(eit(n).j==(ve(),Pn)?t.b=1:t.d=1),h1n(t,e,n)}function Cwn(t){var e,n,r,s,o,h,d,v,k,C,M;return M=D4t(t),e=t.a,v=e!=null,v&&E8(M,"category",t.a),s=wM(new Sm(t.d)),h=!s,h&&(k=new Eg,Yf(M,"knownOptions",k),n=new Nzt(k),va(new Sm(t.d),n)),o=wM(t.g),d=!o,d&&(C=new Eg,Yf(M,"supportedFeatures",C),r=new Bzt(C),va(t.g,r)),M}function _wn(t){var e,n,r,s,o,h,d,v,k;for(r=!1,e=336,n=0,o=new XWt(t.length),d=t,v=0,k=d.length;v>16!=7&&e){if(vE(t,e))throw it(new Fn(Q_+eoe(t)));r=null,t.Cb&&(r=(n=t.Db>>16,n>=0?i4t(t,r):t.Cb.ih(t,-1-n,null,r))),e&&(r=u(e,49).gh(t,1,lP,r)),r=nvt(t,e,r),r&&r.Fi()}else t.Db&4&&!(t.Db&1)&&mi(t,new Js(t,1,7,e,e))}function Kce(t,e){var n,r;if(e!=t.Cb||t.Db>>16!=3&&e){if(vE(t,e))throw it(new Fn(Q_+lie(t)));r=null,t.Cb&&(r=(n=t.Db>>16,n>=0?a4t(t,r):t.Cb.ih(t,-1-n,null,r))),e&&(r=u(e,49).gh(t,0,fP,r)),r=rvt(t,e,r),r&&r.Fi()}else t.Db&4&&!(t.Db&1)&&mi(t,new Js(t,1,3,e,e))}function uat(t,e){TE();var n,r,s,o,h,d,v,k,C;return e.d>t.d&&(d=t,t=e,e=d),e.d<63?bvn(t,e):(h=(t.d&-2)<<4,k=bmt(t,h),C=bmt(e,h),r=Cat(t,Qx(k,h)),s=Cat(e,Qx(C,h)),v=uat(k,C),n=uat(r,s),o=uat(Cat(k,r),Cat(s,C)),o=Oat(Oat(o,v),n),o=Qx(o,h),v=Qx(v,h<<1),Oat(Oat(v,o),n))}function Awn(t,e,n){var r,s,o,h,d;for(h=t_(t,n),d=Nt(l0,Yg,10,e.length,0,1),r=0,o=h.Kc();o.Ob();)s=u(o.Pb(),11),je(Re(Q(s,(ae(),SO))))&&(d[r++]=u(Q(s,Ju),10));if(r=0;o+=n?1:-1)h=h|e.c.Sf(v,o,n,r&&!je(Re(Q(e.j,(ae(),Ov))))&&!je(Re(Q(e.j,(ae(),X4))))),h=h|e.q._f(v,o,n),h=h|Pue(t,v[o],n,r);return Fs(t.c,e),h}function xq(t,e,n){var r,s,o,h,d,v,k,C,M,j;for(C=OZt(t.j),M=0,j=C.length;M1&&(t.a=!0),Ven(u(n.b,65),Li(nc(u(e.b,65).c),fd(ia(nc(u(n.b,65).a),u(e.b,65).a),s))),WQt(t,e),Xce(t,n)}function Qce(t){var e,n,r,s,o,h,d;for(o=new S(t.a.a);o.a0&&o>0?h.p=e++:r>0?h.p=n++:o>0?h.p=s++:h.p=n++}wn(),Zs(t.j,new DL)}function Own(t){var e,n;n=null,e=u(Ne(t.g,0),17);do{if(n=e.d.i,Us(n,(ae(),$h)))return u(Q(n,$h),11).i;if(n.k!=(Vn(),Os)&&zr(new ar(lr(Ds(n).a.Kc(),new z))))e=u(Mr(new ar(lr(Ds(n).a.Kc(),new z))),17);else if(n.k!=Os)return null}while(n&&n.k!=(Vn(),Os));return n}function Pwn(t,e){var n,r,s,o,h,d,v,k,C;for(d=e.j,h=e.g,v=u(Ne(d,d.c.length-1),113),C=(An(0,d.c.length),u(d.c[0],113)),k=Ast(t,h,v,C),o=1;ok&&(v=n,C=s,k=r);e.a=C,e.c=v}function Fwn(t,e){var n,r;if(r=tD(t.b,e.b),!r)throw it(new No("Invalid hitboxes for scanline constraint calculation."));(ire(e.b,u(FZe(t.b,e.b),57))||ire(e.b,u(PZe(t.b,e.b),57)))&&(Gd(),e.b+""),t.a[e.b.f]=u(Cnt(t.b,e.b),57),n=u(Tnt(t.b,e.b),57),n&&(t.a[n.f]=e.b)}function yf(t){if(!t.a.d||!t.a.e)throw it(new No((P0(fpe),fpe.k+" must have a source and target "+(P0(a7t),a7t.k)+" specified.")));if(t.a.d==t.a.e)throw it(new No("Network simplex does not support self-loops: "+t.a+" "+t.a.d+" "+t.a.e));return _j(t.a.d.g,t.a),_j(t.a.e.b,t.a),t.a}function Nwn(t,e,n){var r,s,o,h,d,v,k;for(k=new Op(new F$t(t)),h=lt(ct(Jbe,1),h1e,11,0,[e,n]),d=0,v=h.length;dv-t.b&&dv-t.a&&d0&&++H;++j}return H}function Uwn(t,e){var n,r,s,o,h;for(h=u(Q(e,(gv(),d_t)),425),o=ei(e.b,0);o.b!=o.d.c;)if(s=u(ti(o),86),t.b[s.g]==0){switch(h.g){case 0:Cse(t,s);break;case 1:Ybn(t,s)}t.b[s.g]=2}for(r=ei(t.a,0);r.b!=r.d.c;)n=u(ti(r),188),ay(n.b.d,n,!0),ay(n.c.b,n,!0);Jt(e,(fc(),a_t),t.a)}function ou(t,e){to();var n,r,s,o;return e?e==(Ii(),H5e)||(e==D5e||e==X2||e==M5e)&&t!=ELt?new Axt(t,e):(r=u(e,677),n=r.pk(),n||(M8(To(($u(),ya),e)),n=r.pk()),o=(!n.i&&(n.i=new _r),n.i),s=u(ec(Lo(o.f,t)),1942),!s&&ki(o,t,s=new Axt(t,e)),s):S5e}function Wwn(t,e){var n,r,s,o,h,d,v,k,C;for(v=u(Q(t,(ae(),_i)),11),k=Yo(lt(ct(Ws,1),ee,8,0,[v.i.n,v.n,v.a])).a,C=t.i.n.b,n=wd(t.e),s=n,o=0,h=s.length;o0?o.a?(d=o.b.rf().a,n>d&&(s=(n-d)/2,o.d.b=s,o.d.c=s)):o.d.c=t.s+n:S9(t.u)&&(r=I4t(o.b),r.c<0&&(o.d.b=-r.c),r.c+r.b>o.b.rf().a&&(o.d.c=r.c+r.b-o.b.rf().a))}function Qwn(t,e){var n,r,s,o;for(vr(e,"Semi-Interactive Crossing Minimization Processor",1),n=!1,s=new S(t.b);s.a=0){if(e==n)return new fa(pe(-e-1),pe(-e-1));if(e==-n)return new fa(pe(-e),pe(n+1))}return b.Math.abs(e)>b.Math.abs(n)?e<0?new fa(pe(-e),pe(n)):new fa(pe(-e),pe(n+1)):new fa(pe(e+1),pe(n))}function tvn(t){var e,n;n=u(Q(t,(Te(),uu)),163),e=u(Q(t,(ae(),B2)),303),n==(dh(),bb)?(Jt(t,uu,MO),Jt(t,B2,(q0(),Y4))):n==jy?(Jt(t,uu,MO),Jt(t,B2,(q0(),F6))):e==(q0(),Y4)?(Jt(t,uu,bb),Jt(t,B2,CO)):e==F6&&(Jt(t,uu,jy),Jt(t,B2,CO))}function kq(){kq=Z,jO=new jQ,Zme=bi(new Vs,(Wa(),cu),(ro(),EV)),eye=Ku(bi(new Vs,cu,DV),Io,MV),nye=uv(uv(VR(Ku(bi(new Vs,Dd,FV),Io,PV),qc),OV),NV),Jme=Ku(bi(bi(bi(new Vs,gb,CV),qc,SV),qc,u7),Io,_V),tye=Ku(bi(bi(new Vs,qc,u7),qc,kV),Io,xV)}function m_(){m_=Z,sye=bi(Ku(new Vs,(Wa(),Io),(ro(),nTt)),cu,EV),uye=uv(uv(VR(Ku(bi(new Vs,Dd,FV),Io,PV),qc),OV),NV),aye=Ku(bi(bi(bi(new Vs,gb,CV),qc,SV),qc,u7),Io,_V),cye=bi(bi(new Vs,cu,DV),Io,MV),oye=Ku(bi(bi(new Vs,qc,u7),qc,kV),Io,xV)}function evn(t,e,n,r,s){var o,h;(!Ga(e)&&e.c.i.c==e.d.i.c||!fne(Yo(lt(ct(Ws,1),ee,8,0,[s.i.n,s.n,s.a])),n))&&!Ga(e)&&(e.c==s?m8(e.a,0,new xo(n)):ri(e.a,new xo(n)),r&&!I0(t.a,n)&&(h=u(Q(e,(Te(),So)),74),h||(h=new Pu,Jt(e,So,h)),o=new xo(n),fs(h,o,h.c.b,h.c),Fs(t.a,o)))}function nvn(t){var e,n;for(n=new ar(lr(jo(t).a.Kc(),new z));zr(n);)if(e=u(Mr(n),17),e.c.i.k!=(Vn(),Ll))throw it(new R3(Kot+rI(t)+"' has its layer constraint set to FIRST, but has at least one incoming edge that does not come from a FIRST_SEPARATE node. That must not happen."))}function rvn(t,e,n){var r,s,o,h,d,v,k;if(s=bie(t.Db&254),s==0)t.Eb=n;else{if(s==1)d=Nt(Qn,De,1,2,5,1),o=Sst(t,e),o==0?(d[0]=n,d[1]=t.Eb):(d[0]=t.Eb,d[1]=n);else for(d=Nt(Qn,De,1,s+1,5,1),h=u2(t.Eb),r=2,v=0,k=0;r<=128;r<<=1)r==e?d[k++]=n:t.Db&r&&(d[k++]=h[v++]);t.Eb=d}t.Db|=e}function Jce(t,e,n){var r,s,o,h;for(this.b=new he,s=0,r=0,h=new S(t);h.a0&&(o=u(Ne(this.b,0),167),s+=o.o,r+=o.p),s*=2,r*=2,e>1?s=ps(b.Math.ceil(s*e)):r=ps(b.Math.ceil(r/e)),this.a=new C3t(s,r)}function tue(t,e,n,r,s,o){var h,d,v,k,C,M,j,H,G,K,tt,gt;for(C=r,e.j&&e.o?(H=u(tr(t.f,e.A),57),K=H.d.c+H.d.b,--C):K=e.a.c+e.a.b,M=s,n.q&&n.o?(H=u(tr(t.f,n.C),57),k=H.d.c,++M):k=n.a.c,tt=k-K,v=b.Math.max(2,M-C),d=tt/v,G=K+d,j=C;j=0;h+=s?1:-1){for(d=e[h],v=r==(ve(),Hn)?s?Ko(d,r):l2(Ko(d,r)):s?l2(Ko(d,r)):Ko(d,r),o&&(t.c[d.p]=v.gc()),M=v.Kc();M.Ob();)C=u(M.Pb(),11),t.d[C.p]=k++;Ls(n,v)}}function eue(t,e,n){var r,s,o,h,d,v,k,C;for(o=Xt(ye(t.b.Kc().Pb())),k=Xt(ye(fun(e.b))),r=fd(nc(t.a),k-n),s=fd(nc(e.a),n-o),C=Li(r,s),fd(C,1/(k-o)),this.a=C,this.b=new he,d=!0,h=t.b.Kc(),h.Pb();h.Ob();)v=Xt(ye(h.Pb())),d&&v-n>Lct&&(this.b.Fc(n),d=!1),this.b.Fc(v);d&&this.b.Fc(n)}function ivn(t){var e,n,r,s;if(pmn(t,t.n),t.d.c.length>0){for(RC(t.c);w5t(t,u(J(new S(t.e.a)),121))>5,e&=31,r>=t.d)return t.e<0?(rb(),But):(rb(),s7);if(o=t.d-r,s=Nt(Cr,Xr,25,o+1,15,1),Qgn(s,o,t.a,r,e),t.e<0){for(n=0;n0&&t.a[n]<<32-e){for(n=0;n=0?!1:(n=C4(($u(),ya),s,e),n?(r=n.Zj(),(r>1||r==-1)&&Hw(To(ya,n))!=3):!0)):!1}function cvn(t,e,n,r){var s,o,h,d,v;return d=Do(u(At((!e.b&&(e.b=new Cn(br,e,4,7)),e.b),0),82)),v=Do(u(At((!e.c&&(e.c=new Cn(br,e,5,8)),e.c),0),82)),es(d)==es(v)||ey(v,d)?null:(h=cD(e),h==n?r:(o=u(tr(t.a,h),10),o&&(s=o.e,s)?s:null))}function uvn(t,e){var n;switch(n=u(Q(t,(Te(),uG)),276),vr(e,"Label side selection ("+n+")",1),n.g){case 0:mce(t,(zl(),f0));break;case 1:mce(t,(zl(),kb));break;case 2:Ple(t,(zl(),f0));break;case 3:Ple(t,(zl(),kb));break;case 4:pue(t,(zl(),f0));break;case 5:pue(t,(zl(),kb))}or(e)}function j5t(t,e,n){var r,s,o,h,d,v;if(r=YKe(n,t.length),h=t[r],h[0].k==(Vn(),ks))for(o=mHt(n,h.length),v=e.j,s=0;s0&&(n[0]+=t.d,h-=n[0]),n[2]>0&&(n[2]+=t.d,h-=n[2]),o=b.Math.max(0,h),n[1]=b.Math.max(n[1],h),vmt(t,eu,s.c+r.b+n[0]-(n[1]-h)/2,n),e==eu&&(t.c.b=o,t.c.c=s.c+r.b+(o-h)/2)}function fue(){this.c=Nt(aa,vo,25,(ve(),lt(ct(Xa,1),xc,61,0,[Zo,Pn,Hn,mr,Bn])).length,15,1),this.b=Nt(aa,vo,25,lt(ct(Xa,1),xc,61,0,[Zo,Pn,Hn,mr,Bn]).length,15,1),this.a=Nt(aa,vo,25,lt(ct(Xa,1),xc,61,0,[Zo,Pn,Hn,mr,Bn]).length,15,1),Abt(this.c,as),Abt(this.b,Cs),Abt(this.a,Cs)}function jc(t,e,n){var r,s,o,h;if(e<=n?(s=e,o=n):(s=n,o=e),r=0,t.b==null)t.b=Nt(Cr,Xr,25,2,15,1),t.b[0]=s,t.b[1]=o,t.c=!0;else{if(r=t.b.length,t.b[r-1]+1==s){t.b[r-1]=o;return}h=Nt(Cr,Xr,25,r+2,15,1),Dc(t.b,0,h,0,r),t.b=h,t.b[r-1]>=s&&(t.c=!1,t.a=!1),t.b[r++]=s,t.b[r]=o,t.c||v4(t)}}function wvn(t,e,n){var r,s,o,h,d,v,k;for(k=e.d,t.a=new Xc(k.c.length),t.c=new _r,d=new S(k);d.a=0?t._g(k,!1,!0):dv(t,n,!1),58));t:for(o=M.Kc();o.Ob();){for(s=u(o.Pb(),56),C=0;C1;)by(s,s.i-1);return r}function kvn(t,e){var n,r,s,o,h,d,v;for(vr(e,"Comment post-processing",1),o=new S(t.b);o.at.d[h.p]&&(n+=fmt(t.b,o),Up(t.a,pe(o)));for(;!BC(t.a);)Hmt(t.b,u(Hx(t.a),19).a)}return n}function bue(t,e,n){var r,s,o,h;for(o=(!e.a&&(e.a=new fe(rs,e,10,11)),e.a).i,s=new nr((!e.a&&(e.a=new fe(rs,e,10,11)),e.a));s.e!=s.i.gc();)r=u(dr(s),33),(!r.a&&(r.a=new fe(rs,r,10,11)),r.a).i==0||(o+=bue(t,r,!1));if(n)for(h=es(e);h;)o+=(!h.a&&(h.a=new fe(rs,h,10,11)),h.a).i,h=es(h);return o}function by(t,e){var n,r,s,o;return t.ej()?(r=null,s=t.fj(),t.ij()&&(r=t.kj(t.pi(e),null)),n=t.Zi(4,o=l6(t,e),null,e,s),t.bj()&&o!=null&&(r=t.dj(o,r)),r?(r.Ei(n),r.Fi()):t.$i(n),o):(o=l6(t,e),t.bj()&&o!=null&&(r=t.dj(o,null),r&&r.Fi()),o)}function Tvn(t){var e,n,r,s,o,h,d,v,k,C;for(k=t.a,e=new Hs,v=0,r=new S(t.d);r.ad.d&&(C=d.d+d.a+k));n.c.d=C,e.a.zc(n,e),v=b.Math.max(v,n.c.d+n.c.a)}return v}function oo(){oo=Z,KV=new Fm("COMMENTS",0),vh=new Fm("EXTERNAL_PORTS",1),yS=new Fm("HYPEREDGES",2),XV=new Fm("HYPERNODES",3),y7=new Fm("NON_FREE_PORTS",4),W4=new Fm("NORTH_SOUTH_PORTS",5),xS=new Fm(M1e,6),v7=new Fm("CENTER_LABELS",7),m7=new Fm("END_LABELS",8),QV=new Fm("PARTITIONS",9)}function wy(t){var e,n,r,s,o;for(s=new he,e=new E9((!t.a&&(t.a=new fe(rs,t,10,11)),t.a)),r=new ar(lr(K0(t).a.Kc(),new z));zr(r);)n=u(Mr(r),79),_t(At((!n.b&&(n.b=new Cn(br,n,4,7)),n.b),0),186)||(o=Do(u(At((!n.c&&(n.c=new Cn(br,n,5,8)),n.c),0),82)),e.a._b(o)||(s.c[s.c.length]=o));return s}function Cvn(t){var e,n,r,s,o,h;for(o=new Hs,e=new E9((!t.a&&(t.a=new fe(rs,t,10,11)),t.a)),s=new ar(lr(K0(t).a.Kc(),new z));zr(s);)r=u(Mr(s),79),_t(At((!r.b&&(r.b=new Cn(br,r,4,7)),r.b),0),186)||(h=Do(u(At((!r.c&&(r.c=new Cn(br,r,5,8)),r.c),0),82)),e.a._b(h)||(n=o.a.zc(h,o),n==null));return o}function _vn(t,e,n,r,s){return r<0?(r=w4(t,s,lt(ct(Ae,1),ee,2,6,[Qat,Zat,Jat,tot,w6,eot,not,rot,iot,sot,aot,oot]),e),r<0&&(r=w4(t,s,lt(ct(Ae,1),ee,2,6,["Jan","Feb","Mar","Apr",w6,"Jun","Jul","Aug","Sep","Oct","Nov","Dec"]),e)),r<0?!1:(n.k=r,!0)):r>0?(n.k=r-1,!0):!1}function Svn(t,e,n,r,s){return r<0?(r=w4(t,s,lt(ct(Ae,1),ee,2,6,[Qat,Zat,Jat,tot,w6,eot,not,rot,iot,sot,aot,oot]),e),r<0&&(r=w4(t,s,lt(ct(Ae,1),ee,2,6,["Jan","Feb","Mar","Apr",w6,"Jun","Jul","Aug","Sep","Oct","Nov","Dec"]),e)),r<0?!1:(n.k=r,!0)):r>0?(n.k=r-1,!0):!1}function Avn(t,e,n,r,s,o){var h,d,v,k;if(d=32,r<0){if(e[0]>=t.length||(d=wa(t,e[0]),d!=43&&d!=45)||(++e[0],r=gq(t,e),r<0))return!1;d==45&&(r=-r)}return d==32&&e[0]-n==2&&s.b==2&&(v=new BR,k=v.q.getFullYear()-ab+ab-80,h=k%100,o.a=r==h,r+=(k/100|0)*100+(r=k&&(v=r);v&&(C=b.Math.max(C,v.a.o.a)),C>j&&(M=k,j=C)}return M}function Dvn(t,e,n){var r,s,o;if(t.e=n,t.d=0,t.b=0,t.f=1,t.i=e,(t.e&16)==16&&(t.i=wmn(t.i)),t.j=t.i.length,fi(t),o=cv(t),t.d!=t.j)throw it(new Nr(qr((Pr(),Zde))));if(t.g){for(r=0;rJ1e?Zs(v,t.b):r<=J1e&&r>tde?Zs(v,t.d):r<=tde&&r>ede?Zs(v,t.c):r<=ede&&Zs(v,t.a),o=yue(t,v,o);return s}function rb(){rb=Z;var t;for(eV=new Ng(1,1),Rut=new Ng(1,10),s7=new Ng(0,0),But=new Ng(-1,1),CEt=lt(ct(j4,1),ee,91,0,[s7,eV,new Ng(1,2),new Ng(1,3),new Ng(1,4),new Ng(1,5),new Ng(1,6),new Ng(1,7),new Ng(1,8),new Ng(1,9),Rut]),nV=Nt(j4,ee,91,32,0,1),t=0;t1,d&&(r=new $e(s,n.b),ri(e.a,r)),V9(e.a,lt(ct(Ws,1),ee,8,0,[j,M]))}function Cue(t){Mw(t,new k2(_w(Ew(Cw(Tw(new kg,AH),"ELK Randomizer"),'Distributes the nodes randomly on the plane, leading to very obfuscating layouts. Can be useful to demonstrate the power of "real" layout algorithms.'),new ZZ))),xe(t,AH,xv,FAt),xe(t,AH,Cy,15),xe(t,AH,tH,pe(0)),xe(t,AH,E6,GE)}function q5t(){q5t=Z;var t,e,n,r,s,o;for(dA=Nt(Gu,N4,25,255,15,1),yU=Nt(xh,yd,25,16,15,1),e=0;e<255;e++)dA[e]=-1;for(n=57;n>=48;n--)dA[n]=n-48<<24>>24;for(r=70;r>=65;r--)dA[r]=r-65+10<<24>>24;for(s=102;s>=97;s--)dA[s]=s-97+10<<24>>24;for(o=0;o<10;o++)yU[o]=48+o&ys;for(t=10;t<=15;t++)yU[t]=65+t-10&ys}function Tq(t,e,n){var r,s,o,h,d,v,k,C;return d=e.i-t.g/2,v=n.i-t.g/2,k=e.j-t.g/2,C=n.j-t.g/2,o=e.g+t.g/2,h=n.g+t.g/2,r=e.f+t.g/2,s=n.f+t.g/2,d>19)return"-"+_ue(rE(t));for(n=t,r="";!(n.l==0&&n.m==0&&n.h==0);){if(s=Vrt(Gq),n=yxt(n,s,!0),e=""+RHt(hb),!(n.l==0&&n.m==0&&n.h==0))for(o=9-e.length;o>0;o--)e="0"+e;r=e+r}return r}function Bvn(){if(!Object.create||!Object.getOwnPropertyNames)return!1;var t="__proto__",e=Object.create(null);if(e[t]!==void 0)return!1;var n=Object.getOwnPropertyNames(e);return!(n.length!=0||(e[t]=42,e[t]!==42)||Object.getOwnPropertyNames(e).length==0)}function Rvn(t){var e,n,r,s,o,h,d;for(e=!1,n=0,s=new S(t.d.b);s.a=t.a||!L4t(e,n))return-1;if(F8(u(r.Kb(e),20)))return 1;for(s=0,h=u(r.Kb(e),20).Kc();h.Ob();)if(o=u(h.Pb(),17),v=o.c.i==e?o.d.i:o.c.i,d=V5t(t,v,n,r),d==-1||(s=b.Math.max(s,d),s>t.c-1))return-1;return s+1}function Sue(t,e){var n,r,s,o,h,d;if(Vt(e)===Vt(t))return!0;if(!_t(e,15)||(r=u(e,15),d=t.gc(),r.gc()!=d))return!1;if(h=r.Kc(),t.ni()){for(n=0;n0){if(t.qj(),e!=null){for(o=0;o>24;case 97:case 98:case 99:case 100:case 101:case 102:return t-97+10<<24>>24;case 65:case 66:case 67:case 68:case 69:case 70:return t-65+10<<24>>24;default:throw it(new ld("Invalid hexadecimal"))}}function qvn(t,e,n){var r,s,o,h;for(vr(n,"Processor order nodes",2),t.a=Xt(ye(Q(e,(gv(),g_t)))),s=new Zi,h=ei(e.b,0);h.b!=h.d.c;)o=u(ti(h),86),je(Re(Q(o,(fc(),Xy))))&&fs(s,o,s.c.b,s.c);r=(Zn(s.b!=0),u(s.a.a.c,86)),Wle(t,r),!n.b&&pit(n,1),K5t(t,r,0-Xt(ye(Q(r,(fc(),IG))))/2,0),!n.b&&pit(n,1),or(n)}function Cq(){Cq=Z,i7t=new z3("SPIRAL",0),t7t=new z3("LINE_BY_LINE",1),e7t=new z3("MANHATTAN",2),JEt=new z3("JITTER",3),Vut=new z3("QUADRANTS_LINE_BY_LINE",4),r7t=new z3("QUADRANTS_MANHATTAN",5),n7t=new z3("QUADRANTS_JITTER",6),ZEt=new z3("COMBINE_LINE_BY_LINE_MANHATTAN",7),QEt=new z3("COMBINE_JITTER_MANHATTAN",8)}function Lue(t,e,n,r){var s,o,h,d,v,k;for(v=Ost(t,n),k=Ost(e,n),s=!1;v&&k&&(r||R1n(v,k,n));)h=Ost(v,n),d=Ost(k,n),kD(e),kD(t),o=v.c,Bat(v,!1),Bat(k,!1),n?(ly(e,k.p,o),e.p=k.p,ly(t,v.p+1,o),t.p=v.p):(ly(t,v.p,o),t.p=v.p,ly(e,k.p+1,o),e.p=k.p),Eo(v,null),Eo(k,null),v=h,k=d,s=!0;return s}function Hvn(t,e,n,r){var s,o,h,d,v;for(s=!1,o=!1,d=new S(r.j);d.a=e.length)throw it(new yo("Greedy SwitchDecider: Free layer not in graph."));this.c=e[t],this.e=new YM(r),mit(this.e,this.c,(ve(),Bn)),this.i=new YM(r),mit(this.i,this.c,Hn),this.f=new SKt(this.c),this.a=!o&&s.i&&!s.s&&this.c[0].k==(Vn(),ks),this.a&&apn(this,t,e.length)}function Due(t,e){var n,r,s,o,h,d;o=!t.B.Hc((ll(),cP)),h=t.B.Hc(Aft),t.a=new _ie(h,o,t.c),t.n&&Pvt(t.a.n,t.n),het(t.g,(Kf(),eu),t.a),e||(r=new a_(1,o,t.c),r.n.a=t.k,zx(t.p,(ve(),Pn),r),s=new a_(1,o,t.c),s.n.d=t.k,zx(t.p,mr,s),d=new a_(0,o,t.c),d.n.c=t.k,zx(t.p,Bn,d),n=new a_(0,o,t.c),n.n.b=t.k,zx(t.p,Hn,n))}function Gvn(t){var e,n,r;switch(e=u(Q(t.d,(Te(),eg)),218),e.g){case 2:n=xxn(t);break;case 3:n=(r=new he,ls(Ri(wu(Wo(Wo(new Tn(null,new _n(t.d.b,16)),new NX),new BX),new HT),new _X),new Utt(r)),r);break;default:throw it(new No("Compaction not supported for "+e+" edges."))}H3n(t,n),va(new Sm(t.g),new Vtt(t))}function Uvn(t,e){var n;return n=new ka,e&&Mo(n,u(tr(t.a,lP),94)),_t(e,470)&&Mo(n,u(tr(t.a,hP),94)),_t(e,354)?(Mo(n,u(tr(t.a,qo),94)),n):(_t(e,82)&&Mo(n,u(tr(t.a,br),94)),_t(e,239)?(Mo(n,u(tr(t.a,rs),94)),n):_t(e,186)?(Mo(n,u(tr(t.a,gl),94)),n):(_t(e,352)&&Mo(n,u(tr(t.a,Ys),94)),n))}function Jf(){Jf=Z,c7=new eo((ui(),ZG),pe(1)),bV=new eo(W2,80),kbe=new eo(fAt,5),dbe=new eo(W6,GE),ybe=new eo(Eft,pe(1)),xbe=new eo(Tft,(Nn(),!0)),x7t=new Ow(50),vbe=new eo(U2,x7t),v7t=KG,k7t=KS,gbe=new eo(gft,!1),y7t=tP,wbe=xb,bbe=G2,pbe=o5,mbe=Qy,m7t=(q4t(),abe),nlt=lbe,pV=sbe,elt=obe,E7t=ube}function Wvn(t){var e,n,r,s,o,h,d,v;for(v=new OJt,d=new S(t.a);d.a0&&e=0)return!1;if(e.p=n.b,le(n.e,e),s==(Vn(),ta)||s==Hc){for(h=new S(e.j);h.a1||h==-1)&&(o|=16),s.Bb&dc&&(o|=64)),n.Bb&Ka&&(o|=Dy),o|=xf):_t(e,457)?o|=512:(r=e.Bj(),r&&r.i&1&&(o|=256)),t.Bb&512&&(o|=128),o}function y_(t,e){var n,r,s,o,h;for(t=t==null?_u:(On(t),t),s=0;st.d[d.p]&&(n+=fmt(t.b,o),Up(t.a,pe(o)))):++h;for(n+=t.b.d*h;!BC(t.a);)Hmt(t.b,u(Hx(t.a),19).a)}return n}function nmn(t,e){var n;return t.f==$ft?(n=Hw(To(($u(),ya),e)),t.e?n==4&&e!=(d6(),tk)&&e!=(d6(),J6)&&e!=(d6(),zft)&&e!=(d6(),qft):n==2):t.d&&(t.d.Hc(e)||t.d.Hc(Kx(To(($u(),ya),e)))||t.d.Hc(C4(($u(),ya),t.b,e)))?!0:t.f&&O5t(($u(),t.f),rD(To(ya,e)))?(n=Hw(To(ya,e)),t.e?n==4:n==2):!1}function rmn(t,e,n,r){var s,o,h,d,v,k,C,M;return h=u(qe(n,(ui(),Y6)),8),v=h.a,C=h.b+t,s=b.Math.atan2(C,v),s<0&&(s+=O4),s+=e,s>O4&&(s-=O4),d=u(qe(r,Y6),8),k=d.a,M=d.b+t,o=b.Math.atan2(M,k),o<0&&(o+=O4),o+=e,o>O4&&(o-=O4),k1(),wf(1e-10),b.Math.abs(s-o)<=1e-10||s==o||isNaN(s)&&isNaN(o)?0:so?1:Iw(isNaN(s),isNaN(o))}function gat(t){var e,n,r,s,o,h,d;for(d=new _r,r=new S(t.a.b);r.a=t.o)throw it(new Opt);d=e>>5,h=e&31,o=F0(1,Ar(F0(h,1))),s?t.n[n][d]=S1(t.n[n][d],o):t.n[n][d]=Ns(t.n[n][d],Rwt(o)),o=F0(o,1),r?t.n[n][d]=S1(t.n[n][d],o):t.n[n][d]=Ns(t.n[n][d],Rwt(o))}catch(v){throw v=Wi(v),_t(v,320)?it(new yo(Fot+t.o+"*"+t.p+Not+e+Ya+n+Bot)):it(v)}}function K5t(t,e,n,r){var s,o,h;e&&(o=Xt(ye(Q(e,(fc(),np))))+r,h=n+Xt(ye(Q(e,IG)))/2,Jt(e,$ht,pe(Ar(Tu(b.Math.round(o))))),Jt(e,o_t,pe(Ar(Tu(b.Math.round(h))))),e.d.b==0||K5t(t,u(xj((s=ei(new Lp(e).a.d,0),new Ex(s))),86),n+Xt(ye(Q(e,IG)))+t.a,r+Xt(ye(Q(e,M7)))),Q(e,jht)!=null&&K5t(t,u(Q(e,jht),86),n,r))}function smn(t,e){var n,r,s,o,h,d,v,k,C,M,j;for(v=Na(e.a),s=Xt(ye(Q(v,(Te(),q2))))*2,C=Xt(ye(Q(v,t5))),k=b.Math.max(s,C),o=Nt(aa,vo,25,e.f-e.c+1,15,1),r=-k,n=0,d=e.b.Kc();d.Ob();)h=u(d.Pb(),10),r+=t.a[h.c.p]+k,o[n++]=r;for(r+=t.a[e.a.c.p]+k,o[n++]=r,j=new S(e.e);j.a0&&(r=(!t.n&&(t.n=new fe(qo,t,1,7)),u(At(t.n,0),137)).a,!r||Gr(Gr((e.a+=' "',e),r),'"'))),Gr(Aw(Gr(Aw(Gr(Aw(Gr(Aw((e.a+=" (",e),t.i),","),t.j)," | "),t.g),","),t.f),")"),e.a)}function zue(t){var e,n,r;return t.Db&64?Vst(t):(e=new Ol(y8t),n=t.k,n?Gr(Gr((e.a+=' "',e),n),'"'):(!t.n&&(t.n=new fe(qo,t,1,7)),t.n.i>0&&(r=(!t.n&&(t.n=new fe(qo,t,1,7)),u(At(t.n,0),137)).a,!r||Gr(Gr((e.a+=' "',e),r),'"'))),Gr(Aw(Gr(Aw(Gr(Aw(Gr(Aw((e.a+=" (",e),t.i),","),t.j)," | "),t.g),","),t.f),")"),e.a)}function bat(t,e){var n,r,s,o,h,d,v;if(e==null||e.length==0)return null;if(s=u(Nc(t.a,e),149),!s){for(r=(d=new v1(t.b).a.vc().Kc(),new m1(d));r.a.Ob();)if(n=(o=u(r.a.Pb(),42),u(o.dd(),149)),h=n.c,v=e.length,hn(h.substr(h.length-v,v),e)&&(e.length==h.length||wa(h,h.length-e.length-1)==46)){if(s)return null;s=n}s&&ko(t.a,e,s)}return s}function cmn(t,e){var n,r,s,o;return n=new eh,r=u(Bl(wu(new Tn(null,new _n(t.f,16)),n),Zm(new on,new ni,new di,new Ee,lt(ct(fl,1),oe,132,0,[(O1(),Iy),Ul]))),21),s=r.gc(),r=u(Bl(wu(new Tn(null,new _n(e.f,16)),n),Zm(new on,new ni,new di,new Ee,lt(ct(fl,1),oe,132,0,[Iy,Ul]))),21),o=r.gc(),ss.p?(Bs(o,mr),o.d&&(d=o.o.b,e=o.a.b,o.a.b=d-e)):o.j==mr&&s.p>t.p&&(Bs(o,Pn),o.d&&(d=o.o.b,e=o.a.b,o.a.b=-(d-e)));break}return s}function lmn(t,e,n,r){var s,o,h,d,v,k,C,M,j,H,G;if(o=n,n1,d&&(r=new $e(s,n.b),ri(e.a,r)),V9(e.a,lt(ct(Ws,1),ee,8,0,[j,M]))}function wat(t,e,n){var r,s,o,h,d,v;if(e)if(n<=-1){if(r=yn(e.Tg(),-1-n),_t(r,99))return u(r,18);for(h=u(e.ah(r),153),d=0,v=h.gc();d0){for(s=v.length;s>0&&v[s-1]=="";)--s;s=40,h&&xyn(t),C3n(t),ivn(t),n=fie(t),r=0;n&&r0&&ri(t.f,o)):(t.c[h]-=k+1,t.c[h]<=0&&t.a[h]>0&&ri(t.e,o))))}function Nmn(t){var e,n,r,s,o,h,d,v,k;for(d=new Op(u(Lr(new jd),62)),k=Cs,n=new S(t.d);n.a=0&&vn?e:n;k<=M;++k)k==n?d=r++:(o=s[k],C=G.rl(o.ak()),k==e&&(v=k==M&&!C?r-1:r),C&&++r);return j=u(r_(t,e,n),72),d!=v&&n8(t,new mD(t.e,7,h,pe(d),H.dd(),v)),j}}else return u(Jst(t,e,n),72);return u(r_(t,e,n),72)}function $mn(t,e){var n,r,s,o,h,d,v;for(vr(e,"Port order processing",1),v=u(Q(t,(Te(),v9t)),421),r=new S(t.b);r.a=0&&(d=H1n(t,h),!(d&&(k<22?v.l|=1<>>1,h.m=C>>>1|(M&1)<<21,h.l=j>>>1|(C&1)<<21,--k;return n&&Ait(v),o&&(r?(hb=rE(t),s&&(hb=tre(hb,(q8(),aEt)))):hb=iu(t.l,t.m,t.h)),v}function Hmn(t,e){var n,r,s,o,h,d,v,k,C,M;for(k=t.e[e.c.p][e.p]+1,v=e.c.a.c.length+1,d=new S(t.a);d.a0&&(Rr(0,t.length),t.charCodeAt(0)==45||(Rr(0,t.length),t.charCodeAt(0)==43))?1:0,r=h;rn)throw it(new ld(yv+t+'"'));return d}function Vmn(t){var e,n,r,s,o,h,d;for(h=new Zi,o=new S(t.a);o.a1)&&e==1&&u(t.a[t.b],10).k==(Vn(),Ll)?p6(u(t.a[t.b],10),(zl(),f0)):r&&(!n||(t.c-t.b&t.a.length-1)>1)&&e==1&&u(t.a[t.c-1&t.a.length-1],10).k==(Vn(),Ll)?p6(u(t.a[t.c-1&t.a.length-1],10),(zl(),kb)):(t.c-t.b&t.a.length-1)==2?(p6(u(Q9(t),10),(zl(),f0)),p6(u(Q9(t),10),kb)):R2n(t,s),lmt(t)}function Wmn(t,e,n){var r,s,o,h,d;for(o=0,s=new nr((!t.a&&(t.a=new fe(rs,t,10,11)),t.a));s.e!=s.i.gc();)r=u(dr(s),33),h="",(!r.n&&(r.n=new fe(qo,r,1,7)),r.n).i==0||(h=u(At((!r.n&&(r.n=new fe(qo,r,1,7)),r.n),0),137).a),d=new Dit(o++,e,h),Mo(d,r),Jt(d,(fc(),qS),r),d.e.b=r.j+r.f/2,d.f.a=b.Math.max(r.g,1),d.e.a=r.i+r.g/2,d.f.b=b.Math.max(r.f,1),ri(e.b,d),au(n.f,r,d)}function Ymn(t){var e,n,r,s,o;r=u(Q(t,(ae(),_i)),33),o=u(qe(r,(Te(),$2)),174).Hc((Al(),K2)),t.e||(s=u(Q(t,Vc),21),e=new $e(t.f.a+t.d.b+t.d.c,t.f.b+t.d.d+t.d.a),s.Hc((oo(),vh))?(wo(r,cs,(ua(),Gc)),wv(r,e.a,e.b,!1,!0)):je(Re(qe(r,uht)))||wv(r,e.a,e.b,!0,!0)),o?wo(r,$2,un(K2)):wo(r,$2,(n=u(Vf(rA),9),new sh(n,u(ff(n,n.length),9),0)))}function rxt(t,e,n){var r,s,o,h;if(e[0]>=t.length)return n.o=0,!0;switch(wa(t,e[0])){case 43:s=1;break;case 45:s=-1;break;default:return n.o=0,!0}if(++e[0],o=e[0],h=gq(t,e),h==0&&e[0]==o)return!1;if(e[0]=0&&d!=n&&(o=new Js(t,1,d,h,null),r?r.Ei(o):r=o),n>=0&&(o=new Js(t,1,n,d==n?h:null,e),r?r.Ei(o):r=o)),r}function sle(t){var e,n,r;if(t.b==null){if(r=new Ag,t.i!=null&&(go(r,t.i),r.a+=":"),t.f&256){for(t.f&256&&t.a!=null&&(lrn(t.i)||(r.a+="//"),go(r,t.a)),t.d!=null&&(r.a+="/",go(r,t.d)),t.f&16&&(r.a+="/"),e=0,n=t.j.length;ej?!1:(M=(v=__(r,j,!1),v.a),C+d+M<=e.b&&(vD(n,o-n.s),n.c=!0,vD(r,o-n.s),tI(r,n.s,n.t+n.d+d),r.k=!0,pyt(n.q,r),H=!0,s&&(az(e,r),r.j=e,t.c.length>h&&(sI((An(h,t.c.length),u(t.c[h],200)),r),(An(h,t.c.length),u(t.c[h],200)).a.c.length==0&&Fg(t,h)))),H)}function nyn(t,e){var n,r,s,o,h,d;if(vr(e,"Partition midprocessing",1),s=new Uw,ls(Ri(new Tn(null,new _n(t.a,16)),new KK),new mw(s)),s.d!=0){for(d=u(Bl(ZQt((o=s.i,new Tn(null,(o||(s.i=new K3(s,s.c))).Nc()))),c2(new ke,new ce,new Xn,lt(ct(fl,1),oe,132,0,[(O1(),Ul)]))),15),r=d.Kc(),n=u(r.Pb(),19);r.Ob();)h=u(r.Pb(),19),swn(u(Ai(s,n),21),u(Ai(s,h),21)),n=h;or(e)}}function cle(t,e,n){var r,s,o,h,d,v,k,C;if(e.p==0){for(e.p=1,h=n,h||(s=new he,o=(r=u(Vf(Xa),9),new sh(r,u(ff(r,r.length),9),0)),h=new fa(s,o)),u(h.a,15).Fc(e),e.k==(Vn(),ks)&&u(h.b,21).Fc(u(Q(e,(ae(),oc)),61)),v=new S(e.j);v.a0){if(s=u(t.Ab.g,1934),e==null){for(o=0;o1)for(r=new S(s);r.an.s&&dd&&(d=s,C.c=Nt(Qn,De,1,0,5,1)),s==d&&le(C,new fa(n.c.i,n)));wn(),Zs(C,t.c),Hm(t.b,v.p,C)}}function cyn(t,e){var n,r,s,o,h,d,v,k,C;for(h=new S(e.b);h.ad&&(d=s,C.c=Nt(Qn,De,1,0,5,1)),s==d&&le(C,new fa(n.d.i,n)));wn(),Zs(C,t.c),Hm(t.f,v.p,C)}}function lle(t){Mw(t,new k2(_w(Ew(Cw(Tw(new kg,Tv),"ELK Box"),"Algorithm for packing of unconnected boxes, i.e. graphs without edges."),new qZ))),xe(t,Tv,xv,PSt),xe(t,Tv,Cy,15),xe(t,Tv,VI,pe(0)),xe(t,Tv,CH,Ie(DSt)),xe(t,Tv,D4,Ie(e4e)),xe(t,Tv,T6,Ie(n4e)),xe(t,Tv,E6,cde),xe(t,Tv,GI,Ie(ISt)),xe(t,Tv,C6,Ie(OSt)),xe(t,Tv,g8t,Ie(lft)),xe(t,Tv,mH,Ie(t4e))}function hle(t,e){var n,r,s,o,h,d,v,k,C;if(s=t.i,h=s.o.a,o=s.o.b,h<=0&&o<=0)return ve(),Zo;switch(k=t.n.a,C=t.n.b,d=t.o.a,n=t.o.b,e.g){case 2:case 1:if(k<0)return ve(),Bn;if(k+d>h)return ve(),Hn;break;case 4:case 3:if(C<0)return ve(),Pn;if(C+n>o)return ve(),mr}return v=(k+d/2)/h,r=(C+n/2)/o,v+r<=1&&v-r<=0?(ve(),Bn):v+r>=1&&v-r>=0?(ve(),Hn):r<.5?(ve(),Pn):(ve(),mr)}function uyn(t,e){var n,r,s,o,h,d,v,k,C,M,j,H,G,K;for(n=!1,C=Xt(ye(Q(e,(Te(),$v)))),G=sb*C,s=new S(e.b);s.av+G&&(K=M.g+j.g,j.a=(j.g*j.a+M.g*M.a)/K,j.g=K,M.f=j,n=!0)),o=d,M=j;return n}function fle(t,e,n,r,s,o,h){var d,v,k,C,M,j;for(j=new Fx,k=e.Kc();k.Ob();)for(d=u(k.Pb(),839),M=new S(d.wf());M.a0?d.a?(k=d.b.rf().b,s>k&&(t.v||d.c.d.c.length==1?(h=(s-k)/2,d.d.d=h,d.d.a=h):(n=u(Ne(d.c.d,0),181).rf().b,r=(n-k)/2,d.d.d=b.Math.max(0,r),d.d.a=s-r-k))):d.d.a=t.t+s:S9(t.u)&&(o=I4t(d.b),o.d<0&&(d.d.d=-o.d),o.d+o.a>d.b.rf().b&&(d.d.a=o.d+o.a-d.b.rf().b))}function fyn(t,e){var n;switch(_D(t)){case 6:return ra(e);case 7:return Bm(e);case 8:return Nm(e);case 3:return Array.isArray(e)&&(n=_D(e),!(n>=14&&n<=16));case 11:return e!=null&&typeof e===Gat;case 12:return e!=null&&(typeof e===MI||typeof e==Gat);case 0:return gst(e,t.__elementTypeId$);case 2:return Znt(e)&&e.im!==Et;case 1:return Znt(e)&&e.im!==Et||gst(e,t.__elementTypeId$);default:return!0}}function dle(t,e){var n,r,s,o;return r=b.Math.min(b.Math.abs(t.c-(e.c+e.b)),b.Math.abs(t.c+t.b-e.c)),o=b.Math.min(b.Math.abs(t.d-(e.d+e.a)),b.Math.abs(t.d+t.a-e.d)),n=b.Math.abs(t.c+t.b/2-(e.c+e.b/2)),n>t.b/2+e.b/2||(s=b.Math.abs(t.d+t.a/2-(e.d+e.a/2)),s>t.a/2+e.a/2)?1:n==0&&s==0?0:n==0?o/s+1:s==0?r/n+1:b.Math.min(r/n,o/s)+1}function gle(t,e){var n,r,s,o,h,d;return s=Jmt(t),d=Jmt(e),s==d?t.e==e.e&&t.a<54&&e.a<54?t.fe.f?1:0:(r=t.e-e.e,n=(t.d>0?t.d:b.Math.floor((t.a-1)*Cfe)+1)-(e.d>0?e.d:b.Math.floor((e.a-1)*Cfe)+1),n>r+1?s:n0&&(h=e4(h,Nle(r))),Uie(o,h))):s0&&t.d!=(q9(),slt)&&(d+=h*(r.d.a+t.a[e.b][r.b]*(e.d.a-r.d.a)/n)),n>0&&t.d!=(q9(),rlt)&&(v+=h*(r.d.b+t.a[e.b][r.b]*(e.d.b-r.d.b)/n)));switch(t.d.g){case 1:return new $e(d/o,e.d.b);case 2:return new $e(e.d.a,v/o);default:return new $e(d/o,v/o)}}function ple(t,e){oE();var n,r,s,o,h;if(h=u(Q(t.i,(Te(),cs)),98),o=t.j.g-e.j.g,o!=0||!(h==(ua(),Y2)||h==g0||h==Gc))return 0;if(h==(ua(),Y2)&&(n=u(Q(t,tp),19),r=u(Q(e,tp),19),n&&r&&(s=n.a-r.a,s!=0)))return s;switch(t.j.g){case 1:return Ms(t.n.a,e.n.a);case 2:return Ms(t.n.b,e.n.b);case 3:return Ms(e.n.a,t.n.a);case 4:return Ms(e.n.b,t.n.b);default:throw it(new No(E6t))}}function ble(t){var e,n,r,s,o,h;for(n=(!t.a&&(t.a=new As(Gh,t,5)),t.a).i+2,h=new Xc(n),le(h,new $e(t.j,t.k)),ls(new Tn(null,(!t.a&&(t.a=new As(Gh,t,5)),new _n(t.a,16))),new lzt(h)),le(h,new $e(t.b,t.c)),e=1;e0&&($D(v,!1,(ao(),zh)),$D(v,!0,Cf)),xu(e.g,new oGt(t,n)),ki(t.g,e,n)}function vle(){vle=Z;var t;for(gEt=lt(ct(Cr,1),Xr,25,15,[-1,-1,30,19,15,13,11,11,10,9,9,8,8,8,8,7,7,7,7,7,7,7,6,6,6,6,6,6,6,6,6,6,6,6,6,6,5]),Fut=Nt(Cr,Xr,25,37,15,1),$ge=lt(ct(Cr,1),Xr,25,15,[-1,-1,63,40,32,28,25,23,21,20,19,19,18,18,17,17,16,16,16,15,15,15,15,14,14,14,14,14,14,13,13,13,13,13,13,13,13]),pEt=Nt(Ob,wot,25,37,14,1),t=2;t<=36;t++)Fut[t]=ps(b.Math.pow(t,gEt[t])),pEt[t]=aI(qq,Fut[t])}function gyn(t){var e;if((!t.a&&(t.a=new fe(Ji,t,6,6)),t.a).i!=1)throw it(new Fn(Sde+(!t.a&&(t.a=new fe(Ji,t,6,6)),t.a).i));return e=new Pu,RD(u(At((!t.b&&(t.b=new Cn(br,t,4,7)),t.b),0),82))&&Ua(e,tfe(t,RD(u(At((!t.b&&(t.b=new Cn(br,t,4,7)),t.b),0),82)),!1)),RD(u(At((!t.c&&(t.c=new Cn(br,t,5,8)),t.c),0),82))&&Ua(e,tfe(t,RD(u(At((!t.c&&(t.c=new Cn(br,t,5,8)),t.c),0),82)),!0)),e}function mle(t,e){var n,r,s,o,h;for(e.d?s=t.a.c==(bd(),zv)?jo(e.b):Ds(e.b):s=t.a.c==(bd(),ep)?jo(e.b):Ds(e.b),o=!1,r=new ar(lr(s.a.Kc(),new z));zr(r);)if(n=u(Mr(r),17),h=je(t.a.f[t.a.g[e.b.p].p]),!(!h&&!Ga(n)&&n.c.i.c==n.d.i.c)&&!(je(t.a.n[t.a.g[e.b.p].p])||je(t.a.n[t.a.g[e.b.p].p]))&&(o=!0,I0(t.b,t.a.g[T1n(n,e.b).p])))return e.c=!0,e.a=n,e;return e.c=o,e.a=null,e}function pyn(t,e,n,r,s){var o,h,d,v,k,C,M;for(wn(),Zs(t,new XZ),d=new da(t,0),M=new he,o=0;d.bo*2?(C=new rz(M),k=Ru(h)/El(h),v=zat(C,e,new Cx,n,r,s,k),Li(Gf(C.e),v),M.c=Nt(Qn,De,1,0,5,1),o=0,M.c[M.c.length]=C,M.c[M.c.length]=h,o=Ru(C)*El(C)+Ru(h)*El(h)):(M.c[M.c.length]=h,o+=Ru(h)*El(h));return M}function sxt(t,e,n){var r,s,o,h,d,v,k;if(r=n.gc(),r==0)return!1;if(t.ej())if(v=t.fj(),y3t(t,e,n),h=r==1?t.Zi(3,null,n.Kc().Pb(),e,v):t.Zi(5,null,n,e,v),t.bj()){for(d=r<100?null:new Dp(r),o=e+r,s=e;s0){for(h=0;h>16==-15&&t.Cb.nh()&&rit(new Jrt(t.Cb,9,13,n,t.c,Hg(al(u(t.Cb,59)),t))):_t(t.Cb,88)&&t.Db>>16==-23&&t.Cb.nh()&&(e=t.c,_t(e,88)||(e=(dn(),Kh)),_t(n,88)||(n=(dn(),Kh)),rit(new Jrt(t.Cb,9,10,n,e,Hg(Lc(u(t.Cb,26)),t)))))),t.c}function byn(t,e){var n,r,s,o,h,d,v,k,C,M;for(vr(e,"Hypernodes processing",1),s=new S(t.b);s.an);return s}function xle(t,e){var n,r,s;r=ul(t.d,1)!=0,!je(Re(Q(e.j,(ae(),Ov))))&&!je(Re(Q(e.j,X4)))||Vt(Q(e.j,(Te(),wb)))===Vt((V0(),vb))?e.c.Tf(e.e,r):r=je(Re(Q(e.j,Ov))),yI(t,e,r,!0),je(Re(Q(e.j,X4)))&&Jt(e.j,X4,(Nn(),!1)),je(Re(Q(e.j,Ov)))&&(Jt(e.j,Ov,(Nn(),!1)),Jt(e.j,X4,!0)),n=Kst(t,e);do{if(hyt(t),n==0)return 0;r=!r,s=n,yI(t,e,r,!1),n=Kst(t,e)}while(s>n);return s}function kle(t,e,n){var r,s,o,h,d,v,k,C,M,j,H,G;if(e==n)return!0;if(e=p5t(t,e),n=p5t(t,n),r=xst(e),r){if(C=xst(n),C!=r)return C?(v=r.Dj(),G=C.Dj(),v==G&&v!=null):!1;if(h=(!e.d&&(e.d=new As(ho,e,1)),e.d),o=h.i,j=(!n.d&&(n.d=new As(ho,n,1)),n.d),o==j.i){for(k=0;k0,d=Bz(e,o),N2t(n?d.b:d.g,e),u4(d).c.length==1&&fs(r,d,r.c.b,r.c),s=new fa(o,e),Up(t.o,s),mu(t.e.a,o))}function _le(t,e){var n,r,s,o,h,d,v;return r=b.Math.abs(e$(t.b).a-e$(e.b).a),d=b.Math.abs(e$(t.b).b-e$(e.b).b),s=0,v=0,n=1,h=1,r>t.b.b/2+e.b.b/2&&(s=b.Math.min(b.Math.abs(t.b.c-(e.b.c+e.b.b)),b.Math.abs(t.b.c+t.b.b-e.b.c)),n=1-s/r),d>t.b.a/2+e.b.a/2&&(v=b.Math.min(b.Math.abs(t.b.d-(e.b.d+e.b.a)),b.Math.abs(t.b.d+t.b.a-e.b.d)),h=1-v/d),o=b.Math.min(n,h),(1-o)*b.Math.sqrt(r*r+d*d)}function kyn(t){var e,n,r,s;for($at(t,t.e,t.f,(Gw(),yb),!0,t.c,t.i),$at(t,t.e,t.f,yb,!1,t.c,t.i),$at(t,t.e,t.f,r5,!0,t.c,t.i),$at(t,t.e,t.f,r5,!1,t.c,t.i),Tyn(t,t.c,t.e,t.f,t.i),r=new da(t.i,0);r.b=65;n--)Y1[n]=n-65<<24>>24;for(r=122;r>=97;r--)Y1[r]=r-97+26<<24>>24;for(s=57;s>=48;s--)Y1[s]=s-48+52<<24>>24;for(Y1[43]=62,Y1[47]=63,o=0;o<=25;o++)lp[o]=65+o&ys;for(h=26,v=0;h<=51;++h,v++)lp[h]=97+v&ys;for(t=52,d=0;t<=61;++t,d++)lp[t]=48+d&ys;lp[62]=43,lp[63]=47}function Eyn(t,e){var n,r,s,o,h,d,v,k,C,M,j,H;if(t.dc())return new Ca;for(k=0,M=0,s=t.Kc();s.Ob();)r=u(s.Pb(),37),o=r.f,k=b.Math.max(k,o.a),M+=o.a*o.b;for(k=b.Math.max(k,b.Math.sqrt(M)*Xt(ye(Q(u(t.Kc().Pb(),37),(Te(),rG))))),j=0,H=0,v=0,n=e,d=t.Kc();d.Ob();)h=u(d.Pb(),37),C=h.f,j+C.a>k&&(j=0,H+=v+e,v=0),x_(h,j,H),n=b.Math.max(n,j+C.a),v=b.Math.max(v,C.b),j+=C.a+e;return new $e(n+e,H+v+e)}function Tyn(t,e,n,r,s){var o,h,d,v,k,C,M;for(h=new S(e);h.ao)return ve(),Hn;break;case 4:case 3:if(v<0)return ve(),Pn;if(v+t.f>s)return ve(),mr}return h=(d+t.g/2)/o,n=(v+t.f/2)/s,h+n<=1&&h-n<=0?(ve(),Bn):h+n>=1&&h-n>=0?(ve(),Hn):n<.5?(ve(),Pn):(ve(),mr)}function Cyn(t,e,n,r,s){var o,h;if(o=Pa(Ns(e[0],co),Ns(r[0],co)),t[0]=Ar(o),o=$p(o,32),n>=s){for(h=1;h0&&(s.b[h++]=0,s.b[h++]=o.b[0]-1),e=1;e0&&(oM(v,v.d-s.d),s.c==(Uf(),mb)&&bpt(v,v.a-s.d),v.d<=0&&v.i>0&&fs(e,v,e.c.b,e.c)));for(o=new S(t.f);o.a0&&(TC(d,d.i-s.d),s.c==(Uf(),mb)&&ww(d,d.b-s.d),d.i<=0&&d.d>0&&fs(n,d,n.c.b,n.c)))}function _yn(t,e,n){var r,s,o,h,d,v,k,C;for(vr(n,"Processor compute fanout",1),Xu(t.b),Xu(t.a),d=null,o=ei(e.b,0);!d&&o.b!=o.d.c;)k=u(ti(o),86),je(Re(Q(k,(fc(),Xy))))&&(d=k);for(v=new Zi,fs(v,d,v.c.b,v.c),Bhe(t,v),C=ei(e.b,0);C.b!=C.d.c;)k=u(ti(C),86),h=Br(Q(k,(fc(),zS))),s=Nc(t.b,h)!=null?u(Nc(t.b,h),19).a:0,Jt(k,MG,pe(s)),r=1+(Nc(t.a,h)!=null?u(Nc(t.a,h),19).a:0),Jt(k,pye,pe(r));or(n)}function Syn(t,e,n,r,s){var o,h,d,v,k,C,M,j,H,G;for(j=l0n(t,n),v=0;v0),r.a.Xb(r.c=--r.b),M>j+v&&Cl(r);for(h=new S(H);h.a0),r.a.Xb(r.c=--r.b)}}function Ayn(){gi();var t,e,n,r,s,o;if(Vft)return Vft;for(t=new Nl(4),yy(t,ib(kut,!0)),L_(t,ib("M",!0)),L_(t,ib("C",!0)),o=new Nl(4),r=0;r<11;r++)jc(o,r,r);return e=new Nl(4),yy(e,ib("M",!0)),jc(e,4448,4607),jc(e,65438,65439),s=new d9(2),E2(s,t),E2(s,pA),n=new d9(2),n.$l(Yj(o,ib("L",!0))),n.$l(e),n=new Xm(3,n),n=new mvt(s,n),Vft=n,Vft}function Lyn(t){var e,n;if(e=Br(qe(t,(ui(),YS))),!qne(e,t)&&!o2(t,O7)&&((!t.a&&(t.a=new fe(rs,t,10,11)),t.a).i!=0||je(Re(qe(t,ZO)))))if(e==null||fy(e).length==0){if(!qne(Gn,t))throw n=Gr(Gr(new Ol("Unable to load default layout algorithm "),Gn)," for unconfigured node "),Nq(t,n),it(new R3(n.a))}else throw n=Gr(Gr(new Ol("Layout algorithm '"),e),"' not found for "),Nq(t,n),it(new R3(n.a))}function Eat(t){var e,n,r,s,o,h,d,v,k,C,M,j,H;if(n=t.i,e=t.n,t.b==0)for(H=n.c+e.b,j=n.b-e.b-e.c,h=t.a,v=0,C=h.length;v0&&(M-=r[0]+t.c,r[0]+=t.c),r[2]>0&&(M-=r[2]+t.c),r[1]=b.Math.max(r[1],M),Xj(t.a[1],n.c+e.b+r[0]-(r[1]-M)/2,r[1]);for(o=t.a,d=0,k=o.length;d0?(t.n.c.length-1)*t.i:0,r=new S(t.n);r.a1)for(r=ei(s,0);r.b!=r.d.c;)for(n=u(ti(r),231),o=0,v=new S(n.e);v.a0&&(e[0]+=t.c,M-=e[0]),e[2]>0&&(M-=e[2]+t.c),e[1]=b.Math.max(e[1],M),Qj(t.a[1],r.d+n.d+e[0]-(e[1]-M)/2,e[1]);else for(G=r.d+n.d,H=r.a-n.d-n.a,h=t.a,v=0,C=h.length;v=0&&o!=n))throw it(new Fn(eO));for(s=0,v=0;v0||av(s.b.d,t.b.d+t.b.a)==0&&r.b<0||av(s.b.d+s.b.a,t.b.d)==0&&r.b>0){d=0;break}}else d=b.Math.min(d,Moe(t,s,r));d=b.Math.min(d,Mle(t,o,d,r))}return d}function CI(t,e){var n,r,s,o,h,d,v;if(t.b<2)throw it(new Fn("The vector chain must contain at least a source and a target point."));for(s=(Zn(t.b!=0),u(t.a.a.c,8)),vj(e,s.a,s.b),v=new Nx((!e.a&&(e.a=new As(Gh,e,5)),e.a)),h=ei(t,1);h.aXt(E1(h.g,h.d[0]).a)?(Zn(v.b>0),v.a.Xb(v.c=--v.b),zm(v,h),s=!0):d.e&&d.e.gc()>0&&(o=(!d.e&&(d.e=new he),d.e).Mc(e),k=(!d.e&&(d.e=new he),d.e).Mc(n),(o||k)&&((!d.e&&(d.e=new he),d.e).Fc(h),++h.c));s||(r.c[r.c.length]=h)}function Ole(t){var e,n,r;if(G3(u(Q(t,(Te(),cs)),98)))for(n=new S(t.j);n.a>>0,"0"+e.toString(16)),r="\\x"+Pl(n,n.length-2,n.length)):t>=Ka?(n=(e=t>>>0,"0"+e.toString(16)),r="\\v"+Pl(n,n.length-6,n.length)):r=""+String.fromCharCode(t&ys)}return r}function Cat(t,e){var n,r,s,o,h,d,v,k,C,M;if(h=t.e,v=e.e,v==0)return t;if(h==0)return e.e==0?e:new X3(-e.e,e.d,e.a);if(o=t.d,d=e.d,o+d==2)return n=Ns(t.a[0],co),r=Ns(e.a[0],co),h<0&&(n=z8(n)),v<0&&(r=z8(r)),JD(Jp(n,r));if(s=o!=d?o>d?1:-1:qyt(t.a,e.a,o),s==-1)M=-v,C=h==v?Wrt(e.a,d,t.a,o):Krt(e.a,d,t.a,o);else if(M=h,h==v){if(s==0)return rb(),s7;C=Wrt(t.a,o,e.a,d)}else C=Krt(t.a,o,e.a,d);return k=new X3(M,C.length,C),N9(k),k}function fxt(t){var e,n,r,s,o,h;for(this.e=new he,this.a=new he,n=t.b-1;n<3;n++)m8(t,0,u(Zf(t,0),8));if(t.b<4)throw it(new Fn("At (least dimension + 1) control points are necessary!"));for(this.b=3,this.d=!0,this.c=!1,x2n(this,t.b+this.b-1),h=new he,o=new S(this.e),e=0;e=e.o&&n.f<=e.f||e.a*.5<=n.f&&e.a*1.5>=n.f){if(h=u(Ne(e.n,e.n.c.length-1),211),h.e+h.d+n.g+s<=r&&(o=u(Ne(e.n,e.n.c.length-1),211),o.f-t.f+n.f<=t.b||t.a.c.length==1))return h3t(e,n),!0;if(e.s+n.g<=r&&(e.t+e.d+n.f+s<=t.b||t.a.c.length==1))return le(e.b,n),d=u(Ne(e.n,e.n.c.length-1),211),le(e.n,new E$(e.s,d.f+d.a+e.i,e.i)),W3t(u(Ne(e.n,e.n.c.length-1),211),n),Sle(e,n),!0}return!1}function Fle(t,e,n){var r,s,o,h;return t.ej()?(s=null,o=t.fj(),r=t.Zi(1,h=sit(t,e,n),n,e,o),t.bj()&&!(t.ni()&&h!=null?yi(h,n):Vt(h)===Vt(n))?(h!=null&&(s=t.dj(h,s)),s=t.cj(n,s),t.ij()&&(s=t.lj(h,n,s)),s?(s.Ei(r),s.Fi()):t.$i(r)):(t.ij()&&(s=t.lj(h,n,s)),s?(s.Ei(r),s.Fi()):t.$i(r)),h):(h=sit(t,e,n),t.bj()&&!(t.ni()&&h!=null?yi(h,n):Vt(h)===Vt(n))&&(s=null,h!=null&&(s=t.dj(h,null)),s=t.cj(n,s),s&&s.Fi()),h)}function E_(t,e){var n,r,s,o,h,d,v,k;e%=24,t.q.getHours()!=e&&(r=new b.Date(t.q.getTime()),r.setDate(r.getDate()+1),d=t.q.getTimezoneOffset()-r.getTimezoneOffset(),d>0&&(v=d/60|0,k=d%60,s=t.q.getDate(),n=t.q.getHours(),n+v>=24&&++s,o=new b.Date(t.q.getFullYear(),t.q.getMonth(),s,e+v,t.q.getMinutes()+k,t.q.getSeconds(),t.q.getMilliseconds()),t.q.setTime(o.getTime()))),h=t.q.getTime(),t.q.setTime(h+36e5),t.q.getHours()!=e&&t.q.setTime(h)}function Ryn(t,e){var n,r,s,o,h;if(vr(e,"Path-Like Graph Wrapping",1),t.b.c.length==0){or(e);return}if(s=new m5t(t),h=(s.i==null&&(s.i=fyt(s,new VN)),Xt(s.i)*s.f),n=h/(s.i==null&&(s.i=fyt(s,new VN)),Xt(s.i)),s.b>n){or(e);return}switch(u(Q(t,(Te(),ght)),337).g){case 2:o=new UN;break;case 0:o=new HN;break;default:o=new WN}if(r=o.Vf(t,s),!o.Wf())switch(u(Q(t,wG),338).g){case 2:r=Doe(s,r);break;case 1:r=Mae(s,r)}F3n(t,s,r),or(e)}function jyn(t,e){var n,r,s,o;if(Ein(t.d,t.e),t.c.a.$b(),Xt(ye(Q(e.j,(Te(),aG))))!=0||Xt(ye(Q(e.j,aG)))!=0)for(n=VE,Vt(Q(e.j,wb))!==Vt((V0(),vb))&&Jt(e.j,(ae(),Ov),(Nn(),!0)),o=u(Q(e.j,MS),19).a,s=0;ss&&++k,le(h,(An(d+k,e.c.length),u(e.c[d+k],19))),v+=(An(d+k,e.c.length),u(e.c[d+k],19)).a-r,++n;n1&&(v>Ru(d)*El(d)/2||h.b==0)&&(M=new rz(j),C=Ru(d)/El(d),k=zat(M,e,new Cx,n,r,s,C),Li(Gf(M.e),k),d=M,H.c[H.c.length]=M,v=0,j.c=Nt(Qn,De,1,0,5,1)));return Ls(H,j),H}function qyn(t,e,n,r){var s,o,h,d,v,k,C,M,j,H,G,K;if(n.mh(e)&&(C=(H=e,H?u(r,49).xh(H):null),C))if(K=n.bh(e,t.a),G=e.t,G>1||G==-1)if(M=u(K,69),j=u(C,69),M.dc())j.$b();else for(h=!!no(e),o=0,d=t.a?M.Kc():M.Zh();d.Ob();)k=u(d.Pb(),56),s=u(Xw(t,k),56),s?(h?(v=j.Xc(s),v==-1?j.Xh(o,s):o!=v&&j.ji(o,s)):j.Xh(o,s),++o):t.b&&!h&&(j.Xh(o,k),++o);else K==null?C.Wb(null):(s=Xw(t,K),s==null?t.b&&!no(e)&&C.Wb(K):C.Wb(s))}function Hyn(t,e){var n,r,s,o,h,d,v,k;for(n=new NK,s=new ar(lr(jo(e).a.Kc(),new z));zr(s);)if(r=u(Mr(s),17),!Ga(r)&&(d=r.c.i,L4t(d,yV))){if(k=V5t(t,d,yV,mV),k==-1)continue;n.b=b.Math.max(n.b,k),!n.a&&(n.a=new he),le(n.a,d)}for(h=new ar(lr(Ds(e).a.Kc(),new z));zr(h);)if(o=u(Mr(h),17),!Ga(o)&&(v=o.d.i,L4t(v,mV))){if(k=V5t(t,v,mV,yV),k==-1)continue;n.d=b.Math.max(n.d,k),!n.c&&(n.c=new he),le(n.c,v)}return n}function Nle(t){TE();var e,n,r,s;if(e=ps(t),t1e6)throw it(new _R("power of ten too big"));if(t<=wi)return Qx(bI(D6[1],e),e);for(r=bI(D6[1],wi),s=r,n=Tu(t-wi),e=ps(t%wi);yc(n,wi)>0;)s=e4(s,r),n=Jp(n,wi);for(s=e4(s,bI(D6[1],e)),s=Qx(s,wi),n=Tu(t-wi);yc(n,wi)>0;)s=Qx(s,wi),n=Jp(n,wi);return s=Qx(s,e),s}function Vyn(t,e){var n,r,s,o,h,d,v,k,C;for(vr(e,"Hierarchical port dummy size processing",1),v=new he,C=new he,r=Xt(ye(Q(t,(Te(),J4)))),n=r*2,o=new S(t.b);o.ak&&r>k)C=d,k=Xt(e.p[d.p])+Xt(e.d[d.p])+d.o.b+d.d.a;else{s=!1,n.n&&Jb(n,"bk node placement breaks on "+d+" which should have been after "+C);break}if(!s)break}return n.n&&Jb(n,e+" is feasible: "+s),s}function Kyn(t,e,n,r){var s,o,h,d,v,k,C;for(d=-1,C=new S(t);C.a=tt&&t.e[v.p]>G*t.b||St>=n*tt)&&(j.c[j.c.length]=d,d=new he,Ua(h,o),o.a.$b(),k-=C,H=b.Math.max(H,k*t.b+K),k+=St,Mt=St,St=0,C=0,K=0);return new fa(H,j)}function Jyn(t){var e,n,r,s,o,h,d,v,k,C,M,j,H;for(n=(k=new v1(t.c.b).a.vc().Kc(),new m1(k));n.a.Ob();)e=(d=u(n.a.Pb(),42),u(d.dd(),149)),s=e.a,s==null&&(s=""),r=CZe(t.c,s),!r&&s.length==0&&(r=_ln(t)),r&&!ay(r.c,e,!1)&&ri(r.c,e);for(h=ei(t.a,0);h.b!=h.d.c;)o=u(ti(h),478),C=Hrt(t.c,o.a),H=Hrt(t.c,o.b),C&&H&&ri(C.c,new fa(H,o.c));for(Ah(t.a),j=ei(t.b,0);j.b!=j.d.c;)M=u(ti(j),478),e=TZe(t.c,M.a),v=Hrt(t.c,M.b),e&&v&&gXe(e,v,M.c);Ah(t.b)}function t3n(t,e,n){var r,s,o,h,d,v,k,C,M,j,H;o=new Qk(t),h=new nae,s=(dD(h.g),dD(h.j),Xu(h.b),dD(h.d),dD(h.i),Xu(h.k),Xu(h.c),Xu(h.e),H=joe(h,o,null),Ace(h,o),H),e&&(k=new Qk(e),d=l3n(k),z4t(s,lt(ct(CSt,1),De,527,0,[d]))),j=!1,M=!1,n&&(k=new Qk(n),IH in k.a&&(j=B0(k,IH).ge().a),Qde in k.a&&(M=B0(k,Qde).ge().a)),C=yHt(Kee(new r8,j),M),Wgn(new CZ,s,C),IH in o.a&&Yf(o,IH,null),(j||M)&&(v=new _x,Ile(C,v,j,M),Yf(o,IH,v)),r=new Szt(h),zun(new l2t(s),r)}function e3n(t,e,n){var r,s,o,h,d,v,k,C,M;for(h=new oae,k=lt(ct(Cr,1),Xr,25,15,[0]),s=-1,o=0,r=0,v=0;v0){if(s<0&&C.a&&(s=v,o=k[0],r=0),s>=0){if(d=C.b,v==s&&(d-=r++,d==0))return 0;if(!jhe(e,k,C,d,h)){v=s-1,k[0]=o;continue}}else if(s=-1,!jhe(e,k,C,0,h))return 0}else{if(s=-1,wa(C.c,0)==32){if(M=k[0],aee(e,k),k[0]>M)continue}else if(Frn(e,C.c,k[0])){k[0]+=C.c.length;continue}return 0}return F5n(h,n)?k[0]:0}function C_(t){var e,n,r,s,o,h,d,v;if(!t.f){if(v=new M0,d=new M0,e=uA,h=e.a.zc(t,e),h==null){for(o=new nr(Ao(t));o.e!=o.i.gc();)s=u(dr(o),26),is(v,C_(s));e.a.Bc(t)!=null,e.a.gc()==0}for(r=(!t.s&&(t.s=new fe(Mu,t,21,17)),new nr(t.s));r.e!=r.i.gc();)n=u(dr(r),170),_t(n,99)&&Dr(d,u(n,18));iy(d),t.r=new ZYt(t,(u(At(Wt((Hp(),Ln).o),6),18),d.i),d.g),is(v,t.r),iy(v),t.f=new V3((u(At(Wt(Ln.o),5),18),v.i),v.g),sl(t).b&=-3}return t.f}function n3n(t){var e,n,r,s,o,h,d,v,k,C,M,j,H,G;for(h=t.o,r=Nt(Cr,Xr,25,h,15,1),s=Nt(Cr,Xr,25,h,15,1),n=t.p,e=Nt(Cr,Xr,25,n,15,1),o=Nt(Cr,Xr,25,n,15,1),k=0;k=0&&!f4(t,C,M);)--M;s[C]=M}for(H=0;H=0&&!f4(t,d,G);)--d;o[G]=d}for(v=0;ve[j]&&jr[v]&&Sq(t,v,j,!1,!0)}function dxt(t){var e,n,r,s,o,h,d,v;n=je(Re(Q(t,(Jf(),gbe)))),o=t.a.c.d,d=t.a.d.d,n?(h=fd(ia(new $e(d.a,d.b),o),.5),v=fd(nc(t.e),.5),e=ia(Li(new $e(o.a,o.b),h),v),H2t(t.d,e)):(s=Xt(ye(Q(t.a,kbe))),r=t.d,o.a>=d.a?o.b>=d.b?(r.a=d.a+(o.a-d.a)/2+s,r.b=d.b+(o.b-d.b)/2-s-t.e.b):(r.a=d.a+(o.a-d.a)/2+s,r.b=o.b+(d.b-o.b)/2+s):o.b>=d.b?(r.a=o.a+(d.a-o.a)/2+s,r.b=d.b+(o.b-d.b)/2+s):(r.a=o.a+(d.a-o.a)/2+s,r.b=o.b+(d.b-o.b)/2-s-t.e.b))}function $c(t,e){var n,r,s,o,h,d,v;if(t==null)return null;if(o=t.length,o==0)return"";for(v=Nt(xh,yd,25,o,15,1),Lmt(0,o,t.length),Lmt(0,o,v.length),iXt(t,0,o,v,0),n=null,d=e,s=0,h=0;s0?Pl(n.a,0,o-1):""):t.substr(0,o-1):n?n.a:t}function jle(t){Mw(t,new k2(_w(Ew(Cw(Tw(new kg,A2),"ELK DisCo"),"Layouter for arranging unconnected subgraphs. The subgraphs themselves are, by default, not laid out."),new yg))),xe(t,A2,jot,Ie(p7t)),xe(t,A2,$ot,Ie(Qut)),xe(t,A2,E6,Ie(Jpe)),xe(t,A2,xv,Ie(g7t)),xe(t,A2,Zxt,Ie(rbe)),xe(t,A2,Jxt,Ie(nbe)),xe(t,A2,Qxt,Ie(ibe)),xe(t,A2,t6t,Ie(ebe)),xe(t,A2,o6t,Ie(tbe)),xe(t,A2,c6t,Ie(Xut)),xe(t,A2,u6t,Ie(d7t)),xe(t,A2,l6t,Ie(fV))}function gxt(t,e,n,r){var s,o,h,d,v,k,C,M,j;if(o=new Y0(t),D0(o,(Vn(),Hc)),Jt(o,(Te(),cs),(ua(),Gc)),s=0,e){for(h=new Mc,Jt(h,(ae(),_i),e),Jt(o,_i,e.i),Bs(h,(ve(),Bn)),Uo(h,o),j=wd(e.e),k=j,C=0,M=k.length;C0)if(n-=r.length-e,n>=0){for(s.a+="0.";n>N2.length;n-=N2.length)wKt(s,N2);JWt(s,N2,ps(n)),Gr(s,r.substr(e))}else n=e-n,Gr(s,Pl(r,e,ps(n))),s.a+=".",Gr(s,RM(r,ps(n)));else{for(Gr(s,r.substr(e));n<-N2.length;n+=N2.length)wKt(s,N2);JWt(s,N2,ps(-n))}return s.a}function pxt(t,e,n,r){var s,o,h,d,v,k,C,M,j;return v=ia(new $e(n.a,n.b),t),k=v.a*e.b-v.b*e.a,C=e.a*r.b-e.b*r.a,M=(v.a*r.b-v.b*r.a)/C,j=k/C,C==0?k==0?(s=Li(new $e(n.a,n.b),fd(new $e(r.a,r.b),.5)),o=Wp(t,s),h=Wp(Li(new $e(t.a,t.b),e),s),d=b.Math.sqrt(r.a*r.a+r.b*r.b)*.5,o=0&&M<=1&&j>=0&&j<=1?Li(new $e(t.a,t.b),fd(new $e(e.a,e.b),M)):null}function i3n(t,e,n){var r,s,o,h,d;if(r=u(Q(t,(Te(),tht)),21),n.a>e.a&&(r.Hc((hy(),WO))?t.c.a+=(n.a-e.a)/2:r.Hc(YO)&&(t.c.a+=n.a-e.a)),n.b>e.b&&(r.Hc((hy(),XO))?t.c.b+=(n.b-e.b)/2:r.Hc(KO)&&(t.c.b+=n.b-e.b)),u(Q(t,(ae(),Vc)),21).Hc((oo(),vh))&&(n.a>e.a||n.b>e.b))for(d=new S(t.a);d.ae.a&&(r.Hc((hy(),WO))?t.c.a+=(n.a-e.a)/2:r.Hc(YO)&&(t.c.a+=n.a-e.a)),n.b>e.b&&(r.Hc((hy(),XO))?t.c.b+=(n.b-e.b)/2:r.Hc(KO)&&(t.c.b+=n.b-e.b)),u(Q(t,(ae(),Vc)),21).Hc((oo(),vh))&&(n.a>e.a||n.b>e.b))for(h=new S(t.a);h.ae&&(s=0,o+=C.b+n,M.c[M.c.length]=C,C=new Zvt(o,n),r=new Iit(0,C.f,C,n),az(C,r),s=0),r.b.c.length==0||v.f>=r.o&&v.f<=r.f||r.a*.5<=v.f&&r.a*1.5>=v.f?h3t(r,v):(h=new Iit(r.s+r.r+n,C.f,C,n),az(C,h),h3t(h,v)),s=v.i+v.g;return M.c[M.c.length]=C,M}function T4(t){var e,n,r,s,o,h,d,v;if(!t.a){if(t.o=null,v=new Wzt(t),e=new Ep,n=uA,d=n.a.zc(t,n),d==null){for(h=new nr(Ao(t));h.e!=h.i.gc();)o=u(dr(h),26),is(v,T4(o));n.a.Bc(t)!=null,n.a.gc()==0}for(s=(!t.s&&(t.s=new fe(Mu,t,21,17)),new nr(t.s));s.e!=s.i.gc();)r=u(dr(s),170),_t(r,322)&&Dr(e,u(r,34));iy(e),t.k=new QYt(t,(u(At(Wt((Hp(),Ln).o),7),18),e.i),e.g),is(v,t.k),iy(v),t.a=new V3((u(At(Wt(Ln.o),4),18),v.i),v.g),sl(t).b&=-2}return t.a}function c3n(t,e,n,r,s,o,h){var d,v,k,C,M,j;return M=!1,v=Wce(n.q,e.f+e.b-n.q.f),j=s-(n.q.e+v-h),j=(An(o,t.c.length),u(t.c[o],200)).e,C=(d=__(r,j,!1),d.a),C>e.b&&!k)?!1:((k||C<=e.b)&&(k&&C>e.b?(n.d=C,vD(n,Qae(n,C))):(bae(n.q,v),n.c=!0),vD(r,s-(n.s+n.r)),tI(r,n.q.e+n.q.d,e.f),az(e,r),t.c.length>o&&(sI((An(o,t.c.length),u(t.c[o],200)),r),(An(o,t.c.length),u(t.c[o],200)).a.c.length==0&&Fg(t,o)),M=!0),M)}function bxt(t,e,n,r){var s,o,h,d,v,k,C;if(C=ou(t.e.Tg(),e),s=0,o=u(t.g,119),v=null,to(),u(e,66).Oj()){for(d=0;dt.o.a&&(C=(v-t.o.a)/2,d.b=b.Math.max(d.b,C),d.c=b.Math.max(d.c,C))}}function l3n(t){var e,n,r,s,o,h,d,v;for(o=new vZt,YXe(o,(i6(),G3e)),r=(s=yit(t,Nt(Ae,ee,2,0,6,1)),new mx(new yl(new Eet(t,s).b)));r.b0?t.i:0)>e&&v>0&&(o=0,h+=v+t.i,s=b.Math.max(s,j),r+=v+t.i,v=0,j=0,n&&(++M,le(t.n,new E$(t.s,h,t.i))),d=0),j+=k.g+(d>0?t.i:0),v=b.Math.max(v,k.f),n&&W3t(u(Ne(t.n,M),211),k),o+=k.g+(d>0?t.i:0),++d;return s=b.Math.max(s,j),r+=v,n&&(t.r=s,t.d=r,Q3t(t.j)),new ah(t.s,t.t,s,r)}function Dc(t,e,n,r,s){Gd();var o,h,d,v,k,C,M,j,H;if(bvt(t,"src"),bvt(n,"dest"),j=ol(t),v=ol(n),jwt((j.i&4)!=0,"srcType is not an array"),jwt((v.i&4)!=0,"destType is not an array"),M=j.c,h=v.c,jwt(M.i&1?M==h:(h.i&1)==0,"Array types don't match"),H=t.length,k=n.length,e<0||r<0||s<0||e+s>H||r+s>k)throw it(new Dpt);if(!(M.i&1)&&j!=v)if(C=u2(t),o=u2(n),Vt(t)===Vt(n)&&er;)ts(o,d,C[--e]);else for(d=r+s;r0&&n5t(t,e,n,r,s,!0)}function Lat(){Lat=Z,qge=lt(ct(Cr,1),Xr,25,15,[Sa,1162261467,D_,1220703125,362797056,1977326743,D_,387420489,Gq,214358881,429981696,815730721,1475789056,170859375,268435456,410338673,612220032,893871739,128e7,1801088541,113379904,148035889,191102976,244140625,308915776,387420489,481890304,594823321,729e6,887503681,D_,1291467969,1544804416,1838265625,60466176]),Hge=lt(ct(Cr,1),Xr,25,15,[-1,-1,31,19,15,13,11,11,10,9,9,8,8,8,8,7,7,7,7,7,7,7,6,6,6,6,6,6,6,6,6,6,6,6,6,6,5])}function h3n(t){var e,n,r,s,o,h,d,v;for(s=new S(t.b);s.a=t.b.length?(o[s++]=h.b[r++],o[s++]=h.b[r++]):r>=h.b.length?(o[s++]=t.b[n++],o[s++]=t.b[n++]):h.b[r]0?t.i:0)),++e;for(Ehn(t.n,v),t.d=n,t.r=r,t.g=0,t.f=0,t.e=0,t.o=as,t.p=as,o=new S(t.b);o.a0&&(s=(!t.n&&(t.n=new fe(qo,t,1,7)),u(At(t.n,0),137)).a,!s||Gr(Gr((e.a+=' "',e),s),'"'))),n=(!t.b&&(t.b=new Cn(br,t,4,7)),!(t.b.i<=1&&(!t.c&&(t.c=new Cn(br,t,5,8)),t.c.i<=1))),n?e.a+=" [":e.a+=" ",Gr(e,_2t(new vet,new nr(t.b))),n&&(e.a+="]"),e.a+=Uot,n&&(e.a+="["),Gr(e,_2t(new vet,new nr(t.c))),n&&(e.a+="]"),e.a)}function Mat(t,e){var n,r,s,o,h,d,v;if(t.a){if(d=t.a.ne(),v=null,d!=null?e.a+=""+d:(h=t.a.Dj(),h!=null&&(o=hd(h,Cu(91)),o!=-1?(v=h.substr(o),e.a+=""+Pl(h==null?_u:(On(h),h),0,o)):e.a+=""+h)),t.d&&t.d.i!=0){for(s=!0,e.a+="<",r=new nr(t.d);r.e!=r.i.gc();)n=u(dr(r),87),s?s=!1:e.a+=Ya,Mat(n,e);e.a+=">"}v!=null&&(e.a+=""+v)}else t.e?(d=t.e.zb,d!=null&&(e.a+=""+d)):(e.a+="?",t.b?(e.a+=" super ",Mat(t.b,e)):t.f&&(e.a+=" extends ",Mat(t.f,e)))}function g3n(t,e){var n,r,s,o,h,d,v,k,C,M,j,H,G,K,tt,gt,Mt,St,Rt,Kt,ue,_e,We,Qe,Rn;for(Kt=t.c,ue=e.c,n=Ro(Kt.a,t,0),r=Ro(ue.a,e,0),St=u(ov(t,(so(),tl)).Kc().Pb(),11),Qe=u(ov(t,nu).Kc().Pb(),11),Rt=u(ov(e,tl).Kc().Pb(),11),Rn=u(ov(e,nu).Kc().Pb(),11),gt=wd(St.e),_e=wd(Qe.g),Mt=wd(Rt.e),We=wd(Rn.g),ly(t,r,ue),h=Mt,C=0,G=h.length;CC?new i2((Uf(),Ky),n,e,k-C):k>0&&C>0&&(new i2((Uf(),Ky),e,n,0),new i2(Ky,n,e,0))),h)}function qle(t,e){var n,r,s,o,h,d;for(h=new p2(new Cg(t.f.b).a);h.b;){if(o=Zw(h),s=u(o.cd(),594),e==1){if(s.gf()!=(ao(),rg)&&s.gf()!=ng)continue}else if(s.gf()!=(ao(),zh)&&s.gf()!=Cf)continue;switch(r=u(u(o.dd(),46).b,81),d=u(u(o.dd(),46).a,189),n=d.c,s.gf().g){case 2:r.g.c=t.e.a,r.g.b=b.Math.max(1,r.g.b+n);break;case 1:r.g.c=r.g.c+n,r.g.b=b.Math.max(1,r.g.b-n);break;case 4:r.g.d=t.e.b,r.g.a=b.Math.max(1,r.g.a+n);break;case 3:r.g.d=r.g.d+n,r.g.a=b.Math.max(1,r.g.a-n)}}}function p3n(t,e){var n,r,s,o,h,d,v,k,C,M,j,H,G,K;for(d=Nt(Cr,Xr,25,e.b.c.length,15,1),k=Nt(flt,oe,267,e.b.c.length,0,1),v=Nt(l0,Yg,10,e.b.c.length,0,1),M=t.a,j=0,H=M.length;j0&&v[r]&&(G=W3(t.b,v[r],s)),K=b.Math.max(K,s.c.c.b+G);for(o=new S(C.e);o.a1)throw it(new Fn(aO));v||(o=Zd(e,r.Kc().Pb()),h.Fc(o))}return Syt(t,W4t(t,e,n),h)}function v3n(t,e){var n,r,s,o;for(ecn(e.b.j),ls(wu(new Tn(null,new _n(e.d,16)),new XX),new QX),o=new S(e.d);o.at.o.b||(n=Ko(t,Hn),d=e.d+e.a+(n.gc()-1)*h,d>t.o.b)))}function Oat(t,e){var n,r,s,o,h,d,v,k,C,M,j,H,G;if(h=t.e,v=e.e,h==0)return e;if(v==0)return t;if(o=t.d,d=e.d,o+d==2)return n=Ns(t.a[0],co),r=Ns(e.a[0],co),h==v?(C=Pa(n,r),G=Ar(C),H=Ar(Vm(C,32)),H==0?new Ng(h,G):new X3(h,2,lt(ct(Cr,1),Xr,25,15,[G,H]))):JD(h<0?Jp(r,n):Jp(n,r));if(h==v)j=h,M=o>=d?Krt(t.a,o,e.a,d):Krt(e.a,d,t.a,o);else{if(s=o!=d?o>d?1:-1:qyt(t.a,e.a,o),s==0)return rb(),s7;s==1?(j=h,M=Wrt(t.a,o,e.a,d)):(j=v,M=Wrt(e.a,d,t.a,o))}return k=new X3(j,M.length,M),N9(k),k}function Pat(t,e,n,r,s,o,h){var d,v,k,C,M,j,H;return M=je(Re(Q(e,(Te(),l9t)))),j=null,o==(so(),tl)&&r.c.i==n?j=r.c:o==nu&&r.d.i==n&&(j=r.d),k=h,!k||!M||j?(C=(ve(),Zo),j?C=j.j:G3(u(Q(n,cs),98))&&(C=o==tl?Bn:Hn),v=k3n(t,e,n,o,C,r),d=Grt((Na(n),r)),o==tl?(Oa(d,u(Ne(v.j,0),11)),oa(d,s)):(Oa(d,s),oa(d,u(Ne(v.j,0),11))),k=new oie(r,d,v,u(Q(v,(ae(),_i)),11),o,!j)):(le(k.e,r),H=b.Math.max(Xt(ye(Q(k.d,Jg))),Xt(ye(Q(r,Jg)))),Jt(k.d,Jg,H)),ln(t.a,r,new Fj(k.d,e,o)),k}function Pq(t,e){var n,r,s,o,h,d,v,k,C,M;if(C=null,t.d&&(C=u(Nc(t.d,e),138)),!C){if(o=t.a.Mh(),M=o.i,!t.d||HC(t.d)!=M){for(v=new _r,t.d&&Y9(v,t.d),k=v.f.c+v.g.c,d=k;d0?(H=(G-1)*n,d&&(H+=r),C&&(H+=r),H=t.b[s+1])s+=2;else if(n0)for(r=new Bu(u(Ai(t.a,o),21)),wn(),Zs(r,new Si(e)),s=new da(o.b,0);s.bKt)?(v=2,h=wi):v==0?(v=1,h=_e):(v=0,h=_e)):(H=_e>=h||h-_e0?1:Iw(isNaN(r),isNaN(0)))>=0^(wf(_d),(b.Math.abs(d)<=_d||d==0||isNaN(d)&&isNaN(0)?0:d<0?-1:d>0?1:Iw(isNaN(d),isNaN(0)))>=0)?b.Math.max(d,r):(wf(_d),(b.Math.abs(r)<=_d||r==0||isNaN(r)&&isNaN(0)?0:r<0?-1:r>0?1:Iw(isNaN(r),isNaN(0)))>0?b.Math.sqrt(d*d+r*r):-b.Math.sqrt(d*d+r*r))}function E2(t,e){var n,r,s,o,h,d;if(e){if(!t.a&&(t.a=new ER),t.e==2){kR(t.a,e);return}if(e.e==1){for(s=0;s=Ka?go(n,l3t(r)):S8(n,r&ys),h=new krt(10,null,0),unn(t.a,h,d-1)):(n=(h.bm().length+o,new $C),go(n,h.bm())),e.e==0?(r=e._l(),r>=Ka?go(n,l3t(r)):S8(n,r&ys)):go(n,e.bm()),u(h,521).b=n.a}}function Xle(t){var e,n,r,s,o;return t.g!=null?t.g:t.a<32?(t.g=W5n(Tu(t.f),ps(t.e)),t.g):(s=Hat((!t.c&&(t.c=VD(t.f)),t.c),0),t.e==0?s:(e=(!t.c&&(t.c=VD(t.f)),t.c).e<0?2:1,n=s.length,r=-t.e+n-e,o=new Mp,o.a+=""+s,t.e>0&&r>=-6?r>=0?uD(o,n-ps(t.e),String.fromCharCode(46)):(o.a=Pl(o.a,0,e-1)+"0."+RM(o.a,e-1),uD(o,e+1,Mh(N2,0,-ps(r)-1))):(n-e>=1&&(uD(o,e,String.fromCharCode(46)),++n),uD(o,n,String.fromCharCode(69)),r>0&&uD(o,++n,String.fromCharCode(43)),uD(o,++n,""+_9(Tu(r)))),t.g=o.a,t.g))}function F3n(t,e,n){var r,s,o,h,d,v,k,C,M,j,H,G,K,tt;if(!n.dc()){for(d=0,j=0,r=n.Kc(),G=u(r.Pb(),19).a;d1&&(v=k.mg(v,t.a,d));return v.c.length==1?u(Ne(v,v.c.length-1),220):v.c.length==2?T3n((An(0,v.c.length),u(v.c[0],220)),(An(1,v.c.length),u(v.c[1],220)),h,o):null}function Qle(t){var e,n,r,s,o,h;for(xu(t.a,new xi),n=new S(t.a);n.a=b.Math.abs(r.b)?(r.b=0,o.d+o.a>h.d&&o.dh.c&&o.c0){if(e=new n2t(t.i,t.g),n=t.i,o=n<100?null:new Dp(n),t.ij())for(r=0;r0){for(d=t.g,k=t.i,z9(t),o=k<100?null:new Dp(k),r=0;r>13|(t.m&15)<<9,s=t.m>>4&8191,o=t.m>>17|(t.h&255)<<5,h=(t.h&1048320)>>8,d=e.l&8191,v=e.l>>13|(e.m&15)<<9,k=e.m>>4&8191,C=e.m>>17|(e.h&255)<<5,M=(e.h&1048320)>>8,We=n*d,Qe=r*d,Rn=s*d,zn=o*d,hr=h*d,v!=0&&(Qe+=n*v,Rn+=r*v,zn+=s*v,hr+=o*v),k!=0&&(Rn+=n*k,zn+=r*k,hr+=s*k),C!=0&&(zn+=n*C,hr+=r*C),M!=0&&(hr+=n*M),H=We&hl,G=(Qe&511)<<13,j=H+G,tt=We>>22,gt=Qe>>9,Mt=(Rn&262143)<<4,St=(zn&31)<<17,K=tt+gt+Mt+St,Kt=Rn>>18,ue=zn>>5,_e=(hr&4095)<<8,Rt=Kt+ue+_e,K+=j>>22,j&=hl,Rt+=K>>22,K&=hl,Rt&=Z0,iu(j,K,Rt)}function Zle(t){var e,n,r,s,o,h,d;if(d=u(Ne(t.j,0),11),d.g.c.length!=0&&d.e.c.length!=0)throw it(new No("Interactive layout does not support NORTH/SOUTH ports with incoming _and_ outgoing edges."));if(d.g.c.length!=0){for(o=as,n=new S(d.g);n.a4)if(t.wj(e)){if(t.rk()){if(s=u(e,49),r=s.Ug(),v=r==t.e&&(t.Dk()?s.Og(s.Vg(),t.zk())==t.Ak():-1-s.Vg()==t.aj()),t.Ek()&&!v&&!r&&s.Zg()){for(o=0;o0&&(k=t.n.a/o);break;case 2:case 4:s=t.i.o.b,s>0&&(k=t.n.b/s)}Jt(t,(ae(),Fv),k)}if(v=t.o,h=t.a,r)h.a=r.a,h.b=r.b,t.d=!0;else if(e!=G1&&e!=Tb&&d!=Zo)switch(d.g){case 1:h.a=v.a/2;break;case 2:h.a=v.a,h.b=v.b/2;break;case 3:h.a=v.a/2,h.b=v.b;break;case 4:h.b=v.b/2}else h.a=v.a/2,h.b=v.b/2}function A_(t){var e,n,r,s,o,h,d,v,k,C;if(t.ej())if(C=t.Vi(),v=t.fj(),C>0)if(e=new gyt(t.Gi()),n=C,o=n<100?null:new Dp(n),VM(t,n,e.g),s=n==1?t.Zi(4,At(e,0),null,0,v):t.Zi(6,e,null,-1,v),t.bj()){for(r=new nr(e);r.e!=r.i.gc();)o=t.dj(dr(r),o);o?(o.Ei(s),o.Fi()):t.$i(s)}else o?(o.Ei(s),o.Fi()):t.$i(s);else VM(t,t.Vi(),t.Wi()),t.$i(t.Zi(6,(wn(),io),null,-1,v));else if(t.bj())if(C=t.Vi(),C>0){for(d=t.Wi(),k=C,VM(t,C,d),o=k<100?null:new Dp(k),r=0;rt.d[h.p]&&(n+=fmt(t.b,o)*u(v.b,19).a,Up(t.a,pe(o)));for(;!BC(t.a);)Hmt(t.b,u(Hx(t.a),19).a)}return n}function W3n(t,e,n,r){var s,o,h,d,v,k,C,M,j,H,G,K,tt;for(M=new xo(u(qe(t,(fq(),OSt)),8)),M.a=b.Math.max(M.a-n.b-n.c,0),M.b=b.Math.max(M.b-n.d-n.a,0),s=ye(qe(t,MSt)),(s==null||(On(s),s<=0))&&(s=1.3),d=new he,G=new nr((!t.a&&(t.a=new fe(rs,t,10,11)),t.a));G.e!=G.i.gc();)H=u(dr(G),33),h=new LWt(H),d.c[d.c.length]=h;switch(j=u(qe(t,lft),311),j.g){case 3:tt=pyn(d,e,M.a,M.b,(k=r,On(s),k));break;case 1:tt=zyn(d,e,M.a,M.b,(C=r,On(s),C));break;default:tt=X3n(d,e,M.a,M.b,(v=r,On(s),v))}o=new rz(tt),K=zat(o,e,n,M.a,M.b,r,(On(s),s)),wv(t,K.a,K.b,!1,!0)}function Y3n(t,e){var n,r,s,o;n=e.b,o=new Bu(n.j),s=0,r=n.j,r.c=Nt(Qn,De,1,0,5,1),$w(u(h2(t.b,(ve(),Pn),(nv(),Dv)),15),n),s=nI(o,s,new jX,r),$w(u(h2(t.b,Pn,pb),15),n),s=nI(o,s,new VT,r),$w(u(h2(t.b,Pn,Mv),15),n),$w(u(h2(t.b,Hn,Dv),15),n),$w(u(h2(t.b,Hn,pb),15),n),s=nI(o,s,new PN,r),$w(u(h2(t.b,Hn,Mv),15),n),$w(u(h2(t.b,mr,Dv),15),n),s=nI(o,s,new FN,r),$w(u(h2(t.b,mr,pb),15),n),s=nI(o,s,new NN,r),$w(u(h2(t.b,mr,Mv),15),n),$w(u(h2(t.b,Bn,Dv),15),n),s=nI(o,s,new qX,r),$w(u(h2(t.b,Bn,pb),15),n),$w(u(h2(t.b,Bn,Mv),15),n)}function K3n(t,e){var n,r,s,o,h,d,v,k,C,M,j,H,G,K;for(vr(e,"Layer size calculation",1),C=as,k=Cs,s=!1,d=new S(t.b);d.a.5?gt-=h*2*(G-.5):G<.5&&(gt+=o*2*(.5-G)),s=d.d.b,gttt.a-K-C&&(gt=tt.a-K-C),d.n.a=e+gt}}function X3n(t,e,n,r,s){var o,h,d,v,k,C,M,j,H,G,K,tt;for(d=Nt(aa,vo,25,t.c.length,15,1),j=new n$(new sB),e4t(j,t),k=0,K=new he;j.b.c.length!=0;)if(h=u(j.b.c.length==0?null:Ne(j.b,0),157),k>1&&Ru(h)*El(h)/2>d[0]){for(o=0;od[o];)++o;G=new Qd(K,0,o+1),M=new rz(G),C=Ru(h)/El(h),v=zat(M,e,new Cx,n,r,s,C),Li(Gf(M.e),v),R8(xE(j,M)),H=new Qd(K,o+1,K.c.length),e4t(j,H),K.c=Nt(Qn,De,1,0,5,1),k=0,AKt(d,d.length,0)}else tt=j.b.c.length==0?null:Ne(j.b,0),tt!=null&&vit(j,0),k>0&&(d[k]=d[k-1]),d[k]+=Ru(h)*El(h),++k,K.c[K.c.length]=h;return K}function Q3n(t){var e,n,r,s,o;if(r=u(Q(t,(Te(),uu)),163),r==(dh(),bb)){for(n=new ar(lr(jo(t).a.Kc(),new z));zr(n);)if(e=u(Mr(n),17),!jJt(e))throw it(new R3(Kot+rI(t)+"' has its layer constraint set to FIRST_SEPARATE, but has at least one incoming edge. FIRST_SEPARATE nodes must not have incoming edges."))}else if(r==jy){for(o=new ar(lr(Ds(t).a.Kc(),new z));zr(o);)if(s=u(Mr(o),17),!jJt(s))throw it(new R3(Kot+rI(t)+"' has its layer constraint set to LAST_SEPARATE, but has at least one outgoing edge. LAST_SEPARATE nodes must not have outgoing edges."))}}function Z3n(t,e){var n,r,s,o,h,d,v,k,C,M,j,H,G;for(vr(e,"Label dummy removal",1),r=Xt(ye(Q(t,(Te(),V6)))),s=Xt(ye(Q(t,Wy))),k=u(Q(t,Wl),103),v=new S(t.b);v.a0&&soe(t,d,M);for(s=new S(M);s.a>19&&(e=rE(e),v=!v),h=Q2n(e),o=!1,s=!1,r=!1,t.h==NI&&t.m==0&&t.l==0)if(s=!0,o=!0,h==-1)t=yUt((q8(),sEt)),r=!0,v=!v;else return d=v5t(t,h),v&&Ait(d),n&&(hb=iu(0,0,0)),d;else t.h>>19&&(o=!0,t=rE(t),r=!0,v=!v);return h!=-1?Run(t,h,v,o,n):u4t(t,e)<0?(n&&(o?hb=rE(t):hb=iu(t.l,t.m,t.h)),iu(0,0,0)):qmn(r?t:iu(t.l,t.m,t.h),e,v,o,s,n)}function Fq(t,e){var n,r,s,o,h,d,v,k,C,M,j,H,G;if(t.e&&t.c.ce.f||e.g>t.f)){for(n=0,r=0,h=t.w.a.ec().Kc();h.Ob();)s=u(h.Pb(),11),$it(Yo(lt(ct(Ws,1),ee,8,0,[s.i.n,s.n,s.a])).b,e.g,e.f)&&++n;for(d=t.r.a.ec().Kc();d.Ob();)s=u(d.Pb(),11),$it(Yo(lt(ct(Ws,1),ee,8,0,[s.i.n,s.n,s.a])).b,e.g,e.f)&&--n;for(v=e.w.a.ec().Kc();v.Ob();)s=u(v.Pb(),11),$it(Yo(lt(ct(Ws,1),ee,8,0,[s.i.n,s.n,s.a])).b,t.g,t.f)&&++r;for(o=e.r.a.ec().Kc();o.Ob();)s=u(o.Pb(),11),$it(Yo(lt(ct(Ws,1),ee,8,0,[s.i.n,s.n,s.a])).b,t.g,t.f)&&--r;n=0)return s=ohn(t,e.substr(1,h-1)),C=e.substr(h+1,v-(h+1)),nxn(t,C,s)}else{if(n=-1,lEt==null&&(lEt=new RegExp("\\d")),lEt.test(String.fromCharCode(d))&&(n=bwt(e,Cu(46),v-1),n>=0)){r=u(Urt(t,Dee(t,e.substr(1,n-1)),!1),58),k=0;try{k=ql(e.substr(n+1),Sa,wi)}catch(j){throw j=Wi(j),_t(j,127)?(o=j,it(new W$(o))):it(j)}if(k=0)return n;switch(Hw(To(t,n))){case 2:{if(hn("",$g(t,n.Hj()).ne())){if(v=rD(To(t,n)),d=M8(To(t,n)),C=C5t(t,e,v,d),C)return C;for(s=Z5t(t,e),h=0,M=s.gc();h1)throw it(new Fn(aO));for(C=ou(t.e.Tg(),e),r=u(t.g,119),h=0;h1,k=new L1(j.b);Go(k.a)||Go(k.b);)v=u(Go(k.a)?J(k.a):J(k.b),17),M=v.c==j?v.d:v.c,b.Math.abs(Yo(lt(ct(Ws,1),ee,8,0,[M.i.n,M.n,M.a])).b-h.b)>1&&evn(t,v,h,o,j)}}function l4n(t){var e,n,r,s,o,h;if(s=new da(t.e,0),r=new da(t.a,0),t.d)for(n=0;nLct;){for(o=e,h=0;b.Math.abs(e-o)0),s.a.Xb(s.c=--s.b),Syn(t,t.b-h,o,r,s),Zn(s.b0),r.a.Xb(r.c=--r.b)}if(!t.d)for(n=0;n0?(t.f[C.p]=H/(C.e.c.length+C.g.c.length),t.c=b.Math.min(t.c,t.f[C.p]),t.b=b.Math.max(t.b,t.f[C.p])):d&&(t.f[C.p]=H)}}function f4n(t){t.b=null,t.bb=null,t.fb=null,t.qb=null,t.a=null,t.c=null,t.d=null,t.e=null,t.f=null,t.n=null,t.M=null,t.L=null,t.Q=null,t.R=null,t.K=null,t.db=null,t.eb=null,t.g=null,t.i=null,t.j=null,t.k=null,t.gb=null,t.o=null,t.p=null,t.q=null,t.r=null,t.$=null,t.ib=null,t.S=null,t.T=null,t.t=null,t.s=null,t.u=null,t.v=null,t.w=null,t.B=null,t.A=null,t.C=null,t.D=null,t.F=null,t.G=null,t.H=null,t.I=null,t.J=null,t.P=null,t.Z=null,t.U=null,t.V=null,t.W=null,t.X=null,t.Y=null,t._=null,t.ab=null,t.cb=null,t.hb=null,t.nb=null,t.lb=null,t.mb=null,t.ob=null,t.pb=null,t.jb=null,t.kb=null,t.N=!1,t.O=!1}function d4n(t,e,n){var r,s,o,h;for(vr(n,"Graph transformation ("+t.a+")",1),h=Ww(e.a),o=new S(e.b);o.a0&&(t.a=v+(H-1)*o,e.c.b+=t.a,e.f.b+=t.a)),G.a.gc()!=0&&(j=new ert(1,o),H=Txt(j,e,G,K,e.f.b+v-e.c.b),H>0&&(e.f.b+=v+(H-1)*o))}function OE(t,e){var n,r,s,o;o=t.F,e==null?(t.F=null,aE(t,null)):(t.F=(On(e),e),r=hd(e,Cu(60)),r!=-1?(s=e.substr(0,r),hd(e,Cu(46))==-1&&!hn(s,b6)&&!hn(s,tS)&&!hn(s,FH)&&!hn(s,eS)&&!hn(s,nS)&&!hn(s,rS)&&!hn(s,iS)&&!hn(s,sS)&&(s=$0e),n=Tj(e,Cu(62)),n!=-1&&(s+=""+e.substr(n+1)),aE(t,s)):(s=e,hd(e,Cu(46))==-1&&(r=hd(e,Cu(91)),r!=-1&&(s=e.substr(0,r)),!hn(s,b6)&&!hn(s,tS)&&!hn(s,FH)&&!hn(s,eS)&&!hn(s,nS)&&!hn(s,rS)&&!hn(s,iS)&&!hn(s,sS)?(s=$0e,r!=-1&&(s+=""+e.substr(r))):s=e),aE(t,s),s==e&&(t.F=t.D))),t.Db&4&&!(t.Db&1)&&mi(t,new Js(t,1,5,o,e))}function p4n(t,e){var n,r,s,o,h,d,v,k,C,M,j,H,G,K,tt,gt,Mt,St;if(K=e.b.c.length,!(K<3)){for(H=Nt(Cr,Xr,25,K,15,1),M=0,C=new S(e.b);C.ah)&&Fs(t.b,u(tt.b,17));++d}o=h}}}function xxt(t,e){var n;if(e==null||hn(e,_u)||e.length==0&&t.k!=(Ug(),U6))return null;switch(t.k.g){case 1:return Vz(e,XE)?(Nn(),r7):Vz(e,Vct)?(Nn(),F2):null;case 2:try{return pe(ql(e,Sa,wi))}catch(r){if(r=Wi(r),_t(r,127))return null;throw it(r)}case 4:try{return dy(e)}catch(r){if(r=Wi(r),_t(r,127))return null;throw it(r)}case 3:return e;case 5:return Rre(t),Voe(t,e);case 6:return Rre(t),C2n(t,t.a,e);case 7:try{return n=Bbn(t),n.Jf(e),n}catch(r){if(r=Wi(r),_t(r,32))return null;throw it(r)}default:throw it(new No("Invalid type set for this layout option."))}}function b4n(t){H9();var e,n,r,s,o,h,d;for(d=new pqt,n=new S(t);n.a=d.b.c)&&(d.b=e),(!d.c||e.c<=d.c.c)&&(d.d=d.c,d.c=e),(!d.e||e.d>=d.e.d)&&(d.e=e),(!d.f||e.d<=d.f.d)&&(d.f=e);return r=new Yz((nE(),Lv)),hD(t,Ube,new yl(lt(ct(mO,1),De,369,0,[r]))),h=new Yz(Fy),hD(t,Gbe,new yl(lt(ct(mO,1),De,369,0,[h]))),s=new Yz(Py),hD(t,Vbe,new yl(lt(ct(mO,1),De,369,0,[s]))),o=new Yz(z4),hD(t,Hbe,new yl(lt(ct(mO,1),De,369,0,[o]))),aat(r.c,Lv),aat(s.c,Py),aat(o.c,z4),aat(h.c,Fy),d.a.c=Nt(Qn,De,1,0,5,1),Ls(d.a,r.c),Ls(d.a,l2(s.c)),Ls(d.a,o.c),Ls(d.a,l2(h.c)),d}function kxt(t){var e;switch(t.d){case 1:{if(t.hj())return t.o!=-2;break}case 2:{if(t.hj())return t.o==-2;break}case 3:case 5:case 4:case 6:case 7:return t.o>-2;default:return!1}switch(e=t.gj(),t.p){case 0:return e!=null&&je(Re(e))!=u9(t.k,0);case 1:return e!=null&&u(e,217).a!=Ar(t.k)<<24>>24;case 2:return e!=null&&u(e,172).a!=(Ar(t.k)&ys);case 6:return e!=null&&u9(u(e,162).a,t.k);case 5:return e!=null&&u(e,19).a!=Ar(t.k);case 7:return e!=null&&u(e,184).a!=Ar(t.k)<<16>>16;case 3:return e!=null&&Xt(ye(e))!=t.j;case 4:return e!=null&&u(e,155).a!=t.j;default:return e==null?t.n!=null:!yi(e,t.n)}}function AI(t,e,n){var r,s,o,h;return t.Fk()&&t.Ek()&&(h=Wnt(t,u(n,56)),Vt(h)!==Vt(n))?(t.Oi(e),t.Ui(e,Ite(t,e,h)),t.rk()&&(o=(s=u(n,49),t.Dk()?t.Bk()?s.ih(t.b,no(u(yn(vu(t.b),t.aj()),18)).n,u(yn(vu(t.b),t.aj()).Yj(),26).Bj(),null):s.ih(t.b,Gi(s.Tg(),no(u(yn(vu(t.b),t.aj()),18))),null,null):s.ih(t.b,-1-t.aj(),null,null)),!u(h,49).eh()&&(o=(r=u(h,49),t.Dk()?t.Bk()?r.gh(t.b,no(u(yn(vu(t.b),t.aj()),18)).n,u(yn(vu(t.b),t.aj()).Yj(),26).Bj(),o):r.gh(t.b,Gi(r.Tg(),no(u(yn(vu(t.b),t.aj()),18))),null,o):r.gh(t.b,-1-t.aj(),null,o))),o&&o.Fi()),xl(t.b)&&t.$i(t.Zi(9,n,h,e,!1)),h):n}function nhe(t,e,n){var r,s,o,h,d,v,k,C,M,j,H,G,K,tt,gt,Mt,St,Rt;for(C=Xt(ye(Q(t,(Te(),jv)))),r=Xt(ye(Q(t,x9t))),j=new Yu,Jt(j,jv,C+r),k=e,gt=k.d,K=k.c.i,Mt=k.d.i,tt=o2t(K.c),St=o2t(Mt.c),s=new he,M=tt;M<=St;M++)d=new Y0(t),D0(d,(Vn(),ta)),Jt(d,(ae(),_i),k),Jt(d,cs,(ua(),Gc)),Jt(d,bG,j),H=u(Ne(t.b,M),29),M==tt?ly(d,H.a.c.length-n,H):Eo(d,H),Rt=Xt(ye(Q(k,Jg))),Rt<0&&(Rt=0,Jt(k,Jg,Rt)),d.o.b=Rt,G=b.Math.floor(Rt/2),h=new Mc,Bs(h,(ve(),Bn)),Uo(h,d),h.n.b=G,v=new Mc,Bs(v,Hn),Uo(v,d),v.n.b=G,oa(k,h),o=new Vw,Mo(o,k),Jt(o,So,null),Oa(o,v),oa(o,gt),mdn(d,k,o),s.c[s.c.length]=o,k=o;return s}function Bat(t,e){var n,r,s,o,h,d,v,k,C,M,j,H,G,K,tt,gt,Mt,St;for(v=u(Gg(t,(ve(),Bn)).Kc().Pb(),11).e,H=u(Gg(t,Hn).Kc().Pb(),11).g,d=v.c.length,St=_1(u(Ne(t.j,0),11));d-- >0;){for(K=(An(0,v.c.length),u(v.c[0],17)),s=(An(0,H.c.length),u(H.c[0],17)),Mt=s.d.e,o=Ro(Mt,s,0),Esn(K,s.d,o),Oa(s,null),oa(s,null),G=K.a,e&&ri(G,new xo(St)),r=ei(s.a,0);r.b!=r.d.c;)n=u(ti(r),8),ri(G,new xo(n));for(gt=K.b,j=new S(s.b);j.a0&&(h=b.Math.max(h,Mne(t.C.b+r.d.b,s))),C=r,M=s,j=o;t.C&&t.C.c>0&&(H=j+t.C.c,k&&(H+=C.d.c),h=b.Math.max(h,(k1(),wf(B1),b.Math.abs(M-1)<=B1||M==1||isNaN(M)&&isNaN(1)?0:H/(1-M)))),n.n.b=0,n.a.a=h}function ihe(t,e){var n,r,s,o,h,d,v,k,C,M,j,H;if(n=u(po(t.b,e),124),v=u(u(Ai(t.r,e),21),84),v.dc()){n.n.d=0,n.n.a=0;return}for(k=t.u.Hc((Zu(),sg)),h=0,t.A.Hc((Al(),K2))&&Bue(t,e),d=v.Kc(),C=null,j=0,M=0;d.Ob();)r=u(d.Pb(),111),o=Xt(ye(r.b.We((Cj(),uV)))),s=r.b.rf().b,C?(H=M+C.d.a+t.w+r.d.d,h=b.Math.max(h,(k1(),wf(B1),b.Math.abs(j-o)<=B1||j==o||isNaN(j)&&isNaN(o)?0:H/(o-j)))):t.C&&t.C.d>0&&(h=b.Math.max(h,Mne(t.C.d+r.d.d,o))),C=r,j=o,M=s;t.C&&t.C.a>0&&(H=M+t.C.a,k&&(H+=C.d.a),h=b.Math.max(h,(k1(),wf(B1),b.Math.abs(j-1)<=B1||j==1||isNaN(j)&&isNaN(1)?0:H/(1-j)))),n.n.d=0,n.a.b=h}function she(t,e,n){var r,s,o,h,d,v;for(this.g=t,d=e.d.length,v=n.d.length,this.d=Nt(l0,Yg,10,d+v,0,1),h=0;h0?lit(this,this.f/this.a):E1(e.g,e.d[0]).a!=null&&E1(n.g,n.d[0]).a!=null?lit(this,(Xt(E1(e.g,e.d[0]).a)+Xt(E1(n.g,n.d[0]).a))/2):E1(e.g,e.d[0]).a!=null?lit(this,E1(e.g,e.d[0]).a):E1(n.g,n.d[0]).a!=null&&lit(this,E1(n.g,n.d[0]).a)}function w4n(t,e){var n,r,s,o,h,d,v,k,C,M;for(t.a=new dXt(Ucn(XS)),r=new S(e.a);r.a=1&&(tt-h>0&&M>=0?(v.n.a+=K,v.n.b+=o*h):tt-h<0&&C>=0&&(v.n.a+=K*tt,v.n.b+=o));t.o.a=e.a,t.o.b=e.b,Jt(t,(Te(),$2),(Al(),r=u(Vf(rA),9),new sh(r,u(ff(r,r.length),9),0)))}function x4n(t,e,n,r,s,o){var h;if(!(e==null||!tst(e,nLt,rLt)))throw it(new Fn("invalid scheme: "+e));if(!t&&!(n!=null&&hd(n,Cu(35))==-1&&n.length>0&&(Rr(0,n.length),n.charCodeAt(0)!=47)))throw it(new Fn("invalid opaquePart: "+n));if(t&&!(e!=null&&yM(gU,e.toLowerCase()))&&!(n==null||!tst(n,oA,cA)))throw it(new Fn(S0e+n));if(t&&e!=null&&yM(gU,e.toLowerCase())&&!g0n(n))throw it(new Fn(S0e+n));if(!vhn(r))throw it(new Fn("invalid device: "+r));if(!hln(s))throw h=s==null?"invalid segments: null":"invalid segment: "+oln(s),it(new Fn(h));if(!(o==null||hd(o,Cu(35))==-1))throw it(new Fn("invalid query: "+o))}function k4n(t,e){var n,r,s,o,h,d,v,k,C,M,j,H,G,K,tt,gt;for(vr(e,"Calculate Graph Size",1),e.n&&t&&gf(e,pf(t),(Sl(),Ql)),d=VE,v=VE,o=Ukt,h=Ukt,M=new nr((!t.a&&(t.a=new fe(rs,t,10,11)),t.a));M.e!=M.i.gc();)k=u(dr(M),33),G=k.i,K=k.j,gt=k.g,r=k.f,s=u(qe(k,(ui(),JO)),142),d=b.Math.min(d,G-s.b),v=b.Math.min(v,K-s.d),o=b.Math.max(o,G+gt+s.c),h=b.Math.max(h,K+r+s.a);for(H=u(qe(t,(ui(),U2)),116),j=new $e(d-H.b,v-H.d),C=new nr((!t.a&&(t.a=new fe(rs,t,10,11)),t.a));C.e!=C.i.gc();)k=u(dr(C),33),ku(k,k.i-j.a),Eu(k,k.j-j.b);tt=o-d+(H.b+H.c),n=h-v+(H.d+H.a),tv(t,tt),Jw(t,n),e.n&&t&&gf(e,pf(t),(Sl(),Ql))}function che(t){var e,n,r,s,o,h,d,v,k,C;for(r=new he,h=new S(t.e.a);h.a0){Kz(t,n,0),n.a+=String.fromCharCode(r),s=ofn(e,o),Kz(t,n,s),o+=s-1;continue}r==39?o+11)for(K=Nt(Cr,Xr,25,t.b.b.c.length,15,1),M=0,k=new S(t.b.b);k.a=d&&s<=v)d<=s&&o<=v?(n[C++]=s,n[C++]=o,r+=2):d<=s?(n[C++]=s,n[C++]=v,t.b[r]=v+1,h+=2):o<=v?(n[C++]=d,n[C++]=o,r+=2):(n[C++]=d,n[C++]=v,t.b[r]=v+1);else if(vsb)&&d<10);ubt(t.c,new W5),uhe(t),hnn(t.c),m4n(t.f)}function _4n(t,e,n){var r,s,o,h,d,v,k,C,M,j,H,G,K,tt;if(je(Re(Q(n,(Te(),Hy)))))for(d=new S(n.j);d.a=2){for(v=ei(n,0),h=u(ti(v),8),d=u(ti(v),8);d.a0&&$D(k,!0,(ao(),Cf)),d.k==(Vn(),ks)&&NXt(k),ki(t.f,d,e)}}function M4n(t,e,n){var r,s,o,h,d,v,k,C,M,j;switch(vr(n,"Node promotion heuristic",1),t.g=e,N5n(t),t.q=u(Q(e,(Te(),oht)),260),C=u(Q(t.g,o9t),19).a,o=new pN,t.q.g){case 2:case 1:IE(t,o);break;case 3:for(t.q=(y4(),EG),IE(t,o),v=0,d=new S(t.a);d.at.j&&(t.q=FO,IE(t,o));break;case 4:for(t.q=(y4(),EG),IE(t,o),k=0,s=new S(t.b);s.at.k&&(t.q=NO,IE(t,o));break;case 6:j=ps(b.Math.ceil(t.f.length*C/100)),IE(t,new _p(j));break;case 5:M=ps(b.Math.ceil(t.d*C/100)),IE(t,new Hf(M));break;default:IE(t,o)}Evn(t,e),or(n)}function hhe(t,e,n){var r,s,o,h;this.j=t,this.e=_4t(t),this.o=this.j.e,this.i=!!this.o,this.p=this.i?u(Ne(n,Na(this.o).p),214):null,s=u(Q(t,(ae(),Vc)),21),this.g=s.Hc((oo(),vh)),this.b=new he,this.d=new Oie(this.e),h=u(Q(this.j,$6),230),this.q=cun(e,h,this.e),this.k=new PQt(this),o=A1(lt(ct(g2e,1),De,225,0,[this,this.d,this.k,this.q])),e==(ev(),RO)&&!je(Re(Q(t,(Te(),$y))))?(r=new A4t(this.e),o.c[o.c.length]=r,this.c=new rmt(r,h,u(this.q,402))):e==RO&&je(Re(Q(t,(Te(),$y))))?(r=new A4t(this.e),o.c[o.c.length]=r,this.c=new bne(r,h,u(this.q,402))):this.c=new gGt(e,this),le(o,this.c),Ule(o,this.e),this.s=fxn(this.k)}function D4n(t,e){var n,r,s,o,h,d,v,k,C,M,j,H,G,K,tt,gt,Mt,St,Rt;for(M=u(xj((h=ei(new Lp(e).a.d,0),new Ex(h))),86),G=M?u(Q(M,(fc(),Rht)),86):null,s=1;M&&G;){for(v=0,Rt=0,n=M,r=G,d=0;d=t.i?(++t.i,le(t.a,pe(1)),le(t.b,C)):(r=t.c[e.p][1],ch(t.a,k,pe(u(Ne(t.a,k),19).a+1-r)),ch(t.b,k,Xt(ye(Ne(t.b,k)))+C-r*t.e)),(t.q==(y4(),FO)&&(u(Ne(t.a,k),19).a>t.j||u(Ne(t.a,k-1),19).a>t.j)||t.q==NO&&(Xt(ye(Ne(t.b,k)))>t.k||Xt(ye(Ne(t.b,k-1)))>t.k))&&(v=!1),h=new ar(lr(jo(e).a.Kc(),new z));zr(h);)o=u(Mr(h),17),d=o.c.i,t.f[d.p]==k&&(M=fhe(t,d),s=s+u(M.a,19).a,v=v&&je(Re(M.b)));return t.f[e.p]=k,s=s+t.c[e.p][0],new fa(pe(s),(Nn(),!!v))}function Txt(t,e,n,r,s){var o,h,d,v,k,C,M,j,H,G,K,tt,gt;for(M=new _r,h=new he,Poe(t,n,t.d.fg(),h,M),Poe(t,r,t.d.gg(),h,M),t.b=.2*(K=Ece(Wo(new Tn(null,new _n(h,16)),new eZ)),tt=Ece(Wo(new Tn(null,new _n(h,16)),new nZ)),b.Math.min(K,tt)),o=0,d=0;d=2&&(gt=Gce(h,!0,j),!t.e&&(t.e=new K$t(t)),ufn(t.e,gt,h,t.b)),Cae(h,j),W4n(h),H=-1,C=new S(h);C.ad)}function O4n(t,e){var n,r,s,o,h,d,v,k,C,M,j,H,G,K;for(n=u(Q(t,(Te(),cs)),98),h=t.f,o=t.d,d=h.a+o.b+o.c,v=0-o.d-t.c.b,C=h.b+o.d+o.a-t.c.b,k=new he,M=new he,s=new S(e);s.a0),u(C.a.Xb(C.c=--C.b),17));o!=r&&C.b>0;)t.a[o.p]=!0,t.a[r.p]=!0,o=(Zn(C.b>0),u(C.a.Xb(C.c=--C.b),17));C.b>0&&Cl(C)}}function bhe(t,e,n){var r,s,o,h,d,v,k,C,M;if(t.a!=e.Aj())throw it(new Fn(QE+e.ne()+Cv));if(r=$g(($u(),ya),e).$k(),r)return r.Aj().Nh().Ih(r,n);if(h=$g(ya,e).al(),h){if(n==null)return null;if(d=u(n,15),d.dc())return"";for(M=new Ag,o=d.Kc();o.Ob();)s=o.Pb(),go(M,h.Aj().Nh().Ih(h,s)),M.a+=" ";return int(M,M.a.length-1)}if(C=$g(ya,e).bl(),!C.dc()){for(k=C.Kc();k.Ob();)if(v=u(k.Pb(),148),v.wj(n))try{if(M=v.Aj().Nh().Ih(v,n),M!=null)return M}catch(j){if(j=Wi(j),!_t(j,102))throw it(j)}throw it(new Fn("Invalid value: '"+n+"' for datatype :"+e.ne()))}return u(e,834).Fj(),n==null?null:_t(n,172)?""+u(n,172).a:ol(n)==tV?VUt(aA[0],u(n,199)):$o(n)}function j4n(t){var e,n,r,s,o,h,d,v,k,C;for(k=new Zi,d=new Zi,o=new S(t);o.a-1){for(s=ei(d,0);s.b!=s.d.c;)r=u(ti(s),128),r.v=h;for(;d.b!=0;)for(r=u(Dst(d,0),128),n=new S(r.i);n.a0&&(n+=v.n.a+v.o.a/2,++M),G=new S(v.j);G.a0&&(n/=M),gt=Nt(aa,vo,25,r.a.c.length,15,1),d=0,k=new S(r.a);k.a=d&&s<=v)d<=s&&o<=v?r+=2:d<=s?(t.b[r]=v+1,h+=2):o<=v?(n[C++]=s,n[C++]=d-1,r+=2):(n[C++]=s,n[C++]=d-1,t.b[r]=v+1,h+=2);else if(v0?s-=864e5:s+=864e5,v=new X2t(Pa(Tu(e.q.getTime()),s))),C=new Im,k=t.a.length,o=0;o=97&&r<=122||r>=65&&r<=90){for(h=o+1;h=k)throw it(new Fn("Missing trailing '"));h+10&&n.c==0&&(!e&&(e=new he),e.c[e.c.length]=n);if(e)for(;e.c.length!=0;){if(n=u(Fg(e,0),233),n.b&&n.b.c.length>0){for(o=(!n.b&&(n.b=new he),new S(n.b));o.aRo(t,n,0))return new fa(s,n)}else if(Xt(E1(s.g,s.d[0]).a)>Xt(E1(n.g,n.d[0]).a))return new fa(s,n)}for(d=(!n.e&&(n.e=new he),n.e).Kc();d.Ob();)h=u(d.Pb(),233),v=(!h.b&&(h.b=new he),h.b),Km(0,v.c.length),XC(v.c,0,n),h.c==v.c.length&&(e.c[e.c.length]=h)}return null}function xhe(t,e){var n,r,s,o,h,d,v,k,C;if(t==null)return _u;if(v=e.a.zc(t,e),v!=null)return"[...]";for(n=new f2(Ya,"[","]"),s=t,o=0,h=s.length;o=14&&C<=16))?e.a._b(r)?(n.a?Gr(n.a,n.b):n.a=new Ol(n.d),h9(n.a,"[...]")):(d=u2(r),k=new E9(e),$0(n,xhe(d,k))):_t(r,177)?$0(n,Npn(u(r,177))):_t(r,190)?$0(n,C0n(u(r,190))):_t(r,195)?$0(n,Fgn(u(r,195))):_t(r,2012)?$0(n,_0n(u(r,2012))):_t(r,48)?$0(n,Fpn(u(r,48))):_t(r,364)?$0(n,Kpn(u(r,364))):_t(r,832)?$0(n,Ppn(u(r,832))):_t(r,104)&&$0(n,Opn(u(r,104))):$0(n,r==null?_u:$o(r));return n.a?n.e.length==0?n.a.a:n.a.a+(""+n.e):n.c}function khe(t,e,n,r){var s,o,h,d,v,k,C,M,j,H,G,K,tt,gt,Mt,St;for(d=x4(e,!1,!1),gt=lI(d),r&&(gt=qD(gt)),St=Xt(ye(qe(e,(o_(),Qut)))),tt=(Zn(gt.b!=0),u(gt.a.a.c,8)),M=u(Zf(gt,1),8),gt.b>2?(C=new he,Ls(C,new Qd(gt,1,gt.b)),o=efe(C,St+t.a),Mt=new nat(o),Mo(Mt,e),n.c[n.c.length]=Mt):r?Mt=u(tr(t.b,e0(e)),266):Mt=u(tr(t.b,tb(e)),266),v=e0(e),r&&(v=tb(e)),h=epn(tt,v),k=St+t.a,h.a?(k+=b.Math.abs(tt.b-M.b),K=new $e(M.a,(M.b+tt.b)/2)):(k+=b.Math.abs(tt.a-M.a),K=new $e((M.a+tt.a)/2,M.b)),r?ki(t.d,e,new K3t(Mt,h,K,k)):ki(t.c,e,new K3t(Mt,h,K,k)),ki(t.b,e,Mt),G=(!e.n&&(e.n=new fe(qo,e,1,7)),e.n),H=new nr(G);H.e!=H.i.gc();)j=u(dr(H),137),s=xI(t,j,!0,0,0),n.c[n.c.length]=s}function W4n(t){var e,n,r,s,o,h,d,v,k,C;for(k=new he,d=new he,h=new S(t);h.a-1){for(o=new S(d);o.a0)&&(aR(v,b.Math.min(v.o,s.o-1)),TC(v,v.i-1),v.i==0&&(d.c[d.c.length]=v))}}function PE(t,e,n){var r,s,o,h,d,v,k;if(k=t.c,!e&&(e=oLt),t.c=e,t.Db&4&&!(t.Db&1)&&(v=new Js(t,1,2,k,t.c),n?n.Ei(v):n=v),k!=e){if(_t(t.Cb,284))t.Db>>16==-10?n=u(t.Cb,284).nk(e,n):t.Db>>16==-15&&(!e&&(e=(dn(),W1)),!k&&(k=(dn(),W1)),t.Cb.nh()&&(v=new z0(t.Cb,1,13,k,e,Hg(al(u(t.Cb,59)),t),!1),n?n.Ei(v):n=v));else if(_t(t.Cb,88))t.Db>>16==-23&&(_t(e,88)||(e=(dn(),Kh)),_t(k,88)||(k=(dn(),Kh)),t.Cb.nh()&&(v=new z0(t.Cb,1,10,k,e,Hg(Lc(u(t.Cb,26)),t),!1),n?n.Ei(v):n=v));else if(_t(t.Cb,444))for(d=u(t.Cb,836),h=(!d.b&&(d.b=new mR(new aet)),d.b),o=(r=new p2(new Cg(h.a).a),new yR(r));o.a.b;)s=u(Zw(o.a).cd(),87),n=PE(s,vq(s,d),n)}return n}function Y4n(t,e){var n,r,s,o,h,d,v,k,C,M,j;for(h=je(Re(qe(t,(Te(),Hy)))),j=u(qe(t,Gy),21),v=!1,k=!1,M=new nr((!t.c&&(t.c=new fe(gl,t,9,9)),t.c));M.e!=M.i.gc()&&(!v||!k);){for(o=u(dr(M),118),d=0,s=zp(D1(lt(ct(j1,1),De,20,0,[(!o.d&&(o.d=new Cn(Ys,o,8,5)),o.d),(!o.e&&(o.e=new Cn(Ys,o,7,4)),o.e)])));zr(s)&&(r=u(Mr(s),79),C=h&&fv(r)&&je(Re(qe(r,j2))),n=Jle((!r.b&&(r.b=new Cn(br,r,4,7)),r.b),o)?t==es(Do(u(At((!r.c&&(r.c=new Cn(br,r,5,8)),r.c),0),82))):t==es(Do(u(At((!r.b&&(r.b=new Cn(br,r,4,7)),r.b),0),82))),!((C||n)&&(++d,d>1))););(d>0||j.Hc((Zu(),sg))&&(!o.n&&(o.n=new fe(qo,o,1,7)),o.n).i>0)&&(v=!0),d>1&&(k=!0)}v&&e.Fc((oo(),vh)),k&&e.Fc((oo(),yS))}function Ehe(t){var e,n,r,s,o,h,d,v,k,C,M,j;if(j=u(qe(t,(ui(),G2)),21),j.dc())return null;if(d=0,h=0,j.Hc((Al(),oP))){for(C=u(qe(t,KS),98),r=2,n=2,s=2,o=2,e=es(t)?u(qe(es(t),qv),103):u(qe(t,qv),103),k=new nr((!t.c&&(t.c=new fe(gl,t,9,9)),t.c));k.e!=k.i.gc();)if(v=u(dr(k),118),M=u(qe(v,u5),61),M==(ve(),Zo)&&(M=uxt(v,e),wo(v,u5,M)),C==(ua(),Gc))switch(M.g){case 1:r=b.Math.max(r,v.i+v.g);break;case 2:n=b.Math.max(n,v.j+v.f);break;case 3:s=b.Math.max(s,v.i+v.g);break;case 4:o=b.Math.max(o,v.j+v.f)}else switch(M.g){case 1:r+=v.g+2;break;case 2:n+=v.f+2;break;case 3:s+=v.g+2;break;case 4:o+=v.f+2}d=b.Math.max(r,s),h=b.Math.max(n,o)}return wv(t,d,h,!0,!0)}function Rat(t,e,n,r,s){var o,h,d,v,k,C,M,j,H,G,K,tt,gt,Mt,St,Rt;for(Mt=u(Bl(ez(Ri(new Tn(null,new _n(e.d,16)),new t8(n)),new lM(n)),c2(new ke,new ce,new Xn,lt(ct(fl,1),oe,132,0,[(O1(),Ul)]))),15),M=wi,C=Sa,v=new S(e.b.j);v.a0,k?k&&(j=gt.p,h?++j:--j,M=u(Ne(gt.c.a,j),10),r=gre(M),H=!(cat(r,ue,n[0])||UKt(r,ue,n[0]))):H=!0),G=!1,Kt=e.D.i,Kt&&Kt.c&&d.e&&(C=h&&Kt.p>0||!h&&Kt.p0&&(e.a+=Ya),Nq(u(dr(d),160),e);for(e.a+=Uot,v=new Nx((!r.c&&(r.c=new Cn(br,r,5,8)),r.c));v.e!=v.i.gc();)v.e>0&&(e.a+=Ya),Nq(u(dr(v),160),e);e.a+=")"}}function t5n(t,e,n){var r,s,o,h,d,v,k,C,M,j,H;if(o=u(Q(t,(ae(),_i)),79),!!o){for(r=t.a,s=new xo(n),Li(s,Vdn(t)),J8(t.d.i,t.c.i)?(j=t.c,M=Yo(lt(ct(Ws,1),ee,8,0,[j.n,j.a])),ia(M,n)):M=_1(t.c),fs(r,M,r.a,r.a.a),H=_1(t.d),Q(t,Qlt)!=null&&Li(H,u(Q(t,Qlt),8)),fs(r,H,r.c.b,r.c),ny(r,s),h=x4(o,!0,!0),uz(h,u(At((!o.b&&(o.b=new Cn(br,o,4,7)),o.b),0),82)),lz(h,u(At((!o.c&&(o.c=new Cn(br,o,5,8)),o.c),0),82)),CI(r,h),C=new S(t.b);C.a=0){for(v=null,d=new da(C.a,k+1);d.bh?1:Iw(isNaN(0),isNaN(h)))<0&&(wf(_d),(b.Math.abs(h-1)<=_d||h==1||isNaN(h)&&isNaN(1)?0:h<1?-1:h>1?1:Iw(isNaN(h),isNaN(1)))<0)&&(wf(_d),(b.Math.abs(0-d)<=_d||d==0||isNaN(0)&&isNaN(d)?0:0d?1:Iw(isNaN(0),isNaN(d)))<0)&&(wf(_d),(b.Math.abs(d-1)<=_d||d==1||isNaN(d)&&isNaN(1)?0:d<1?-1:d>1?1:Iw(isNaN(d),isNaN(1)))<0)),o)}function n5n(t){var e,n,r,s,o,h,d,v,k,C,M,j,H,G,K,tt,gt,Mt,St,Rt,Kt,ue;for(M=new Svt(new Dt(t));M.b!=M.c.a.d;)for(C=Ate(M),d=u(C.d,56),e=u(C.e,56),h=d.Tg(),K=0,Rt=(h.i==null&&vd(h),h.i).length;K=0&&K=k.c.c.length?C=omt((Vn(),Os),ta):C=omt((Vn(),ta),ta),C*=2,o=n.a.g,n.a.g=b.Math.max(o,o+(C-o)),h=n.b.g,n.b.g=b.Math.max(h,h+(C-h)),s=e}}function s5n(t,e,n,r,s){var o,h,d,v,k,C,M,j,H,G,K,tt,gt,Mt,St,Rt,Kt;for(Kt=VYt(t),C=new he,d=t.c.length,M=d-1,j=d+1;Kt.a.c!=0;){for(;n.b!=0;)St=(Zn(n.b!=0),u(lh(n,n.a.a),112)),P9(Kt.a,St)!=null,St.g=M--,lxt(St,e,n,r);for(;e.b!=0;)Rt=(Zn(e.b!=0),u(lh(e,e.a.a),112)),P9(Kt.a,Rt)!=null,Rt.g=j++,lxt(Rt,e,n,r);for(k=Sa,gt=(h=new y9(new w9(new y(Kt.a).a).b),new g(h));TM(gt.a.a);){if(tt=(o=Lj(gt.a),u(o.cd(),112)),!r&&tt.b>0&&tt.a<=0){C.c=Nt(Qn,De,1,0,5,1),C.c[C.c.length]=tt;break}K=tt.i-tt.d,K>=k&&(K>k&&(C.c=Nt(Qn,De,1,0,5,1),k=K),C.c[C.c.length]=tt)}C.c.length!=0&&(v=u(Ne(C,Zz(s,C.c.length)),112),P9(Kt.a,v)!=null,v.g=j++,lxt(v,e,n,r),C.c=Nt(Qn,De,1,0,5,1))}for(Mt=t.c.length+1,G=new S(t);G.a0&&(j.d+=C.n.d,j.d+=C.d),j.a>0&&(j.a+=C.n.a,j.a+=C.d),j.b>0&&(j.b+=C.n.b,j.b+=C.d),j.c>0&&(j.c+=C.n.c,j.c+=C.d),j}function Che(t,e,n){var r,s,o,h,d,v,k,C,M,j,H,G;for(j=n.d,M=n.c,o=new $e(n.f.a+n.d.b+n.d.c,n.f.b+n.d.d+n.d.a),h=o.b,k=new S(t.a);k.a0&&(t.c[e.c.p][e.p].d+=ul(t.i,24)*$I*.07000000029802322-.03500000014901161,t.c[e.c.p][e.p].a=t.c[e.c.p][e.p].d/t.c[e.c.p][e.p].b)}}function d5n(t){var e,n,r,s,o,h,d,v,k,C,M,j,H,G,K,tt;for(G=new S(t);G.ar.d,r.d=b.Math.max(r.d,e),d&&n&&(r.d=b.Math.max(r.d,r.a),r.a=r.d+s);break;case 3:n=e>r.a,r.a=b.Math.max(r.a,e),d&&n&&(r.a=b.Math.max(r.a,r.d),r.d=r.a+s);break;case 2:n=e>r.c,r.c=b.Math.max(r.c,e),d&&n&&(r.c=b.Math.max(r.b,r.c),r.b=r.c+s);break;case 4:n=e>r.b,r.b=b.Math.max(r.b,e),d&&n&&(r.b=b.Math.max(r.b,r.c),r.c=r.b+s)}}}function w5n(t){var e,n,r,s,o,h,d,v,k,C,M;for(k=new S(t);k.a0||C.j==Bn&&C.e.c.length-C.g.c.length<0)){e=!1;break}for(s=new S(C.g);s.a=k&&Kt>=tt&&(j+=G.n.b+K.n.b+K.a.b-Rt,++d));if(n)for(h=new S(Mt.e);h.a=k&&Kt>=tt&&(j+=G.n.b+K.n.b+K.a.b-Rt,++d))}d>0&&(ue+=j/d,++H)}H>0?(e.a=s*ue/H,e.g=H):(e.a=0,e.g=0)}function m5n(t,e){var n,r,s,o,h,d,v,k,C,M,j;for(s=new S(t.a.b);s.aCs||e.o==H2&&C0&&ku(gt,Rt*ue),Kt>0&&Eu(gt,Kt*_e);for(K9(t.b,new hw),e=new he,d=new p2(new Cg(t.c).a);d.b;)h=Zw(d),r=u(h.cd(),79),n=u(h.dd(),395).a,s=x4(r,!1,!1),M=_ae(e0(r),lI(s),n),CI(M,s),St=Rae(r),St&&Ro(e,St,0)==-1&&(e.c[e.c.length]=St,VXt(St,(Zn(M.b!=0),u(M.a.a.c,8)),n));for(tt=new p2(new Cg(t.d).a);tt.b;)K=Zw(tt),r=u(K.cd(),79),n=u(K.dd(),395).a,s=x4(r,!1,!1),M=_ae(tb(r),qD(lI(s)),n),M=qD(M),CI(M,s),St=jae(r),St&&Ro(e,St,0)==-1&&(e.c[e.c.length]=St,VXt(St,(Zn(M.b!=0),u(M.c.b.c,8)),n))}function Ahe(t,e,n,r){var s,o,h,d,v,k,C,M,j,H,G,K,tt,gt,Mt,St,Rt,Kt,ue,_e;if(n.c.length!=0){for(H=new he,j=new S(n);j.a1)for(H=new vxt(G,St,r),va(St,new xGt(t,H)),h.c[h.c.length]=H,M=St.a.ec().Kc();M.Ob();)C=u(M.Pb(),46),mu(o,C.b);if(d.a.gc()>1)for(H=new vxt(G,d,r),va(d,new kGt(t,H)),h.c[h.c.length]=H,M=d.a.ec().Kc();M.Ob();)C=u(M.Pb(),46),mu(o,C.b)}}function Mhe(t){Mw(t,new k2(MR(_w(Ew(Cw(Tw(new kg,Sd),"ELK Radial"),'A radial layout provider which is based on the algorithm of Peter Eades published in "Drawing free trees.", published by International Institute for Advanced Study of Social Information Science, Fujitsu Limited in 1991. The radial layouter takes a tree and places the nodes in radial order around the root. The nodes of the same tree level are placed on the same radius.'),new dZ),Sd))),xe(t,Sd,yH,Ie(Qye)),xe(t,Sd,Cy,Ie(Zye)),xe(t,Sd,D4,Ie(Wye)),xe(t,Sd,C6,Ie(Yye)),xe(t,Sd,T6,Ie(Kye)),xe(t,Sd,UE,Ie(Uye)),xe(t,Sd,j_,Ie(L_t)),xe(t,Sd,WE,Ie(Xye)),xe(t,Sd,Pct,Ie(Wht)),xe(t,Sd,Oct,Ie(Yht)),xe(t,Sd,Zkt,Ie(M_t)),xe(t,Sd,Ykt,Ie(BG)),xe(t,Sd,Kkt,Ie(RG)),xe(t,Sd,Xkt,Ie(qO)),xe(t,Sd,Qkt,Ie(D_t))}function Sxt(t){var e;if(this.r=nrn(new bc,new Cc),this.b=new i_(u(Lr(Xa),290)),this.p=new i_(u(Lr(Xa),290)),this.i=new i_(u(Lr($pe),290)),this.e=t,this.o=new xo(t.rf()),this.D=t.Df()||je(Re(t.We((ui(),ZO)))),this.A=u(t.We((ui(),G2)),21),this.B=u(t.We(xb),21),this.q=u(t.We(KS),98),this.u=u(t.We(Qy),21),!ugn(this.u))throw it(new R3("Invalid port label placement: "+this.u));if(this.v=je(Re(t.We(uAt))),this.j=u(t.We(o5),21),!O2n(this.j))throw it(new R3("Invalid node label placement: "+this.j));this.n=u(l_(t,XSt),116),this.k=Xt(ye(l_(t,JG))),this.d=Xt(ye(l_(t,dAt))),this.w=Xt(ye(l_(t,vAt))),this.s=Xt(ye(l_(t,gAt))),this.t=Xt(ye(l_(t,pAt))),this.C=u(l_(t,bAt),142),this.c=2*this.d,e=!this.B.Hc((ll(),cP)),this.f=new a_(0,e,0),this.g=new a_(1,e,0),het(this.f,(Kf(),eu),this.g)}function A5n(t,e,n,r,s){var o,h,d,v,k,C,M,j,H,G,K,tt,gt,Mt,St,Rt,Kt,ue,_e,We,Qe,Rn;for(St=0,G=0,H=0,j=1,Mt=new nr((!t.a&&(t.a=new fe(rs,t,10,11)),t.a));Mt.e!=Mt.i.gc();)tt=u(dr(Mt),33),j+=j0(new ar(lr(K0(tt).a.Kc(),new z))),We=tt.g,G=b.Math.max(G,We),M=tt.f,H=b.Math.max(H,M),St+=We*M;for(K=(!t.a&&(t.a=new fe(rs,t,10,11)),t.a).i,h=St+2*r*r*j*K,o=b.Math.sqrt(h),v=b.Math.max(o*n,G),d=b.Math.max(o/n,H),gt=new nr((!t.a&&(t.a=new fe(rs,t,10,11)),t.a));gt.e!=gt.i.gc();)tt=u(dr(gt),33),Qe=s.b+(ul(e,26)*I_+ul(e,27)*O_)*(v-tt.g),Rn=s.b+(ul(e,26)*I_+ul(e,27)*O_)*(d-tt.f),ku(tt,Qe),Eu(tt,Rn);for(_e=v+(s.b+s.c),ue=d+(s.d+s.a),Kt=new nr((!t.a&&(t.a=new fe(rs,t,10,11)),t.a));Kt.e!=Kt.i.gc();)for(Rt=u(dr(Kt),33),C=new ar(lr(K0(Rt).a.Kc(),new z));zr(C);)k=u(Mr(C),79),w_(k)||Lxn(k,e,_e,ue);_e+=s.b+s.c,ue+=s.d+s.a,wv(t,_e,ue,!1,!0)}function Rq(t){var e,n,r,s,o,h,d,v,k,C,M;if(t==null)throw it(new ld(_u));if(k=t,o=t.length,v=!1,o>0&&(e=(Rr(0,t.length),t.charCodeAt(0)),(e==45||e==43)&&(t=t.substr(1),--o,v=e==45)),o==0)throw it(new ld(yv+k+'"'));for(;t.length>0&&(Rr(0,t.length),t.charCodeAt(0)==48);)t=t.substr(1),--o;if(o>(vle(),$ge)[10])throw it(new ld(yv+k+'"'));for(s=0;s0&&(M=-parseInt(t.substr(0,r),10),t=t.substr(r),o-=r,n=!1);o>=h;){if(r=parseInt(t.substr(0,h),10),t=t.substr(h),o-=h,n)n=!1;else{if(yc(M,d)<0)throw it(new ld(yv+k+'"'));M=_a(M,C)}M=Jp(M,r)}if(yc(M,0)>0)throw it(new ld(yv+k+'"'));if(!v&&(M=z8(M),yc(M,0)<0))throw it(new ld(yv+k+'"'));return M}function Axt(t,e){oKt();var n,r,s,o,h,d,v;if(this.a=new v2t(this),this.b=t,this.c=e,this.f=Xnt(To(($u(),ya),e)),this.f.dc())if((d=d4t(ya,t))==e)for(this.e=!0,this.d=new he,this.f=new Ok,this.f.Fc(O2),u(Pq(TD(ya,Rl(t)),""),26)==t&&this.f.Fc(C9(ya,Rl(t))),s=vat(ya,t).Kc();s.Ob();)switch(r=u(s.Pb(),170),Hw(To(ya,r))){case 4:{this.d.Fc(r);break}case 5:{this.f.Gc(Xnt(To(ya,r)));break}}else if(to(),u(e,66).Oj())for(this.e=!0,this.f=null,this.d=new he,h=0,v=(t.i==null&&vd(t),t.i).length;h=0&&h0&&(u(po(t.b,e),124).a.b=n)}function L5n(t,e){var n,r,s,o,h,d,v,k,C,M,j,H,G,K,tt,gt;for(vr(e,"Comment pre-processing",1),n=0,v=new S(t.a);v.a0&&(v=(Rr(0,e.length),e.charCodeAt(0)),v!=64)){if(v==37&&(M=e.lastIndexOf("%"),k=!1,M!=0&&(M==j-1||(k=(Rr(M+1,e.length),e.charCodeAt(M+1)==46))))){if(h=e.substr(1,M-1),St=hn("%",h)?null:Mxt(h),r=0,k)try{r=ql(e.substr(M+2),Sa,wi)}catch(Rt){throw Rt=Wi(Rt),_t(Rt,127)?(d=Rt,it(new W$(d))):it(Rt)}for(tt=lyt(t.Wg());tt.Ob();)if(G=kz(tt),_t(G,510)&&(s=u(G,590),Mt=s.d,(St==null?Mt==null:hn(St,Mt))&&r--==0))return s;return null}if(C=e.lastIndexOf("."),H=C==-1?e:e.substr(0,C),n=0,C!=-1)try{n=ql(e.substr(C+1),Sa,wi)}catch(Rt){if(Rt=Wi(Rt),_t(Rt,127))H=e;else throw it(Rt)}for(H=hn("%",H)?null:Mxt(H),K=lyt(t.Wg());K.Ob();)if(G=kz(K),_t(G,191)&&(o=u(G,191),gt=o.ne(),(H==null?gt==null:hn(H,gt))&&n--==0))return o;return null}return ehe(t,e)}function I5n(t){var e,n,r,s,o,h,d,v,k,C,M,j,H,G,K,tt,gt,Mt,St,Rt,Kt,ue,_e,We,Qe,Rn,zn;for(ue=new he,G=new S(t.b);G.a=e.length)return{done:!0};var s=e[r++];return{value:[s,n.get(s)],done:!1}}}},Bvn()||(t.prototype.createObject=function(){return{}},t.prototype.get=function(e){return this.obj[":"+e]},t.prototype.set=function(e,n){this.obj[":"+e]=n},t.prototype[kot]=function(e){delete this.obj[":"+e]},t.prototype.keys=function(){var e=[];for(var n in this.obj)n.charCodeAt(0)==58&&e.push(n.substring(1));return e}),t}function P5n(t){cxt();var e,n,r,s,o,h,d,v,k,C,M,j,H,G,K,tt;if(t==null)return null;if(M=t.length*8,M==0)return"";for(d=M%24,H=M/24|0,j=d!=0?H+1:H,o=null,o=Nt(xh,yd,25,j*4,15,1),k=0,C=0,e=0,n=0,r=0,h=0,s=0,v=0;v>24,k=(e&3)<<24>>24,G=e&-128?(e>>2^192)<<24>>24:e>>2<<24>>24,K=n&-128?(n>>4^240)<<24>>24:n>>4<<24>>24,tt=r&-128?(r>>6^252)<<24>>24:r>>6<<24>>24,o[h++]=lp[G],o[h++]=lp[K|k<<4],o[h++]=lp[C<<2|tt],o[h++]=lp[r&63];return d==8?(e=t[s],k=(e&3)<<24>>24,G=e&-128?(e>>2^192)<<24>>24:e>>2<<24>>24,o[h++]=lp[G],o[h++]=lp[k<<4],o[h++]=61,o[h++]=61):d==16&&(e=t[s],n=t[s+1],C=(n&15)<<24>>24,k=(e&3)<<24>>24,G=e&-128?(e>>2^192)<<24>>24:e>>2<<24>>24,K=n&-128?(n>>4^240)<<24>>24:n>>4<<24>>24,o[h++]=lp[G],o[h++]=lp[K|k<<4],o[h++]=lp[C<<2],o[h++]=61),Mh(o,0,o.length)}function F5n(t,e){var n,r,s,o,h,d,v;if(t.e==0&&t.p>0&&(t.p=-(t.p-1)),t.p>Sa&&umt(e,t.p-ab),h=e.q.getDate(),oD(e,1),t.k>=0&&win(e,t.k),t.c>=0?oD(e,t.c):t.k>=0?(v=new Myt(e.q.getFullYear()-ab,e.q.getMonth(),35),r=35-v.q.getDate(),oD(e,b.Math.min(r,h))):oD(e,h),t.f<0&&(t.f=e.q.getHours()),t.b>0&&t.f<12&&(t.f+=12),AQe(e,t.f==24&&t.g?0:t.f),t.j>=0&&Aan(e,t.j),t.n>=0&&Uan(e,t.n),t.i>=0&&aUt(e,Pa(_a(aI(Tu(e.q.getTime()),Wg),Wg),t.i)),t.a&&(s=new BR,umt(s,s.q.getFullYear()-ab-80),Cet(Tu(e.q.getTime()),Tu(s.q.getTime()))&&umt(e,s.q.getFullYear()-ab+100)),t.d>=0){if(t.c==-1)n=(7+t.d-e.q.getDay())%7,n>3&&(n-=7),d=e.q.getMonth(),oD(e,e.q.getDate()+n),e.q.getMonth()!=d&&oD(e,e.q.getDate()+(n>0?-7:7));else if(e.q.getDay()!=t.d)return!1}return t.o>Sa&&(o=e.q.getTimezoneOffset(),aUt(e,Pa(Tu(e.q.getTime()),(t.o-o)*60*Wg))),!0}function Ohe(t,e){var n,r,s,o,h,d,v,k,C,M,j,H,G,K,tt,gt,Mt,St,Rt;if(s=Q(e,(ae(),_i)),!!_t(s,239)){for(G=u(s,33),K=e.e,j=new xo(e.c),o=e.d,j.a+=o.b,j.b+=o.d,Rt=u(qe(G,(Te(),pG)),174),Nu(Rt,(ll(),nU))&&(H=u(qe(G,d9t),116),cpt(H,o.a),Mtt(H,o.d),upt(H,o.b),gpt(H,o.c)),n=new he,C=new S(e.a);C.a0&&le(t.p,C),le(t.o,C);e-=r,H=v+e,k+=e*t.e,ch(t.a,d,pe(H)),ch(t.b,d,k),t.j=b.Math.max(t.j,H),t.k=b.Math.max(t.k,k),t.d+=e,e+=K}}function ve(){ve=Z;var t;Zo=new NM(N_,0),Pn=new NM(Kq,1),Hn=new NM(Iot,2),mr=new NM(Oot,3),Bn=new NM(Pot,4),U1=(wn(),new s8((t=u(Vf(Xa),9),new sh(t,u(ff(t,t.length),9),0)))),Mf=jg(ji(Pn,lt(ct(Xa,1),xc,61,0,[]))),mh=jg(ji(Hn,lt(ct(Xa,1),xc,61,0,[]))),Kl=jg(ji(mr,lt(ct(Xa,1),xc,61,0,[]))),Vh=jg(ji(Bn,lt(ct(Xa,1),xc,61,0,[]))),Au=jg(ji(Pn,lt(ct(Xa,1),xc,61,0,[mr]))),lu=jg(ji(Hn,lt(ct(Xa,1),xc,61,0,[Bn]))),Df=jg(ji(Pn,lt(ct(Xa,1),xc,61,0,[Bn]))),el=jg(ji(Pn,lt(ct(Xa,1),xc,61,0,[Hn]))),Xl=jg(ji(mr,lt(ct(Xa,1),xc,61,0,[Bn]))),yh=jg(ji(Hn,lt(ct(Xa,1),xc,61,0,[mr]))),nl=jg(ji(Pn,lt(ct(Xa,1),xc,61,0,[Hn,Bn]))),Su=jg(ji(Hn,lt(ct(Xa,1),xc,61,0,[mr,Bn]))),Lu=jg(ji(Pn,lt(ct(Xa,1),xc,61,0,[mr,Bn]))),Vu=jg(ji(Pn,lt(ct(Xa,1),xc,61,0,[Hn,mr]))),Uc=jg(ji(Pn,lt(ct(Xa,1),xc,61,0,[Hn,mr,Bn])))}function Bhe(t,e){var n,r,s,o,h,d,v,k,C,M,j,H,G,K,tt,gt,Mt,St;if(e.b!=0){for(H=new Zi,d=null,G=null,r=ps(b.Math.floor(b.Math.log(e.b)*b.Math.LOG10E)+1),v=0,St=ei(e,0);St.b!=St.d.c;)for(gt=u(ti(St),86),Vt(G)!==Vt(Q(gt,(fc(),zS)))&&(G=Br(Q(gt,zS)),v=0),G!=null?d=G+iZt(v++,r):d=iZt(v++,r),Jt(gt,zS,d),tt=(s=ei(new Lp(gt).a.d,0),new Ex(s));OR(tt.a);)K=u(ti(tt.a),188).c,fs(H,K,H.c.b,H.c),Jt(K,zS,d);for(j=new _r,h=0;h=v){Zn(gt.b>0),gt.a.Xb(gt.c=--gt.b);break}else K.a>k&&(s?(Ls(s.b,K.b),s.a=b.Math.max(s.a,K.a),Cl(gt)):(le(K.b,M),K.c=b.Math.min(K.c,k),K.a=b.Math.max(K.a,v),s=K));s||(s=new kqt,s.c=k,s.a=v,zm(gt,s),le(s.b,M))}for(d=e.b,C=0,tt=new S(r);tt.ad?1:0:(t.b&&(t.b._b(o)&&(s=u(t.b.xc(o),19).a),t.b._b(v)&&(d=u(t.b.xc(v),19).a)),sd?1:0)):e.e.c.length!=0&&n.g.c.length!=0?1:-1}function j5n(t,e){var n,r,s,o,h,d,v,k,C,M,j,H,G,K,tt,gt,Mt,St,Rt,Kt,ue,_e;for(vr(e,S1e,1),K=new he,ue=new he,k=new S(t.b);k.a0&&(St-=H),mxt(h,St),C=0,j=new S(h.a);j.a0),d.a.Xb(d.c=--d.b)),v=.4*r*C,!o&&d.be.d.c){if(H=t.c[e.a.d],tt=t.c[M.a.d],H==tt)continue;yf(lf(uf(hf(cf(new Ch,1),100),H),tt))}}}}}function Mxt(t){Fat();var e,n,r,s,o,h,d,v;if(t==null)return null;if(s=hd(t,Cu(37)),s<0)return t;for(v=new Ol(t.substr(0,s)),e=Nt(Gu,N4,25,4,15,1),d=0,r=0,h=t.length;ss+2&&Sit((Rr(s+1,t.length),t.charCodeAt(s+1)),tLt,eLt)&&Sit((Rr(s+2,t.length),t.charCodeAt(s+2)),tLt,eLt))if(n=fen((Rr(s+1,t.length),t.charCodeAt(s+1)),(Rr(s+2,t.length),t.charCodeAt(s+2))),s+=2,r>0?(n&192)==128?e[d++]=n<<24>>24:r=0:n>=128&&((n&224)==192?(e[d++]=n<<24>>24,r=2):(n&240)==224?(e[d++]=n<<24>>24,r=3):(n&248)==240&&(e[d++]=n<<24>>24,r=4)),r>0){if(d==r){switch(d){case 2:{qp(v,((e[0]&31)<<6|e[1]&63)&ys);break}case 3:{qp(v,((e[0]&15)<<12|(e[1]&63)<<6|e[2]&63)&ys);break}}d=0,r=0}}else{for(o=0;o0){if(h+r>t.length)return!1;d=gq(t.substr(0,h+r),e)}else d=gq(t,e);switch(o){case 71:return d=w4(t,h,lt(ct(Ae,1),ee,2,6,[mfe,yfe]),e),s.e=d,!0;case 77:return _vn(t,e,s,d,h);case 76:return Svn(t,e,s,d,h);case 69:return vpn(t,e,h,s);case 99:return mpn(t,e,h,s);case 97:return d=w4(t,h,lt(ct(Ae,1),ee,2,6,["AM","PM"]),e),s.b=d,!0;case 121:return Avn(t,e,h,d,n,s);case 100:return d<=0?!1:(s.c=d,!0);case 83:return d<0?!1:Ihn(d,h,e[0],s);case 104:d==12&&(d=0);case 75:case 72:return d<0?!1:(s.f=d,s.g=!1,!0);case 107:return d<0?!1:(s.f=d,s.g=!0,!0);case 109:return d<0?!1:(s.j=d,!0);case 115:return d<0?!1:(s.n=d,!0);case 90:if(hue&&(G.c=ue-G.b),le(h.d,new Hnt(G,a3t(h,G))),Mt=e==Pn?b.Math.max(Mt,K.b+k.b.rf().b):b.Math.min(Mt,K.b));for(Mt+=e==Pn?t.t:-t.t,St=k3t((h.e=Mt,h)),St>0&&(u(po(t.b,e),124).a.b=St),C=j.Kc();C.Ob();)k=u(C.Pb(),111),!(!k.c||k.c.d.c.length<=0)&&(G=k.c.i,G.c-=k.e.a,G.d-=k.e.b)}function U5n(t){var e,n,r,s,o,h,d,v,k,C,M,j,H;for(e=new _r,v=new nr(t);v.e!=v.i.gc();){for(d=u(dr(v),33),n=new Hs,ki(Jut,d,n),H=new bm,s=u(Bl(new Tn(null,new jw(new ar(lr(wI(d).a.Kc(),new z)))),LKt(H,c2(new ke,new ce,new Xn,lt(ct(fl,1),oe,132,0,[(O1(),Ul)])))),83),Zee(n,u(s.xc((Nn(),!0)),14),new Ek),r=u(Bl(Ri(u(s.xc(!1),15).Lc(),new E3),c2(new ke,new ce,new Xn,lt(ct(fl,1),oe,132,0,[Ul]))),15),h=r.Kc();h.Ob();)o=u(h.Pb(),79),j=Rae(o),j&&(k=u(ec(Lo(e.f,j)),21),k||(k=iue(j),au(e.f,j,k)),Ua(n,k));for(s=u(Bl(new Tn(null,new jw(new ar(lr(K0(d).a.Kc(),new z)))),LKt(H,c2(new ke,new ce,new Xn,lt(ct(fl,1),oe,132,0,[Ul])))),83),Zee(n,u(s.xc(!0),14),new Il),r=u(Bl(Ri(u(s.xc(!1),15).Lc(),new L0),c2(new ke,new ce,new Xn,lt(ct(fl,1),oe,132,0,[Ul]))),15),M=r.Kc();M.Ob();)C=u(M.Pb(),79),j=jae(C),j&&(k=u(ec(Lo(e.f,j)),21),k||(k=iue(j),au(e.f,j,k)),Ua(n,k))}}function W5n(t,e){Lat();var n,r,s,o,h,d,v,k,C,M,j,H,G,K;if(v=yc(t,0)<0,v&&(t=z8(t)),yc(t,0)==0)switch(e){case 0:return"0";case 1:return $E;case 2:return"0.00";case 3:return"0.000";case 4:return"0.0000";case 5:return"0.00000";case 6:return"0.000000";default:return H=new Mp,e<0?H.a+="0E+":H.a+="0E",H.a+=e==Sa?"2147483648":""+-e,H.a}C=18,M=Nt(xh,yd,25,C+1,15,1),n=C,K=t;do k=K,K=aI(K,10),M[--n]=Ar(Pa(48,Jp(k,_a(K,10))))&ys;while(yc(K,0)!=0);if(s=Jp(Jp(Jp(C,n),e),1),e==0)return v&&(M[--n]=45),Mh(M,n,C-n);if(e>0&&yc(s,-6)>=0){if(yc(s,0)>=0){for(o=n+Ar(s),d=C-1;d>=o;d--)M[d+1]=M[d];return M[++o]=46,v&&(M[--n]=45),Mh(M,n,C-n+1)}for(h=2;Cet(h,Pa(z8(s),1));h++)M[--n]=48;return M[--n]=46,M[--n]=48,v&&(M[--n]=45),Mh(M,n,C-n)}return G=n+1,r=C,j=new Im,v&&(j.a+="-"),r-G>=1?(qp(j,M[n]),j.a+=".",j.a+=Mh(M,n+1,C-n-1)):j.a+=Mh(M,n,C-n),j.a+="E",yc(s,0)>0&&(j.a+="+"),j.a+=""+_9(s),j.a}function Y5n(t,e,n){var r,s,o,h,d,v,k,C,M,j,H;if(t.e.a.$b(),t.f.a.$b(),t.c.c=Nt(Qn,De,1,0,5,1),t.i.c=Nt(Qn,De,1,0,5,1),t.g.a.$b(),e)for(h=new S(e.a);h.a=1&&(Kt-k>0&&G>=0?(ku(M,M.i+Rt),Eu(M,M.j+v*k)):Kt-k<0&&H>=0&&(ku(M,M.i+Rt*Kt),Eu(M,M.j+v)));return wo(t,(ui(),G2),(Al(),o=u(Vf(rA),9),new sh(o,u(ff(o,o.length),9),0))),new $e(ue,C)}function $he(t){var e,n,r,s,o,h,d,v,k,C,M,j,H,G;if(H=es(Do(u(At((!t.b&&(t.b=new Cn(br,t,4,7)),t.b),0),82))),G=es(Do(u(At((!t.c&&(t.c=new Cn(br,t,5,8)),t.c),0),82))),M=H==G,d=new Ca,e=u(qe(t,(Sz(),_At)),74),e&&e.b>=2){if((!t.a&&(t.a=new fe(Ji,t,6,6)),t.a).i==0)n=(Sw(),s=new ad,s),Dr((!t.a&&(t.a=new fe(Ji,t,6,6)),t.a),n);else if((!t.a&&(t.a=new fe(Ji,t,6,6)),t.a).i>1)for(j=new Nx((!t.a&&(t.a=new fe(Ji,t,6,6)),t.a));j.e!=j.i.gc();)f_(j);CI(e,u(At((!t.a&&(t.a=new fe(Ji,t,6,6)),t.a),0),202))}if(M)for(r=new nr((!t.a&&(t.a=new fe(Ji,t,6,6)),t.a));r.e!=r.i.gc();)for(n=u(dr(r),202),k=new nr((!n.a&&(n.a=new As(Gh,n,5)),n.a));k.e!=k.i.gc();)v=u(dr(k),469),d.a=b.Math.max(d.a,v.a),d.b=b.Math.max(d.b,v.b);for(h=new nr((!t.n&&(t.n=new fe(qo,t,1,7)),t.n));h.e!=h.i.gc();)o=u(dr(h),137),C=u(qe(o,QS),8),C&&x1(o,C.a,C.b),M&&(d.a=b.Math.max(d.a,o.i+o.g),d.b=b.Math.max(d.b,o.j+o.f));return d}function K5n(t,e,n){var r,s,o,h,d,v,k,C,M,j,H,G,K,tt,gt,Mt,St,Rt,Kt,ue,_e,We;for(St=e.c.length,s=new E4(t.a,n,null,null),We=Nt(aa,vo,25,St,15,1),K=Nt(aa,vo,25,St,15,1),G=Nt(aa,vo,25,St,15,1),tt=0,d=0;dWe[v]&&(tt=v),M=new S(t.a.b);M.aH&&(o&&(Zb(ue,j),Zb(We,pe(k.b-1))),pi=n.b,js+=j+e,j=0,C=b.Math.max(C,n.b+n.c+hr)),ku(d,pi),Eu(d,js),C=b.Math.max(C,pi+hr+n.c),j=b.Math.max(j,M),pi+=hr+e;if(C=b.Math.max(C,r),zn=js+j+n.a,znEd,Qe=b.Math.abs(j.b-G.b)>Ed,(!n&&We&&Qe||n&&(We||Qe))&&ri(tt.a,Rt)),Ua(tt.a,r),r.b==0?j=Rt:j=(Zn(r.b!=0),u(r.c.b.c,8)),dun(H,M,K),Lne(s)==_e&&(Na(_e.i)!=s.a&&(K=new Ca,Y4t(K,Na(_e.i),Mt)),Jt(tt,Qlt,K)),Bgn(H,tt,Mt),C.a.zc(H,C);Oa(tt,Kt),oa(tt,_e)}for(k=C.a.ec().Kc();k.Ob();)v=u(k.Pb(),17),Oa(v,null),oa(v,null);or(e)}function zhe(t){var e,n,r,s,o,h,d,v,k,C,M,j,H,G,K,tt,gt,Mt,St,Rt;if(t.gc()==1)return u(t.Xb(0),231);if(t.gc()<=0)return new B$;for(s=t.Kc();s.Ob();){for(n=u(s.Pb(),231),G=0,C=wi,M=wi,v=Sa,k=Sa,H=new S(n.e);H.ad&&(St=0,Rt+=h+gt,h=0),Fmn(K,n,St,Rt),e=b.Math.max(e,St+tt.a),h=b.Math.max(h,tt.b),St+=tt.a+gt;return K}function qhe(t,e){var n,r,s,o,h,d,v,k,C,M,j,H,G;switch(C=new Pu,t.a.g){case 3:j=u(Q(e.e,(ae(),R2)),15),H=u(Q(e.j,R2),15),G=u(Q(e.f,R2),15),n=u(Q(e.e,Z4),15),r=u(Q(e.j,Z4),15),s=u(Q(e.f,Z4),15),h=new he,Ls(h,j),H.Jc(new cQ),Ls(h,_t(H,152)?Zx(u(H,152)):_t(H,131)?u(H,131).a:_t(H,54)?new kw(H):new Om(H)),Ls(h,G),o=new he,Ls(o,n),Ls(o,_t(r,152)?Zx(u(r,152)):_t(r,131)?u(r,131).a:_t(r,54)?new kw(r):new Om(r)),Ls(o,s),Jt(e.f,R2,h),Jt(e.f,Z4,o),Jt(e.f,hCt,e.f),Jt(e.e,R2,null),Jt(e.e,Z4,null),Jt(e.j,R2,null),Jt(e.j,Z4,null);break;case 1:Ua(C,e.e.a),ri(C,e.i.n),Ua(C,l2(e.j.a)),ri(C,e.a.n),Ua(C,e.f.a);break;default:Ua(C,e.e.a),Ua(C,l2(e.j.a)),Ua(C,e.f.a)}Ah(e.f.a),Ua(e.f.a,C),Oa(e.f,e.e.c),d=u(Q(e.e,(Te(),So)),74),k=u(Q(e.j,So),74),v=u(Q(e.f,So),74),(d||k||v)&&(M=new Pu,wvt(M,v),wvt(M,k),wvt(M,d),Jt(e.f,So,M)),Oa(e.j,null),oa(e.j,null),Oa(e.e,null),oa(e.e,null),Eo(e.a,null),Eo(e.i,null),e.g&&qhe(t,e.g)}function J5n(t){cxt();var e,n,r,s,o,h,d,v,k,C,M,j,H,G,K,tt;if(t==null||(o=K$(t),G=$ln(o),G%4!=0))return null;if(K=G/4|0,K==0)return Nt(Gu,N4,25,0,15,1);for(M=null,e=0,n=0,r=0,s=0,h=0,d=0,v=0,k=0,H=0,j=0,C=0,M=Nt(Gu,N4,25,K*3,15,1);H>4)<<24>>24,M[j++]=((n&15)<<4|r>>2&15)<<24>>24,M[j++]=(r<<6|s)<<24>>24}return!vM(h=o[C++])||!vM(d=o[C++])?null:(e=Y1[h],n=Y1[d],v=o[C++],k=o[C++],Y1[v]==-1||Y1[k]==-1?v==61&&k==61?n&15?null:(tt=Nt(Gu,N4,25,H*3+1,15,1),Dc(M,0,tt,0,H*3),tt[j]=(e<<2|n>>4)<<24>>24,tt):v!=61&&k==61?(r=Y1[v],r&3?null:(tt=Nt(Gu,N4,25,H*3+2,15,1),Dc(M,0,tt,0,H*3),tt[j++]=(e<<2|n>>4)<<24>>24,tt[j]=((n&15)<<4|r>>2&15)<<24>>24,tt)):null:(r=Y1[v],s=Y1[k],M[j++]=(e<<2|n>>4)<<24>>24,M[j++]=((n&15)<<4|r>>2&15)<<24>>24,M[j++]=(r<<6|s)<<24>>24,M))}function txn(t,e){var n,r,s,o,h,d,v,k,C,M,j,H,G,K,tt,gt,Mt,St,Rt,Kt;for(vr(e,S1e,1),G=u(Q(t,(Te(),eg)),218),s=new S(t.b);s.a=2){for(K=!0,j=new S(o.j),n=u(J(j),11),H=null;j.a0&&(s=u(Ne(tt.c.a,ue-1),10),h=t.i[s.p],We=b.Math.ceil(W3(t.n,s,tt)),o=Kt.a.e-tt.d.d-(h.a.e+s.o.b+s.d.a)-We),k=as,ue0&&_e.a.e.e-_e.a.a-(_e.b.e.e-_e.b.a)<0,G=St.a.e.e-St.a.a-(St.b.e.e-St.b.a)<0&&_e.a.e.e-_e.a.a-(_e.b.e.e-_e.b.a)>0,H=St.a.e.e+St.b.a<_e.b.e.e+_e.a.a,j=St.a.e.e+St.b.a>_e.b.e.e+_e.a.a,Rt=0,!K&&!G&&(j?o+M>0?Rt=M:k-r>0&&(Rt=r):H&&(o+d>0?Rt=d:k-Mt>0&&(Rt=Mt))),Kt.a.e+=Rt,Kt.b&&(Kt.d.e+=Rt),!1))}function Vhe(t,e,n){var r,s,o,h,d,v,k,C,M,j;if(r=new ah(e.qf().a,e.qf().b,e.rf().a,e.rf().b),s=new Fx,t.c)for(h=new S(e.wf());h.ak&&(r.a+=KUt(Nt(xh,yd,25,-k,15,1))),r.a+="Is",hd(v,Cu(32))>=0)for(s=0;s=r.o.b/2}else Mt=!M;Mt?(gt=u(Q(r,(ae(),z6)),15),gt?j?o=gt:(s=u(Q(r,N6),15),s?gt.gc()<=s.gc()?o=gt:o=s:(o=new he,Jt(r,N6,o))):(o=new he,Jt(r,z6,o))):(s=u(Q(r,(ae(),N6)),15),s?M?o=s:(gt=u(Q(r,z6),15),gt?s.gc()<=gt.gc()?o=s:o=gt:(o=new he,Jt(r,z6,o))):(o=new he,Jt(r,N6,o))),o.Fc(t),Jt(t,(ae(),ZV),n),e.d==n?(oa(e,null),n.e.c.length+n.g.c.length==0&&Uo(n,null),Yun(n)):(Oa(e,null),n.e.c.length+n.g.c.length==0&&Uo(n,null)),Ah(e.a)}function ixn(t,e){var n,r,s,o,h,d,v,k,C,M,j,H,G,K,tt,gt,Mt,St,Rt,Kt,ue,_e,We,Qe,Rn,zn,hr,pi;for(Mt=new da(t.b,0),C=e.Kc(),G=0,k=u(C.Pb(),19).a,Kt=0,n=new Hs,_e=new O0;Mt.b=t.a&&(r=Hyn(t,Mt),C=b.Math.max(C,r.b),Rt=b.Math.max(Rt,r.d),le(d,new fa(Mt,r)));for(We=new he,k=0;k0),tt.a.Xb(tt.c=--tt.b),Qe=new Sh(t.b),zm(tt,Qe),Zn(tt.b0?(k=0,tt&&(k+=d),k+=(Qe-1)*h,St&&(k+=d),We&&St&&(k=b.Math.max(k,qwn(St,h,Mt,_e))),k0){for(j=C<100?null:new Dp(C),k=new gyt(e),G=k.g,gt=Nt(Cr,Xr,25,C,15,1),r=0,Rt=new Qw(C),s=0;s=0;)if(H!=null?yi(H,G[v]):Vt(H)===Vt(G[v])){gt.length<=r&&(tt=gt,gt=Nt(Cr,Xr,25,2*gt.length,15,1),Dc(tt,0,gt,0,r)),gt[r++]=s,Dr(Rt,G[v]);break t}if(H=H,Vt(H)===Vt(d))break}}if(k=Rt,G=Rt.g,C=r,r>gt.length&&(tt=gt,gt=Nt(Cr,Xr,25,r,15,1),Dc(tt,0,gt,0,r)),r>0){for(St=!0,o=0;o=0;)l6(t,gt[h]);if(r!=C){for(s=C;--s>=r;)l6(k,s);tt=gt,gt=Nt(Cr,Xr,25,r,15,1),Dc(tt,0,gt,0,r)}e=k}}}else for(e=$1n(t,e),s=t.i;--s>=0;)e.Hc(t.g[s])&&(l6(t,s),St=!0);if(St){if(gt!=null){for(n=e.gc(),M=n==1?F9(t,4,e.Kc().Pb(),null,gt[0],K):F9(t,6,e,gt,gt[0],K),j=n<100?null:new Dp(n),s=e.Kc();s.Ob();)H=s.Pb(),j=vwt(t,u(H,72),j);j?(j.Ei(M),j.Fi()):mi(t.e,M)}else{for(j=JZe(e.gc()),s=e.Kc();s.Ob();)H=s.Pb(),j=vwt(t,u(H,72),j);j&&j.Fi()}return!0}else return!1}function uxn(t,e){var n,r,s,o,h,d,v,k,C,M,j,H,G,K,tt,gt,Mt,St;for(n=new vse(e),n.a||Umn(e),k=Wvn(e),v=new Uw,tt=new fue,K=new S(e.a);K.a0||n.o==H1&&s0?(M=u(Ne(j.c.a,h-1),10),We=W3(t.b,j,M),tt=j.n.b-j.d.d-(M.n.b+M.o.b+M.d.a+We)):tt=j.n.b-j.d.d,k=b.Math.min(tt,k),hh?LE(t,e,n):LE(t,n,e),sh?1:0}return r=u(Q(e,(ae(),Tc)),19).a,o=u(Q(n,Tc),19).a,r>o?LE(t,e,n):LE(t,n,e),ro?1:0}function Dxt(t,e,n,r){var s,o,h,d,v,k,C,M,j,H,G,K,tt,gt,Mt;if(je(Re(qe(e,(ui(),QG)))))return wn(),wn(),io;if(k=(!e.a&&(e.a=new fe(rs,e,10,11)),e.a).i!=0,M=Qpn(e),C=!M.dc(),k||C){if(s=u(qe(e,O7),149),!s)throw it(new R3("Resolved algorithm is not set; apply a LayoutAlgorithmResolver before computing layout."));if(Mt=t2t(s,(CE(),lU)),Jie(e),!k&&C&&!Mt)return wn(),wn(),io;if(v=new he,Vt(qe(e,s5))===Vt((G0(),sp))&&(t2t(s,cU)||t2t(s,oU)))for(H=Fue(t,e),G=new Zi,Ua(G,(!e.a&&(e.a=new fe(rs,e,10,11)),e.a));G.b!=0;)j=u(G.b==0?null:(Zn(G.b!=0),lh(G,G.a.a)),33),Jie(j),gt=Vt(qe(j,s5))===Vt(ZS),gt||o2(j,YS)&&!gmt(s,qe(j,O7))?(d=Dxt(t,j,n,r),Ls(v,d),wo(j,s5,ZS),Zue(j)):Ua(G,(!j.a&&(j.a=new fe(rs,j,10,11)),j.a));else for(H=(!e.a&&(e.a=new fe(rs,e,10,11)),e.a).i,h=new nr((!e.a&&(e.a=new fe(rs,e,10,11)),e.a));h.e!=h.i.gc();)o=u(dr(h),33),d=Dxt(t,o,n,r),Ls(v,d),Zue(o);for(tt=new S(v);tt.a=0?H=a6(d):H=YD(a6(d)),t.Ye(C7,H)),k=new Ca,j=!1,t.Xe(Rv)?(H2t(k,u(t.We(Rv),8)),j=!0):RQe(k,h.a/2,h.b/2),H.g){case 4:Jt(C,uu,(dh(),bb)),Jt(C,tG,(d2(),U4)),C.o.b=h.b,K<0&&(C.o.a=-K),Bs(M,(ve(),Hn)),j||(k.a=h.a),k.a-=h.a;break;case 2:Jt(C,uu,(dh(),jy)),Jt(C,tG,(d2(),w7)),C.o.b=h.b,K<0&&(C.o.a=-K),Bs(M,(ve(),Bn)),j||(k.a=0);break;case 1:Jt(C,B2,(q0(),Y4)),C.o.a=h.a,K<0&&(C.o.b=-K),Bs(M,(ve(),mr)),j||(k.b=h.b),k.b-=h.b;break;case 3:Jt(C,B2,(q0(),F6)),C.o.a=h.a,K<0&&(C.o.b=-K),Bs(M,(ve(),Pn)),j||(k.b=0)}if(H2t(M.n,k),Jt(C,Rv,k),e==Y2||e==g0||e==Gc){if(G=0,e==Y2&&t.Xe(tp))switch(H.g){case 1:case 2:G=u(t.We(tp),19).a;break;case 3:case 4:G=-u(t.We(tp),19).a}else switch(H.g){case 4:case 2:G=o.b,e==g0&&(G/=s.b);break;case 1:case 3:G=o.a,e==g0&&(G/=s.a)}Jt(C,Fv,G)}return Jt(C,oc,H),C}function fxn(t){var e,n,r,s,o,h,d,v,k,C,M,j,H,G,K,tt,gt,Mt,St,Rt,Kt,ue,_e,We,Qe;if(n=Xt(ye(Q(t.a.j,(Te(),GCt)))),n<-1||!t.a.i||jx(u(Q(t.a.o,cs),98))||Ko(t.a.o,(ve(),Hn)).gc()<2&&Ko(t.a.o,Bn).gc()<2)return!0;if(t.a.c.Rf())return!1;for(Kt=0,Rt=0,St=new he,v=t.a.e,k=0,C=v.length;k=n}function dxn(){dbt();function t(r){var s=this;this.dispatch=function(o){var h=o.data;switch(h.cmd){case"algorithms":var d=x3t((wn(),new T(new v1(Ab.b))));r.postMessage({id:h.id,data:d});break;case"categories":var v=x3t((wn(),new T(new v1(Ab.c))));r.postMessage({id:h.id,data:v});break;case"options":var k=x3t((wn(),new T(new v1(Ab.d))));r.postMessage({id:h.id,data:k});break;case"register":y4n(h.algorithms),r.postMessage({id:h.id});break;case"layout":t3n(h.graph,h.layoutOptions||{},h.options||{}),r.postMessage({id:h.id,data:h.graph});break}},this.saveDispatch=function(o){try{s.dispatch(o)}catch(h){r.postMessage({id:o.data.id,error:h})}}}function e(r){var s=this;this.dispatcher=new t({postMessage:function(o){s.onmessage({data:o})}}),this.postMessage=function(o){setTimeout(function(){s.dispatcher.saveDispatch({data:o})},0)}}if(typeof document===_ot&&typeof self!==_ot){var n=new t(self);self.onmessage=n.saveDispatch}else typeof p!==_ot&&p.exports&&(Object.defineProperty(w,"__esModule",{value:!0}),p.exports={default:e,Worker:e})}function gxn(t){t.N||(t.N=!0,t.b=ic(t,0),ns(t.b,0),ns(t.b,1),ns(t.b,2),t.bb=ic(t,1),ns(t.bb,0),ns(t.bb,1),t.fb=ic(t,2),ns(t.fb,3),ns(t.fb,4),Fi(t.fb,5),t.qb=ic(t,3),ns(t.qb,0),Fi(t.qb,1),Fi(t.qb,2),ns(t.qb,3),ns(t.qb,4),Fi(t.qb,5),ns(t.qb,6),t.a=oi(t,4),t.c=oi(t,5),t.d=oi(t,6),t.e=oi(t,7),t.f=oi(t,8),t.g=oi(t,9),t.i=oi(t,10),t.j=oi(t,11),t.k=oi(t,12),t.n=oi(t,13),t.o=oi(t,14),t.p=oi(t,15),t.q=oi(t,16),t.s=oi(t,17),t.r=oi(t,18),t.t=oi(t,19),t.u=oi(t,20),t.v=oi(t,21),t.w=oi(t,22),t.B=oi(t,23),t.A=oi(t,24),t.C=oi(t,25),t.D=oi(t,26),t.F=oi(t,27),t.G=oi(t,28),t.H=oi(t,29),t.J=oi(t,30),t.I=oi(t,31),t.K=oi(t,32),t.M=oi(t,33),t.L=oi(t,34),t.P=oi(t,35),t.Q=oi(t,36),t.R=oi(t,37),t.S=oi(t,38),t.T=oi(t,39),t.U=oi(t,40),t.V=oi(t,41),t.X=oi(t,42),t.W=oi(t,43),t.Y=oi(t,44),t.Z=oi(t,45),t.$=oi(t,46),t._=oi(t,47),t.ab=oi(t,48),t.cb=oi(t,49),t.db=oi(t,50),t.eb=oi(t,51),t.gb=oi(t,52),t.hb=oi(t,53),t.ib=oi(t,54),t.jb=oi(t,55),t.kb=oi(t,56),t.lb=oi(t,57),t.mb=oi(t,58),t.nb=oi(t,59),t.ob=oi(t,60),t.pb=oi(t,61))}function pxn(t,e){var n,r,s,o,h,d,v,k,C,M,j,H,G,K,tt,gt,Mt,St,Rt;if(Mt=0,e.f.a==0)for(tt=new S(t);tt.ak&&(An(k,e.c.length),u(e.c[k],200)).a.c.length==0;)mu(e,(An(k,e.c.length),e.c[k]));if(!v){--o;continue}if(eyn(e,C,s,v,j,n,k,r)){M=!0;continue}if(j){if(c3n(e,C,s,v,n,k,r)){M=!0;continue}else if(Yyt(C,s)){s.c=!0,M=!0;continue}}else if(Yyt(C,s)){s.c=!0,M=!0;continue}if(M)continue}if(Yyt(C,s)){s.c=!0,M=!0,v&&(v.k=!1);continue}else nq(s.q)}return M}function zat(t,e,n,r,s,o,h){var d,v,k,C,M,j,H,G,K,tt,gt,Mt,St,Rt,Kt,ue,_e,We,Qe,Rn,zn,hr,pi,js;for(K=0,Rn=0,k=new S(t.b);k.aK&&(o&&(Zb(ue,H),Zb(We,pe(C.b-1)),le(t.d,G),d.c=Nt(Qn,De,1,0,5,1)),pi=n.b,js+=H+e,H=0,M=b.Math.max(M,n.b+n.c+hr)),d.c[d.c.length]=v,hse(v,pi,js),M=b.Math.max(M,pi+hr+n.c),H=b.Math.max(H,j),pi+=hr+e,G=v;if(Ls(t.a,d),le(t.d,u(Ne(d,d.c.length-1),157)),M=b.Math.max(M,r),zn=js+H+n.a,zn1&&(h=b.Math.min(h,b.Math.abs(u(Zf(d.a,1),8).b-C.b)))));else for(K=new S(e.j);K.as&&(o=j.a-s,h=wi,r.c=Nt(Qn,De,1,0,5,1),s=j.a),j.a>=s&&(r.c[r.c.length]=d,d.a.b>1&&(h=b.Math.min(h,b.Math.abs(u(Zf(d.a,d.a.b-2),8).b-j.b)))));if(r.c.length!=0&&o>e.o.a/2&&h>e.o.b/2){for(H=new Mc,Uo(H,e),Bs(H,(ve(),Pn)),H.n.a=e.o.a/2,gt=new Mc,Uo(gt,e),Bs(gt,mr),gt.n.a=e.o.a/2,gt.n.b=e.o.b,v=new S(r);v.a=k.b?Oa(d,gt):Oa(d,H)):(k=u(hen(d.a),8),tt=d.a.b==0?_1(d.c):u(Aj(d.a),8),tt.b>=k.b?oa(d,gt):oa(d,H)),M=u(Q(d,(Te(),So)),74),M&&ay(M,k,!0);e.n.a=s-e.o.a/2}}function yxn(t,e,n){var r,s,o,h,d,v,k,C,M,j,H,G,K,tt,gt,Mt,St,Rt,Kt,ue,_e,We,Qe,Rn,zn,hr,pi,js,Zl,Xh;if(Rn=null,hr=e,zn=ZZt(t,YZt(n),hr),G9(zn,R0(hr,Ad)),pi=u(n4(t.g,f6(B0(hr,Xct))),33),j=B0(hr,"sourcePort"),r=null,j&&(r=f6(j)),js=u(n4(t.j,r),118),!pi)throw d=pE(hr),G="An edge must have a source node (edge id: '"+d,K=G+JE,it(new ud(K));if(js&&!pd(T1(js),pi))throw v=R0(hr,Ad),tt="The source port of an edge must be a port of the edge's source node (edge id: '"+v,gt=tt+JE,it(new ud(gt));if(We=(!zn.b&&(zn.b=new Cn(br,zn,4,7)),zn.b),o=null,js?o=js:o=pi,Dr(We,o),Zl=u(n4(t.g,f6(B0(hr,M8t))),33),H=B0(hr,"targetPort"),s=null,H&&(s=f6(H)),Xh=u(n4(t.j,s),118),!Zl)throw M=pE(hr),Mt="An edge must have a target node (edge id: '"+M,St=Mt+JE,it(new ud(St));if(Xh&&!pd(T1(Xh),Zl))throw k=R0(hr,Ad),Rt="The target port of an edge must be a port of the edge's target node (edge id: '"+k,Kt=Rt+JE,it(new ud(Kt));if(Qe=(!zn.c&&(zn.c=new Cn(br,zn,5,8)),zn.c),h=null,Xh?h=Xh:h=Zl,Dr(Qe,h),(!zn.b&&(zn.b=new Cn(br,zn,4,7)),zn.b).i==0||(!zn.c&&(zn.c=new Cn(br,zn,5,8)),zn.c).i==0)throw C=R0(hr,Ad),ue=Vde+C,_e=ue+JE,it(new ud(_e));return lq(hr,zn),l2n(hr,zn),Rn=Lit(t,hr,zn),Rn}function Khe(t,e){var n,r,s,o,h,d,v,k,C,M,j,H,G,K,tt,gt,Mt,St,Rt,Kt,ue,_e,We,Qe,Rn;return M=Eyn(bu(t,(ve(),U1)),e),G=d4(bu(t,Mf),e),Rt=d4(bu(t,Kl),e),We=rq(bu(t,Vh),e),j=rq(bu(t,mh),e),Mt=d4(bu(t,Df),e),K=d4(bu(t,el),e),ue=d4(bu(t,Xl),e),Kt=d4(bu(t,yh),e),Qe=rq(bu(t,lu),e),gt=d4(bu(t,Au),e),St=d4(bu(t,nl),e),_e=d4(bu(t,Su),e),Rn=rq(bu(t,Lu),e),H=rq(bu(t,Vu),e),tt=d4(bu(t,Uc),e),n=s4(lt(ct(aa,1),vo,25,15,[Mt.a,We.a,ue.a,Rn.a])),r=s4(lt(ct(aa,1),vo,25,15,[G.a,M.a,Rt.a,tt.a])),s=gt.a,o=s4(lt(ct(aa,1),vo,25,15,[K.a,j.a,Kt.a,H.a])),k=s4(lt(ct(aa,1),vo,25,15,[Mt.b,G.b,K.b,St.b])),v=s4(lt(ct(aa,1),vo,25,15,[We.b,M.b,j.b,tt.b])),C=Qe.b,d=s4(lt(ct(aa,1),vo,25,15,[ue.b,Rt.b,Kt.b,_e.b])),Bg(bu(t,U1),n+s,k+C),Bg(bu(t,Uc),n+s,k+C),Bg(bu(t,Mf),n+s,0),Bg(bu(t,Kl),n+s,k+C+v),Bg(bu(t,Vh),0,k+C),Bg(bu(t,mh),n+s+r,k+C),Bg(bu(t,el),n+s+r,0),Bg(bu(t,Xl),0,k+C+v),Bg(bu(t,yh),n+s+r,k+C+v),Bg(bu(t,lu),0,k),Bg(bu(t,Au),n,0),Bg(bu(t,Su),0,k+C+v),Bg(bu(t,Vu),n+s+r,0),h=new Ca,h.a=s4(lt(ct(aa,1),vo,25,15,[n+r+s+o,Qe.a,St.a,_e.a])),h.b=s4(lt(ct(aa,1),vo,25,15,[k+v+C+d,gt.b,Rn.b,H.b])),h}function xxn(t){var e,n,r,s,o,h,d,v,k,C,M,j,H,G,K,tt;for(K=new he,j=new S(t.d.b);j.as.d.d+s.d.a?C.f.d=!0:(C.f.d=!0,C.f.a=!0))),r.b!=r.d.c&&(e=n);C&&(o=u(tr(t.f,h.d.i),57),e.bo.d.d+o.d.a?C.f.d=!0:(C.f.d=!0,C.f.a=!0))}for(d=new ar(lr(jo(H).a.Kc(),new z));zr(d);)h=u(Mr(d),17),h.a.b!=0&&(e=u(Aj(h.a),8),h.d.j==(ve(),Pn)&&(tt=new T_(e,new $e(e.a,s.d.d),s,h),tt.f.a=!0,tt.a=h.d,K.c[K.c.length]=tt),h.d.j==mr&&(tt=new T_(e,new $e(e.a,s.d.d+s.d.a),s,h),tt.f.d=!0,tt.a=h.d,K.c[K.c.length]=tt))}return K}function kxn(t,e,n){var r,s,o,h,d,v,k,C,M;if(vr(n,"Network simplex node placement",1),t.e=e,t.n=u(Q(e,(ae(),Q4)),304),j3n(t),m0n(t),ls(Wo(new Tn(null,new _n(t.e.b,16)),new EQ),new q$t(t)),ls(Ri(Wo(Ri(Wo(new Tn(null,new _n(t.e.b,16)),new WT),new OQ),new PQ),new FQ),new z$t(t)),je(Re(Q(t.e,(Te(),SS))))&&(h=Rc(n,1),vr(h,"Straight Edges Pre-Processing",1),i5n(t),or(h)),t1n(t.f),o=u(Q(e,MS),19).a*t.f.a.c.length,mat(abt(obt(Mnt(t.f),o),!1),Rc(n,1)),t.d.a.gc()!=0){for(h=Rc(n,1),vr(h,"Flexible Where Space Processing",1),d=u(Nw(t$(wu(new Tn(null,new _n(t.f.a,16)),new TQ),new wQ)),19).a,v=u(Nw(Jj(wu(new Tn(null,new _n(t.f.a,16)),new CQ),new vQ)),19).a,k=v-d,C=Fw(new Xb,t.f),M=Fw(new Xb,t.f),yf(lf(uf(cf(hf(new Ch,2e4),k),C),M)),ls(Ri(Ri(Qnt(t.i),new _Q),new SQ),new jXt(d,C,k,M)),s=t.d.a.ec().Kc();s.Ob();)r=u(s.Pb(),213),r.g=1;mat(abt(obt(Mnt(t.f),o),!1),Rc(h,1)),or(h)}je(Re(Q(e,SS)))&&(h=Rc(n,1),vr(h,"Straight Edges Post-Processing",1),upn(t),or(h)),q4n(t),t.e=null,t.f=null,t.i=null,t.c=null,Xu(t.k),t.j=null,t.a=null,t.o=null,t.d.a.$b(),or(n)}function Exn(t,e,n){var r,s,o,h,d,v,k,C,M,j,H,G,K,tt,gt,Mt,St,Rt,Kt;for(d=new S(t.a.b);d.a0)if(r=M.gc(),k=ps(b.Math.floor((r+1)/2))-1,s=ps(b.Math.ceil((r+1)/2))-1,e.o==H1)for(C=s;C>=k;C--)e.a[Rt.p]==Rt&&(K=u(M.Xb(C),46),G=u(K.a,10),!I0(n,K.b)&&H>t.b.e[G.p]&&(e.a[G.p]=Rt,e.g[Rt.p]=e.g[G.p],e.a[Rt.p]=e.g[Rt.p],e.f[e.g[Rt.p].p]=(Nn(),!!(je(e.f[e.g[Rt.p].p])&Rt.k==(Vn(),ta))),H=t.b.e[G.p]));else for(C=k;C<=s;C++)e.a[Rt.p]==Rt&&(gt=u(M.Xb(C),46),tt=u(gt.a,10),!I0(n,gt.b)&&H=G&&(Mt>G&&(H.c=Nt(Qn,De,1,0,5,1),G=Mt),H.c[H.c.length]=h);H.c.length!=0&&(j=u(Ne(H,Zz(e,H.c.length)),128),zn.a.Bc(j)!=null,j.s=K++,A5t(j,Qe,ue),H.c=Nt(Qn,De,1,0,5,1))}for(Rt=t.c.length+1,d=new S(t);d.aRn.s&&(Cl(n),mu(Rn.i,r),r.c>0&&(r.a=Rn,le(Rn.t,r),r.b=_e,le(_e.i,r)))}function Ixt(t){var e,n,r,s,o;switch(e=t.c,e){case 11:return t.Ml();case 12:return t.Ol();case 14:return t.Ql();case 15:return t.Tl();case 16:return t.Rl();case 17:return t.Ul();case 21:return fi(t),gi(),gi(),pA;case 10:switch(t.a){case 65:return t.yl();case 90:return t.Dl();case 122:return t.Kl();case 98:return t.El();case 66:return t.zl();case 60:return t.Jl();case 62:return t.Hl()}}switch(o=vxn(t),e=t.c,e){case 3:return t.Zl(o);case 4:return t.Xl(o);case 5:return t.Yl(o);case 0:if(t.a==123&&t.d=48&&e<=57){for(r=e-48;s=48&&e<=57;)if(r=r*10+e-48,r<0)throw it(new Nr(qr((Pr(),N8t))))}else throw it(new Nr(qr((Pr(),v0e))));if(n=r,e==44){if(s>=t.j)throw it(new Nr(qr((Pr(),y0e))));if((e=wa(t.i,s++))>=48&&e<=57){for(n=e-48;s=48&&e<=57;)if(n=n*10+e-48,n<0)throw it(new Nr(qr((Pr(),N8t))));if(r>n)throw it(new Nr(qr((Pr(),x0e))))}else n=-1}if(e!=125)throw it(new Nr(qr((Pr(),m0e))));t.sl(s)?(o=(gi(),gi(),new Xm(9,o)),t.d=s+1):(o=(gi(),gi(),new Xm(3,o)),t.d=s),o.dm(r),o.cm(n),fi(t)}}return o}function Xhe(t,e,n,r,s){var o,h,d,v,k,C,M,j,H,G,K,tt,gt,Mt,St,Rt,Kt,ue,_e,We,Qe,Rn,zn;for(K=new Xc(e.b),Rt=new Xc(e.b),j=new Xc(e.b),We=new Xc(e.b),tt=new Xc(e.b),_e=ei(e,0);_e.b!=_e.d.c;)for(Kt=u(ti(_e),11),d=new S(Kt.g);d.a0,gt=Kt.g.c.length>0,k&>?j.c[j.c.length]=Kt:k?K.c[K.c.length]=Kt:gt&&(Rt.c[Rt.c.length]=Kt);for(G=new S(K);G.a1)for(G=new Nx((!t.a&&(t.a=new fe(Ji,t,6,6)),t.a));G.e!=G.i.gc();)f_(G);for(h=u(At((!t.a&&(t.a=new fe(Ji,t,6,6)),t.a),0),202),tt=pi,pi>Kt+Rt?tt=Kt+Rt:piue+K?gt=ue+K:jsKt-Rt&&ttue-K&>pi+hr?We=pi+hr:Ktjs+_e?Qe=js+_e:uepi-hr&&Wejs-_e&&Qen&&(j=n-1),H=xP+ul(e,24)*$I*M-M/2,H<0?H=1:H>r&&(H=r-1),s=(Sw(),v=new xp,v),iz(s,j),sz(s,H),Dr((!h.a&&(h.a=new As(Gh,h,5)),h.a),s)}function Te(){Te=Z,lht=(ui(),p4e),y9t=b4e,OO=hAt,Tf=w4e,V6=fAt,jv=v4e,Wy=dAt,S7=gAt,A7=pAt,hht=JG,$v=W2,fht=m4e,LS=vAt,bG=K6,IO=(Fxt(),fve),J4=dve,q2=gve,t5=pve,Zve=new eo(ZG,pe(0)),_7=uve,m9t=lve,H6=hve,A9t=Bve,x9t=vve,k9t=xve,ght=Ave,E9t=Tve,T9t=_ve,wG=zve,pht=Rve,_9t=Ove,C9t=Dve,S9t=Fve,Bv=rve,AS=ive,sht=xwe,QCt=Ewe,g9t=new Ow(12),d9t=new eo(U2,g9t),YCt=(W0(),N7),eg=new eo(zSt,YCt),Vy=new eo(dl,0),Jve=new eo(Eft,pe(1)),rG=new eo(W6,GE),z2=QG,cs=KS,C7=u5,Gve=QO,Id=a4e,qy=s5,tme=new eo(Tft,(Nn(),!0)),Hy=ZO,j2=bft,$2=G2,pG=xb,uht=XG,WCt=(ao(),h0),Wl=new eo(qv,WCt),Nv=o5,dG=XSt,Gy=Qy,Qve=kft,w9t=uAt,b9t=(l4(),iP),new eo(iAt,b9t),Yve=vft,Kve=mft,Xve=yft,Wve=wft,dht=wve,c9t=Gwe,oht=Vwe,MS=bve,uu=Bwe,zy=dwe,_S=fwe,$y=J2e,VCt=twe,eht=iwe,DO=ewe,nht=lwe,u9t=Uwe,l9t=Wwe,r9t=Dwe,gG=ove,cht=Xwe,aht=_we,f9t=eve,XCt=mwe,iht=ywe,tht=YG,h9t=Ywe,sG=U2e,zCt=G2e,iG=V2e,t9t=Lwe,JCt=Awe,e9t=Mwe,E7=c5,So=a5,Jg=HSt,Od=pft,rht=gft,GCt=awe,tp=xft,CS=u4e,lG=l4e,Rv=aAt,p9t=h4e,T7=f4e,s9t=jwe,a9t=zwe,Uy=Y6,Zlt=H2e,o9t=Hwe,uG=bwe,cG=pwe,fG=JO,i9t=Pwe,SS=Zwe,PO=bAt,UCt=gwe,v9t=cve,KCt=wwe,Uve=Nwe,Vve=cwe,n9t=WSt,hG=Rwe,oG=uwe,wb=Z2e,HCt=X2e,aG=Y2e,qCt=K2e,Jlt=Q2e,q6=W2e,ZCt=Swe}function Hat(t,e){Lat();var n,r,s,o,h,d,v,k,C,M,j,H,G,K,tt,gt,Mt,St,Rt,Kt,ue,_e,We,Qe,Rn,zn,hr,pi;if(We=t.e,G=t.d,s=t.a,We==0)switch(e){case 0:return"0";case 1:return $E;case 2:return"0.00";case 3:return"0.000";case 4:return"0.0000";case 5:return"0.00000";case 6:return"0.000000";default:return ue=new Mp,e<0?ue.a+="0E+":ue.a+="0E",ue.a+=-e,ue.a}if(St=G*10+1+7,Rt=Nt(xh,yd,25,St+1,15,1),n=St,G==1)if(d=s[0],d<0){pi=Ns(d,co);do K=pi,pi=aI(pi,10),Rt[--n]=48+Ar(Jp(K,_a(pi,10)))&ys;while(yc(pi,0)!=0)}else{pi=d;do K=pi,pi=pi/10|0,Rt[--n]=48+(K-pi*10)&ys;while(pi!=0)}else{Rn=Nt(Cr,Xr,25,G,15,1),hr=G,Dc(s,0,Rn,0,hr);t:for(;;){for(_e=0,k=hr-1;k>=0;k--)zn=Pa(F0(_e,32),Ns(Rn[k],co)),gt=P0n(zn),Rn[k]=Ar(gt),_e=Ar($p(gt,32));Mt=Ar(_e),tt=n;do Rt[--n]=48+Mt%10&ys;while((Mt=Mt/10|0)!=0&&n!=0);for(r=9-tt+n,v=0;v0;v++)Rt[--n]=48;for(M=hr-1;Rn[M]==0;M--)if(M==0)break t;hr=M+1}for(;Rt[n]==48;)++n}if(H=We<0,h=St-n-e-1,e==0)return H&&(Rt[--n]=45),Mh(Rt,n,St-n);if(e>0&&h>=-6){if(h>=0){for(C=n+h,j=St-1;j>=C;j--)Rt[j+1]=Rt[j];return Rt[++C]=46,H&&(Rt[--n]=45),Mh(Rt,n,St-n+1)}for(M=2;M<-h+1;M++)Rt[--n]=48;return Rt[--n]=46,Rt[--n]=48,H&&(Rt[--n]=45),Mh(Rt,n,St-n)}return Qe=n+1,o=St,Kt=new Im,H&&(Kt.a+="-"),o-Qe>=1?(qp(Kt,Rt[n]),Kt.a+=".",Kt.a+=Mh(Rt,n+1,St-n-1)):Kt.a+=Mh(Rt,n,St-n),Kt.a+="E",h>0&&(Kt.a+="+"),Kt.a+=""+h,Kt.a}function Jhe(t,e){var n,r,s,o,h,d,v,k,C,M,j,H,G,K,tt,gt,Mt,St,Rt,Kt,ue;switch(t.c=e,t.g=new _r,n=(Pm(),new Mm(t.c)),r=new er(n),p3t(r),St=Br(qe(t.c,(cI(),lSt))),v=u(qe(t.c,sft),316),Kt=u(qe(t.c,aft),429),h=u(qe(t.c,oSt),482),Rt=u(qe(t.c,ift),430),t.j=Xt(ye(qe(t.c,M3e))),d=t.a,v.g){case 0:d=t.a;break;case 1:d=t.b;break;case 2:d=t.i;break;case 3:d=t.e;break;case 4:d=t.f;break;default:throw it(new Fn(_H+(v.f!=null?v.f:""+v.g)))}if(t.d=new EQt(d,Kt,h),Jt(t.d,(Z8(),fS),Re(qe(t.c,A3e))),t.d.c=je(Re(qe(t.c,cSt))),p$(t.c).i==0)return t.d;for(M=new nr(p$(t.c));M.e!=M.i.gc();){for(C=u(dr(M),33),H=C.g/2,j=C.f/2,ue=new $e(C.i+H,C.j+j);Tl(t.g,ue);)jm(ue,(b.Math.random()-.5)*Ed,(b.Math.random()-.5)*Ed);K=u(qe(C,(ui(),JO)),142),tt=new $Qt(ue,new ah(ue.a-H-t.j/2-K.b,ue.b-j-t.j/2-K.d,C.g+t.j+(K.b+K.c),C.f+t.j+(K.d+K.a))),le(t.d.i,tt),ki(t.g,ue,new fa(tt,C))}switch(Rt.g){case 0:if(St==null)t.d.d=u(Ne(t.d.i,0),65);else for(Mt=new S(t.d.i);Mt.a1&&fs(C,gt,C.c.b,C.c),tz(s)));gt=Mt}return C}function Mxn(t,e,n){var r,s,o,h,d,v,k,C,M,j,H,G,K,tt,gt,Mt,St,Rt,Kt,ue,_e,We,Qe,Rn,zn,hr,pi,js,Zl,Xh,K1;for(vr(n,"Greedy cycle removal",1),St=e.a,K1=St.c.length,t.a=Nt(Cr,Xr,25,K1,15,1),t.c=Nt(Cr,Xr,25,K1,15,1),t.b=Nt(Cr,Xr,25,K1,15,1),k=0,gt=new S(St);gt.a0?hr+1:1);for(h=new S(ue.g);h.a0?hr+1:1)}t.c[k]==0?ri(t.e,K):t.a[k]==0&&ri(t.f,K),++k}for(G=-1,H=1,M=new he,t.d=u(Q(e,(ae(),$6)),230);K1>0;){for(;t.e.b!=0;)js=u(Ont(t.e),10),t.b[js.p]=G--,ext(t,js),--K1;for(;t.f.b!=0;)Zl=u(Ont(t.f),10),t.b[Zl.p]=H++,ext(t,Zl),--K1;if(K1>0){for(j=Sa,Mt=new S(St);Mt.a=j&&(Rt>j&&(M.c=Nt(Qn,De,1,0,5,1),j=Rt),M.c[M.c.length]=K));C=t.Zf(M),t.b[C.p]=H++,ext(t,C),--K1}}for(pi=St.c.length+1,k=0;kt.b[Xh]&&(bv(r,!0),Jt(e,_O,(Nn(),!0)));t.a=null,t.c=null,t.b=null,Ah(t.f),Ah(t.e),or(n)}function efe(t,e){var n,r,s,o,h,d,v,k,C,M,j,H,G,K,tt,gt;for(r=new he,d=new he,tt=e/2,H=t.gc(),s=u(t.Xb(0),8),gt=u(t.Xb(1),8),G=rat(s.a,s.b,gt.a,gt.b,tt),le(r,(An(0,G.c.length),u(G.c[0],8))),le(d,(An(1,G.c.length),u(G.c[1],8))),k=2;k=0;v--)ri(n,(An(v,h.c.length),u(h.c[v],8)));return n}function Dxn(t){var e,n,r,s,o,h,d,v,k,C,M,j,H;if(h=!0,M=null,r=null,s=null,e=!1,H=o5e,k=null,o=null,d=0,v=ust(t,d,nLt,rLt),v=0&&hn(t.substr(d,2),"//")?(d+=2,v=ust(t,d,oA,cA),r=t.substr(d,v-d),d=v):M!=null&&(d==t.length||(Rr(d,t.length),t.charCodeAt(d)!=47))&&(h=!1,v=O2t(t,Cu(35),d),v==-1&&(v=t.length),r=t.substr(d,v-d),d=v);if(!n&&d0&&wa(C,C.length-1)==58&&(s=C,d=v)),d=t.j){t.a=-1,t.c=1;return}if(e=wa(t.i,t.d++),t.a=e,t.b==1){switch(e){case 92:if(r=10,t.d>=t.j)throw it(new Nr(qr((Pr(),OH))));t.a=wa(t.i,t.d++);break;case 45:(t.e&512)==512&&t.d=t.j||wa(t.i,t.d)!=63)break;if(++t.d>=t.j)throw it(new Nr(qr((Pr(),out))));switch(e=wa(t.i,t.d++),e){case 58:r=13;break;case 61:r=14;break;case 33:r=15;break;case 91:r=19;break;case 62:r=18;break;case 60:if(t.d>=t.j)throw it(new Nr(qr((Pr(),out))));if(e=wa(t.i,t.d++),e==61)r=16;else if(e==33)r=17;else throw it(new Nr(qr((Pr(),t0e))));break;case 35:for(;t.d=t.j)throw it(new Nr(qr((Pr(),OH))));t.a=wa(t.i,t.d++);break;default:r=0}t.c=r}function Oxn(t){var e,n,r,s,o,h,d,v,k,C,M,j,H,G,K,tt,gt,Mt,St,Rt,Kt,ue,_e,We,Qe,Rn,zn,hr;if(_e=u(Q(t,(Te(),cs)),98),_e!=(ua(),G1)&&_e!=Tb){for(G=t.b,H=G.c.length,C=new Xc((jl(H+2,Yat),J$(Pa(Pa(5,H+2),(H+2)/10|0)))),K=new Xc((jl(H+2,Yat),J$(Pa(Pa(5,H+2),(H+2)/10|0)))),le(C,new _r),le(C,new _r),le(K,new he),le(K,new he),ue=new he,e=0;e=Kt||!tfn(gt,r))&&(r=XQt(e,C)),Eo(gt,r),o=new ar(lr(jo(gt).a.Kc(),new z));zr(o);)s=u(Mr(o),17),!t.a[s.p]&&(K=s.c.i,--t.e[K.p],t.e[K.p]==0&&R8(xE(H,K)));for(k=C.c.length-1;k>=0;--k)le(e.b,(An(k,C.c.length),u(C.c[k],29)));e.a.c=Nt(Qn,De,1,0,5,1),or(n)}function nfe(t){var e,n,r,s,o,h,d,v,k;for(t.b=1,fi(t),e=null,t.c==0&&t.a==94?(fi(t),e=(gi(),gi(),new Nl(4)),jc(e,0,e7),d=new Nl(4)):d=(gi(),gi(),new Nl(4)),s=!0;(k=t.c)!=1;){if(k==0&&t.a==93&&!s){e&&(L_(e,d),d=e);break}if(n=t.a,r=!1,k==10)switch(n){case 100:case 68:case 119:case 87:case 115:case 83:yy(d,ME(n)),r=!0;break;case 105:case 73:case 99:case 67:n=(yy(d,ME(n)),-1),n<0&&(r=!0);break;case 112:case 80:if(v=u5t(t,n),!v)throw it(new Nr(qr((Pr(),cut))));yy(d,v),r=!0;break;default:n=H5t(t)}else if(k==24&&!s){if(e&&(L_(e,d),d=e),o=nfe(t),L_(d,o),t.c!=0||t.a!=93)throw it(new Nr(qr((Pr(),l0e))));break}if(fi(t),!r){if(k==0){if(n==91)throw it(new Nr(qr((Pr(),P8t))));if(n==93)throw it(new Nr(qr((Pr(),F8t))));if(n==45&&!s&&t.a!=93)throw it(new Nr(qr((Pr(),uut))))}if(t.c!=0||t.a!=45||n==45&&s)jc(d,n,n);else{if(fi(t),(k=t.c)==1)throw it(new Nr(qr((Pr(),PH))));if(k==0&&t.a==93)jc(d,n,n),jc(d,45,45);else{if(k==0&&t.a==93||k==24)throw it(new Nr(qr((Pr(),uut))));if(h=t.a,k==0){if(h==91)throw it(new Nr(qr((Pr(),P8t))));if(h==93)throw it(new Nr(qr((Pr(),F8t))));if(h==45)throw it(new Nr(qr((Pr(),uut))))}else k==10&&(h=H5t(t));if(fi(t),n>h)throw it(new Nr(qr((Pr(),d0e))));jc(d,n,h)}}}s=!1}if(t.c==1)throw it(new Nr(qr((Pr(),PH))));return v4(d),S_(d),t.b=0,fi(t),d}function Fxn(t){Ir(t.c,Yr,lt(ct(Ae,1),ee,2,6,[Aa,"http://www.w3.org/2001/XMLSchema#decimal"])),Ir(t.d,Yr,lt(ct(Ae,1),ee,2,6,[Aa,"http://www.w3.org/2001/XMLSchema#integer"])),Ir(t.e,Yr,lt(ct(Ae,1),ee,2,6,[Aa,"http://www.w3.org/2001/XMLSchema#boolean"])),Ir(t.f,Yr,lt(ct(Ae,1),ee,2,6,[Aa,"EBoolean",ci,"EBoolean:Object"])),Ir(t.i,Yr,lt(ct(Ae,1),ee,2,6,[Aa,"http://www.w3.org/2001/XMLSchema#byte"])),Ir(t.g,Yr,lt(ct(Ae,1),ee,2,6,[Aa,"http://www.w3.org/2001/XMLSchema#hexBinary"])),Ir(t.j,Yr,lt(ct(Ae,1),ee,2,6,[Aa,"EByte",ci,"EByte:Object"])),Ir(t.n,Yr,lt(ct(Ae,1),ee,2,6,[Aa,"EChar",ci,"EChar:Object"])),Ir(t.t,Yr,lt(ct(Ae,1),ee,2,6,[Aa,"http://www.w3.org/2001/XMLSchema#double"])),Ir(t.u,Yr,lt(ct(Ae,1),ee,2,6,[Aa,"EDouble",ci,"EDouble:Object"])),Ir(t.F,Yr,lt(ct(Ae,1),ee,2,6,[Aa,"http://www.w3.org/2001/XMLSchema#float"])),Ir(t.G,Yr,lt(ct(Ae,1),ee,2,6,[Aa,"EFloat",ci,"EFloat:Object"])),Ir(t.I,Yr,lt(ct(Ae,1),ee,2,6,[Aa,"http://www.w3.org/2001/XMLSchema#int"])),Ir(t.J,Yr,lt(ct(Ae,1),ee,2,6,[Aa,"EInt",ci,"EInt:Object"])),Ir(t.N,Yr,lt(ct(Ae,1),ee,2,6,[Aa,"http://www.w3.org/2001/XMLSchema#long"])),Ir(t.O,Yr,lt(ct(Ae,1),ee,2,6,[Aa,"ELong",ci,"ELong:Object"])),Ir(t.Z,Yr,lt(ct(Ae,1),ee,2,6,[Aa,"http://www.w3.org/2001/XMLSchema#short"])),Ir(t.$,Yr,lt(ct(Ae,1),ee,2,6,[Aa,"EShort",ci,"EShort:Object"])),Ir(t._,Yr,lt(ct(Ae,1),ee,2,6,[Aa,"http://www.w3.org/2001/XMLSchema#string"]))}function Nxn(t){var e,n,r,s,o,h,d,v,k,C,M,j,H,G,K,tt,gt,Mt,St,Rt,Kt,ue,_e,We,Qe,Rn,zn,hr;if(t.c.length==1)return An(0,t.c.length),u(t.c[0],135);if(t.c.length<=0)return new j$;for(v=new S(t);v.aM&&(zn=0,hr+=C+_e,C=0),U2n(Kt,h,zn,hr),e=b.Math.max(e,zn+ue.a),C=b.Math.max(C,ue.b),zn+=ue.a+_e;for(Rt=new _r,n=new _r,Qe=new S(t);Qe.aiat(o))&&(M=o);for(!M&&(M=(An(0,tt.c.length),u(tt.c[0],180))),K=new S(e.b);K.a=-1900?1:0,n>=4?Gr(t,lt(ct(Ae,1),ee,2,6,[mfe,yfe])[d]):Gr(t,lt(ct(Ae,1),ee,2,6,["BC","AD"])[d]);break;case 121:Mfn(t,n,r);break;case 77:Pmn(t,n,r);break;case 107:v=s.q.getHours(),v==0?Jd(t,24,n):Jd(t,v,n);break;case 83:ewn(t,n,s);break;case 69:C=r.q.getDay(),n==5?Gr(t,lt(ct(Ae,1),ee,2,6,["S","M","T","W","T","F","S"])[C]):n==4?Gr(t,lt(ct(Ae,1),ee,2,6,[cot,uot,lot,hot,fot,dot,got])[C]):Gr(t,lt(ct(Ae,1),ee,2,6,["Sun","Mon","Tue","Wed","Thu","Fri","Sat"])[C]);break;case 97:s.q.getHours()>=12&&s.q.getHours()<24?Gr(t,lt(ct(Ae,1),ee,2,6,["AM","PM"])[1]):Gr(t,lt(ct(Ae,1),ee,2,6,["AM","PM"])[0]);break;case 104:M=s.q.getHours()%12,M==0?Jd(t,12,n):Jd(t,M,n);break;case 75:j=s.q.getHours()%12,Jd(t,j,n);break;case 72:H=s.q.getHours(),Jd(t,H,n);break;case 99:G=r.q.getDay(),n==5?Gr(t,lt(ct(Ae,1),ee,2,6,["S","M","T","W","T","F","S"])[G]):n==4?Gr(t,lt(ct(Ae,1),ee,2,6,[cot,uot,lot,hot,fot,dot,got])[G]):n==3?Gr(t,lt(ct(Ae,1),ee,2,6,["Sun","Mon","Tue","Wed","Thu","Fri","Sat"])[G]):Jd(t,G,1);break;case 76:K=r.q.getMonth(),n==5?Gr(t,lt(ct(Ae,1),ee,2,6,["J","F","M","A","M","J","J","A","S","O","N","D"])[K]):n==4?Gr(t,lt(ct(Ae,1),ee,2,6,[Qat,Zat,Jat,tot,w6,eot,not,rot,iot,sot,aot,oot])[K]):n==3?Gr(t,lt(ct(Ae,1),ee,2,6,["Jan","Feb","Mar","Apr",w6,"Jun","Jul","Aug","Sep","Oct","Nov","Dec"])[K]):Jd(t,K+1,n);break;case 81:tt=r.q.getMonth()/3|0,n<4?Gr(t,lt(ct(Ae,1),ee,2,6,["Q1","Q2","Q3","Q4"])[tt]):Gr(t,lt(ct(Ae,1),ee,2,6,["1st quarter","2nd quarter","3rd quarter","4th quarter"])[tt]);break;case 100:gt=r.q.getDate(),Jd(t,gt,n);break;case 109:k=s.q.getMinutes(),Jd(t,k,n);break;case 115:h=s.q.getSeconds(),Jd(t,h,n);break;case 122:n<4?Gr(t,o.c[0]):Gr(t,o.c[1]);break;case 118:Gr(t,o.b);break;case 90:n<3?Gr(t,Vpn(o)):n==3?Gr(t,Wpn(o)):Gr(t,Ypn(o.a));break;default:return!1}return!0}function Pxt(t,e,n,r){var s,o,h,d,v,k,C,M,j,H,G,K,tt,gt,Mt,St,Rt,Kt,ue,_e,We,Qe,Rn,zn,hr,pi;if(Hue(e),v=u(At((!e.b&&(e.b=new Cn(br,e,4,7)),e.b),0),82),C=u(At((!e.c&&(e.c=new Cn(br,e,5,8)),e.c),0),82),d=Do(v),k=Do(C),h=(!e.a&&(e.a=new fe(Ji,e,6,6)),e.a).i==0?null:u(At((!e.a&&(e.a=new fe(Ji,e,6,6)),e.a),0),202),_e=u(tr(t.a,d),10),zn=u(tr(t.a,k),10),We=null,hr=null,_t(v,186)&&(ue=u(tr(t.a,v),299),_t(ue,11)?We=u(ue,11):_t(ue,10)&&(_e=u(ue,10),We=u(Ne(_e.j,0),11))),_t(C,186)&&(Rn=u(tr(t.a,C),299),_t(Rn,11)?hr=u(Rn,11):_t(Rn,10)&&(zn=u(Rn,10),hr=u(Ne(zn.j,0),11))),!_e||!zn)throw it(new jC("The source or the target of edge "+e+" could not be found. This usually happens when an edge connects a node laid out by ELK Layered to a node in another level of hierarchy laid out by either another instance of ELK Layered or another layout algorithm alltogether. The former can be solved by setting the hierarchyHandling option to INCLUDE_CHILDREN."));for(K=new Vw,Mo(K,e),Jt(K,(ae(),_i),e),Jt(K,(Te(),So),null),H=u(Q(r,Vc),21),_e==zn&&H.Fc((oo(),xS)),We||(Kt=(so(),nu),Qe=null,h&&G3(u(Q(_e,cs),98))&&(Qe=new $e(h.j,h.k),JZt(Qe,cD(e)),LJt(Qe,n),ey(k,d)&&(Kt=tl,Li(Qe,_e.n))),We=zle(_e,Qe,Kt,r)),hr||(Kt=(so(),tl),pi=null,h&&G3(u(Q(zn,cs),98))&&(pi=new $e(h.b,h.c),JZt(pi,cD(e)),LJt(pi,n)),hr=zle(zn,pi,Kt,Na(zn))),Oa(K,We),oa(K,hr),(We.e.c.length>1||We.g.c.length>1||hr.e.c.length>1||hr.g.c.length>1)&&H.Fc((oo(),yS)),j=new nr((!e.n&&(e.n=new fe(qo,e,1,7)),e.n));j.e!=j.i.gc();)if(M=u(dr(j),137),!je(Re(qe(M,z2)))&&M.a)switch(tt=Vit(M),le(K.b,tt),u(Q(tt,Od),272).g){case 1:case 2:H.Fc((oo(),m7));break;case 0:H.Fc((oo(),v7)),Jt(tt,Od,(M1(),P7))}if(o=u(Q(r,_S),314),gt=u(Q(r,gG),315),s=o==(n6(),EO)||gt==(u_(),xht),h&&(!h.a&&(h.a=new As(Gh,h,5)),h.a).i!=0&&s){for(Mt=lI(h),G=new Pu,Rt=ei(Mt,0);Rt.b!=Rt.d.c;)St=u(ti(Rt),8),ri(G,new xo(St));Jt(K,aCt,G)}return K}function $xn(t){t.gb||(t.gb=!0,t.b=ic(t,0),ns(t.b,18),Fi(t.b,19),t.a=ic(t,1),ns(t.a,1),Fi(t.a,2),Fi(t.a,3),Fi(t.a,4),Fi(t.a,5),t.o=ic(t,2),ns(t.o,8),ns(t.o,9),Fi(t.o,10),Fi(t.o,11),Fi(t.o,12),Fi(t.o,13),Fi(t.o,14),Fi(t.o,15),Fi(t.o,16),Fi(t.o,17),Fi(t.o,18),Fi(t.o,19),Fi(t.o,20),Fi(t.o,21),Fi(t.o,22),Fi(t.o,23),Co(t.o),Co(t.o),Co(t.o),Co(t.o),Co(t.o),Co(t.o),Co(t.o),Co(t.o),Co(t.o),Co(t.o),t.p=ic(t,3),ns(t.p,2),ns(t.p,3),ns(t.p,4),ns(t.p,5),Fi(t.p,6),Fi(t.p,7),Co(t.p),Co(t.p),t.q=ic(t,4),ns(t.q,8),t.v=ic(t,5),Fi(t.v,9),Co(t.v),Co(t.v),Co(t.v),t.w=ic(t,6),ns(t.w,2),ns(t.w,3),ns(t.w,4),Fi(t.w,5),t.B=ic(t,7),Fi(t.B,1),Co(t.B),Co(t.B),Co(t.B),t.Q=ic(t,8),Fi(t.Q,0),Co(t.Q),t.R=ic(t,9),ns(t.R,1),t.S=ic(t,10),Co(t.S),Co(t.S),Co(t.S),Co(t.S),Co(t.S),Co(t.S),Co(t.S),Co(t.S),Co(t.S),Co(t.S),Co(t.S),Co(t.S),Co(t.S),Co(t.S),Co(t.S),t.T=ic(t,11),Fi(t.T,10),Fi(t.T,11),Fi(t.T,12),Fi(t.T,13),Fi(t.T,14),Co(t.T),Co(t.T),t.U=ic(t,12),ns(t.U,2),ns(t.U,3),Fi(t.U,4),Fi(t.U,5),Fi(t.U,6),Fi(t.U,7),Co(t.U),t.V=ic(t,13),Fi(t.V,10),t.W=ic(t,14),ns(t.W,18),ns(t.W,19),ns(t.W,20),Fi(t.W,21),Fi(t.W,22),Fi(t.W,23),t.bb=ic(t,15),ns(t.bb,10),ns(t.bb,11),ns(t.bb,12),ns(t.bb,13),ns(t.bb,14),ns(t.bb,15),ns(t.bb,16),Fi(t.bb,17),Co(t.bb),Co(t.bb),t.eb=ic(t,16),ns(t.eb,2),ns(t.eb,3),ns(t.eb,4),ns(t.eb,5),ns(t.eb,6),ns(t.eb,7),Fi(t.eb,8),Fi(t.eb,9),t.ab=ic(t,17),ns(t.ab,0),ns(t.ab,1),t.H=ic(t,18),Fi(t.H,0),Fi(t.H,1),Fi(t.H,2),Fi(t.H,3),Fi(t.H,4),Fi(t.H,5),Co(t.H),t.db=ic(t,19),Fi(t.db,2),t.c=oi(t,20),t.d=oi(t,21),t.e=oi(t,22),t.f=oi(t,23),t.i=oi(t,24),t.g=oi(t,25),t.j=oi(t,26),t.k=oi(t,27),t.n=oi(t,28),t.r=oi(t,29),t.s=oi(t,30),t.t=oi(t,31),t.u=oi(t,32),t.fb=oi(t,33),t.A=oi(t,34),t.C=oi(t,35),t.D=oi(t,36),t.F=oi(t,37),t.G=oi(t,38),t.I=oi(t,39),t.J=oi(t,40),t.L=oi(t,41),t.M=oi(t,42),t.N=oi(t,43),t.O=oi(t,44),t.P=oi(t,45),t.X=oi(t,46),t.Y=oi(t,47),t.Z=oi(t,48),t.$=oi(t,49),t._=oi(t,50),t.cb=oi(t,51),t.K=oi(t,52))}function ui(){ui=Z;var t,e;YS=new Vi(ude),O7=new Vi(lde),NSt=(t0(),uft),a4e=new mn(xkt,NSt),W6=new mn(E6,null),o4e=new Vi(p8t),RSt=(hy(),ji(fft,lt(ct(dft,1),oe,291,0,[hft]))),YG=new mn(mH,RSt),QO=new mn(JI,(Nn(),!1)),jSt=(ao(),h0),qv=new mn(Tkt,jSt),qSt=(W0(),Cft),zSt=new mn(QI,qSt),GSt=new mn(CH,!1),USt=(G0(),tU),s5=new mn(vH,USt),nAt=new Ow(12),U2=new mn(xv,nAt),KG=new mn(GI,!1),WSt=new mn(_ct,!1),tP=new mn(j_,!1),oAt=(ua(),Tb),KS=new mn(Got,oAt),Y6=new Vi(yH),ZG=new Vi(VI),Eft=new Vi(tH),Tft=new Vi(R_),YSt=new Pu,a5=new mn(Okt,YSt),u4e=new mn(Nkt,!1),l4e=new mn(Bkt,!1),KSt=new OC,JO=new mn(jkt,KSt),QG=new mn(mkt,!1),g4e=new mn(hde,1),new mn(fde,!0),pe(0),new mn(dde,pe(100)),new mn(gde,!1),pe(0),new mn(pde,pe(4e3)),pe(0),new mn(bde,pe(400)),new mn(wde,!1),new mn(vde,!1),new mn(mde,!0),new mn(yde,!1),BSt=(jz(),Lft),c4e=new mn(g8t,BSt),p4e=new mn(okt,10),b4e=new mn(ckt,10),hAt=new mn(jot,20),w4e=new mn(ukt,10),fAt=new mn(Vot,2),v4e=new mn(lkt,10),dAt=new mn(hkt,0),JG=new mn(gkt,5),gAt=new mn(fkt,1),pAt=new mn(dkt,1),W2=new mn(Cy,20),m4e=new mn(pkt,10),vAt=new mn(bkt,10),K6=new Vi(wkt),wAt=new CUt,bAt=new mn($kt,wAt),f4e=new Vi(Cct),rAt=!1,h4e=new mn(Tct,rAt),QSt=new Ow(5),XSt=new mn(Ckt,QSt),ZSt=(py(),e=u(Vf(lo),9),new sh(e,u(ff(e,e.length),9),0)),o5=new mn(UE,ZSt),sAt=(l4(),Eb),iAt=new mn(Akt,sAt),vft=new Vi(Lkt),mft=new Vi(Mkt),yft=new Vi(Dkt),wft=new Vi(Ikt),JSt=(t=u(Vf(rA),9),new sh(t,u(ff(t,t.length),9),0)),G2=new mn(D4,JSt),eAt=un((ll(),R7)),xb=new mn(T6,eAt),tAt=new $e(0,0),c5=new mn(C6,tAt),XG=new mn(Ect,!1),$St=(M1(),P7),pft=new mn(Pkt,$St),gft=new mn(eH,!1),pe(1),new mn(xde,null),aAt=new Vi(Rkt),xft=new Vi(Fkt),lAt=(ve(),Zo),u5=new mn(ykt,lAt),dl=new Vi(vkt),cAt=(Zu(),un(Cb)),Qy=new mn(WE,cAt),kft=new mn(_kt,!1),uAt=new mn(Skt,!0),ZO=new mn(kkt,!1),bft=new mn(Ekt,!1),HSt=new mn($ot,1),VSt=(hq(),Sft),new mn(kde,VSt),d4e=!0}function ae(){ae=Z;var t,e;_i=new Vi(w6t),nCt=new Vi("coordinateOrigin"),Klt=new Vi("processors"),eCt=new Ps("compoundNode",(Nn(),!1)),SO=new Ps("insideConnections",!1),aCt=new Vi("originalBendpoints"),oCt=new Vi("originalDummyNodePosition"),cCt=new Vi("originalLabelEdge"),LO=new Vi("representedLabels"),kS=new Vi("endLabels"),B6=new Vi("endLabel.origin"),j6=new Ps("labelSide",(zl(),rP)),K4=new Ps("maxEdgeThickness",0),q1=new Ps("reversed",!1),$6=new Vi(i1e),r1=new Ps("longEdgeSource",null),$h=new Ps("longEdgeTarget",null),Ry=new Ps("longEdgeHasLabelDummies",!1),AO=new Ps("longEdgeBeforeLabelDummy",!1),tG=new Ps("edgeConstraint",(d2(),Ilt)),Pv=new Vi("inLayerLayoutUnit"),B2=new Ps("inLayerConstraint",(q0(),CO)),R6=new Ps("inLayerSuccessorConstraint",new he),sCt=new Ps("inLayerSuccessorConstraintBetweenNonDummies",!1),Ju=new Vi("portDummy"),JV=new Ps("crossingHint",pe(0)),Vc=new Ps("graphProperties",(e=u(Vf(jlt),9),new sh(e,u(ff(e,e.length),9),0))),oc=new Ps("externalPortSide",(ve(),Zo)),iCt=new Ps("externalPortSize",new Ca),Vlt=new Vi("externalPortReplacedDummies"),eG=new Vi("externalPortReplacedDummy"),By=new Ps("externalPortConnections",(t=u(Vf(Xa),9),new sh(t,u(ff(t,t.length),9),0))),Fv=new Ps(Xfe,0),tCt=new Vi("barycenterAssociates"),z6=new Vi("TopSideComments"),N6=new Vi("BottomSideComments"),ZV=new Vi("CommentConnectionPort"),Ult=new Ps("inputCollect",!1),Ylt=new Ps("outputCollect",!1),_O=new Ps("cyclic",!1),rCt=new Vi("crossHierarchyMap"),Qlt=new Vi("targetOffset"),new Ps("splineLabelSize",new Ca),Q4=new Vi("spacings"),nG=new Ps("partitionConstraint",!1),Iv=new Vi("breakingPoint.info"),hCt=new Vi("splines.survivingEdge"),R2=new Vi("splines.route.start"),Z4=new Vi("splines.edgeChain"),lCt=new Vi("originalPortConstraints"),x7=new Vi("selfLoopHolder"),k7=new Vi("splines.nsPortY"),Tc=new Vi("modelOrder"),Wlt=new Vi("longEdgeTargetNode"),Ov=new Ps(D1e,!1),X4=new Ps(D1e,!1),Glt=new Vi("layerConstraints.hiddenNodes"),uCt=new Vi("layerConstraints.opposidePort"),Xlt=new Vi("targetNode.modelOrder")}function Fxt(){Fxt=Z,kCt=(LD(),GV),gwe=new mn(C6t,kCt),_we=new mn(_6t,(Nn(),!1)),ACt=(I$(),Hlt),Dwe=new mn(sH,ACt),Uwe=new mn(S6t,!1),Wwe=new mn(A6t,!0),H2e=new mn(L6t,!1),NCt=(CD(),Tht),cve=new mn(M6t,NCt),pe(1),bve=new mn(D6t,pe(7)),wve=new mn(I6t,!1),Swe=new mn(O6t,!1),xCt=(x2(),Mlt),dwe=new mn(Qot,xCt),DCt=(uq(),wht),Gwe=new mn(KI,DCt),LCt=(dh(),MO),Bwe=new mn(P6t,LCt),pe(-1),Nwe=new mn(F6t,pe(-1)),pe(-1),Rwe=new mn(N6t,pe(-1)),pe(-1),jwe=new mn(Zot,pe(4)),pe(-1),zwe=new mn(Jot,pe(2)),MCt=(y4(),kG),Vwe=new mn(tct,MCt),pe(0),Hwe=new mn(ect,pe(0)),Pwe=new mn(nct,pe(wi)),yCt=(n6(),P6),fwe=new mn(H_,yCt),J2e=new mn(B6t,!1),awe=new mn(rct,.1),lwe=new mn(ict,!1),pe(-1),cwe=new mn(R6t,pe(-1)),pe(-1),uwe=new mn(j6t,pe(-1)),pe(0),twe=new mn($6t,pe(40)),mCt=(eE(),zlt),iwe=new mn(sct,mCt),vCt=TO,ewe=new mn(aH,vCt),FCt=(u_(),DS),ove=new mn(I4,FCt),Zwe=new Vi(oH),ICt=(xD(),WV),Ywe=new mn(act,ICt),OCt=(oI(),YV),Xwe=new mn(oct,OCt),eve=new mn(cct,.3),rve=new Vi(uct),PCt=(cy(),xG),ive=new mn(lct,PCt),CCt=(yz(),_ht),mwe=new mn(z6t,CCt),_Ct=(pD(),Sht),ywe=new mn(q6t,_Ct),SCt=(cE(),PS),xwe=new mn(cH,SCt),Ewe=new mn(uH,.2),wwe=new mn(hct,2),fve=new mn(H6t,null),gve=new mn(V6t,10),dve=new mn(G6t,10),pve=new mn(U6t,20),pe(0),uve=new mn(W6t,pe(0)),pe(0),lve=new mn(Y6t,pe(0)),pe(0),hve=new mn(K6t,pe(0)),V2e=new mn(fct,!1),gCt=(kE(),mS),U2e=new mn(X6t,gCt),dCt=(H$(),Alt),G2e=new mn(Q6t,dCt),Lwe=new mn(lH,!1),pe(0),Awe=new mn(dct,pe(16)),pe(0),Mwe=new mn(gct,pe(5)),jCt=(Cz(),Mht),Bve=new mn(tg,jCt),vve=new mn(hH,10),xve=new mn(fH,1),RCt=(oz(),VV),Ave=new mn(V_,RCt),Tve=new Vi(pct),BCt=pe(1),pe(0),_ve=new mn(bct,BCt),$Ct=(vz(),Lht),zve=new mn(dH,$Ct),Rve=new Vi(gH),Ove=new mn(pH,!0),Dve=new mn(bH,2),Fve=new mn(wct,!0),TCt=(dq(),UV),bwe=new mn(Z6t,TCt),ECt=(h6(),p7),pwe=new mn(J6t,ECt),wCt=(V0(),vb),Z2e=new mn(wH,wCt),Q2e=new mn(tkt,!1),pCt=(iv(),q4),W2e=new mn(vct,pCt),bCt=(Z9(),vht),X2e=new mn(ekt,bCt),Y2e=new mn(mct,0),K2e=new mn(yct,0),Owe=Dlt,Iwe=EO,$we=mG,qwe=mG,Fwe=bht,owe=(G0(),sp),hwe=P6,swe=P6,nwe=P6,rwe=sp,Jwe=IS,tve=DS,Kwe=DS,Qwe=DS,nve=kht,ave=IS,sve=IS,kwe=(W0(),X6),Twe=X6,Cwe=PS,vwe=eP,mve=L7,yve=Yy,kve=L7,Eve=Yy,Lve=L7,Mve=Yy,Cve=Llt,Sve=VV,qve=L7,Hve=Yy,jve=L7,$ve=Yy,Pve=Yy,Ive=Yy,Nve=Yy}function ro(){ro=Z,J7t=new ms("DIRECTION_PREPROCESSOR",0),X7t=new ms("COMMENT_PREPROCESSOR",1),gS=new ms("EDGE_AND_LAYER_CONSTRAINT_EDGE_REVERSER",2),glt=new ms("INTERACTIVE_EXTERNAL_PORT_POSITIONER",3),vTt=new ms("PARTITION_PREPROCESSOR",4),CV=new ms("LABEL_DUMMY_INSERTER",5),FV=new ms("SELF_LOOP_PREPROCESSOR",6),h7=new ms("LAYER_CONSTRAINT_PREPROCESSOR",7),bTt=new ms("PARTITION_MIDPROCESSOR",8),oTt=new ms("HIGH_DEGREE_NODE_LAYER_PROCESSOR",9),gTt=new ms("NODE_PROMOTION",10),l7=new ms("LAYER_CONSTRAINT_POSTPROCESSOR",11),wTt=new ms("PARTITION_POSTPROCESSOR",12),iTt=new ms("HIERARCHICAL_PORT_CONSTRAINT_PROCESSOR",13),mTt=new ms("SEMI_INTERACTIVE_CROSSMIN_PROCESSOR",14),V7t=new ms("BREAKING_POINT_INSERTER",15),LV=new ms("LONG_EDGE_SPLITTER",16),plt=new ms("PORT_SIDE_PROCESSOR",17),EV=new ms("INVERTED_PORT_PROCESSOR",18),IV=new ms("PORT_LIST_SORTER",19),xTt=new ms("SORT_BY_INPUT_ORDER_OF_MODEL",20),DV=new ms("NORTH_SOUTH_PORT_PREPROCESSOR",21),G7t=new ms("BREAKING_POINT_PROCESSOR",22),pTt=new ms(E1e,23),kTt=new ms(T1e,24),OV=new ms("SELF_LOOP_PORT_RESTORER",25),yTt=new ms("SINGLE_EDGE_GRAPH_WRAPPER",26),TV=new ms("IN_LAYER_CONSTRAINT_PROCESSOR",27),eTt=new ms("END_NODE_PORT_LABEL_MANAGEMENT_PROCESSOR",28),fTt=new ms("LABEL_AND_NODE_SIZE_PROCESSOR",29),hTt=new ms("INNERMOST_NODE_MARGIN_CALCULATOR",30),NV=new ms("SELF_LOOP_ROUTER",31),Y7t=new ms("COMMENT_NODE_MARGIN_CALCULATOR",32),kV=new ms("END_LABEL_PREPROCESSOR",33),SV=new ms("LABEL_DUMMY_SWITCHER",34),W7t=new ms("CENTER_LABEL_MANAGEMENT_PROCESSOR",35),u7=new ms("LABEL_SIDE_SELECTOR",36),uTt=new ms("HYPEREDGE_DUMMY_MERGER",37),sTt=new ms("HIERARCHICAL_PORT_DUMMY_SIZE_PROCESSOR",38),dTt=new ms("LAYER_SIZE_AND_GRAPH_HEIGHT_CALCULATOR",39),pS=new ms("HIERARCHICAL_PORT_POSITION_PROCESSOR",40),Q7t=new ms("CONSTRAINTS_POSTPROCESSOR",41),K7t=new ms("COMMENT_POSTPROCESSOR",42),lTt=new ms("HYPERNODE_PROCESSOR",43),aTt=new ms("HIERARCHICAL_PORT_ORTHOGONAL_EDGE_ROUTER",44),AV=new ms("LONG_EDGE_JOINER",45),PV=new ms("SELF_LOOP_POSTPROCESSOR",46),U7t=new ms("BREAKING_POINT_REMOVER",47),MV=new ms("NORTH_SOUTH_PORT_POSTPROCESSOR",48),cTt=new ms("HORIZONTAL_COMPACTOR",49),_V=new ms("LABEL_DUMMY_REMOVER",50),nTt=new ms("FINAL_SPLINE_BENDPOINTS_CALCULATOR",51),tTt=new ms("END_LABEL_SORTER",52),xO=new ms("REVERSED_EDGE_RESTORER",53),xV=new ms("END_LABEL_POSTPROCESSOR",54),rTt=new ms("HIERARCHICAL_NODE_RESIZER",55),Z7t=new ms("DIRECTION_POSTPROCESSOR",56)}function zxn(t,e,n){var r,s,o,h,d,v,k,C,M,j,H,G,K,tt,gt,Mt,St,Rt,Kt,ue,_e,We,Qe,Rn,zn,hr,pi,js,Zl,Xh,K1,kU,xP,bA,kP,H7,Gft,ixe,Uft,hp,Yv,V7,EP,TP,nk,Wft,wA,sxe,BLt,Kv,vA,Yft,rk,mA,o3,yA,Kft,axe;for(BLt=0,pi=e,Xh=0,xP=pi.length;Xh0&&(t.a[hp.p]=BLt++)}for(mA=0,js=n,K1=0,bA=js.length;K10;){for(hp=(Zn(TP.b>0),u(TP.a.Xb(TP.c=--TP.b),11)),EP=0,d=new S(hp.e);d.a0&&(hp.j==(ve(),Pn)?(t.a[hp.p]=mA,++mA):(t.a[hp.p]=mA+kP+Gft,++Gft))}mA+=Gft}for(V7=new _r,G=new O0,hr=e,Zl=0,kU=hr.length;Zlk.b&&(k.b=nk)):hp.i.c==sxe&&(nkk.c&&(k.c=nk));for($8(K,0,K.length,null),rk=Nt(Cr,Xr,25,K.length,15,1),r=Nt(Cr,Xr,25,mA+1,15,1),gt=0;gt0;)_e%2>0&&(s+=Kft[_e+1]),_e=(_e-1)/2|0,++Kft[_e];for(Qe=Nt(Ime,De,362,K.length*2,0,1),Rt=0;Rt'?":hn(t0e,t)?"'(?<' or '(? toIndex: ",Yxt=", toIndex: ",Kxt="Index: ",Xxt=", Size: ",zE="org.eclipse.elk.alg.common",Oi={62:1},Ife="org.eclipse.elk.alg.common.compaction",Ofe="Scanline/EventHandler",a0="org.eclipse.elk.alg.common.compaction.oned",Pfe="CNode belongs to another CGroup.",Ffe="ISpacingsHandler/1",Sot="The ",Aot=" instance has been finished already.",Nfe="The direction ",Bfe=" is not supported by the CGraph instance.",Rfe="OneDimensionalCompactor",jfe="OneDimensionalCompactor/lambda$0$Type",$fe="Quadruplet",zfe="ScanlineConstraintCalculator",qfe="ScanlineConstraintCalculator/ConstraintsScanlineHandler",Hfe="ScanlineConstraintCalculator/ConstraintsScanlineHandler/lambda$0$Type",Vfe="ScanlineConstraintCalculator/Timestamp",Gfe="ScanlineConstraintCalculator/lambda$0$Type",xd={169:1,45:1},Lot="org.eclipse.elk.alg.common.compaction.options",Qo="org.eclipse.elk.core.data",Qxt="org.eclipse.elk.polyomino.traversalStrategy",Zxt="org.eclipse.elk.polyomino.lowLevelSort",Jxt="org.eclipse.elk.polyomino.highLevelSort",t6t="org.eclipse.elk.polyomino.fill",Oh={130:1},Mot="polyomino",F_="org.eclipse.elk.alg.common.networksimplex",o0={177:1,3:1,4:1},Ufe="org.eclipse.elk.alg.common.nodespacing",_2="org.eclipse.elk.alg.common.nodespacing.cellsystem",qE="CENTER",Wfe={212:1,326:1},e6t={3:1,4:1,5:1,595:1},y6="LEFT",x6="RIGHT",n6t="Vertical alignment cannot be null",r6t="BOTTOM",Yq="org.eclipse.elk.alg.common.nodespacing.internal",N_="UNDEFINED",B1=.01,zI="org.eclipse.elk.alg.common.nodespacing.internal.algorithm",Yfe="LabelPlacer/lambda$0$Type",Kfe="LabelPlacer/lambda$1$Type",Xfe="portRatioOrPosition",HE="org.eclipse.elk.alg.common.overlaps",Dot="DOWN",kd="org.eclipse.elk.alg.common.polyomino",Kq="NORTH",Iot="EAST",Oot="SOUTH",Pot="WEST",Xq="org.eclipse.elk.alg.common.polyomino.structures",i6t="Direction",Fot="Grid is only of size ",Not=". Requested point (",Bot=") is out of bounds.",Qq=" Given center based coordinates were (",qI="org.eclipse.elk.graph.properties",Qfe="IPropertyHolder",s6t={3:1,94:1,134:1},k6="org.eclipse.elk.alg.common.spore",Zfe="org.eclipse.elk.alg.common.utils",S2={209:1},L4="org.eclipse.elk.core",Jfe="Connected Components Compaction",t1e="org.eclipse.elk.alg.disco",Zq="org.eclipse.elk.alg.disco.graph",Rot="org.eclipse.elk.alg.disco.options",a6t="CompactionStrategy",o6t="org.eclipse.elk.disco.componentCompaction.strategy",c6t="org.eclipse.elk.disco.componentCompaction.componentLayoutAlgorithm",u6t="org.eclipse.elk.disco.debug.discoGraph",l6t="org.eclipse.elk.disco.debug.discoPolys",e1e="componentCompaction",A2="org.eclipse.elk.disco",jot="org.eclipse.elk.spacing.componentComponent",$ot="org.eclipse.elk.edge.thickness",E6="org.eclipse.elk.aspectRatio",xv="org.eclipse.elk.padding",M4="org.eclipse.elk.alg.disco.transform",zot=1.5707963267948966,VE=17976931348623157e292,Ty={3:1,4:1,5:1,192:1},h6t={3:1,6:1,4:1,5:1,106:1,120:1},f6t="org.eclipse.elk.alg.force",d6t="ComponentsProcessor",n1e="ComponentsProcessor/1",HI="org.eclipse.elk.alg.force.graph",r1e="Component Layout",g6t="org.eclipse.elk.alg.force.model",Jq="org.eclipse.elk.force.model",p6t="org.eclipse.elk.force.iterations",b6t="org.eclipse.elk.force.repulsivePower",qot="org.eclipse.elk.force.temperature",Ed=.001,Hot="org.eclipse.elk.force.repulsion",B_="org.eclipse.elk.alg.force.options",GE=1.600000023841858,Vl="org.eclipse.elk.force",VI="org.eclipse.elk.priority",Cy="org.eclipse.elk.spacing.nodeNode",Vot="org.eclipse.elk.spacing.edgeLabel",tH="org.eclipse.elk.randomSeed",R_="org.eclipse.elk.separateConnectedComponents",GI="org.eclipse.elk.interactive",Got="org.eclipse.elk.portConstraints",eH="org.eclipse.elk.edgeLabels.inline",j_="org.eclipse.elk.omitNodeMicroLayout",T6="org.eclipse.elk.nodeSize.options",D4="org.eclipse.elk.nodeSize.constraints",UE="org.eclipse.elk.nodeLabels.placement",WE="org.eclipse.elk.portLabels.placement",w6t="origin",i1e="random",s1e="boundingBox.upLeft",a1e="boundingBox.lowRight",v6t="org.eclipse.elk.stress.fixed",m6t="org.eclipse.elk.stress.desiredEdgeLength",y6t="org.eclipse.elk.stress.dimension",x6t="org.eclipse.elk.stress.epsilon",k6t="org.eclipse.elk.stress.iterationLimit",ob="org.eclipse.elk.stress",o1e="ELK Stress",C6="org.eclipse.elk.nodeSize.minimum",nH="org.eclipse.elk.alg.force.stress",c1e="Layered layout",_6="org.eclipse.elk.alg.layered",UI="org.eclipse.elk.alg.layered.compaction.components",$_="org.eclipse.elk.alg.layered.compaction.oned",rH="org.eclipse.elk.alg.layered.compaction.oned.algs",L2="org.eclipse.elk.alg.layered.compaction.recthull",Td="org.eclipse.elk.alg.layered.components",J0="NONE",xc={3:1,6:1,4:1,9:1,5:1,122:1},u1e={3:1,6:1,4:1,5:1,141:1,106:1,120:1},iH="org.eclipse.elk.alg.layered.compound",os={51:1},tu="org.eclipse.elk.alg.layered.graph",Uot=" -> ",l1e="Not supported by LGraph",E6t="Port side is undefined",Wot={3:1,6:1,4:1,5:1,474:1,141:1,106:1,120:1},Yg={3:1,6:1,4:1,5:1,141:1,193:1,203:1,106:1,120:1},h1e={3:1,6:1,4:1,5:1,141:1,1943:1,203:1,106:1,120:1},f1e=`([{"' \r +`,d1e=`)]}"' \r +`,g1e="The given string contains parts that cannot be parsed as numbers.",WI="org.eclipse.elk.core.math",p1e={3:1,4:1,142:1,207:1,414:1},b1e={3:1,4:1,116:1,207:1,414:1},Gn="org.eclipse.elk.layered",Kg="org.eclipse.elk.alg.layered.graph.transform",w1e="ElkGraphImporter",v1e="ElkGraphImporter/lambda$0$Type",m1e="ElkGraphImporter/lambda$1$Type",y1e="ElkGraphImporter/lambda$2$Type",x1e="ElkGraphImporter/lambda$4$Type",k1e="Node margin calculation",$n="org.eclipse.elk.alg.layered.intermediate",E1e="ONE_SIDED_GREEDY_SWITCH",T1e="TWO_SIDED_GREEDY_SWITCH",Yot="No implementation is available for the layout processor ",T6t="IntermediateProcessorStrategy",Kot="Node '",C1e="FIRST_SEPARATE",_1e="LAST_SEPARATE",S1e="Odd port side processing",_s="org.eclipse.elk.alg.layered.intermediate.compaction",z_="org.eclipse.elk.alg.layered.intermediate.greedyswitch",c0="org.eclipse.elk.alg.layered.p3order.counting",YI={225:1},S6="org.eclipse.elk.alg.layered.intermediate.loops",Gl="org.eclipse.elk.alg.layered.intermediate.loops.ordering",cb="org.eclipse.elk.alg.layered.intermediate.loops.routing",q_="org.eclipse.elk.alg.layered.intermediate.preserveorder",Cd="org.eclipse.elk.alg.layered.intermediate.wrapping",kc="org.eclipse.elk.alg.layered.options",Xot="INTERACTIVE",A1e="DEPTH_FIRST",L1e="EDGE_LENGTH",M1e="SELF_LOOPS",D1e="firstTryWithInitialOrder",C6t="org.eclipse.elk.layered.directionCongruency",_6t="org.eclipse.elk.layered.feedbackEdges",sH="org.eclipse.elk.layered.interactiveReferencePoint",S6t="org.eclipse.elk.layered.mergeEdges",A6t="org.eclipse.elk.layered.mergeHierarchyEdges",L6t="org.eclipse.elk.layered.allowNonFlowPortsToSwitchSides",M6t="org.eclipse.elk.layered.portSortingStrategy",D6t="org.eclipse.elk.layered.thoroughness",I6t="org.eclipse.elk.layered.unnecessaryBendpoints",O6t="org.eclipse.elk.layered.generatePositionAndLayerIds",Qot="org.eclipse.elk.layered.cycleBreaking.strategy",KI="org.eclipse.elk.layered.layering.strategy",P6t="org.eclipse.elk.layered.layering.layerConstraint",F6t="org.eclipse.elk.layered.layering.layerChoiceConstraint",N6t="org.eclipse.elk.layered.layering.layerId",Zot="org.eclipse.elk.layered.layering.minWidth.upperBoundOnWidth",Jot="org.eclipse.elk.layered.layering.minWidth.upperLayerEstimationScalingFactor",tct="org.eclipse.elk.layered.layering.nodePromotion.strategy",ect="org.eclipse.elk.layered.layering.nodePromotion.maxIterations",nct="org.eclipse.elk.layered.layering.coffmanGraham.layerBound",H_="org.eclipse.elk.layered.crossingMinimization.strategy",B6t="org.eclipse.elk.layered.crossingMinimization.forceNodeModelOrder",rct="org.eclipse.elk.layered.crossingMinimization.hierarchicalSweepiness",ict="org.eclipse.elk.layered.crossingMinimization.semiInteractive",R6t="org.eclipse.elk.layered.crossingMinimization.positionChoiceConstraint",j6t="org.eclipse.elk.layered.crossingMinimization.positionId",$6t="org.eclipse.elk.layered.crossingMinimization.greedySwitch.activationThreshold",sct="org.eclipse.elk.layered.crossingMinimization.greedySwitch.type",aH="org.eclipse.elk.layered.crossingMinimization.greedySwitchHierarchical.type",I4="org.eclipse.elk.layered.nodePlacement.strategy",oH="org.eclipse.elk.layered.nodePlacement.favorStraightEdges",act="org.eclipse.elk.layered.nodePlacement.bk.edgeStraightening",oct="org.eclipse.elk.layered.nodePlacement.bk.fixedAlignment",cct="org.eclipse.elk.layered.nodePlacement.linearSegments.deflectionDampening",uct="org.eclipse.elk.layered.nodePlacement.networkSimplex.nodeFlexibility",lct="org.eclipse.elk.layered.nodePlacement.networkSimplex.nodeFlexibility.default",z6t="org.eclipse.elk.layered.edgeRouting.selfLoopDistribution",q6t="org.eclipse.elk.layered.edgeRouting.selfLoopOrdering",cH="org.eclipse.elk.layered.edgeRouting.splines.mode",uH="org.eclipse.elk.layered.edgeRouting.splines.sloppy.layerSpacingFactor",hct="org.eclipse.elk.layered.edgeRouting.polyline.slopedEdgeZoneWidth",H6t="org.eclipse.elk.layered.spacing.baseValue",V6t="org.eclipse.elk.layered.spacing.edgeNodeBetweenLayers",G6t="org.eclipse.elk.layered.spacing.edgeEdgeBetweenLayers",U6t="org.eclipse.elk.layered.spacing.nodeNodeBetweenLayers",W6t="org.eclipse.elk.layered.priority.direction",Y6t="org.eclipse.elk.layered.priority.shortness",K6t="org.eclipse.elk.layered.priority.straightness",fct="org.eclipse.elk.layered.compaction.connectedComponents",X6t="org.eclipse.elk.layered.compaction.postCompaction.strategy",Q6t="org.eclipse.elk.layered.compaction.postCompaction.constraints",lH="org.eclipse.elk.layered.highDegreeNodes.treatment",dct="org.eclipse.elk.layered.highDegreeNodes.threshold",gct="org.eclipse.elk.layered.highDegreeNodes.treeHeight",tg="org.eclipse.elk.layered.wrapping.strategy",hH="org.eclipse.elk.layered.wrapping.additionalEdgeSpacing",fH="org.eclipse.elk.layered.wrapping.correctionFactor",V_="org.eclipse.elk.layered.wrapping.cutting.strategy",pct="org.eclipse.elk.layered.wrapping.cutting.cuts",bct="org.eclipse.elk.layered.wrapping.cutting.msd.freedom",dH="org.eclipse.elk.layered.wrapping.validify.strategy",gH="org.eclipse.elk.layered.wrapping.validify.forbiddenIndices",pH="org.eclipse.elk.layered.wrapping.multiEdge.improveCuts",bH="org.eclipse.elk.layered.wrapping.multiEdge.distancePenalty",wct="org.eclipse.elk.layered.wrapping.multiEdge.improveWrappedEdges",Z6t="org.eclipse.elk.layered.edgeLabels.sideSelection",J6t="org.eclipse.elk.layered.edgeLabels.centerLabelPlacementStrategy",wH="org.eclipse.elk.layered.considerModelOrder.strategy",tkt="org.eclipse.elk.layered.considerModelOrder.noModelOrder",vct="org.eclipse.elk.layered.considerModelOrder.components",ekt="org.eclipse.elk.layered.considerModelOrder.longEdgeStrategy",mct="org.eclipse.elk.layered.considerModelOrder.crossingCounterNodeInfluence",yct="org.eclipse.elk.layered.considerModelOrder.crossingCounterPortInfluence",xct="layering",I1e="layering.minWidth",O1e="layering.nodePromotion",XI="crossingMinimization",vH="org.eclipse.elk.hierarchyHandling",P1e="crossingMinimization.greedySwitch",F1e="nodePlacement",N1e="nodePlacement.bk",B1e="edgeRouting",QI="org.eclipse.elk.edgeRouting",R1="spacing",nkt="priority",rkt="compaction",R1e="compaction.postCompaction",j1e="Specifies whether and how post-process compaction is applied.",ikt="highDegreeNodes",skt="wrapping",$1e="wrapping.cutting",z1e="wrapping.validify",akt="wrapping.multiEdge",kct="edgeLabels",ZI="considerModelOrder",okt="org.eclipse.elk.spacing.commentComment",ckt="org.eclipse.elk.spacing.commentNode",ukt="org.eclipse.elk.spacing.edgeEdge",lkt="org.eclipse.elk.spacing.edgeNode",hkt="org.eclipse.elk.spacing.labelLabel",fkt="org.eclipse.elk.spacing.labelPortHorizontal",dkt="org.eclipse.elk.spacing.labelPortVertical",gkt="org.eclipse.elk.spacing.labelNode",pkt="org.eclipse.elk.spacing.nodeSelfLoop",bkt="org.eclipse.elk.spacing.portPort",wkt="org.eclipse.elk.spacing.individual",vkt="org.eclipse.elk.port.borderOffset",mkt="org.eclipse.elk.noLayout",ykt="org.eclipse.elk.port.side",JI="org.eclipse.elk.debugMode",xkt="org.eclipse.elk.alignment",kkt="org.eclipse.elk.insideSelfLoops.activate",Ekt="org.eclipse.elk.insideSelfLoops.yo",Ect="org.eclipse.elk.nodeSize.fixedGraphSize",Tkt="org.eclipse.elk.direction",Ckt="org.eclipse.elk.nodeLabels.padding",_kt="org.eclipse.elk.portLabels.nextToPortIfPossible",Skt="org.eclipse.elk.portLabels.treatAsGroup",Akt="org.eclipse.elk.portAlignment.default",Lkt="org.eclipse.elk.portAlignment.north",Mkt="org.eclipse.elk.portAlignment.south",Dkt="org.eclipse.elk.portAlignment.west",Ikt="org.eclipse.elk.portAlignment.east",mH="org.eclipse.elk.contentAlignment",Okt="org.eclipse.elk.junctionPoints",Pkt="org.eclipse.elk.edgeLabels.placement",Fkt="org.eclipse.elk.port.index",Nkt="org.eclipse.elk.commentBox",Bkt="org.eclipse.elk.hypernode",Rkt="org.eclipse.elk.port.anchor",Tct="org.eclipse.elk.partitioning.activate",Cct="org.eclipse.elk.partitioning.partition",yH="org.eclipse.elk.position",jkt="org.eclipse.elk.margins",$kt="org.eclipse.elk.spacing.portsSurrounding",_ct="org.eclipse.elk.interactiveLayout",Ec="org.eclipse.elk.core.util",zkt={3:1,4:1,5:1,593:1},q1e="NETWORK_SIMPLEX",zc={123:1,51:1},xH="org.eclipse.elk.alg.layered.p1cycles",_y="org.eclipse.elk.alg.layered.p2layers",qkt={402:1,225:1},H1e={832:1,3:1,4:1},qu="org.eclipse.elk.alg.layered.p3order",uo="org.eclipse.elk.alg.layered.p4nodes",V1e={3:1,4:1,5:1,840:1},_d=1e-5,ub="org.eclipse.elk.alg.layered.p4nodes.bk",Sct="org.eclipse.elk.alg.layered.p5edges",t1="org.eclipse.elk.alg.layered.p5edges.orthogonal",Act="org.eclipse.elk.alg.layered.p5edges.orthogonal.direction",Lct=1e-6,Sy="org.eclipse.elk.alg.layered.p5edges.splines",Mct=.09999999999999998,kH=1e-8,G1e=4.71238898038469,U1e=3.141592653589793,G_="org.eclipse.elk.alg.mrtree",U_="org.eclipse.elk.alg.mrtree.graph",A6="org.eclipse.elk.alg.mrtree.intermediate",W1e="Set neighbors in level",Y1e="DESCENDANTS",Hkt="org.eclipse.elk.mrtree.weighting",Vkt="org.eclipse.elk.mrtree.searchOrder",EH="org.eclipse.elk.alg.mrtree.options",Xg="org.eclipse.elk.mrtree",K1e="org.eclipse.elk.tree",Gkt="org.eclipse.elk.alg.radial",O4=6.283185307179586,Ukt=5e-324,X1e="org.eclipse.elk.alg.radial.intermediate",Dct="org.eclipse.elk.alg.radial.intermediate.compaction",Q1e={3:1,4:1,5:1,106:1},Wkt="org.eclipse.elk.alg.radial.intermediate.optimization",Ict="No implementation is available for the layout option ",W_="org.eclipse.elk.alg.radial.options",Ykt="org.eclipse.elk.radial.orderId",Kkt="org.eclipse.elk.radial.radius",Oct="org.eclipse.elk.radial.compactor",Pct="org.eclipse.elk.radial.compactionStepSize",Xkt="org.eclipse.elk.radial.sorter",Qkt="org.eclipse.elk.radial.wedgeCriteria",Zkt="org.eclipse.elk.radial.optimizationCriteria",Sd="org.eclipse.elk.radial",Z1e="org.eclipse.elk.alg.radial.p1position.wedge",Jkt="org.eclipse.elk.alg.radial.sorting",J1e=5.497787143782138,tde=3.9269908169872414,ede=2.356194490192345,nde="org.eclipse.elk.alg.rectpacking",TH="org.eclipse.elk.alg.rectpacking.firstiteration",Fct="org.eclipse.elk.alg.rectpacking.options",t8t="org.eclipse.elk.rectpacking.optimizationGoal",e8t="org.eclipse.elk.rectpacking.lastPlaceShift",n8t="org.eclipse.elk.rectpacking.currentPosition",r8t="org.eclipse.elk.rectpacking.desiredPosition",i8t="org.eclipse.elk.rectpacking.onlyFirstIteration",s8t="org.eclipse.elk.rectpacking.rowCompaction",Nct="org.eclipse.elk.rectpacking.expandToAspectRatio",a8t="org.eclipse.elk.rectpacking.targetWidth",CH="org.eclipse.elk.expandNodes",Ph="org.eclipse.elk.rectpacking",tO="org.eclipse.elk.alg.rectpacking.util",_H="No implementation available for ",Ay="org.eclipse.elk.alg.spore",Ly="org.eclipse.elk.alg.spore.options",kv="org.eclipse.elk.sporeCompaction",Bct="org.eclipse.elk.underlyingLayoutAlgorithm",o8t="org.eclipse.elk.processingOrder.treeConstruction",c8t="org.eclipse.elk.processingOrder.spanningTreeCostFunction",Rct="org.eclipse.elk.processingOrder.preferredRoot",jct="org.eclipse.elk.processingOrder.rootSelection",$ct="org.eclipse.elk.structure.structureExtractionStrategy",u8t="org.eclipse.elk.compaction.compactionStrategy",l8t="org.eclipse.elk.compaction.orthogonal",h8t="org.eclipse.elk.overlapRemoval.maxIterations",f8t="org.eclipse.elk.overlapRemoval.runScanline",zct="processingOrder",rde="overlapRemoval",YE="org.eclipse.elk.sporeOverlap",ide="org.eclipse.elk.alg.spore.p1structure",qct="org.eclipse.elk.alg.spore.p2processingorder",Hct="org.eclipse.elk.alg.spore.p3execution",sde="Invalid index: ",KE="org.eclipse.elk.core.alg",P4={331:1},My={288:1},ade="Make sure its type is registered with the ",d8t=" utility class.",XE="true",Vct="false",ode="Couldn't clone property '",Ev=.05,Fh="org.eclipse.elk.core.options",cde=1.2999999523162842,Tv="org.eclipse.elk.box",g8t="org.eclipse.elk.box.packingMode",ude="org.eclipse.elk.algorithm",lde="org.eclipse.elk.resolvedAlgorithm",p8t="org.eclipse.elk.bendPoints",Uxn="org.eclipse.elk.labelManager",hde="org.eclipse.elk.scaleFactor",fde="org.eclipse.elk.animate",dde="org.eclipse.elk.animTimeFactor",gde="org.eclipse.elk.layoutAncestors",pde="org.eclipse.elk.maxAnimTime",bde="org.eclipse.elk.minAnimTime",wde="org.eclipse.elk.progressBar",vde="org.eclipse.elk.validateGraph",mde="org.eclipse.elk.validateOptions",yde="org.eclipse.elk.zoomToFit",Wxn="org.eclipse.elk.font.name",xde="org.eclipse.elk.font.size",kde="org.eclipse.elk.edge.type",Ede="partitioning",Tde="nodeLabels",SH="portAlignment",Gct="nodeSize",Uct="port",b8t="portLabels",Cde="insideSelfLoops",Y_="org.eclipse.elk.fixed",AH="org.eclipse.elk.random",_de="port must have a parent node to calculate the port side",Sde="The edge needs to have exactly one edge section. Found: ",K_="org.eclipse.elk.core.util.adapters",ph="org.eclipse.emf.ecore",F4="org.eclipse.elk.graph",Ade="EMapPropertyHolder",Lde="ElkBendPoint",Mde="ElkGraphElement",Dde="ElkConnectableShape",w8t="ElkEdge",Ide="ElkEdgeSection",Ode="EModelElement",Pde="ENamedElement",v8t="ElkLabel",m8t="ElkNode",y8t="ElkPort",Fde={92:1,90:1},L6="org.eclipse.emf.common.notify.impl",lb="The feature '",X_="' is not a valid changeable feature",Nde="Expecting null",Wct="' is not a valid feature",Bde="The feature ID",Rde=" is not a valid feature ID",dc=32768,jde={105:1,92:1,90:1,56:1,49:1,97:1},Mn="org.eclipse.emf.ecore.impl",M2="org.eclipse.elk.graph.impl",Q_="Recursive containment not allowed for ",QE="The datatype '",Cv="' is not a valid classifier",Yct="The value '",N4={190:1,3:1,4:1},Kct="The class '",ZE="http://www.eclipse.org/elk/ElkGraph",xf=1024,x8t="property",Z_="value",Xct="source",$de="properties",zde="identifier",Qct="height",Zct="width",Jct="parent",tut="text",eut="children",qde="hierarchical",k8t="sources",nut="targets",E8t="sections",LH="bendPoints",T8t="outgoingShape",C8t="incomingShape",_8t="outgoingSections",S8t="incomingSections",Ra="org.eclipse.emf.common.util",A8t="Severe implementation error in the Json to ElkGraph importer.",Ad="id",ma="org.eclipse.elk.graph.json",L8t="Unhandled parameter types: ",Hde="startPoint",Vde="An edge must have at least one source and one target (edge id: '",JE="').",Gde="Referenced edge section does not exist: ",Ude=" (edge id: '",M8t="target",Wde="sourcePoint",Yde="targetPoint",MH="group",ci="name",Kde="connectableShape cannot be null",Xde="edge cannot be null",rut="Passed edge is not 'simple'.",DH="org.eclipse.elk.graph.util",eO="The 'no duplicates' constraint is violated",iut="targetIndex=",D2=", size=",sut="sourceIndex=",Ld={3:1,4:1,20:1,28:1,52:1,14:1,15:1,54:1,67:1,63:1,58:1},aut={3:1,4:1,20:1,28:1,52:1,14:1,47:1,15:1,54:1,67:1,63:1,58:1,588:1},IH="logging",Qde="measureExecutionTime",Zde="parser.parse.1",Jde="parser.parse.2",OH="parser.next.1",out="parser.next.2",t0e="parser.next.3",e0e="parser.next.4",I2="parser.factor.1",D8t="parser.factor.2",n0e="parser.factor.3",r0e="parser.factor.4",i0e="parser.factor.5",s0e="parser.factor.6",a0e="parser.atom.1",o0e="parser.atom.2",c0e="parser.atom.3",I8t="parser.atom.4",cut="parser.atom.5",O8t="parser.cc.1",PH="parser.cc.2",u0e="parser.cc.3",l0e="parser.cc.5",P8t="parser.cc.6",F8t="parser.cc.7",uut="parser.cc.8",h0e="parser.ope.1",f0e="parser.ope.2",d0e="parser.ope.3",Qg="parser.descape.1",g0e="parser.descape.2",p0e="parser.descape.3",b0e="parser.descape.4",w0e="parser.descape.5",bh="parser.process.1",v0e="parser.quantifier.1",m0e="parser.quantifier.2",y0e="parser.quantifier.3",x0e="parser.quantifier.4",N8t="parser.quantifier.5",k0e="org.eclipse.emf.common.notify",B8t={415:1,672:1},E0e={3:1,4:1,20:1,28:1,52:1,14:1,15:1,67:1,58:1},nO={366:1,143:1},J_="index=",lut={3:1,4:1,5:1,126:1},T0e={3:1,4:1,20:1,28:1,52:1,14:1,15:1,54:1,67:1,58:1},R8t={3:1,6:1,4:1,5:1,192:1},C0e={3:1,4:1,5:1,165:1,367:1},_0e=";/?:@&=+$,",S0e="invalid authority: ",A0e="EAnnotation",L0e="ETypedElement",M0e="EStructuralFeature",D0e="EAttribute",I0e="EClassifier",O0e="EEnumLiteral",P0e="EGenericType",F0e="EOperation",N0e="EParameter",B0e="EReference",R0e="ETypeParameter",$i="org.eclipse.emf.ecore.util",hut={76:1},j8t={3:1,20:1,14:1,15:1,58:1,589:1,76:1,69:1,95:1},j0e="org.eclipse.emf.ecore.util.FeatureMap$Entry",Hu=8192,Dy=2048,tS="byte",FH="char",eS="double",nS="float",rS="int",iS="long",sS="short",$0e="java.lang.Object",B4={3:1,4:1,5:1,247:1},$8t={3:1,4:1,5:1,673:1},z0e={3:1,4:1,20:1,28:1,52:1,14:1,15:1,54:1,67:1,63:1,58:1,69:1},zo={3:1,4:1,20:1,28:1,52:1,14:1,15:1,54:1,67:1,63:1,58:1,76:1,69:1,95:1},rO="mixed",Yr="http:///org/eclipse/emf/ecore/util/ExtendedMetaData",Nh="kind",q0e={3:1,4:1,5:1,674:1},z8t={3:1,4:1,20:1,28:1,52:1,14:1,15:1,67:1,58:1,76:1,69:1,95:1},NH={20:1,28:1,52:1,14:1,15:1,58:1,69:1},BH={47:1,125:1,279:1},RH={72:1,332:1},jH="The value of type '",$H="' must be of type '",R4=1316,Bh="http://www.eclipse.org/emf/2002/Ecore",zH=-32768,_v="constraints",Aa="baseType",H0e="getEStructuralFeature",V0e="getFeatureID",aS="feature",G0e="getOperationID",q8t="operation",U0e="defaultValue",W0e="eTypeParameters",Y0e="isInstance",K0e="getEEnumLiteral",X0e="eContainingClass",si={55:1},Q0e={3:1,4:1,5:1,119:1},Z0e="org.eclipse.emf.ecore.resource",J0e={92:1,90:1,591:1,1935:1},fut="org.eclipse.emf.ecore.resource.impl",H8t="unspecified",iO="simple",qH="attribute",tge="attributeWildcard",HH="element",dut="elementWildcard",e1="collapse",gut="itemType",VH="namespace",sO="##targetNamespace",Rh="whiteSpace",V8t="wildcards",O2="http://www.eclipse.org/emf/2003/XMLType",put="##any",t7="uninitialized",aO="The multiplicity constraint is violated",GH="org.eclipse.emf.ecore.xml.type",ege="ProcessingInstruction",nge="SimpleAnyType",rge="XMLTypeDocumentRoot",xs="org.eclipse.emf.ecore.xml.type.impl",oO="INF",ige="processing",sge="ENTITIES_._base",G8t="minLength",U8t="ENTITY",UH="NCName",age="IDREFS_._base",W8t="integer",but="token",wut="pattern",oge="[a-zA-Z]{1,8}(-[a-zA-Z0-9]{1,8})*",Y8t="\\i\\c*",cge="[\\i-[:]][\\c-[:]]*",uge="nonPositiveInteger",cO="maxInclusive",K8t="NMTOKEN",lge="NMTOKENS_._base",X8t="nonNegativeInteger",uO="minInclusive",hge="normalizedString",fge="unsignedByte",dge="unsignedInt",gge="18446744073709551615",pge="unsignedShort",bge="processingInstruction",Zg="org.eclipse.emf.ecore.xml.type.internal",e7=1114111,wge="Internal Error: shorthands: \\u",oS="xml:isDigit",vut="xml:isWord",mut="xml:isSpace",yut="xml:isNameChar",xut="xml:isInitialNameChar",vge="09٠٩۰۹०९০৯੦੯૦૯୦୯௧௯౦౯೦೯൦൯๐๙໐໙༠༩",mge="AZazÀÖØöøıĴľŁňŊžƀǃǍǰǴǵǺȗɐʨʻˁΆΆΈΊΌΌΎΡΣώϐϖϚϚϜϜϞϞϠϠϢϳЁЌЎяёќўҁҐӄӇӈӋӌӐӫӮӵӸӹԱՖՙՙաֆאתװײءغفيٱڷںھۀێېۓەەۥۦअहऽऽक़ॡঅঌএঐওনপরললশহড়ঢ়য়ৡৰৱਅਊਏਐਓਨਪਰਲਲ਼ਵਸ਼ਸਹਖ਼ੜਫ਼ਫ਼ੲੴઅઋઍઍએઑઓનપરલળવહઽઽૠૠଅଌଏଐଓନପରଲଳଶହଽଽଡ଼ଢ଼ୟୡஅஊஎஐஒகஙசஜஜஞடணதநபமவஷஹఅఌఎఐఒనపళవహౠౡಅಌಎಐಒನಪಳವಹೞೞೠೡഅഌഎഐഒനപഹൠൡกฮะะาำเๅກຂຄຄງຈຊຊຍຍດທນຟມຣລລວວສຫອຮະະາຳຽຽເໄཀཇཉཀྵႠჅაჶᄀᄀᄂᄃᄅᄇᄉᄉᄋᄌᄎᄒᄼᄼᄾᄾᅀᅀᅌᅌᅎᅎᅐᅐᅔᅕᅙᅙᅟᅡᅣᅣᅥᅥᅧᅧᅩᅩᅭᅮᅲᅳᅵᅵᆞᆞᆨᆨᆫᆫᆮᆯᆷᆸᆺᆺᆼᇂᇫᇫᇰᇰᇹᇹḀẛẠỹἀἕἘἝἠὅὈὍὐὗὙὙὛὛὝὝὟώᾀᾴᾶᾼιιῂῄῆῌῐΐῖΊῠῬῲῴῶῼΩΩKÅ℮℮ↀↂ〇〇〡〩ぁゔァヺㄅㄬ一龥가힣",yge="Private Use",kut="ASSIGNED",Eut="\0€ÿĀſƀɏɐʯʰ˿̀ͯͰϿЀӿ԰֏֐׿؀ۿ܀ݏހ޿ऀॿঀ৿਀੿઀૿଀୿஀௿ఀ౿ಀ೿ഀൿ඀෿฀๿຀໿ༀ࿿က႟Ⴀჿᄀᇿሀ፿Ꭰ᏿᐀ᙿ ᚟ᚠ᛿ក៿᠀᢯Ḁỿἀ῿ ⁰₟₠⃏⃐⃿℀⅏⅐↏←⇿∀⋿⌀⏿␀␿⑀⑟①⓿─╿▀▟■◿☀⛿✀➿⠀⣿⺀⻿⼀⿟⿰⿿ 〿぀ゟ゠ヿ㄀ㄯ㄰㆏㆐㆟ㆠㆿ㈀㋿㌀㏿㐀䶵一鿿ꀀ꒏꒐꓏가힣豈﫿ffﭏﭐ﷿︠︯︰﹏﹐﹯ﹰ﻾\uFEFF\uFEFF＀￯",Q8t="UNASSIGNED",n7={3:1,117:1},xge="org.eclipse.emf.ecore.xml.type.util",WH={3:1,4:1,5:1,368:1},Z8t="org.eclipse.xtext.xbase.lib",kge="Cannot add elements to a Range",Ege="Cannot set elements in a Range",Tge="Cannot remove elements from a Range",YH="locale",KH="default",XH="user.agent",l,QH,Tut;b.goog=b.goog||{},b.goog.global=b.goog.global||b,mgn(),D(1,null,{},_),l.Fb=function(e){return mUt(this,e)},l.Gb=function(){return this.gm},l.Hb=function(){return Pw(this)},l.Ib=function(){var e;return Ip(ol(this))+"@"+(e=Hi(this)>>>0,e.toString(16))},l.equals=function(t){return this.Fb(t)},l.hashCode=function(){return this.Hb()},l.toString=function(){return this.Ib()};var Cge,_ge,Sge;D(290,1,{290:1,2026:1},Lyt),l.le=function(e){var n;return n=new Lyt,n.i=4,e>1?n.c=NQt(this,e-1):n.c=this,n},l.me=function(){return P0(this),this.b},l.ne=function(){return Ip(this)},l.oe=function(){return P0(this),this.k},l.pe=function(){return(this.i&4)!=0},l.qe=function(){return(this.i&1)!=0},l.Ib=function(){return Vmt(this)},l.i=0;var Qn=F(Xo,"Object",1),J8t=F(Xo,"Class",290);D(1998,1,DI),F(II,"Optional",1998),D(1170,1998,DI,A),l.Fb=function(e){return e===this},l.Hb=function(){return 2040732332},l.Ib=function(){return"Optional.absent()"},l.Jb=function(e){return Lr(e),PC(),Cut};var Cut;F(II,"Absent",1170),D(628,1,{},vet),F(II,"Joiner",628);var Yxn=Ki(II,"Predicate");D(582,1,{169:1,582:1,3:1,45:1},mC),l.Mb=function(e){return kre(this,e)},l.Lb=function(e){return kre(this,e)},l.Fb=function(e){var n;return _t(e,582)?(n=u(e,582),k5t(this.a,n.a)):!1},l.Hb=function(){return Pyt(this.a)+306654252},l.Ib=function(){return spn(this.a)},F(II,"Predicates/AndPredicate",582),D(408,1998,{408:1,3:1},Wk),l.Fb=function(e){var n;return _t(e,408)?(n=u(e,408),yi(this.a,n.a)):!1},l.Hb=function(){return 1502476572+Hi(this.a)},l.Ib=function(){return cfe+this.a+")"},l.Jb=function(e){return new Wk(g$(e.Kb(this.a),"the Function passed to Optional.transform() must not return null."))},F(II,"Present",408),D(198,1,FE),l.Nb=function(e){ba(this,e)},l.Qb=function(){uHt()},F(Ke,"UnmodifiableIterator",198),D(1978,198,NE),l.Qb=function(){uHt()},l.Rb=function(e){throw it(new Or)},l.Wb=function(e){throw it(new Or)},F(Ke,"UnmodifiableListIterator",1978),D(386,1978,NE),l.Ob=function(){return this.c0},l.Pb=function(){if(this.c>=this.d)throw it(new lc);return this.Xb(this.c++)},l.Tb=function(){return this.c},l.Ub=function(){if(this.c<=0)throw it(new lc);return this.Xb(--this.c)},l.Vb=function(){return this.c-1},l.c=0,l.d=0,F(Ke,"AbstractIndexedListIterator",386),D(699,198,FE),l.Ob=function(){return bit(this)},l.Pb=function(){return Rmt(this)},l.e=1,F(Ke,"AbstractIterator",699),D(1986,1,{224:1}),l.Zb=function(){var e;return e=this.f,e||(this.f=this.ac())},l.Fb=function(e){return Pit(this,e)},l.Hb=function(){return Hi(this.Zb())},l.dc=function(){return this.gc()==0},l.ec=function(){return qx(this)},l.Ib=function(){return $o(this.Zb())},F(Ke,"AbstractMultimap",1986),D(726,1986,T2),l.$b=function(){cz(this)},l._b=function(e){return AHt(this,e)},l.ac=function(){return new l8(this,this.c)},l.ic=function(e){return this.hc()},l.bc=function(){return new K3(this,this.c)},l.jc=function(){return this.mc(this.hc())},l.kc=function(){return new Uqt(this)},l.lc=function(){return zst(this.c.vc().Nc(),new B,64,this.d)},l.cc=function(e){return Ai(this,e)},l.fc=function(e){return GD(this,e)},l.gc=function(){return this.d},l.mc=function(e){return wn(),new T(e)},l.nc=function(){return new Gqt(this)},l.oc=function(){return zst(this.c.Cc().Nc(),new I,64,this.d)},l.pc=function(e,n){return new q$(this,e,n,null)},l.d=0,F(Ke,"AbstractMapBasedMultimap",726),D(1631,726,T2),l.hc=function(){return new Xc(this.a)},l.jc=function(){return wn(),wn(),io},l.cc=function(e){return u(Ai(this,e),15)},l.fc=function(e){return u(GD(this,e),15)},l.Zb=function(){return Wx(this)},l.Fb=function(e){return Pit(this,e)},l.qc=function(e){return u(Ai(this,e),15)},l.rc=function(e){return u(GD(this,e),15)},l.mc=function(e){return iD(u(e,15))},l.pc=function(e,n){return zZt(this,e,u(n,15),null)},F(Ke,"AbstractListMultimap",1631),D(732,1,sa),l.Nb=function(e){ba(this,e)},l.Ob=function(){return this.c.Ob()||this.e.Ob()},l.Pb=function(){var e;return this.e.Ob()||(e=u(this.c.Pb(),42),this.b=e.cd(),this.a=u(e.dd(),14),this.e=this.a.Kc()),this.sc(this.b,this.e.Pb())},l.Qb=function(){this.e.Qb(),this.a.dc()&&this.c.Qb(),--this.d.d},F(Ke,"AbstractMapBasedMultimap/Itr",732),D(1099,732,sa,Gqt),l.sc=function(e,n){return n},F(Ke,"AbstractMapBasedMultimap/1",1099),D(1100,1,{},I),l.Kb=function(e){return u(e,14).Nc()},F(Ke,"AbstractMapBasedMultimap/1methodref$spliterator$Type",1100),D(1101,732,sa,Uqt),l.sc=function(e,n){return new Lw(e,n)},F(Ke,"AbstractMapBasedMultimap/2",1101);var tEt=Ki(pr,"Map");D(1967,1,mv),l.wc=function(e){K9(this,e)},l.yc=function(e,n,r){return Qit(this,e,n,r)},l.$b=function(){this.vc().$b()},l.tc=function(e){return Tst(this,e)},l._b=function(e){return!!C4t(this,e,!1)},l.uc=function(e){var n,r,s;for(r=this.vc().Kc();r.Ob();)if(n=u(r.Pb(),42),s=n.dd(),Vt(e)===Vt(s)||e!=null&&yi(e,s))return!0;return!1},l.Fb=function(e){var n,r,s;if(e===this)return!0;if(!_t(e,83)||(s=u(e,83),this.gc()!=s.gc()))return!1;for(r=s.vc().Kc();r.Ob();)if(n=u(r.Pb(),42),!this.tc(n))return!1;return!0},l.xc=function(e){return ec(C4t(this,e,!1))},l.Hb=function(){return Tyt(this.vc())},l.dc=function(){return this.gc()==0},l.ec=function(){return new Sm(this)},l.zc=function(e,n){throw it(new Sg("Put not supported on this map"))},l.Ac=function(e){Y9(this,e)},l.Bc=function(e){return ec(C4t(this,e,!0))},l.gc=function(){return this.vc().gc()},l.Ib=function(){return Tae(this)},l.Cc=function(){return new v1(this)},F(pr,"AbstractMap",1967),D(1987,1967,mv),l.bc=function(){return new FR(this)},l.vc=function(){return $Kt(this)},l.ec=function(){var e;return e=this.g,e||(this.g=this.bc())},l.Cc=function(){var e;return e=this.i,e||(this.i=new yVt(this))},F(Ke,"Maps/ViewCachingAbstractMap",1987),D(389,1987,mv,l8),l.xc=function(e){return zon(this,e)},l.Bc=function(e){return rln(this,e)},l.$b=function(){this.d==this.e.c?this.e.$b():Vj(new Uwt(this))},l._b=function(e){return eie(this.d,e)},l.Ec=function(){return new Yk(this)},l.Dc=function(){return this.Ec()},l.Fb=function(e){return this===e||yi(this.d,e)},l.Hb=function(){return Hi(this.d)},l.ec=function(){return this.e.ec()},l.gc=function(){return this.d.gc()},l.Ib=function(){return $o(this.d)},F(Ke,"AbstractMapBasedMultimap/AsMap",389);var j1=Ki(Xo,"Iterable");D(28,1,xy),l.Jc=function(e){va(this,e)},l.Lc=function(){return this.Oc()},l.Nc=function(){return new _n(this,0)},l.Oc=function(){return new Tn(null,this.Nc())},l.Fc=function(e){throw it(new Sg("Add not supported on this collection"))},l.Gc=function(e){return Ua(this,e)},l.$b=function(){Dvt(this)},l.Hc=function(e){return ay(this,e,!1)},l.Ic=function(e){return ND(this,e)},l.dc=function(){return this.gc()==0},l.Mc=function(e){return ay(this,e,!0)},l.Pc=function(){return svt(this)},l.Qc=function(e){return eI(this,e)},l.Ib=function(){return eb(this)},F(pr,"AbstractCollection",28);var jh=Ki(pr,"Set");D(N1,28,zu),l.Nc=function(){return new _n(this,1)},l.Fb=function(e){return Yie(this,e)},l.Hb=function(){return Tyt(this)},F(pr,"AbstractSet",N1),D(1970,N1,zu),F(Ke,"Sets/ImprovedAbstractSet",1970),D(1971,1970,zu),l.$b=function(){this.Rc().$b()},l.Hc=function(e){return Lie(this,e)},l.dc=function(){return this.Rc().dc()},l.Mc=function(e){var n;return this.Hc(e)?(n=u(e,42),this.Rc().ec().Mc(n.cd())):!1},l.gc=function(){return this.Rc().gc()},F(Ke,"Maps/EntrySet",1971),D(1097,1971,zu,Yk),l.Hc=function(e){return Jyt(this.a.d.vc(),e)},l.Kc=function(){return new Uwt(this.a)},l.Rc=function(){return this.a},l.Mc=function(e){var n;return Jyt(this.a.d.vc(),e)?(n=u(e,42),San(this.a.e,n.cd()),!0):!1},l.Nc=function(){return XM(this.a.d.vc().Nc(),new nR(this.a))},F(Ke,"AbstractMapBasedMultimap/AsMap/AsMapEntries",1097),D(1098,1,{},nR),l.Kb=function(e){return MJt(this.a,u(e,42))},F(Ke,"AbstractMapBasedMultimap/AsMap/AsMapEntries/0methodref$wrapEntry$Type",1098),D(730,1,sa,Uwt),l.Nb=function(e){ba(this,e)},l.Pb=function(){var e;return e=u(this.b.Pb(),42),this.a=u(e.dd(),14),MJt(this.c,e)},l.Ob=function(){return this.b.Ob()},l.Qb=function(){i4(!!this.a),this.b.Qb(),this.c.e.d-=this.a.gc(),this.a.$b(),this.a=null},F(Ke,"AbstractMapBasedMultimap/AsMap/AsMapIterator",730),D(532,1970,zu,FR),l.$b=function(){this.b.$b()},l.Hc=function(e){return this.b._b(e)},l.Jc=function(e){Lr(e),this.b.wc(new Ctt(e))},l.dc=function(){return this.b.dc()},l.Kc=function(){return new FC(this.b.vc().Kc())},l.Mc=function(e){return this.b._b(e)?(this.b.Bc(e),!0):!1},l.gc=function(){return this.b.gc()},F(Ke,"Maps/KeySet",532),D(318,532,zu,K3),l.$b=function(){var e;Vj((e=this.b.vc().Kc(),new vbt(this,e)))},l.Ic=function(e){return this.b.ec().Ic(e)},l.Fb=function(e){return this===e||yi(this.b.ec(),e)},l.Hb=function(){return Hi(this.b.ec())},l.Kc=function(){var e;return e=this.b.vc().Kc(),new vbt(this,e)},l.Mc=function(e){var n,r;return r=0,n=u(this.b.Bc(e),14),n&&(r=n.gc(),n.$b(),this.a.d-=r),r>0},l.Nc=function(){return this.b.ec().Nc()},F(Ke,"AbstractMapBasedMultimap/KeySet",318),D(731,1,sa,vbt),l.Nb=function(e){ba(this,e)},l.Ob=function(){return this.c.Ob()},l.Pb=function(){return this.a=u(this.c.Pb(),42),this.a.cd()},l.Qb=function(){var e;i4(!!this.a),e=u(this.a.dd(),14),this.c.Qb(),this.b.a.d-=e.gc(),e.$b(),this.a=null},F(Ke,"AbstractMapBasedMultimap/KeySet/1",731),D(491,389,{83:1,161:1},HM),l.bc=function(){return this.Sc()},l.ec=function(){return this.Tc()},l.Sc=function(){return new mM(this.c,this.Uc())},l.Tc=function(){var e;return e=this.b,e||(this.b=this.Sc())},l.Uc=function(){return u(this.d,161)},F(Ke,"AbstractMapBasedMultimap/SortedAsMap",491),D(542,491,ufe,Dj),l.bc=function(){return new u8(this.a,u(u(this.d,161),171))},l.Sc=function(){return new u8(this.a,u(u(this.d,161),171))},l.ec=function(){var e;return e=this.b,u(e||(this.b=new u8(this.a,u(u(this.d,161),171))),271)},l.Tc=function(){var e;return e=this.b,u(e||(this.b=new u8(this.a,u(u(this.d,161),171))),271)},l.Uc=function(){return u(u(this.d,161),171)},F(Ke,"AbstractMapBasedMultimap/NavigableAsMap",542),D(490,318,lfe,mM),l.Nc=function(){return this.b.ec().Nc()},F(Ke,"AbstractMapBasedMultimap/SortedKeySet",490),D(388,490,Bxt,u8),F(Ke,"AbstractMapBasedMultimap/NavigableKeySet",388),D(541,28,xy,q$),l.Fc=function(e){var n,r;return cl(this),r=this.d.dc(),n=this.d.Fc(e),n&&(++this.f.d,r&&WM(this)),n},l.Gc=function(e){var n,r,s;return e.dc()?!1:(s=(cl(this),this.d.gc()),n=this.d.Gc(e),n&&(r=this.d.gc(),this.f.d+=r-s,s==0&&WM(this)),n)},l.$b=function(){var e;e=(cl(this),this.d.gc()),e!=0&&(this.d.$b(),this.f.d-=e,Kj(this))},l.Hc=function(e){return cl(this),this.d.Hc(e)},l.Ic=function(e){return cl(this),this.d.Ic(e)},l.Fb=function(e){return e===this?!0:(cl(this),yi(this.d,e))},l.Hb=function(){return cl(this),Hi(this.d)},l.Kc=function(){return cl(this),new Iwt(this)},l.Mc=function(e){var n;return cl(this),n=this.d.Mc(e),n&&(--this.f.d,Kj(this)),n},l.gc=function(){return iUt(this)},l.Nc=function(){return cl(this),this.d.Nc()},l.Ib=function(){return cl(this),$o(this.d)},F(Ke,"AbstractMapBasedMultimap/WrappedCollection",541);var wh=Ki(pr,"List");D(728,541,{20:1,28:1,14:1,15:1},ovt),l.ad=function(e){r4(this,e)},l.Nc=function(){return cl(this),this.d.Nc()},l.Vc=function(e,n){var r;cl(this),r=this.d.dc(),u(this.d,15).Vc(e,n),++this.a.d,r&&WM(this)},l.Wc=function(e,n){var r,s,o;return n.dc()?!1:(o=(cl(this),this.d.gc()),r=u(this.d,15).Wc(e,n),r&&(s=this.d.gc(),this.a.d+=s-o,o==0&&WM(this)),r)},l.Xb=function(e){return cl(this),u(this.d,15).Xb(e)},l.Xc=function(e){return cl(this),u(this.d,15).Xc(e)},l.Yc=function(){return cl(this),new BUt(this)},l.Zc=function(e){return cl(this),new XXt(this,e)},l.$c=function(e){var n;return cl(this),n=u(this.d,15).$c(e),--this.a.d,Kj(this),n},l._c=function(e,n){return cl(this),u(this.d,15)._c(e,n)},l.bd=function(e,n){return cl(this),zZt(this.a,this.e,u(this.d,15).bd(e,n),this.b?this.b:this)},F(Ke,"AbstractMapBasedMultimap/WrappedList",728),D(1096,728,{20:1,28:1,14:1,15:1,54:1},SWt),F(Ke,"AbstractMapBasedMultimap/RandomAccessWrappedList",1096),D(620,1,sa,Iwt),l.Nb=function(e){ba(this,e)},l.Ob=function(){return D8(this),this.b.Ob()},l.Pb=function(){return D8(this),this.b.Pb()},l.Qb=function(){lWt(this)},F(Ke,"AbstractMapBasedMultimap/WrappedCollection/WrappedIterator",620),D(729,620,n0,BUt,XXt),l.Qb=function(){lWt(this)},l.Rb=function(e){var n;n=iUt(this.a)==0,(D8(this),u(this.b,125)).Rb(e),++this.a.a.d,n&&WM(this.a)},l.Sb=function(){return(D8(this),u(this.b,125)).Sb()},l.Tb=function(){return(D8(this),u(this.b,125)).Tb()},l.Ub=function(){return(D8(this),u(this.b,125)).Ub()},l.Vb=function(){return(D8(this),u(this.b,125)).Vb()},l.Wb=function(e){(D8(this),u(this.b,125)).Wb(e)},F(Ke,"AbstractMapBasedMultimap/WrappedList/WrappedListIterator",729),D(727,541,lfe,J2t),l.Nc=function(){return cl(this),this.d.Nc()},F(Ke,"AbstractMapBasedMultimap/WrappedSortedSet",727),D(1095,727,Bxt,LUt),F(Ke,"AbstractMapBasedMultimap/WrappedNavigableSet",1095),D(1094,541,zu,zWt),l.Nc=function(){return cl(this),this.d.Nc()},F(Ke,"AbstractMapBasedMultimap/WrappedSet",1094),D(1103,1,{},B),l.Kb=function(e){return Oan(u(e,42))},F(Ke,"AbstractMapBasedMultimap/lambda$1$Type",1103),D(1102,1,{},ftt),l.Kb=function(e){return new Lw(this.a,e)},F(Ke,"AbstractMapBasedMultimap/lambda$2$Type",1102);var P2=Ki(pr,"Map/Entry");D(345,1,zq),l.Fb=function(e){var n;return _t(e,42)?(n=u(e,42),pd(this.cd(),n.cd())&&pd(this.dd(),n.dd())):!1},l.Hb=function(){var e,n;return e=this.cd(),n=this.dd(),(e==null?0:Hi(e))^(n==null?0:Hi(n))},l.ed=function(e){throw it(new Or)},l.Ib=function(){return this.cd()+"="+this.dd()},F(Ke,hfe,345),D(1988,28,xy),l.$b=function(){this.fd().$b()},l.Hc=function(e){var n;return _t(e,42)?(n=u(e,42),dsn(this.fd(),n.cd(),n.dd())):!1},l.Mc=function(e){var n;return _t(e,42)?(n=u(e,42),xZt(this.fd(),n.cd(),n.dd())):!1},l.gc=function(){return this.fd().d},F(Ke,"Multimaps/Entries",1988),D(733,1988,xy,nM),l.Kc=function(){return this.a.kc()},l.fd=function(){return this.a},l.Nc=function(){return this.a.lc()},F(Ke,"AbstractMultimap/Entries",733),D(734,733,zu,Ypt),l.Nc=function(){return this.a.lc()},l.Fb=function(e){return H4t(this,e)},l.Hb=function(){return kne(this)},F(Ke,"AbstractMultimap/EntrySet",734),D(735,28,xy,I3),l.$b=function(){this.a.$b()},l.Hc=function(e){return Qun(this.a,e)},l.Kc=function(){return this.a.nc()},l.gc=function(){return this.a.d},l.Nc=function(){return this.a.oc()},F(Ke,"AbstractMultimap/Values",735),D(1989,28,{835:1,20:1,28:1,14:1}),l.Jc=function(e){Lr(e),Q3(this).Jc(new Ttt(e))},l.Nc=function(){var e;return e=Q3(this).Nc(),zst(e,new vt,64|e.qd()&1296,this.a.d)},l.Fc=function(e){return rbt(),!0},l.Gc=function(e){return Lr(this),Lr(e),_t(e,543)?vsn(u(e,835)):!e.dc()&&oit(this,e.Kc())},l.Hc=function(e){var n;return n=u(sy(Wx(this.a),e),14),(n?n.gc():0)>0},l.Fb=function(e){return h2n(this,e)},l.Hb=function(){return Hi(Q3(this))},l.dc=function(){return Q3(this).dc()},l.Mc=function(e){return zoe(this,e,1)>0},l.Ib=function(){return $o(Q3(this))},F(Ke,"AbstractMultiset",1989),D(1991,1970,zu),l.$b=function(){cz(this.a.a)},l.Hc=function(e){var n,r;return _t(e,492)?(r=u(e,416),u(r.a.dd(),14).gc()<=0?!1:(n=QQt(this.a,r.a.cd()),n==u(r.a.dd(),14).gc())):!1},l.Mc=function(e){var n,r,s,o;return _t(e,492)&&(r=u(e,416),n=r.a.cd(),s=u(r.a.dd(),14).gc(),s!=0)?(o=this.a,Jpn(o,n,s)):!1},F(Ke,"Multisets/EntrySet",1991),D(1109,1991,zu,rM),l.Kc=function(){return new tHt($Kt(Wx(this.a.a)).Kc())},l.gc=function(){return Wx(this.a.a).gc()},F(Ke,"AbstractMultiset/EntrySet",1109),D(619,726,T2),l.hc=function(){return this.gd()},l.jc=function(){return this.hd()},l.cc=function(e){return this.jd(e)},l.fc=function(e){return this.kd(e)},l.Zb=function(){var e;return e=this.f,e||(this.f=this.ac())},l.hd=function(){return wn(),wn(),rV},l.Fb=function(e){return Pit(this,e)},l.jd=function(e){return u(Ai(this,e),21)},l.kd=function(e){return u(GD(this,e),21)},l.mc=function(e){return wn(),new s8(u(e,21))},l.pc=function(e,n){return new zWt(this,e,u(n,21))},F(Ke,"AbstractSetMultimap",619),D(1657,619,T2),l.hc=function(){return new Op(this.b)},l.gd=function(){return new Op(this.b)},l.jc=function(){return kvt(new Op(this.b))},l.hd=function(){return kvt(new Op(this.b))},l.cc=function(e){return u(u(Ai(this,e),21),84)},l.jd=function(e){return u(u(Ai(this,e),21),84)},l.fc=function(e){return u(u(GD(this,e),21),84)},l.kd=function(e){return u(u(GD(this,e),21),84)},l.mc=function(e){return _t(e,271)?kvt(u(e,271)):(wn(),new I2t(u(e,84)))},l.Zb=function(){var e;return e=this.f,e||(this.f=_t(this.c,171)?new Dj(this,u(this.c,171)):_t(this.c,161)?new HM(this,u(this.c,161)):new l8(this,this.c))},l.pc=function(e,n){return _t(n,271)?new LUt(this,e,u(n,271)):new J2t(this,e,u(n,84))},F(Ke,"AbstractSortedSetMultimap",1657),D(1658,1657,T2),l.Zb=function(){var e;return e=this.f,u(u(e||(this.f=_t(this.c,171)?new Dj(this,u(this.c,171)):_t(this.c,161)?new HM(this,u(this.c,161)):new l8(this,this.c)),161),171)},l.ec=function(){var e;return e=this.i,u(u(e||(this.i=_t(this.c,171)?new u8(this,u(this.c,171)):_t(this.c,161)?new mM(this,u(this.c,161)):new K3(this,this.c)),84),271)},l.bc=function(){return _t(this.c,171)?new u8(this,u(this.c,171)):_t(this.c,161)?new mM(this,u(this.c,161)):new K3(this,this.c)},F(Ke,"AbstractSortedKeySortedSetMultimap",1658),D(2010,1,{1947:1}),l.Fb=function(e){return qdn(this,e)},l.Hb=function(){var e;return Tyt((e=this.g,e||(this.g=new yC(this))))},l.Ib=function(){var e;return Tae((e=this.f,e||(this.f=new T2t(this))))},F(Ke,"AbstractTable",2010),D(665,N1,zu,yC),l.$b=function(){lHt()},l.Hc=function(e){var n,r;return _t(e,468)?(n=u(e,682),r=u(sy(uXt(this.a),Np(n.c.e,n.b)),83),!!r&&Jyt(r.vc(),new Lw(Np(n.c.c,n.a),t6(n.c,n.b,n.a)))):!1},l.Kc=function(){return _rn(this.a)},l.Mc=function(e){var n,r;return _t(e,468)?(n=u(e,682),r=u(sy(uXt(this.a),Np(n.c.e,n.b)),83),!!r&&Tln(r.vc(),new Lw(Np(n.c.c,n.a),t6(n.c,n.b,n.a)))):!1},l.gc=function(){return xKt(this.a)},l.Nc=function(){return xsn(this.a)},F(Ke,"AbstractTable/CellSet",665),D(1928,28,xy,dtt),l.$b=function(){lHt()},l.Hc=function(e){return O0n(this.a,e)},l.Kc=function(){return Srn(this.a)},l.gc=function(){return xKt(this.a)},l.Nc=function(){return TZt(this.a)},F(Ke,"AbstractTable/Values",1928),D(1632,1631,T2),F(Ke,"ArrayListMultimapGwtSerializationDependencies",1632),D(513,1632,T2,wet,Wvt),l.hc=function(){return new Xc(this.a)},l.a=0,F(Ke,"ArrayListMultimap",513),D(664,2010,{664:1,1947:1,3:1},Qoe),F(Ke,"ArrayTable",664),D(1924,386,NE,iWt),l.Xb=function(e){return new Ayt(this.a,e)},F(Ke,"ArrayTable/1",1924),D(1925,1,{},eR),l.ld=function(e){return new Ayt(this.a,e)},F(Ke,"ArrayTable/1methodref$getCell$Type",1925),D(2011,1,{682:1}),l.Fb=function(e){var n;return e===this?!0:_t(e,468)?(n=u(e,682),pd(Np(this.c.e,this.b),Np(n.c.e,n.b))&&pd(Np(this.c.c,this.a),Np(n.c.c,n.a))&&pd(t6(this.c,this.b,this.a),t6(n.c,n.b,n.a))):!1},l.Hb=function(){return Az(lt(ct(Qn,1),De,1,5,[Np(this.c.e,this.b),Np(this.c.c,this.a),t6(this.c,this.b,this.a)]))},l.Ib=function(){return"("+Np(this.c.e,this.b)+","+Np(this.c.c,this.a)+")="+t6(this.c,this.b,this.a)},F(Ke,"Tables/AbstractCell",2011),D(468,2011,{468:1,682:1},Ayt),l.a=0,l.b=0,l.d=0,F(Ke,"ArrayTable/2",468),D(1927,1,{},gx),l.ld=function(e){return Fte(this.a,e)},F(Ke,"ArrayTable/2methodref$getValue$Type",1927),D(1926,386,NE,sWt),l.Xb=function(e){return Fte(this.a,e)},F(Ke,"ArrayTable/3",1926),D(1979,1967,mv),l.$b=function(){Vj(this.kc())},l.vc=function(){return new bx(this)},l.lc=function(){return new BXt(this.kc(),this.gc())},F(Ke,"Maps/IteratorBasedAbstractMap",1979),D(828,1979,mv),l.$b=function(){throw it(new Or)},l._b=function(e){return LHt(this.c,e)},l.kc=function(){return new aWt(this,this.c.b.c.gc())},l.lc=function(){return Bnt(this.c.b.c.gc(),16,new bw(this))},l.xc=function(e){var n;return n=u(x9(this.c,e),19),n?this.nd(n.a):null},l.dc=function(){return this.c.b.c.dc()},l.ec=function(){return Gnt(this.c)},l.zc=function(e,n){var r;if(r=u(x9(this.c,e),19),!r)throw it(new Fn(this.md()+" "+e+" not in "+Gnt(this.c)));return this.od(r.a,n)},l.Bc=function(e){throw it(new Or)},l.gc=function(){return this.c.b.c.gc()},F(Ke,"ArrayTable/ArrayMap",828),D(1923,1,{},bw),l.ld=function(e){return hXt(this.a,e)},F(Ke,"ArrayTable/ArrayMap/0methodref$getEntry$Type",1923),D(1921,345,zq,uVt),l.cd=function(){return qQe(this.a,this.b)},l.dd=function(){return this.a.nd(this.b)},l.ed=function(e){return this.a.od(this.b,e)},l.b=0,F(Ke,"ArrayTable/ArrayMap/1",1921),D(1922,386,NE,aWt),l.Xb=function(e){return hXt(this.a,e)},F(Ke,"ArrayTable/ArrayMap/2",1922),D(1920,828,mv,ZKt),l.md=function(){return"Column"},l.nd=function(e){return t6(this.b,this.a,e)},l.od=function(e,n){return ore(this.b,this.a,e,n)},l.a=0,F(Ke,"ArrayTable/Row",1920),D(829,828,mv,T2t),l.nd=function(e){return new ZKt(this.a,e)},l.zc=function(e,n){return u(n,83),CKe()},l.od=function(e,n){return u(n,83),_Ke()},l.md=function(){return"Row"},F(Ke,"ArrayTable/RowMap",829),D(1120,1,Ih,lVt),l.qd=function(){return this.a.qd()&-262},l.rd=function(){return this.a.rd()},l.Nb=function(e){this.a.Nb(new sVt(e,this.b))},l.sd=function(e){return this.a.sd(new iVt(e,this.b))},F(Ke,"CollectSpliterators/1",1120),D(1121,1,Un,iVt),l.td=function(e){this.a.td(this.b.Kb(e))},F(Ke,"CollectSpliterators/1/lambda$0$Type",1121),D(1122,1,Un,sVt),l.td=function(e){this.a.td(this.b.Kb(e))},F(Ke,"CollectSpliterators/1/lambda$1$Type",1122),D(1123,1,Ih,FZt),l.qd=function(){return this.a},l.rd=function(){return this.d&&(this.b=jUt(this.b,this.d.rd())),jUt(this.b,0)},l.Nb=function(e){this.d&&(this.d.Nb(e),this.d=null),this.c.Nb(new rVt(this.e,e)),this.b=0},l.sd=function(e){for(;;){if(this.d&&this.d.sd(e))return u9(this.b,qq)&&(this.b=Jp(this.b,1)),!0;if(this.d=null,!this.c.sd(new aVt(this,this.e)))return!1}},l.a=0,l.b=0,F(Ke,"CollectSpliterators/1FlatMapSpliterator",1123),D(1124,1,Un,aVt),l.td=function(e){GZe(this.a,this.b,e)},F(Ke,"CollectSpliterators/1FlatMapSpliterator/lambda$0$Type",1124),D(1125,1,Un,rVt),l.td=function(e){LQe(this.b,this.a,e)},F(Ke,"CollectSpliterators/1FlatMapSpliterator/lambda$1$Type",1125),D(1117,1,Ih,wYt),l.qd=function(){return 16464|this.b},l.rd=function(){return this.a.rd()},l.Nb=function(e){this.a.xe(new cVt(e,this.c))},l.sd=function(e){return this.a.ye(new oVt(e,this.c))},l.b=0,F(Ke,"CollectSpliterators/1WithCharacteristics",1117),D(1118,1,OI,oVt),l.ud=function(e){this.a.td(this.b.ld(e))},F(Ke,"CollectSpliterators/1WithCharacteristics/lambda$0$Type",1118),D(1119,1,OI,cVt),l.ud=function(e){this.a.td(this.b.ld(e))},F(Ke,"CollectSpliterators/1WithCharacteristics/lambda$1$Type",1119),D(245,1,Uat),l.wd=function(e){return this.vd(u(e,245))},l.vd=function(e){var n;return e==(oet(),Sut)?1:e==(cet(),_ut)?-1:(n=(zj(),ID(this.a,e.a)),n!=0?n:_t(this,519)==_t(e,519)?0:_t(this,519)?1:-1)},l.zd=function(){return this.a},l.Fb=function(e){return D3t(this,e)},F(Ke,"Cut",245),D(1761,245,Uat,dHt),l.vd=function(e){return e==this?0:1},l.xd=function(e){throw it(new Mpt)},l.yd=function(e){e.a+="+∞)"},l.zd=function(){throw it(new No(dfe))},l.Hb=function(){return Gd(),$3t(this)},l.Ad=function(e){return!1},l.Ib=function(){return"+∞"};var _ut;F(Ke,"Cut/AboveAll",1761),D(519,245,{245:1,519:1,3:1,35:1},hWt),l.xd=function(e){hc((e.a+="(",e),this.a)},l.yd=function(e){qp(hc(e,this.a),93)},l.Hb=function(){return~Hi(this.a)},l.Ad=function(e){return zj(),ID(this.a,e)<0},l.Ib=function(){return"/"+this.a+"\\"},F(Ke,"Cut/AboveValue",519),D(1760,245,Uat,gHt),l.vd=function(e){return e==this?0:-1},l.xd=function(e){e.a+="(-∞"},l.yd=function(e){throw it(new Mpt)},l.zd=function(){throw it(new No(dfe))},l.Hb=function(){return Gd(),$3t(this)},l.Ad=function(e){return!0},l.Ib=function(){return"-∞"};var Sut;F(Ke,"Cut/BelowAll",1760),D(1762,245,Uat,fWt),l.xd=function(e){hc((e.a+="[",e),this.a)},l.yd=function(e){qp(hc(e,this.a),41)},l.Hb=function(){return Hi(this.a)},l.Ad=function(e){return zj(),ID(this.a,e)<=0},l.Ib=function(){return"\\"+this.a+"/"},F(Ke,"Cut/BelowValue",1762),D(537,1,r0),l.Jc=function(e){va(this,e)},l.Ib=function(){return thn(u(g$(this,"use Optional.orNull() instead of Optional.or(null)"),20).Kc())},F(Ke,"FluentIterable",537),D(433,537,r0,f9),l.Kc=function(){return new ar(lr(this.a.Kc(),new z))},F(Ke,"FluentIterable/2",433),D(1046,537,r0,bUt),l.Kc=function(){return zp(this)},F(Ke,"FluentIterable/3",1046),D(708,386,NE,C2t),l.Xb=function(e){return this.a[e].Kc()},F(Ke,"FluentIterable/3/1",708),D(1972,1,{}),l.Ib=function(){return $o(this.Bd().b)},F(Ke,"ForwardingObject",1972),D(1973,1972,gfe),l.Bd=function(){return this.Cd()},l.Jc=function(e){va(this,e)},l.Lc=function(){return this.Oc()},l.Nc=function(){return new _n(this,0)},l.Oc=function(){return new Tn(null,this.Nc())},l.Fc=function(e){return this.Cd(),OHt()},l.Gc=function(e){return this.Cd(),PHt()},l.$b=function(){this.Cd(),FHt()},l.Hc=function(e){return this.Cd().Hc(e)},l.Ic=function(e){return this.Cd().Ic(e)},l.dc=function(){return this.Cd().b.dc()},l.Kc=function(){return this.Cd().Kc()},l.Mc=function(e){return this.Cd(),NHt()},l.gc=function(){return this.Cd().b.gc()},l.Pc=function(){return this.Cd().Pc()},l.Qc=function(e){return this.Cd().Qc(e)},F(Ke,"ForwardingCollection",1973),D(1980,28,Rxt),l.Kc=function(){return this.Ed()},l.Fc=function(e){throw it(new Or)},l.Gc=function(e){throw it(new Or)},l.$b=function(){throw it(new Or)},l.Hc=function(e){return e!=null&&ay(this,e,!1)},l.Dd=function(){switch(this.gc()){case 0:return Wm(),Wm(),Aut;case 1:return Wm(),new Rnt(Lr(this.Ed().Pb()));default:return new JKt(this,this.Pc())}},l.Mc=function(e){throw it(new Or)},F(Ke,"ImmutableCollection",1980),D(712,1980,Rxt,Apt),l.Kc=function(){return e6(this.a.Kc())},l.Hc=function(e){return e!=null&&this.a.Hc(e)},l.Ic=function(e){return this.a.Ic(e)},l.dc=function(){return this.a.dc()},l.Ed=function(){return e6(this.a.Kc())},l.gc=function(){return this.a.gc()},l.Pc=function(){return this.a.Pc()},l.Qc=function(e){return this.a.Qc(e)},l.Ib=function(){return $o(this.a)},F(Ke,"ForwardingImmutableCollection",712),D(152,1980,M_),l.Kc=function(){return this.Ed()},l.Yc=function(){return this.Fd(0)},l.Zc=function(e){return this.Fd(e)},l.ad=function(e){r4(this,e)},l.Nc=function(){return new _n(this,16)},l.bd=function(e,n){return this.Gd(e,n)},l.Vc=function(e,n){throw it(new Or)},l.Wc=function(e,n){throw it(new Or)},l.Fb=function(e){return Kbn(this,e)},l.Hb=function(){return aun(this)},l.Xc=function(e){return e==null?-1:m1n(this,e)},l.Ed=function(){return this.Fd(0)},l.Fd=function(e){return $2t(this,e)},l.$c=function(e){throw it(new Or)},l._c=function(e,n){throw it(new Or)},l.Gd=function(e,n){var r;return Dz((r=new xVt(this),new Qd(r,e,n)))};var Aut;F(Ke,"ImmutableList",152),D(2006,152,M_),l.Kc=function(){return e6(this.Hd().Kc())},l.bd=function(e,n){return Dz(this.Hd().bd(e,n))},l.Hc=function(e){return e!=null&&this.Hd().Hc(e)},l.Ic=function(e){return this.Hd().Ic(e)},l.Fb=function(e){return yi(this.Hd(),e)},l.Xb=function(e){return Np(this,e)},l.Hb=function(){return Hi(this.Hd())},l.Xc=function(e){return this.Hd().Xc(e)},l.dc=function(){return this.Hd().dc()},l.Ed=function(){return e6(this.Hd().Kc())},l.gc=function(){return this.Hd().gc()},l.Gd=function(e,n){return Dz(this.Hd().bd(e,n))},l.Pc=function(){return this.Hd().Qc(Nt(Qn,De,1,this.Hd().gc(),5,1))},l.Qc=function(e){return this.Hd().Qc(e)},l.Ib=function(){return $o(this.Hd())},F(Ke,"ForwardingImmutableList",2006),D(714,1,BE),l.vc=function(){return Rw(this)},l.wc=function(e){K9(this,e)},l.ec=function(){return Gnt(this)},l.yc=function(e,n,r){return Qit(this,e,n,r)},l.Cc=function(){return this.Ld()},l.$b=function(){throw it(new Or)},l._b=function(e){return this.xc(e)!=null},l.uc=function(e){return this.Ld().Hc(e)},l.Jd=function(){return new iqt(this)},l.Kd=function(){return new sqt(this)},l.Fb=function(e){return Zun(this,e)},l.Hb=function(){return Rw(this).Hb()},l.dc=function(){return this.gc()==0},l.zc=function(e,n){return SKe()},l.Bc=function(e){throw it(new Or)},l.Ib=function(){return Mgn(this)},l.Ld=function(){return this.e?this.e:this.e=this.Kd()},l.c=null,l.d=null,l.e=null;var Age;F(Ke,"ImmutableMap",714),D(715,714,BE),l._b=function(e){return LHt(this,e)},l.uc=function(e){return CVt(this.b,e)},l.Id=function(){return tie(new kC(this))},l.Jd=function(){return tie(OXt(this.b))},l.Kd=function(){return gd(),new Apt(IXt(this.b))},l.Fb=function(e){return _Vt(this.b,e)},l.xc=function(e){return x9(this,e)},l.Hb=function(){return Hi(this.b.c)},l.dc=function(){return this.b.c.dc()},l.gc=function(){return this.b.c.gc()},l.Ib=function(){return $o(this.b.c)},F(Ke,"ForwardingImmutableMap",715),D(1974,1973,Wat),l.Bd=function(){return this.Md()},l.Cd=function(){return this.Md()},l.Nc=function(){return new _n(this,1)},l.Fb=function(e){return e===this||this.Md().Fb(e)},l.Hb=function(){return this.Md().Hb()},F(Ke,"ForwardingSet",1974),D(1069,1974,Wat,kC),l.Bd=function(){return L8(this.a.b)},l.Cd=function(){return L8(this.a.b)},l.Hc=function(e){if(_t(e,42)&&u(e,42).cd()==null)return!1;try{return TVt(L8(this.a.b),e)}catch(n){if(n=Wi(n),_t(n,205))return!1;throw it(n)}},l.Md=function(){return L8(this.a.b)},l.Qc=function(e){var n;return n=gQt(L8(this.a.b),e),L8(this.a.b).b.gc()=0?"+":"")+(r/60|0),n=gj(b.Math.abs(r)%60),(Pae(),Vge)[this.q.getDay()]+" "+Gge[this.q.getMonth()]+" "+gj(this.q.getDate())+" "+gj(this.q.getHours())+":"+gj(this.q.getMinutes())+":"+gj(this.q.getSeconds())+" GMT"+e+n+" "+this.q.getFullYear()};var tV=F(pr,"Date",199);D(1915,199,Efe,oae),l.a=!1,l.b=0,l.c=0,l.d=0,l.e=0,l.f=0,l.g=!1,l.i=0,l.j=0,l.k=0,l.n=0,l.o=0,l.p=0,F("com.google.gwt.i18n.shared.impl","DateRecord",1915),D(1966,1,{}),l.fe=function(){return null},l.ge=function(){return null},l.he=function(){return null},l.ie=function(){return null},l.je=function(){return null},F(v6,"JSONValue",1966),D(216,1966,{216:1},Eg,wx),l.Fb=function(e){return _t(e,216)?Xvt(this.a,u(e,216).a):!1},l.ee=function(){return KYe},l.Hb=function(){return Bvt(this.a)},l.fe=function(){return this},l.Ib=function(){var e,n,r;for(r=new Ol("["),n=0,e=this.a.length;n0&&(r.a+=","),hc(r,Jm(this,n));return r.a+="]",r.a},F(v6,"JSONArray",216),D(483,1966,{483:1},Xk),l.ee=function(){return XYe},l.ge=function(){return this},l.Ib=function(){return Nn(),""+this.a},l.a=!1;var Fge,Nge;F(v6,"JSONBoolean",483),D(985,60,Q0,eHt),F(v6,"JSONException",985),D(1023,1966,{},ft),l.ee=function(){return eKe},l.Ib=function(){return _u};var Bge;F(v6,"JSONNull",1023),D(258,1966,{258:1},EC),l.Fb=function(e){return _t(e,258)?this.a==u(e,258).a:!1},l.ee=function(){return QYe},l.Hb=function(){return p8(this.a)},l.he=function(){return this},l.Ib=function(){return this.a+""},l.a=0,F(v6,"JSONNumber",258),D(183,1966,{183:1},_x,Qk),l.Fb=function(e){return _t(e,183)?Xvt(this.a,u(e,183).a):!1},l.ee=function(){return ZYe},l.Hb=function(){return Bvt(this.a)},l.ie=function(){return this},l.Ib=function(){var e,n,r,s,o,h,d;for(d=new Ol("{"),e=!0,h=yit(this,Nt(Ae,ee,2,0,6,1)),r=h,s=0,o=r.length;s=0?":"+this.c:"")+")"},l.c=0;var wEt=F(Xo,"StackTraceElement",310);Sge={3:1,475:1,35:1,2:1};var Ae=F(Xo,jxt,2);D(107,418,{475:1},Ag,$C,_h),F(Xo,"StringBuffer",107),D(100,418,{475:1},Mp,Im,Ol),F(Xo,"StringBuilder",100),D(687,73,bot,sbt),F(Xo,"StringIndexOutOfBoundsException",687),D(2043,1,{});var vEt;D(844,1,{},Ft),l.Kb=function(e){return u(e,78).e},F(Xo,"Throwable/lambda$0$Type",844),D(41,60,{3:1,102:1,60:1,78:1,41:1},Or,Sg),F(Xo,"UnsupportedOperationException",41),D(240,236,{3:1,35:1,236:1,240:1},SD,gbt),l.wd=function(e){return gle(this,u(e,240))},l.ke=function(){return dy(Xle(this))},l.Fb=function(e){var n;return this===e?!0:_t(e,240)?(n=u(e,240),this.e==n.e&&gle(this,n)==0):!1},l.Hb=function(){var e;return this.b!=0?this.b:this.a<54?(e=Tu(this.f),this.b=Ar(Ns(e,-1)),this.b=33*this.b+Ar(Ns($p(e,32),-1)),this.b=17*this.b+ps(this.e),this.b):(this.b=17*Yre(this.c)+ps(this.e),this.b)},l.Ib=function(){return Xle(this)},l.a=0,l.b=0,l.d=0,l.e=0,l.f=0;var zge,N2,mEt,yEt,xEt,kEt,EEt,TEt,Nut=F("java.math","BigDecimal",240);D(91,236,{3:1,35:1,236:1,91:1},j3t,Ng,X3,x4t,Qie,Rp),l.wd=function(e){return Uie(this,u(e,91))},l.ke=function(){return dy(Hat(this,0))},l.Fb=function(e){return v3t(this,e)},l.Hb=function(){return Yre(this)},l.Ib=function(){return Hat(this,0)},l.b=-2,l.c=0,l.d=0,l.e=0;var But,eV,CEt,Rut,nV,s7,j4=F("java.math","BigInteger",91),qge,Hge,D6,lS;D(488,1967,mv),l.$b=function(){Xu(this)},l._b=function(e){return Tl(this,e)},l.uc=function(e){return Ire(this,e,this.g)||Ire(this,e,this.f)},l.vc=function(){return new Cg(this)},l.xc=function(e){return tr(this,e)},l.zc=function(e,n){return ki(this,e,n)},l.Bc=function(e){return Jx(this,e)},l.gc=function(){return HC(this)},F(pr,"AbstractHashMap",488),D(261,N1,zu,Cg),l.$b=function(){this.a.$b()},l.Hc=function(e){return MZt(this,e)},l.Kc=function(){return new p2(this.a)},l.Mc=function(e){var n;return MZt(this,e)?(n=u(e,42).cd(),this.a.Bc(n),!0):!1},l.gc=function(){return this.a.gc()},F(pr,"AbstractHashMap/EntrySet",261),D(262,1,sa,p2),l.Nb=function(e){ba(this,e)},l.Pb=function(){return Zw(this)},l.Ob=function(){return this.b},l.Qb=function(){Ste(this)},l.b=!1,F(pr,"AbstractHashMap/EntrySetIterator",262),D(417,1,sa,mx),l.Nb=function(e){ba(this,e)},l.Ob=function(){return TM(this)},l.Pb=function(){return ZXt(this)},l.Qb=function(){Cl(this)},l.b=0,l.c=-1,F(pr,"AbstractList/IteratorImpl",417),D(96,417,n0,da),l.Qb=function(){Cl(this)},l.Rb=function(e){zm(this,e)},l.Sb=function(){return this.b>0},l.Tb=function(){return this.b},l.Ub=function(){return Zn(this.b>0),this.a.Xb(this.c=--this.b)},l.Vb=function(){return this.b-1},l.Wb=function(e){Rm(this.c!=-1),this.a._c(this.c,e)},F(pr,"AbstractList/ListIteratorImpl",96),D(219,52,jE,Qd),l.Vc=function(e,n){Km(e,this.b),this.c.Vc(this.a+e,n),++this.b},l.Xb=function(e){return An(e,this.b),this.c.Xb(this.a+e)},l.$c=function(e){var n;return An(e,this.b),n=this.c.$c(this.a+e),--this.b,n},l._c=function(e,n){return An(e,this.b),this.c._c(this.a+e,n)},l.gc=function(){return this.b},l.a=0,l.b=0,F(pr,"AbstractList/SubList",219),D(384,N1,zu,Sm),l.$b=function(){this.a.$b()},l.Hc=function(e){return this.a._b(e)},l.Kc=function(){var e;return e=this.a.vc().Kc(),new cM(e)},l.Mc=function(e){return this.a._b(e)?(this.a.Bc(e),!0):!1},l.gc=function(){return this.a.gc()},F(pr,"AbstractMap/1",384),D(691,1,sa,cM),l.Nb=function(e){ba(this,e)},l.Ob=function(){return this.a.Ob()},l.Pb=function(){var e;return e=u(this.a.Pb(),42),e.cd()},l.Qb=function(){this.a.Qb()},F(pr,"AbstractMap/1/1",691),D(226,28,xy,v1),l.$b=function(){this.a.$b()},l.Hc=function(e){return this.a.uc(e)},l.Kc=function(){var e;return e=this.a.vc().Kc(),new m1(e)},l.gc=function(){return this.a.gc()},F(pr,"AbstractMap/2",226),D(294,1,sa,m1),l.Nb=function(e){ba(this,e)},l.Ob=function(){return this.a.Ob()},l.Pb=function(){var e;return e=u(this.a.Pb(),42),e.dd()},l.Qb=function(){this.a.Qb()},F(pr,"AbstractMap/2/1",294),D(484,1,{484:1,42:1}),l.Fb=function(e){var n;return _t(e,42)?(n=u(e,42),Fc(this.d,n.cd())&&Fc(this.e,n.dd())):!1},l.cd=function(){return this.d},l.dd=function(){return this.e},l.Hb=function(){return U3(this.d)^U3(this.e)},l.ed=function(e){return awt(this,e)},l.Ib=function(){return this.d+"="+this.e},F(pr,"AbstractMap/AbstractEntry",484),D(383,484,{484:1,383:1,42:1},KR),F(pr,"AbstractMap/SimpleEntry",383),D(1984,1,yot),l.Fb=function(e){var n;return _t(e,42)?(n=u(e,42),Fc(this.cd(),n.cd())&&Fc(this.dd(),n.dd())):!1},l.Hb=function(){return U3(this.cd())^U3(this.dd())},l.Ib=function(){return this.cd()+"="+this.dd()},F(pr,hfe,1984),D(1992,1967,ufe),l.tc=function(e){return RJt(this,e)},l._b=function(e){return _nt(this,e)},l.vc=function(){return new x(this)},l.xc=function(e){var n;return n=e,ec(jyt(this,n))},l.ec=function(){return new y(this)},F(pr,"AbstractNavigableMap",1992),D(739,N1,zu,x),l.Hc=function(e){return _t(e,42)&&RJt(this.b,u(e,42))},l.Kc=function(){return new y9(this.b)},l.Mc=function(e){var n;return _t(e,42)?(n=u(e,42),Cte(this.b,n)):!1},l.gc=function(){return this.b.c},F(pr,"AbstractNavigableMap/EntrySet",739),D(493,N1,Bxt,y),l.Nc=function(){return new WR(this)},l.$b=function(){NC(this.a)},l.Hc=function(e){return _nt(this.a,e)},l.Kc=function(){var e;return e=new y9(new w9(this.a).b),new g(e)},l.Mc=function(e){return _nt(this.a,e)?(P9(this.a,e),!0):!1},l.gc=function(){return this.a.c},F(pr,"AbstractNavigableMap/NavigableKeySet",493),D(494,1,sa,g),l.Nb=function(e){ba(this,e)},l.Ob=function(){return TM(this.a.a)},l.Pb=function(){var e;return e=Lj(this.a),e.cd()},l.Qb=function(){AYt(this.a)},F(pr,"AbstractNavigableMap/NavigableKeySet/1",494),D(2004,28,xy),l.Fc=function(e){return R8(xE(this,e)),!0},l.Gc=function(e){return On(e),Bj(e!=this,"Can't add a queue to itself"),Ua(this,e)},l.$b=function(){for(;cit(this)!=null;);},F(pr,"AbstractQueue",2004),D(302,28,{4:1,20:1,28:1,14:1},B3,eZt),l.Fc=function(e){return imt(this,e),!0},l.$b=function(){lmt(this)},l.Hc=function(e){return ere(new O9(this),e)},l.dc=function(){return BC(this)},l.Kc=function(){return new O9(this)},l.Mc=function(e){return hin(new O9(this),e)},l.gc=function(){return this.c-this.b&this.a.length-1},l.Nc=function(){return new _n(this,272)},l.Qc=function(e){var n;return n=this.c-this.b&this.a.length-1,e.lengthn&&ts(e,n,null),e},l.b=0,l.c=0,F(pr,"ArrayDeque",302),D(446,1,sa,O9),l.Nb=function(e){ba(this,e)},l.Ob=function(){return this.a!=this.b},l.Pb=function(){return Mz(this)},l.Qb=function(){Jee(this)},l.a=0,l.b=0,l.c=-1,F(pr,"ArrayDeque/IteratorImpl",446),D(12,52,_fe,he,Xc,Bu),l.Vc=function(e,n){Hm(this,e,n)},l.Fc=function(e){return le(this,e)},l.Wc=function(e,n){return Gyt(this,e,n)},l.Gc=function(e){return Ls(this,e)},l.$b=function(){this.c=Nt(Qn,De,1,0,5,1)},l.Hc=function(e){return Ro(this,e,0)!=-1},l.Jc=function(e){xu(this,e)},l.Xb=function(e){return Ne(this,e)},l.Xc=function(e){return Ro(this,e,0)},l.dc=function(){return this.c.length==0},l.Kc=function(){return new S(this)},l.$c=function(e){return Fg(this,e)},l.Mc=function(e){return mu(this,e)},l.Ud=function(e,n){tZt(this,e,n)},l._c=function(e,n){return ch(this,e,n)},l.gc=function(){return this.c.length},l.ad=function(e){Zs(this,e)},l.Pc=function(){return pnt(this)},l.Qc=function(e){return P1(this,e)};var Kxn=F(pr,"ArrayList",12);D(7,1,sa,S),l.Nb=function(e){ba(this,e)},l.Ob=function(){return Go(this)},l.Pb=function(){return J(this)},l.Qb=function(){L9(this)},l.a=0,l.b=-1,F(pr,"ArrayList/1",7),D(2013,b.Function,{},Tt),l.te=function(e,n){return Ms(e,n)},D(154,52,Sfe,yl),l.Hc=function(e){return ene(this,e)!=-1},l.Jc=function(e){var n,r,s,o;for(On(e),r=this.a,s=0,o=r.length;s>>0,e.toString(16)))},l.f=0,l.i=Cs;var oV=F(a0,"CNode",57);D(814,1,{},jpt),F(a0,"CNode/CNodeBuilder",814);var spe;D(1525,1,{},Po),l.Oe=function(e,n){return 0},l.Pe=function(e,n){return 0},F(a0,Ffe,1525),D(1790,1,{},vs),l.Le=function(e){var n,r,s,o,h,d,v,k,C,M,j,H,G,K,tt;for(C=as,s=new S(e.a.b);s.as.d.c||s.d.c==h.d.c&&s.d.b0?e+this.n.d+this.n.a:0},l.Se=function(){var e,n,r,s,o;if(o=0,this.e)this.b?o=this.b.a:this.a[1][1]&&(o=this.a[1][1].Se());else if(this.g)o=d3t(this,Ist(this,null,!0));else for(n=(Kf(),lt(ct(Oy,1),oe,232,0,[sc,eu,ac])),r=0,s=n.length;r0?o+this.n.b+this.n.c:0},l.Te=function(){var e,n,r,s,o;if(this.g)for(e=Ist(this,null,!1),r=(Kf(),lt(ct(Oy,1),oe,232,0,[sc,eu,ac])),s=0,o=r.length;s0&&(s[0]+=this.d,r-=s[0]),s[2]>0&&(s[2]+=this.d,r-=s[2]),this.c.a=b.Math.max(0,r),this.c.d=n.d+e.d+(this.c.a-r)/2,s[1]=b.Math.max(s[1],r),wmt(this,eu,n.d+e.d+s[0]-(s[1]-r)/2,s)},l.b=null,l.d=0,l.e=!1,l.f=!1,l.g=!1;var Gut=0,cV=0;F(_2,"GridContainerCell",1473),D(461,22,{3:1,35:1,22:1,461:1},Let);var fb,Md,kf,ppe=jr(_2,"HorizontalLabelAlignment",461,Hr,_in,lJe),bpe;D(306,212,{212:1,306:1},xQt,Aee,vQt),l.Re=function(){return sKt(this)},l.Se=function(){return Vwt(this)},l.a=0,l.c=!1;var s6n=F(_2,"LabelCell",306);D(244,326,{212:1,326:1,244:1},a_),l.Re=function(){return dI(this)},l.Se=function(){return gI(this)},l.Te=function(){Eat(this)},l.Ue=function(){Tat(this)},l.b=0,l.c=0,l.d=!1,F(_2,"StripContainerCell",244),D(1626,1,li,th),l.Mb=function(e){return EKe(u(e,212))},F(_2,"StripContainerCell/lambda$0$Type",1626),D(1627,1,{},Fa),l.Fe=function(e){return u(e,212).Se()},F(_2,"StripContainerCell/lambda$1$Type",1627),D(1628,1,li,Ml),l.Mb=function(e){return TKe(u(e,212))},F(_2,"StripContainerCell/lambda$2$Type",1628),D(1629,1,{},ha),l.Fe=function(e){return u(e,212).Re()},F(_2,"StripContainerCell/lambda$3$Type",1629),D(462,22,{3:1,35:1,22:1,462:1},Met);var Ef,db,n1,wpe=jr(_2,"VerticalLabelAlignment",462,Hr,Sin,hJe),vpe;D(789,1,{},Sxt),l.c=0,l.d=0,l.k=0,l.s=0,l.t=0,l.v=!1,l.w=0,l.D=!1,F(Yq,"NodeContext",789),D(1471,1,Oi,bc),l.ue=function(e,n){return xUt(u(e,61),u(n,61))},l.Fb=function(e){return this===e},l.ve=function(){return new dt(this)},F(Yq,"NodeContext/0methodref$comparePortSides$Type",1471),D(1472,1,Oi,Cc),l.ue=function(e,n){return Q0n(u(e,111),u(n,111))},l.Fb=function(e){return this===e},l.ve=function(){return new dt(this)},F(Yq,"NodeContext/1methodref$comparePortContexts$Type",1472),D(159,22,{3:1,35:1,22:1,159:1},hh);var mpe,ype,xpe,kpe,Epe,Tpe,Cpe,_pe,Spe,Ape,Lpe,Mpe,Dpe,Ipe,Ope,Ppe,Fpe,Npe,Bpe,Rpe,jpe,Uut,$pe=jr(Yq,"NodeLabelLocation",159,Hr,lst,fJe),zpe;D(111,1,{111:1},tce),l.a=!1,F(Yq,"PortContext",111),D(1476,1,Un,pa),l.td=function(e){$Ht(u(e,306))},F(zI,Yfe,1476),D(1477,1,li,Da),l.Mb=function(e){return!!u(e,111).c},F(zI,Kfe,1477),D(1478,1,Un,Ha),l.td=function(e){$Ht(u(e,111).c)},F(zI,"LabelPlacer/lambda$2$Type",1478);var o7t;D(1475,1,Un,_c),l.td=function(e){$m(),rKe(u(e,111))},F(zI,"NodeLabelAndSizeUtilities/lambda$0$Type",1475),D(790,1,Un,Ewt),l.td=function(e){pXe(this.b,this.c,this.a,u(e,181))},l.a=!1,l.c=!1,F(zI,"NodeLabelCellCreator/lambda$0$Type",790),D(1474,1,Un,vn),l.td=function(e){aKe(this.a,u(e,181))},F(zI,"PortContextCreator/lambda$0$Type",1474);var uV;D(1829,1,{},lw),F(HE,"GreedyRectangleStripOverlapRemover",1829),D(1830,1,Oi,Dl),l.ue=function(e,n){return WQe(u(e,222),u(n,222))},l.Fb=function(e){return this===e},l.ve=function(){return new dt(this)},F(HE,"GreedyRectangleStripOverlapRemover/0methodref$compareByYCoordinate$Type",1830),D(1786,1,{},vqt),l.a=5,l.e=0,F(HE,"RectangleStripOverlapRemover",1786),D(1787,1,Oi,ed),l.ue=function(e,n){return YQe(u(e,222),u(n,222))},l.Fb=function(e){return this===e},l.ve=function(){return new dt(this)},F(HE,"RectangleStripOverlapRemover/0methodref$compareLeftRectangleBorders$Type",1787),D(1789,1,Oi,jd),l.ue=function(e,n){return vnn(u(e,222),u(n,222))},l.Fb=function(e){return this===e},l.ve=function(){return new dt(this)},F(HE,"RectangleStripOverlapRemover/1methodref$compareRightRectangleBorders$Type",1789),D(406,22,{3:1,35:1,22:1,406:1},ZR);var lO,Wut,Yut,hO,qpe=jr(HE,"RectangleStripOverlapRemover/OverlapRemovalDirection",406,Hr,_sn,dJe),Hpe;D(222,1,{222:1},Hnt),F(HE,"RectangleStripOverlapRemover/RectangleNode",222),D(1788,1,Un,gr),l.td=function(e){k1n(this.a,u(e,222))},F(HE,"RectangleStripOverlapRemover/lambda$1$Type",1788),D(1304,1,Oi,nd),l.ue=function(e,n){return A3n(u(e,167),u(n,167))},l.Fb=function(e){return this===e},l.ve=function(){return new dt(this)},F(kd,"PolyominoCompactor/CornerCasesGreaterThanRestComparator",1304),D(1307,1,{},$d),l.Kb=function(e){return u(e,324).a},F(kd,"PolyominoCompactor/CornerCasesGreaterThanRestComparator/lambda$0$Type",1307),D(1308,1,li,A0),l.Mb=function(e){return u(e,323).a},F(kd,"PolyominoCompactor/CornerCasesGreaterThanRestComparator/lambda$1$Type",1308),D(1309,1,li,Bi),l.Mb=function(e){return u(e,323).a},F(kd,"PolyominoCompactor/CornerCasesGreaterThanRestComparator/lambda$2$Type",1309),D(1302,1,Oi,cn),l.ue=function(e,n){return cmn(u(e,167),u(n,167))},l.Fb=function(e){return this===e},l.ve=function(){return new dt(this)},F(kd,"PolyominoCompactor/MinNumOfExtensionDirectionsComparator",1302),D(1305,1,{},eh),l.Kb=function(e){return u(e,324).a},F(kd,"PolyominoCompactor/MinNumOfExtensionDirectionsComparator/lambda$0$Type",1305),D(767,1,Oi,kr),l.ue=function(e,n){return lun(u(e,167),u(n,167))},l.Fb=function(e){return this===e},l.ve=function(){return new dt(this)},F(kd,"PolyominoCompactor/MinNumOfExtensionsComparator",767),D(1300,1,Oi,Ei),l.ue=function(e,n){return mcn(u(e,321),u(n,321))},l.Fb=function(e){return this===e},l.ve=function(){return new dt(this)},F(kd,"PolyominoCompactor/MinPerimeterComparator",1300),D(1301,1,Oi,Jo),l.ue=function(e,n){return Kfn(u(e,321),u(n,321))},l.Fb=function(e){return this===e},l.ve=function(){return new dt(this)},F(kd,"PolyominoCompactor/MinPerimeterComparatorWithShape",1301),D(1303,1,Oi,wc),l.ue=function(e,n){return Dmn(u(e,167),u(n,167))},l.Fb=function(e){return this===e},l.ve=function(){return new dt(this)},F(kd,"PolyominoCompactor/SingleExtensionSideGreaterThanRestComparator",1303),D(1306,1,{},rf),l.Kb=function(e){return u(e,324).a},F(kd,"PolyominoCompactor/SingleExtensionSideGreaterThanRestComparator/lambda$0$Type",1306),D(777,1,{},Mbt),l.Ce=function(e,n){return ksn(this,u(e,46),u(n,167))},F(kd,"SuccessorCombination",777),D(644,1,{},Oc),l.Ce=function(e,n){var r;return hbn((r=u(e,46),u(n,167),r))},F(kd,"SuccessorJitter",644),D(643,1,{},sf),l.Ce=function(e,n){var r;return Jwn((r=u(e,46),u(n,167),r))},F(kd,"SuccessorLineByLine",643),D(568,1,{},af),l.Ce=function(e,n){var r;return f2n((r=u(e,46),u(n,167),r))},F(kd,"SuccessorManhattan",568),D(1356,1,{},Qi),l.Ce=function(e,n){var r;return Ewn((r=u(e,46),u(n,167),r))},F(kd,"SuccessorMaxNormWindingInMathPosSense",1356),D(400,1,{},fr),l.Ce=function(e,n){return vvt(this,e,n)},l.c=!1,l.d=!1,l.e=!1,l.f=!1,F(kd,"SuccessorQuadrantsGeneric",400),D(1357,1,{},Ts),l.Kb=function(e){return u(e,324).a},F(kd,"SuccessorQuadrantsGeneric/lambda$0$Type",1357),D(323,22,{3:1,35:1,22:1,323:1},QR),l.a=!1;var fO,dO,gO,pO,Vpe=jr(Xq,i6t,323,Hr,Lsn,gJe),Gpe;D(1298,1,{}),l.Ib=function(){var e,n,r,s,o,h;for(r=" ",e=pe(0),o=0;o=0?"b"+e+"["+zrt(this.a)+"]":"b["+zrt(this.a)+"]"):"b_"+Pw(this)},F(HI,"FBendpoint",559),D(282,134,{3:1,282:1,94:1,134:1},eYt),l.Ib=function(){return zrt(this)},F(HI,"FEdge",282),D(231,134,{3:1,231:1,94:1,134:1},B$);var o6n=F(HI,"FGraph",231);D(447,357,{3:1,447:1,357:1,94:1,134:1},iJt),l.Ib=function(){return this.b==null||this.b.length==0?"l["+zrt(this.a)+"]":"l_"+this.b},F(HI,"FLabel",447),D(144,357,{3:1,144:1,357:1,94:1,134:1},gXt),l.Ib=function(){return Kvt(this)},l.b=0,F(HI,"FNode",144),D(2003,1,{}),l.bf=function(e){axt(this,e)},l.cf=function(){Bse(this)},l.d=0,F(g6t,"AbstractForceModel",2003),D(631,2003,{631:1},Wne),l.af=function(e,n){var r,s,o,h,d;return Ooe(this.f,e,n),o=ia(nc(n.d),e.d),d=b.Math.sqrt(o.a*o.a+o.b*o.b),s=b.Math.max(0,d-D9(e.e)/2-D9(n.e)/2),r=Ere(this.e,e,n),r>0?h=-pnn(s,this.c)*r:h=oZe(s,this.b)*u(Q(e,(Jf(),c7)),19).a,fd(o,h/d),o},l.bf=function(e){axt(this,e),this.a=u(Q(e,(Jf(),pV)),19).a,this.c=Xt(ye(Q(e,bV))),this.b=Xt(ye(Q(e,elt)))},l.df=function(e){return e0&&(h-=mKe(s,this.a)*r),fd(o,h*this.b/d),o},l.bf=function(e){var n,r,s,o,h,d,v;for(axt(this,e),this.b=Xt(ye(Q(e,(Jf(),nlt)))),this.c=this.b/u(Q(e,pV),19).a,s=e.e.c.length,h=0,o=0,v=new S(e.e);v.a0},l.a=0,l.b=0,l.c=0,F(g6t,"FruchtermanReingoldModel",632),D(849,1,Oh,HJ),l.Qe=function(e){an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,Jq),""),"Force Model"),"Determines the model for force calculation."),b7t),(Ug(),us)),w7t),un((Qf(),qn))))),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,p6t),""),"Iterations"),"The number of iterations on the force model."),pe(300)),gc),ja),un(qn)))),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,b6t),""),"Repulsive Power"),"Determines how many bend points are added to the edge; such bend points are regarded as repelling particles in the force model"),pe(0)),gc),ja),un(Pd)))),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,qot),""),"FR Temperature"),"The temperature is used as a scaling factor for particle displacements."),Ed),Oo),la),un(qn)))),ca(e,qot,Jq,hbe),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,Hot),""),"Eades Repulsion"),"Factor for repulsive forces in Eades' model."),5),Oo),la),un(qn)))),ca(e,Hot,Jq,cbe),Phe((new bC,e))};var sbe,abe,b7t,obe,cbe,ube,lbe,hbe;F(B_,"ForceMetaDataProvider",849),D(424,22,{3:1,35:1,22:1,424:1},Pbt);var tlt,gV,w7t=jr(B_,"ForceModelStrategy",424,Hr,ein,wJe),fbe;D(988,1,Oh,bC),l.Qe=function(e){Phe(e)};var dbe,gbe,v7t,pV,m7t,pbe,bbe,wbe,y7t,vbe,x7t,k7t,mbe,c7,ybe,elt,E7t,xbe,kbe,bV,nlt;F(B_,"ForceOptions",988),D(989,1,{},V5),l.$e=function(){var e;return e=new Npt,e},l._e=function(e){},F(B_,"ForceOptions/ForceFactory",989);var vO,dS,I6,wV;D(850,1,Oh,VJ),l.Qe=function(e){an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,v6t),""),"Fixed Position"),"Prevent that the node is moved by the layout algorithm."),(Nn(),!1)),(Ug(),La)),Rs),un((Qf(),ea))))),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,m6t),""),"Desired Edge Length"),"Either specified for parent nodes or for individual edges, where the latter takes higher precedence."),100),Oo),la),ji(qn,lt(ct(ip,1),oe,175,0,[Pd]))))),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,y6t),""),"Layout Dimension"),"Dimensions that are permitted to be altered during layout."),T7t),us),D7t),un(qn)))),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,x6t),""),"Stress Epsilon"),"Termination criterion for the iterative process."),Ed),Oo),la),un(qn)))),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,k6t),""),"Iteration Limit"),"Maximum number of performed iterations. Takes higher precedence than 'epsilon'."),pe(wi)),gc),ja),un(qn)))),vhe((new GJ,e))};var Ebe,Tbe,T7t,Cbe,_be,Sbe;F(B_,"StressMetaDataProvider",850),D(992,1,Oh,GJ),l.Qe=function(e){vhe(e)};var vV,C7t,_7t,S7t,A7t,L7t,Abe,Lbe,Mbe,Dbe,M7t,Ibe;F(B_,"StressOptions",992),D(993,1,{},f1),l.$e=function(){var e;return e=new nYt,e},l._e=function(e){},F(B_,"StressOptions/StressFactory",993),D(1128,209,S2,nYt),l.Ze=function(e,n){var r,s,o,h,d;for(vr(n,o1e,1),je(Re(qe(e,(iI(),A7t))))?je(Re(qe(e,M7t)))||y$((r=new rr((Pm(),new Mm(e))),r)):jce(new Npt,e,Rc(n,1)),o=pre(e),s=Ale(this.a,o),d=s.Kc();d.Ob();)h=u(d.Pb(),231),!(h.e.c.length<=1)&&(_3n(this.b,h),i2n(this.b),xu(h.d,new rd));o=zhe(s),Rhe(o),or(n)},F(nH,"StressLayoutProvider",1128),D(1129,1,Un,rd),l.td=function(e){dxt(u(e,447))},F(nH,"StressLayoutProvider/lambda$0$Type",1129),D(990,1,{},hqt),l.c=0,l.e=0,l.g=0,F(nH,"StressMajorization",990),D(379,22,{3:1,35:1,22:1,379:1},Det);var rlt,ilt,slt,D7t=jr(nH,"StressMajorization/Dimension",379,Hr,Lin,vJe),Obe;D(991,1,Oi,Ci),l.ue=function(e,n){return YZe(this.a,u(e,144),u(n,144))},l.Fb=function(e){return this===e},l.ve=function(){return new dt(this)},F(nH,"StressMajorization/lambda$0$Type",991),D(1229,1,{},wZt),F(_6,"ElkLayered",1229),D(1230,1,Un,id),l.td=function(e){sbn(u(e,37))},F(_6,"ElkLayered/lambda$0$Type",1230),D(1231,1,Un,hi),l.td=function(e){KZe(this.a,u(e,37))},F(_6,"ElkLayered/lambda$1$Type",1231),D(1263,1,{},HUt);var Pbe,Fbe,Nbe;F(_6,"GraphConfigurator",1263),D(759,1,Un,gs),l.td=function(e){Gae(this.a,u(e,10))},F(_6,"GraphConfigurator/lambda$0$Type",759),D(760,1,{},G5),l.Kb=function(e){return l4t(),new Tn(null,new _n(u(e,29).a,16))},F(_6,"GraphConfigurator/lambda$1$Type",760),D(761,1,Un,qi),l.td=function(e){Gae(this.a,u(e,10))},F(_6,"GraphConfigurator/lambda$2$Type",761),D(1127,209,S2,gqt),l.Ze=function(e,n){var r;r=Wyn(new yqt,e),Vt(qe(e,(Te(),qy)))===Vt((G0(),sp))?Chn(this.a,r,n):xbn(this.a,r,n),Ohe(new WJ,r)},F(_6,"LayeredLayoutProvider",1127),D(356,22,{3:1,35:1,22:1,356:1},_M);var Dd,gb,cu,qc,Io,I7t=jr(_6,"LayeredPhases",356,Hr,fan,mJe),Bbe;D(1651,1,{},nne),l.i=0;var Rbe;F(UI,"ComponentsToCGraphTransformer",1651);var jbe;D(1652,1,{},fw),l.ef=function(e,n){return b.Math.min(e.a!=null?Xt(e.a):e.c.i,n.a!=null?Xt(n.a):n.c.i)},l.ff=function(e,n){return b.Math.min(e.a!=null?Xt(e.a):e.c.i,n.a!=null?Xt(n.a):n.c.i)},F(UI,"ComponentsToCGraphTransformer/1",1652),D(81,1,{81:1}),l.i=0,l.k=!0,l.o=Cs;var alt=F($_,"CNode",81);D(460,81,{460:1,81:1},F2t,N3t),l.Ib=function(){return""},F(UI,"ComponentsToCGraphTransformer/CRectNode",460),D(1623,1,{},U5);var olt,clt;F(UI,"OneDimensionalComponentsCompaction",1623),D(1624,1,{},mp),l.Kb=function(e){return yin(u(e,46))},l.Fb=function(e){return this===e},F(UI,"OneDimensionalComponentsCompaction/lambda$0$Type",1624),D(1625,1,{},W5),l.Kb=function(e){return Ohn(u(e,46))},l.Fb=function(e){return this===e},F(UI,"OneDimensionalComponentsCompaction/lambda$1$Type",1625),D(1654,1,{},dXt),F($_,"CGraph",1654),D(189,1,{189:1},ost),l.b=0,l.c=0,l.e=0,l.g=!0,l.i=Cs,F($_,"CGroup",189),D(1653,1,{},EL),l.ef=function(e,n){return b.Math.max(e.a!=null?Xt(e.a):e.c.i,n.a!=null?Xt(n.a):n.c.i)},l.ff=function(e,n){return b.Math.max(e.a!=null?Xt(e.a):e.c.i,n.a!=null?Xt(n.a):n.c.i)},F($_,Ffe,1653),D(1655,1,{},Uoe),l.d=!1;var $be,ult=F($_,Rfe,1655);D(1656,1,{},vl),l.Kb=function(e){return xbt(),Nn(),u(u(e,46).a,81).d.e!=0},l.Fb=function(e){return this===e},F($_,jfe,1656),D(823,1,{},Gwt),l.a=!1,l.b=!1,l.c=!1,l.d=!1,F($_,$fe,823),D(1825,1,{},DKt),F(rH,zfe,1825);var mO=Ki(L2,Ofe);D(1826,1,{369:1},cQt),l.Ke=function(e){gvn(this,u(e,466))},F(rH,qfe,1826),D(1827,1,Oi,iN),l.ue=function(e,n){return grn(u(e,81),u(n,81))},l.Fb=function(e){return this===e},l.ve=function(){return new dt(this)},F(rH,Hfe,1827),D(466,1,{466:1},Nbt),l.a=!1,F(rH,Vfe,466),D(1828,1,Oi,Sc),l.ue=function(e,n){return _dn(u(e,466),u(n,466))},l.Fb=function(e){return this===e},l.ve=function(){return new dt(this)},F(rH,Gfe,1828),D(140,1,{140:1},g8,$wt),l.Fb=function(e){var n;return e==null||c6n!=ol(e)?!1:(n=u(e,140),Fc(this.c,n.c)&&Fc(this.d,n.d))},l.Hb=function(){return Az(lt(ct(Qn,1),De,1,5,[this.c,this.d]))},l.Ib=function(){return"("+this.c+Ya+this.d+(this.a?"cx":"")+this.b+")"},l.a=!0,l.c=0,l.d=0;var c6n=F(L2,"Point",140);D(405,22,{3:1,35:1,22:1,405:1},JR);var Lv,Py,z4,Fy,zbe=jr(L2,"Point/Quadrant",405,Hr,Msn,yJe),qbe;D(1642,1,{},pqt),l.b=null,l.c=null,l.d=null,l.e=null,l.f=null;var Hbe,Vbe,Gbe,Ube,Wbe;F(L2,"RectilinearConvexHull",1642),D(574,1,{369:1},Yz),l.Ke=function(e){don(this,u(e,140))},l.b=0;var O7t;F(L2,"RectilinearConvexHull/MaximalElementsEventHandler",574),D(1644,1,Oi,wm),l.ue=function(e,n){return rrn(ye(e),ye(n))},l.Fb=function(e){return this===e},l.ve=function(){return new dt(this)},F(L2,"RectilinearConvexHull/MaximalElementsEventHandler/lambda$0$Type",1644),D(1643,1,{369:1},Cee),l.Ke=function(e){Swn(this,u(e,140))},l.a=0,l.b=null,l.c=null,l.d=null,l.e=null,F(L2,"RectilinearConvexHull/RectangleEventHandler",1643),D(1645,1,Oi,xg),l.ue=function(e,n){return asn(u(e,140),u(n,140))},l.Fb=function(e){return this===e},l.ve=function(){return new dt(this)},F(L2,"RectilinearConvexHull/lambda$0$Type",1645),D(1646,1,Oi,T3),l.ue=function(e,n){return osn(u(e,140),u(n,140))},l.Fb=function(e){return this===e},l.ve=function(){return new dt(this)},F(L2,"RectilinearConvexHull/lambda$1$Type",1646),D(1647,1,Oi,cK),l.ue=function(e,n){return usn(u(e,140),u(n,140))},l.Fb=function(e){return this===e},l.ve=function(){return new dt(this)},F(L2,"RectilinearConvexHull/lambda$2$Type",1647),D(1648,1,Oi,Vb),l.ue=function(e,n){return csn(u(e,140),u(n,140))},l.Fb=function(e){return this===e},l.ve=function(){return new dt(this)},F(L2,"RectilinearConvexHull/lambda$3$Type",1648),D(1649,1,Oi,uK),l.ue=function(e,n){return hgn(u(e,140),u(n,140))},l.Fb=function(e){return this===e},l.ve=function(){return new dt(this)},F(L2,"RectilinearConvexHull/lambda$4$Type",1649),D(1650,1,{},jQt),F(L2,"Scanline",1650),D(2005,1,{}),F(Td,"AbstractGraphPlacer",2005),D(325,1,{325:1},DWt),l.mf=function(e){return this.nf(e)?(ln(this.b,u(Q(e,(ae(),By)),21),e),!0):!1},l.nf=function(e){var n,r,s,o;for(n=u(Q(e,(ae(),By)),21),o=u(Ai(Pi,n),21),s=o.Kc();s.Ob();)if(r=u(s.Pb(),21),!u(Ai(this.b,r),15).dc())return!1;return!0};var Pi;F(Td,"ComponentGroup",325),D(765,2005,{},$pt),l.of=function(e){var n,r;for(r=new S(this.a);r.aG&&(ue=0,_e+=H+o,H=0),gt=d.c,x_(d,ue+gt.a,_e+gt.b),Gf(gt),r=b.Math.max(r,ue+St.a),H=b.Math.max(H,St.b),ue+=St.a+o;if(n.f.a=r,n.f.b=_e+H,je(Re(Q(h,iG)))){for(s=new PT,Oxt(s,e,o),j=e.Kc();j.Ob();)M=u(j.Pb(),37),Li(Gf(M.c),s.e);Li(Gf(n.f),s.a)}Omt(n,e)},F(Td,"SimpleRowGraphPlacer",1291),D(1292,1,Oi,Rf),l.ue=function(e,n){return uun(u(e,37),u(n,37))},l.Fb=function(e){return this===e},l.ve=function(){return new dt(this)},F(Td,"SimpleRowGraphPlacer/1",1292);var Kbe;D(1262,1,xd,vm),l.Lb=function(e){var n;return n=u(Q(u(e,243).b,(Te(),So)),74),!!n&&n.b!=0},l.Fb=function(e){return this===e},l.Mb=function(e){var n;return n=u(Q(u(e,243).b,(Te(),So)),74),!!n&&n.b!=0},F(iH,"CompoundGraphPostprocessor/1",1262),D(1261,1,os,xqt),l.pf=function(e,n){yse(this,u(e,37),n)},F(iH,"CompoundGraphPreprocessor",1261),D(441,1,{441:1},oie),l.c=!1,F(iH,"CompoundGraphPreprocessor/ExternalPort",441),D(243,1,{243:1},Fj),l.Ib=function(){return bnt(this.c)+":"+qoe(this.b)},F(iH,"CrossHierarchyEdge",243),D(763,1,Oi,Si),l.ue=function(e,n){return Z1n(this,u(e,243),u(n,243))},l.Fb=function(e){return this===e},l.ve=function(){return new dt(this)},F(iH,"CrossHierarchyEdgeComparator",763),D(299,134,{3:1,299:1,94:1,134:1}),l.p=0,F(tu,"LGraphElement",299),D(17,299,{3:1,17:1,299:1,94:1,134:1},Vw),l.Ib=function(){return qoe(this)};var hlt=F(tu,"LEdge",17);D(37,299,{3:1,20:1,37:1,299:1,94:1,134:1},eyt),l.Jc=function(e){va(this,e)},l.Kc=function(){return new S(this.b)},l.Ib=function(){return this.b.c.length==0?"G-unlayered"+eb(this.a):this.a.c.length==0?"G-layered"+eb(this.b):"G[layerless"+eb(this.a)+", layers"+eb(this.b)+"]"};var Xbe=F(tu,"LGraph",37),Qbe;D(657,1,{}),l.qf=function(){return this.e.n},l.We=function(e){return Q(this.e,e)},l.rf=function(){return this.e.o},l.sf=function(){return this.e.p},l.Xe=function(e){return Us(this.e,e)},l.tf=function(e){this.e.n.a=e.a,this.e.n.b=e.b},l.uf=function(e){this.e.o.a=e.a,this.e.o.b=e.b},l.vf=function(e){this.e.p=e},F(tu,"LGraphAdapters/AbstractLShapeAdapter",657),D(577,1,{839:1},Ui),l.wf=function(){var e,n;if(!this.b)for(this.b=Ud(this.a.b.c.length),n=new S(this.a.b);n.a0&&Wre((Rr(n-1,e.length),e.charCodeAt(n-1)),d1e);)--n;if(h> ",e),iq(r)),Gr(hc((e.a+="[",e),r.i),"]")),e.a},l.c=!0,l.d=!1;var R7t,j7t,$7t,z7t,q7t,H7t,Jbe=F(tu,"LPort",11);D(397,1,r0,Qs),l.Jc=function(e){va(this,e)},l.Kc=function(){var e;return e=new S(this.a.e),new qs(e)},F(tu,"LPort/1",397),D(1290,1,sa,qs),l.Nb=function(e){ba(this,e)},l.Pb=function(){return u(J(this.a),17).c},l.Ob=function(){return Go(this.a)},l.Qb=function(){L9(this.a)},F(tu,"LPort/1/1",1290),D(359,1,r0,Tr),l.Jc=function(e){va(this,e)},l.Kc=function(){var e;return e=new S(this.a.g),new Qt(e)},F(tu,"LPort/2",359),D(762,1,sa,Qt),l.Nb=function(e){ba(this,e)},l.Pb=function(){return u(J(this.a),17).d},l.Ob=function(){return Go(this.a)},l.Qb=function(){L9(this.a)},F(tu,"LPort/2/1",762),D(1283,1,r0,cGt),l.Jc=function(e){va(this,e)},l.Kc=function(){return new L1(this)},F(tu,"LPort/CombineIter",1283),D(201,1,sa,L1),l.Nb=function(e){ba(this,e)},l.Qb=function(){IHt()},l.Ob=function(){return v9(this)},l.Pb=function(){return Go(this.a)?J(this.a):J(this.b)},F(tu,"LPort/CombineIter/1",201),D(1285,1,xd,yp),l.Lb=function(e){return HKt(e)},l.Fb=function(e){return this===e},l.Mb=function(e){return ju(),u(e,11).e.c.length!=0},F(tu,"LPort/lambda$0$Type",1285),D(1284,1,xd,mm),l.Lb=function(e){return VKt(e)},l.Fb=function(e){return this===e},l.Mb=function(e){return ju(),u(e,11).g.c.length!=0},F(tu,"LPort/lambda$1$Type",1284),D(1286,1,xd,hK),l.Lb=function(e){return ju(),u(e,11).j==(ve(),Pn)},l.Fb=function(e){return this===e},l.Mb=function(e){return ju(),u(e,11).j==(ve(),Pn)},F(tu,"LPort/lambda$2$Type",1286),D(1287,1,xd,Gb),l.Lb=function(e){return ju(),u(e,11).j==(ve(),Hn)},l.Fb=function(e){return this===e},l.Mb=function(e){return ju(),u(e,11).j==(ve(),Hn)},F(tu,"LPort/lambda$3$Type",1287),D(1288,1,xd,fK),l.Lb=function(e){return ju(),u(e,11).j==(ve(),mr)},l.Fb=function(e){return this===e},l.Mb=function(e){return ju(),u(e,11).j==(ve(),mr)},F(tu,"LPort/lambda$4$Type",1288),D(1289,1,xd,dK),l.Lb=function(e){return ju(),u(e,11).j==(ve(),Bn)},l.Fb=function(e){return this===e},l.Mb=function(e){return ju(),u(e,11).j==(ve(),Bn)},F(tu,"LPort/lambda$5$Type",1289),D(29,299,{3:1,20:1,299:1,29:1,94:1,134:1},Sh),l.Jc=function(e){va(this,e)},l.Kc=function(){return new S(this.a)},l.Ib=function(){return"L_"+Ro(this.b.b,this,0)+eb(this.a)},F(tu,"Layer",29),D(1342,1,{},yqt),F(Kg,w1e,1342),D(1346,1,{},Y5),l.Kb=function(e){return Do(u(e,82))},F(Kg,"ElkGraphImporter/0methodref$connectableShapeToNode$Type",1346),D(1349,1,{},FT),l.Kb=function(e){return Do(u(e,82))},F(Kg,"ElkGraphImporter/1methodref$connectableShapeToNode$Type",1349),D(1343,1,Un,jn),l.td=function(e){nce(this.a,u(e,118))},F(Kg,v1e,1343),D(1344,1,Un,Sr),l.td=function(e){nce(this.a,u(e,118))},F(Kg,m1e,1344),D(1345,1,{},oN),l.Kb=function(e){return new Tn(null,new _n(Znn(u(e,79)),16))},F(Kg,y1e,1345),D(1347,1,li,ir),l.Mb=function(e){return JXe(this.a,u(e,33))},F(Kg,x1e,1347),D(1348,1,{},Tk),l.Kb=function(e){return new Tn(null,new _n(Jnn(u(e,79)),16))},F(Kg,"ElkGraphImporter/lambda$5$Type",1348),D(1350,1,li,sr),l.Mb=function(e){return tQe(this.a,u(e,33))},F(Kg,"ElkGraphImporter/lambda$7$Type",1350),D(1351,1,li,gK),l.Mb=function(e){return brn(u(e,79))},F(Kg,"ElkGraphImporter/lambda$8$Type",1351),D(1278,1,{},WJ);var t2e;F(Kg,"ElkGraphLayoutTransferrer",1278),D(1279,1,li,Ia),l.Mb=function(e){return qZe(this.a,u(e,17))},F(Kg,"ElkGraphLayoutTransferrer/lambda$0$Type",1279),D(1280,1,Un,$r),l.td=function(e){kM(),le(this.a,u(e,17))},F(Kg,"ElkGraphLayoutTransferrer/lambda$1$Type",1280),D(1281,1,li,Yi),l.Mb=function(e){return SZe(this.a,u(e,17))},F(Kg,"ElkGraphLayoutTransferrer/lambda$2$Type",1281),D(1282,1,Un,Fo),l.td=function(e){kM(),le(this.a,u(e,17))},F(Kg,"ElkGraphLayoutTransferrer/lambda$3$Type",1282),D(1485,1,os,Ck),l.pf=function(e,n){Lcn(u(e,37),n)},F($n,"CommentNodeMarginCalculator",1485),D(1486,1,{},pK),l.Kb=function(e){return new Tn(null,new _n(u(e,29).a,16))},F($n,"CommentNodeMarginCalculator/lambda$0$Type",1486),D(1487,1,Un,bK),l.td=function(e){u3n(u(e,10))},F($n,"CommentNodeMarginCalculator/lambda$1$Type",1487),D(1488,1,os,wK),l.pf=function(e,n){kvn(u(e,37),n)},F($n,"CommentPostprocessor",1488),D(1489,1,os,vK),l.pf=function(e,n){L5n(u(e,37),n)},F($n,"CommentPreprocessor",1489),D(1490,1,os,mK),l.pf=function(e,n){G2n(u(e,37),n)},F($n,"ConstraintsPostprocessor",1490),D(1491,1,os,yK),l.pf=function(e,n){Zcn(u(e,37),n)},F($n,"EdgeAndLayerConstraintEdgeReverser",1491),D(1492,1,os,xK),l.pf=function(e,n){$hn(u(e,37),n)},F($n,"EndLabelPostprocessor",1492),D(1493,1,{},kK),l.Kb=function(e){return new Tn(null,new _n(u(e,29).a,16))},F($n,"EndLabelPostprocessor/lambda$0$Type",1493),D(1494,1,li,EK),l.Mb=function(e){return Prn(u(e,10))},F($n,"EndLabelPostprocessor/lambda$1$Type",1494),D(1495,1,Un,TK),l.td=function(e){Sdn(u(e,10))},F($n,"EndLabelPostprocessor/lambda$2$Type",1495),D(1496,1,os,CK),l.pf=function(e,n){bpn(u(e,37),n)},F($n,"EndLabelPreprocessor",1496),D(1497,1,{},CL),l.Kb=function(e){return new Tn(null,new _n(u(e,29).a,16))},F($n,"EndLabelPreprocessor/lambda$0$Type",1497),D(1498,1,Un,PYt),l.td=function(e){bXe(this.a,this.b,this.c,u(e,10))},l.a=0,l.b=0,l.c=!1,F($n,"EndLabelPreprocessor/lambda$1$Type",1498),D(1499,1,li,_K),l.Mb=function(e){return Vt(Q(u(e,70),(Te(),Od)))===Vt((M1(),F7))},F($n,"EndLabelPreprocessor/lambda$2$Type",1499),D(1500,1,Un,Pc),l.td=function(e){ri(this.a,u(e,70))},F($n,"EndLabelPreprocessor/lambda$3$Type",1500),D(1501,1,li,SK),l.Mb=function(e){return Vt(Q(u(e,70),(Te(),Od)))===Vt((M1(),Zy))},F($n,"EndLabelPreprocessor/lambda$4$Type",1501),D(1502,1,Un,Za),l.td=function(e){ri(this.a,u(e,70))},F($n,"EndLabelPreprocessor/lambda$5$Type",1502),D(1551,1,os,UJ),l.pf=function(e,n){Yln(u(e,37),n)};var e2e;F($n,"EndLabelSorter",1551),D(1552,1,Oi,NT),l.ue=function(e,n){return Tfn(u(e,456),u(n,456))},l.Fb=function(e){return this===e},l.ve=function(){return new dt(this)},F($n,"EndLabelSorter/1",1552),D(456,1,{456:1},tQt),F($n,"EndLabelSorter/LabelGroup",456),D(1553,1,{},cN),l.Kb=function(e){return EM(),new Tn(null,new _n(u(e,29).a,16))},F($n,"EndLabelSorter/lambda$0$Type",1553),D(1554,1,li,K5),l.Mb=function(e){return EM(),u(e,10).k==(Vn(),Os)},F($n,"EndLabelSorter/lambda$1$Type",1554),D(1555,1,Un,AK),l.td=function(e){Sgn(u(e,10))},F($n,"EndLabelSorter/lambda$2$Type",1555),D(1556,1,li,LK),l.Mb=function(e){return EM(),Vt(Q(u(e,70),(Te(),Od)))===Vt((M1(),Zy))},F($n,"EndLabelSorter/lambda$3$Type",1556),D(1557,1,li,MK),l.Mb=function(e){return EM(),Vt(Q(u(e,70),(Te(),Od)))===Vt((M1(),F7))},F($n,"EndLabelSorter/lambda$4$Type",1557),D(1503,1,os,DK),l.pf=function(e,n){y3n(this,u(e,37))},l.b=0,l.c=0,F($n,"FinalSplineBendpointsCalculator",1503),D(1504,1,{},IK),l.Kb=function(e){return new Tn(null,new _n(u(e,29).a,16))},F($n,"FinalSplineBendpointsCalculator/lambda$0$Type",1504),D(1505,1,{},BT),l.Kb=function(e){return new Tn(null,new jw(new ar(lr(Ds(u(e,10)).a.Kc(),new z))))},F($n,"FinalSplineBendpointsCalculator/lambda$1$Type",1505),D(1506,1,li,_L),l.Mb=function(e){return!Ga(u(e,17))},F($n,"FinalSplineBendpointsCalculator/lambda$2$Type",1506),D(1507,1,li,uN),l.Mb=function(e){return Us(u(e,17),(ae(),R2))},F($n,"FinalSplineBendpointsCalculator/lambda$3$Type",1507),D(1508,1,Un,mc),l.td=function(e){Omn(this.a,u(e,128))},F($n,"FinalSplineBendpointsCalculator/lambda$4$Type",1508),D(1509,1,Un,C3),l.td=function(e){Yst(u(e,17).a)},F($n,"FinalSplineBendpointsCalculator/lambda$5$Type",1509),D(792,1,os,Ta),l.pf=function(e,n){d4n(this,u(e,37),n)},F($n,"GraphTransformer",792),D(511,22,{3:1,35:1,22:1,511:1},Fbt);var dlt,yO,n2e=jr($n,"GraphTransformer/Mode",511,Hr,nin,Ptn),r2e;D(1510,1,os,_3),l.pf=function(e,n){Hwn(u(e,37),n)},F($n,"HierarchicalNodeResizingProcessor",1510),D(1511,1,os,OK),l.pf=function(e,n){Tcn(u(e,37),n)},F($n,"HierarchicalPortConstraintProcessor",1511),D(1512,1,Oi,of),l.ue=function(e,n){return Ffn(u(e,10),u(n,10))},l.Fb=function(e){return this===e},l.ve=function(){return new dt(this)},F($n,"HierarchicalPortConstraintProcessor/NodeComparator",1512),D(1513,1,os,X5),l.pf=function(e,n){Vyn(u(e,37),n)},F($n,"HierarchicalPortDummySizeProcessor",1513),D(1514,1,os,PK),l.pf=function(e,n){zvn(this,u(e,37),n)},l.a=0,F($n,"HierarchicalPortOrthogonalEdgeRouter",1514),D(1515,1,Oi,_k),l.ue=function(e,n){return UQe(u(e,10),u(n,10))},l.Fb=function(e){return this===e},l.ve=function(){return new dt(this)},F($n,"HierarchicalPortOrthogonalEdgeRouter/1",1515),D(1516,1,Oi,zd),l.ue=function(e,n){return aon(u(e,10),u(n,10))},l.Fb=function(e){return this===e},l.ve=function(){return new dt(this)},F($n,"HierarchicalPortOrthogonalEdgeRouter/2",1516),D(1517,1,os,FK),l.pf=function(e,n){fgn(u(e,37),n)},F($n,"HierarchicalPortPositionProcessor",1517),D(1518,1,os,YJ),l.pf=function(e,n){oxn(this,u(e,37))},l.a=0,l.c=0;var mV,yV;F($n,"HighDegreeNodeLayeringProcessor",1518),D(571,1,{571:1},NK),l.b=-1,l.d=-1,F($n,"HighDegreeNodeLayeringProcessor/HighDegreeNodeInformation",571),D(1519,1,{},BK),l.Kb=function(e){return KM(),jo(u(e,10))},l.Fb=function(e){return this===e},F($n,"HighDegreeNodeLayeringProcessor/lambda$0$Type",1519),D(1520,1,{},RK),l.Kb=function(e){return KM(),Ds(u(e,10))},l.Fb=function(e){return this===e},F($n,"HighDegreeNodeLayeringProcessor/lambda$1$Type",1520),D(1526,1,os,RT),l.pf=function(e,n){vyn(this,u(e,37),n)},F($n,"HyperedgeDummyMerger",1526),D(793,1,{},Cwt),l.a=!1,l.b=!1,l.c=!1,F($n,"HyperedgeDummyMerger/MergeState",793),D(1527,1,{},SL),l.Kb=function(e){return new Tn(null,new _n(u(e,29).a,16))},F($n,"HyperedgeDummyMerger/lambda$0$Type",1527),D(1528,1,{},lN),l.Kb=function(e){return new Tn(null,new _n(u(e,10).j,16))},F($n,"HyperedgeDummyMerger/lambda$1$Type",1528),D(1529,1,Un,AL),l.td=function(e){u(e,11).p=-1},F($n,"HyperedgeDummyMerger/lambda$2$Type",1529),D(1530,1,os,Q5),l.pf=function(e,n){byn(u(e,37),n)},F($n,"HypernodesProcessor",1530),D(1531,1,os,jK),l.pf=function(e,n){wyn(u(e,37),n)},F($n,"InLayerConstraintProcessor",1531),D(1532,1,os,hN),l.pf=function(e,n){Wcn(u(e,37),n)},F($n,"InnermostNodeMarginCalculator",1532),D(1533,1,os,fN),l.pf=function(e,n){T5n(this,u(e,37))},l.a=Cs,l.b=Cs,l.c=as,l.d=as;var u6n=F($n,"InteractiveExternalPortPositioner",1533);D(1534,1,{},$K),l.Kb=function(e){return u(e,17).d.i},l.Fb=function(e){return this===e},F($n,"InteractiveExternalPortPositioner/lambda$0$Type",1534),D(1535,1,{},Ja),l.Kb=function(e){return KQe(this.a,ye(e))},l.Fb=function(e){return this===e},F($n,"InteractiveExternalPortPositioner/lambda$1$Type",1535),D(1536,1,{},zK),l.Kb=function(e){return u(e,17).c.i},l.Fb=function(e){return this===e},F($n,"InteractiveExternalPortPositioner/lambda$2$Type",1536),D(1537,1,{},ml),l.Kb=function(e){return XQe(this.a,ye(e))},l.Fb=function(e){return this===e},F($n,"InteractiveExternalPortPositioner/lambda$3$Type",1537),D(1538,1,{},qf),l.Kb=function(e){return jZe(this.a,ye(e))},l.Fb=function(e){return this===e},F($n,"InteractiveExternalPortPositioner/lambda$4$Type",1538),D(1539,1,{},Cp),l.Kb=function(e){return $Ze(this.a,ye(e))},l.Fb=function(e){return this===e},F($n,"InteractiveExternalPortPositioner/lambda$5$Type",1539),D(77,22,{3:1,35:1,22:1,77:1,234:1},ms),l.Kf=function(){switch(this.g){case 15:return new rQ;case 22:return new iQ;case 47:return new oQ;case 28:case 35:return new S3;case 32:return new Ck;case 42:return new wK;case 1:return new vK;case 41:return new mK;case 56:return new Ta((X8(),yO));case 0:return new Ta((X8(),dlt));case 2:return new yK;case 54:return new xK;case 33:return new CK;case 51:return new DK;case 55:return new _3;case 13:return new OK;case 38:return new X5;case 44:return new PK;case 40:return new FK;case 9:return new YJ;case 49:return new yWt;case 37:return new RT;case 43:return new Q5;case 27:return new jK;case 30:return new hN;case 3:return new fN;case 18:return new HK;case 29:return new VK;case 5:return new zB;case 50:return new qK;case 34:return new KJ;case 36:return new Sk;case 52:return new UJ;case 11:return new ym;case 7:return new QJ;case 39:return new Ak;case 45:return new YK;case 16:return new jT;case 10:return new sd;case 48:return new ML;case 21:return new Lk;case 23:return new det((ev(),FS));case 8:return new bN;case 12:return new IL;case 4:return new XK;case 19:return new wC;case 17:return new eX;case 53:return new nX;case 6:return new EN;case 25:return new Tqt;case 46:return new aX;case 31:return new iYt;case 14:return new PL;case 26:return new lQ;case 20:return new gX;case 24:return new det((ev(),TG));default:throw it(new Fn(Yot+(this.f!=null?this.f:""+this.g)))}};var V7t,G7t,U7t,W7t,Y7t,K7t,X7t,Q7t,Z7t,J7t,gS,xV,kV,tTt,eTt,nTt,rTt,iTt,sTt,aTt,pS,oTt,cTt,uTt,lTt,hTt,glt,EV,TV,fTt,CV,_V,SV,u7,l7,h7,dTt,AV,LV,gTt,MV,DV,pTt,bTt,wTt,vTt,IV,plt,xO,OV,PV,FV,NV,mTt,yTt,xTt,kTt,l6n=jr($n,T6t,77,Hr,Yce,Otn),i2e;D(1540,1,os,HK),l.pf=function(e,n){_5n(u(e,37),n)},F($n,"InvertedPortProcessor",1540),D(1541,1,os,VK),l.pf=function(e,n){_mn(u(e,37),n)},F($n,"LabelAndNodeSizeProcessor",1541),D(1542,1,li,GK),l.Mb=function(e){return u(e,10).k==(Vn(),Os)},F($n,"LabelAndNodeSizeProcessor/lambda$0$Type",1542),D(1543,1,li,qd),l.Mb=function(e){return u(e,10).k==(Vn(),ks)},F($n,"LabelAndNodeSizeProcessor/lambda$1$Type",1543),D(1544,1,Un,FYt),l.td=function(e){wXe(this.b,this.a,this.c,u(e,10))},l.a=!1,l.c=!1,F($n,"LabelAndNodeSizeProcessor/lambda$2$Type",1544),D(1545,1,os,zB),l.pf=function(e,n){X4n(u(e,37),n)};var s2e;F($n,"LabelDummyInserter",1545),D(1546,1,xd,dw),l.Lb=function(e){return Vt(Q(u(e,70),(Te(),Od)))===Vt((M1(),P7))},l.Fb=function(e){return this===e},l.Mb=function(e){return Vt(Q(u(e,70),(Te(),Od)))===Vt((M1(),P7))},F($n,"LabelDummyInserter/1",1546),D(1547,1,os,qK),l.pf=function(e,n){Z3n(u(e,37),n)},F($n,"LabelDummyRemover",1547),D(1548,1,li,UK),l.Mb=function(e){return je(Re(Q(u(e,70),(Te(),rht))))},F($n,"LabelDummyRemover/lambda$0$Type",1548),D(1359,1,os,KJ),l.pf=function(e,n){S4n(this,u(e,37),n)},l.a=null;var blt;F($n,"LabelDummySwitcher",1359),D(286,1,{286:1},Uue),l.c=0,l.d=null,l.f=0,F($n,"LabelDummySwitcher/LabelDummyInfo",286),D(1360,1,{},dN),l.Kb=function(e){return r6(),new Tn(null,new _n(u(e,29).a,16))},F($n,"LabelDummySwitcher/lambda$0$Type",1360),D(1361,1,li,gN),l.Mb=function(e){return r6(),u(e,10).k==(Vn(),Ll)},F($n,"LabelDummySwitcher/lambda$1$Type",1361),D(1362,1,{},_g),l.Kb=function(e){return AZe(this.a,u(e,10))},F($n,"LabelDummySwitcher/lambda$2$Type",1362),D(1363,1,Un,cd),l.td=function(e){Snn(this.a,u(e,286))},F($n,"LabelDummySwitcher/lambda$3$Type",1363),D(1364,1,Oi,WK),l.ue=function(e,n){return enn(u(e,286),u(n,286))},l.Fb=function(e){return this===e},l.ve=function(){return new dt(this)},F($n,"LabelDummySwitcher/lambda$4$Type",1364),D(791,1,os,S3),l.pf=function(e,n){Ran(u(e,37),n)},F($n,"LabelManagementProcessor",791),D(1549,1,os,Sk),l.pf=function(e,n){uvn(u(e,37),n)},F($n,"LabelSideSelector",1549),D(1550,1,li,LL),l.Mb=function(e){return je(Re(Q(u(e,70),(Te(),rht))))},F($n,"LabelSideSelector/lambda$0$Type",1550),D(1558,1,os,ym),l.pf=function(e,n){Gyn(u(e,37),n)},F($n,"LayerConstraintPostprocessor",1558),D(1559,1,os,QJ),l.pf=function(e,n){s2n(u(e,37),n)};var ETt;F($n,"LayerConstraintPreprocessor",1559),D(360,22,{3:1,35:1,22:1,360:1},tj);var kO,BV,RV,wlt,a2e=jr($n,"LayerConstraintPreprocessor/HiddenNodeConnections",360,Hr,Dsn,TJe),o2e;D(1560,1,os,Ak),l.pf=function(e,n){K3n(u(e,37),n)},F($n,"LayerSizeAndGraphHeightCalculator",1560),D(1561,1,os,YK),l.pf=function(e,n){Z2n(u(e,37),n)},F($n,"LongEdgeJoiner",1561),D(1562,1,os,jT),l.pf=function(e,n){M3n(u(e,37),n)},F($n,"LongEdgeSplitter",1562),D(1563,1,os,sd),l.pf=function(e,n){M4n(this,u(e,37),n)},l.d=0,l.e=0,l.i=0,l.j=0,l.k=0,l.n=0,F($n,"NodePromotion",1563),D(1564,1,{},pN),l.Kb=function(e){return u(e,46),Nn(),!0},l.Fb=function(e){return this===e},F($n,"NodePromotion/lambda$0$Type",1564),D(1565,1,{},_p),l.Kb=function(e){return Ynn(this.a,u(e,46))},l.Fb=function(e){return this===e},l.a=0,F($n,"NodePromotion/lambda$1$Type",1565),D(1566,1,{},Hf),l.Kb=function(e){return Knn(this.a,u(e,46))},l.Fb=function(e){return this===e},l.a=0,F($n,"NodePromotion/lambda$2$Type",1566),D(1567,1,os,ML),l.pf=function(e,n){txn(u(e,37),n)},F($n,"NorthSouthPortPostprocessor",1567),D(1568,1,os,Lk),l.pf=function(e,n){j5n(u(e,37),n)},F($n,"NorthSouthPortPreprocessor",1568),D(1569,1,Oi,DL),l.ue=function(e,n){return gun(u(e,11),u(n,11))},l.Fb=function(e){return this===e},l.ve=function(){return new dt(this)},F($n,"NorthSouthPortPreprocessor/lambda$0$Type",1569),D(1570,1,os,bN),l.pf=function(e,n){nyn(u(e,37),n)},F($n,"PartitionMidprocessor",1570),D(1571,1,li,KK),l.Mb=function(e){return Us(u(e,10),(Te(),T7))},F($n,"PartitionMidprocessor/lambda$0$Type",1571),D(1572,1,Un,mw),l.td=function(e){wrn(this.a,u(e,10))},F($n,"PartitionMidprocessor/lambda$1$Type",1572),D(1573,1,os,IL),l.pf=function(e,n){vwn(u(e,37),n)},F($n,"PartitionPostprocessor",1573),D(1574,1,os,XK),l.pf=function(e,n){Abn(u(e,37),n)},F($n,"PartitionPreprocessor",1574),D(1575,1,li,QK),l.Mb=function(e){return Us(u(e,10),(Te(),T7))},F($n,"PartitionPreprocessor/lambda$0$Type",1575),D(1576,1,{},wN),l.Kb=function(e){return new Tn(null,new jw(new ar(lr(Ds(u(e,10)).a.Kc(),new z))))},F($n,"PartitionPreprocessor/lambda$1$Type",1576),D(1577,1,li,Z5),l.Mb=function(e){return xfn(u(e,17))},F($n,"PartitionPreprocessor/lambda$2$Type",1577),D(1578,1,Un,vN),l.td=function(e){Tun(u(e,17))},F($n,"PartitionPreprocessor/lambda$3$Type",1578),D(1579,1,os,wC),l.pf=function(e,n){$mn(u(e,37),n)};var TTt,c2e,u2e,l2e,CTt,_Tt;F($n,"PortListSorter",1579),D(1580,1,{},J5),l.Kb=function(e){return oE(),u(e,11).e},F($n,"PortListSorter/lambda$0$Type",1580),D(1581,1,{},ZK),l.Kb=function(e){return oE(),u(e,11).g},F($n,"PortListSorter/lambda$1$Type",1581),D(1582,1,Oi,OL),l.ue=function(e,n){return aJt(u(e,11),u(n,11))},l.Fb=function(e){return this===e},l.ve=function(){return new dt(this)},F($n,"PortListSorter/lambda$2$Type",1582),D(1583,1,Oi,JK),l.ue=function(e,n){return G1n(u(e,11),u(n,11))},l.Fb=function(e){return this===e},l.ve=function(){return new dt(this)},F($n,"PortListSorter/lambda$3$Type",1583),D(1584,1,Oi,tX),l.ue=function(e,n){return ple(u(e,11),u(n,11))},l.Fb=function(e){return this===e},l.ve=function(){return new dt(this)},F($n,"PortListSorter/lambda$4$Type",1584),D(1585,1,os,eX),l.pf=function(e,n){Jbn(u(e,37),n)},F($n,"PortSideProcessor",1585),D(1586,1,os,nX),l.pf=function(e,n){tmn(u(e,37),n)},F($n,"ReversedEdgeRestorer",1586),D(1591,1,os,Tqt),l.pf=function(e,n){L1n(this,u(e,37),n)},F($n,"SelfLoopPortRestorer",1591),D(1592,1,{},mN),l.Kb=function(e){return new Tn(null,new _n(u(e,29).a,16))},F($n,"SelfLoopPortRestorer/lambda$0$Type",1592),D(1593,1,li,rX),l.Mb=function(e){return u(e,10).k==(Vn(),Os)},F($n,"SelfLoopPortRestorer/lambda$1$Type",1593),D(1594,1,li,iX),l.Mb=function(e){return Us(u(e,10),(ae(),x7))},F($n,"SelfLoopPortRestorer/lambda$2$Type",1594),D(1595,1,{},sX),l.Kb=function(e){return u(Q(u(e,10),(ae(),x7)),403)},F($n,"SelfLoopPortRestorer/lambda$3$Type",1595),D(1596,1,Un,Lm),l.td=function(e){Rgn(this.a,u(e,403))},F($n,"SelfLoopPortRestorer/lambda$4$Type",1596),D(794,1,Un,yN),l.td=function(e){Jgn(u(e,101))},F($n,"SelfLoopPortRestorer/lambda$5$Type",794),D(1597,1,os,aX),l.pf=function(e,n){Rfn(u(e,37),n)},F($n,"SelfLoopPostProcessor",1597),D(1598,1,{},oX),l.Kb=function(e){return new Tn(null,new _n(u(e,29).a,16))},F($n,"SelfLoopPostProcessor/lambda$0$Type",1598),D(1599,1,li,cX),l.Mb=function(e){return u(e,10).k==(Vn(),Os)},F($n,"SelfLoopPostProcessor/lambda$1$Type",1599),D(1600,1,li,xN),l.Mb=function(e){return Us(u(e,10),(ae(),x7))},F($n,"SelfLoopPostProcessor/lambda$2$Type",1600),D(1601,1,Un,uX),l.td=function(e){Gdn(u(e,10))},F($n,"SelfLoopPostProcessor/lambda$3$Type",1601),D(1602,1,{},lX),l.Kb=function(e){return new Tn(null,new _n(u(e,101).f,1))},F($n,"SelfLoopPostProcessor/lambda$4$Type",1602),D(1603,1,Un,xx),l.td=function(e){Psn(this.a,u(e,409))},F($n,"SelfLoopPostProcessor/lambda$5$Type",1603),D(1604,1,li,kN),l.Mb=function(e){return!!u(e,101).i},F($n,"SelfLoopPostProcessor/lambda$6$Type",1604),D(1605,1,Un,F3),l.td=function(e){vKe(this.a,u(e,101))},F($n,"SelfLoopPostProcessor/lambda$7$Type",1605),D(1587,1,os,EN),l.pf=function(e,n){D2n(u(e,37),n)},F($n,"SelfLoopPreProcessor",1587),D(1588,1,{},TN),l.Kb=function(e){return new Tn(null,new _n(u(e,101).f,1))},F($n,"SelfLoopPreProcessor/lambda$0$Type",1588),D(1589,1,{},hX),l.Kb=function(e){return u(e,409).a},F($n,"SelfLoopPreProcessor/lambda$1$Type",1589),D(1590,1,Un,fX),l.td=function(e){EQe(u(e,17))},F($n,"SelfLoopPreProcessor/lambda$2$Type",1590),D(1606,1,os,iYt),l.pf=function(e,n){Agn(this,u(e,37),n)},F($n,"SelfLoopRouter",1606),D(1607,1,{},Mk),l.Kb=function(e){return new Tn(null,new _n(u(e,29).a,16))},F($n,"SelfLoopRouter/lambda$0$Type",1607),D(1608,1,li,tx),l.Mb=function(e){return u(e,10).k==(Vn(),Os)},F($n,"SelfLoopRouter/lambda$1$Type",1608),D(1609,1,li,$T),l.Mb=function(e){return Us(u(e,10),(ae(),x7))},F($n,"SelfLoopRouter/lambda$2$Type",1609),D(1610,1,{},dX),l.Kb=function(e){return u(Q(u(e,10),(ae(),x7)),403)},F($n,"SelfLoopRouter/lambda$3$Type",1610),D(1611,1,Un,tGt),l.td=function(e){crn(this.a,this.b,u(e,403))},F($n,"SelfLoopRouter/lambda$4$Type",1611),D(1612,1,os,PL),l.pf=function(e,n){Qwn(u(e,37),n)},F($n,"SemiInteractiveCrossMinProcessor",1612),D(1613,1,li,zT),l.Mb=function(e){return u(e,10).k==(Vn(),Os)},F($n,"SemiInteractiveCrossMinProcessor/lambda$0$Type",1613),D(1614,1,li,FL),l.Mb=function(e){return yKt(u(e,10))._b((Te(),Uy))},F($n,"SemiInteractiveCrossMinProcessor/lambda$1$Type",1614),D(1615,1,Oi,CN),l.ue=function(e,n){return _cn(u(e,10),u(n,10))},l.Fb=function(e){return this===e},l.ve=function(){return new dt(this)},F($n,"SemiInteractiveCrossMinProcessor/lambda$2$Type",1615),D(1616,1,{},_N),l.Ce=function(e,n){return Crn(u(e,10),u(n,10))},F($n,"SemiInteractiveCrossMinProcessor/lambda$3$Type",1616),D(1618,1,os,gX),l.pf=function(e,n){Uyn(u(e,37),n)},F($n,"SortByInputModelProcessor",1618),D(1619,1,li,pX),l.Mb=function(e){return u(e,11).g.c.length!=0},F($n,"SortByInputModelProcessor/lambda$0$Type",1619),D(1620,1,Un,kx),l.td=function(e){ipn(this.a,u(e,11))},F($n,"SortByInputModelProcessor/lambda$1$Type",1620),D(1693,803,{},pne),l.Me=function(e){var n,r,s,o;switch(this.c=e,this.a.g){case 2:n=new he,ls(Ri(new Tn(null,new _n(this.c.a.b,16)),new MN),new sGt(this,n)),hI(this,new AN),xu(n,new wX),n.c=Nt(Qn,De,1,0,5,1),ls(Ri(new Tn(null,new _n(this.c.a.b,16)),new vX),new N3(n)),hI(this,new mX),xu(n,new yX),n.c=Nt(Qn,De,1,0,5,1),r=RUt(Ane(l$(new Tn(null,new _n(this.c.a.b,16)),new Hd(this))),new xX),ls(new Tn(null,new _n(this.c.a.a,16)),new nGt(r,n)),hI(this,new kX),xu(n,new bX),n.c=Nt(Qn,De,1,0,5,1);break;case 3:s=new he,hI(this,new SN),o=RUt(Ane(l$(new Tn(null,new _n(this.c.a.b,16)),new SC(this))),new LN),ls(Ri(new Tn(null,new _n(this.c.a.b,16)),new EX),new iGt(o,s)),hI(this,new TX),xu(s,new CX),s.c=Nt(Qn,De,1,0,5,1);break;default:throw it(new uqt)}},l.b=0,F(_s,"EdgeAwareScanlineConstraintCalculation",1693),D(1694,1,xd,SN),l.Lb=function(e){return _t(u(e,57).g,145)},l.Fb=function(e){return this===e},l.Mb=function(e){return _t(u(e,57).g,145)},F(_s,"EdgeAwareScanlineConstraintCalculation/lambda$0$Type",1694),D(1695,1,{},SC),l.Fe=function(e){return Bpn(this.a,u(e,57))},F(_s,"EdgeAwareScanlineConstraintCalculation/lambda$1$Type",1695),D(1703,1,Vq,eGt),l.Vd=function(){h_(this.a,this.b,-1)},l.b=0,F(_s,"EdgeAwareScanlineConstraintCalculation/lambda$10$Type",1703),D(1705,1,xd,AN),l.Lb=function(e){return _t(u(e,57).g,145)},l.Fb=function(e){return this===e},l.Mb=function(e){return _t(u(e,57).g,145)},F(_s,"EdgeAwareScanlineConstraintCalculation/lambda$11$Type",1705),D(1706,1,Un,wX),l.td=function(e){u(e,365).Vd()},F(_s,"EdgeAwareScanlineConstraintCalculation/lambda$12$Type",1706),D(1707,1,li,vX),l.Mb=function(e){return _t(u(e,57).g,10)},F(_s,"EdgeAwareScanlineConstraintCalculation/lambda$13$Type",1707),D(1709,1,Un,N3),l.td=function(e){lhn(this.a,u(e,57))},F(_s,"EdgeAwareScanlineConstraintCalculation/lambda$14$Type",1709),D(1708,1,Vq,uGt),l.Vd=function(){h_(this.b,this.a,-1)},l.a=0,F(_s,"EdgeAwareScanlineConstraintCalculation/lambda$15$Type",1708),D(1710,1,xd,mX),l.Lb=function(e){return _t(u(e,57).g,10)},l.Fb=function(e){return this===e},l.Mb=function(e){return _t(u(e,57).g,10)},F(_s,"EdgeAwareScanlineConstraintCalculation/lambda$16$Type",1710),D(1711,1,Un,yX),l.td=function(e){u(e,365).Vd()},F(_s,"EdgeAwareScanlineConstraintCalculation/lambda$17$Type",1711),D(1712,1,{},Hd),l.Fe=function(e){return Rpn(this.a,u(e,57))},F(_s,"EdgeAwareScanlineConstraintCalculation/lambda$18$Type",1712),D(1713,1,{},xX),l.De=function(){return 0},F(_s,"EdgeAwareScanlineConstraintCalculation/lambda$19$Type",1713),D(1696,1,{},LN),l.De=function(){return 0},F(_s,"EdgeAwareScanlineConstraintCalculation/lambda$2$Type",1696),D(1715,1,Un,nGt),l.td=function(e){Gen(this.a,this.b,u(e,307))},l.a=0,F(_s,"EdgeAwareScanlineConstraintCalculation/lambda$20$Type",1715),D(1714,1,Vq,rGt),l.Vd=function(){Cce(this.a,this.b,-1)},l.b=0,F(_s,"EdgeAwareScanlineConstraintCalculation/lambda$21$Type",1714),D(1716,1,xd,kX),l.Lb=function(e){return u(e,57),!0},l.Fb=function(e){return this===e},l.Mb=function(e){return u(e,57),!0},F(_s,"EdgeAwareScanlineConstraintCalculation/lambda$22$Type",1716),D(1717,1,Un,bX),l.td=function(e){u(e,365).Vd()},F(_s,"EdgeAwareScanlineConstraintCalculation/lambda$23$Type",1717),D(1697,1,li,EX),l.Mb=function(e){return _t(u(e,57).g,10)},F(_s,"EdgeAwareScanlineConstraintCalculation/lambda$3$Type",1697),D(1699,1,Un,iGt),l.td=function(e){Uen(this.a,this.b,u(e,57))},l.a=0,F(_s,"EdgeAwareScanlineConstraintCalculation/lambda$4$Type",1699),D(1698,1,Vq,lGt),l.Vd=function(){h_(this.b,this.a,-1)},l.a=0,F(_s,"EdgeAwareScanlineConstraintCalculation/lambda$5$Type",1698),D(1700,1,xd,TX),l.Lb=function(e){return u(e,57),!0},l.Fb=function(e){return this===e},l.Mb=function(e){return u(e,57),!0},F(_s,"EdgeAwareScanlineConstraintCalculation/lambda$6$Type",1700),D(1701,1,Un,CX),l.td=function(e){u(e,365).Vd()},F(_s,"EdgeAwareScanlineConstraintCalculation/lambda$7$Type",1701),D(1702,1,li,MN),l.Mb=function(e){return _t(u(e,57).g,145)},F(_s,"EdgeAwareScanlineConstraintCalculation/lambda$8$Type",1702),D(1704,1,Un,sGt),l.td=function(e){Hon(this.a,this.b,u(e,57))},F(_s,"EdgeAwareScanlineConstraintCalculation/lambda$9$Type",1704),D(1521,1,os,yWt),l.pf=function(e,n){B3n(this,u(e,37),n)};var h2e;F(_s,"HorizontalGraphCompactor",1521),D(1522,1,{},y1),l.Oe=function(e,n){var r,s,o;return qmt(e,n)||(r=t4(e),s=t4(n),r&&r.k==(Vn(),ks)||s&&s.k==(Vn(),ks))?0:(o=u(Q(this.a.a,(ae(),Q4)),304),QQe(o,r?r.k:(Vn(),ta),s?s.k:(Vn(),ta)))},l.Pe=function(e,n){var r,s,o;return qmt(e,n)?1:(r=t4(e),s=t4(n),o=u(Q(this.a.a,(ae(),Q4)),304),B2t(o,r?r.k:(Vn(),ta),s?s.k:(Vn(),ta)))},F(_s,"HorizontalGraphCompactor/1",1522),D(1523,1,{},qT),l.Ne=function(e,n){return GC(),e.a.i==0},F(_s,"HorizontalGraphCompactor/lambda$0$Type",1523),D(1524,1,{},Vd),l.Ne=function(e,n){return xrn(this.a,e,n)},F(_s,"HorizontalGraphCompactor/lambda$1$Type",1524),D(1664,1,{},tee);var f2e,d2e;F(_s,"LGraphToCGraphTransformer",1664),D(1672,1,li,_X),l.Mb=function(e){return e!=null},F(_s,"LGraphToCGraphTransformer/0methodref$nonNull$Type",1672),D(1665,1,{},SX),l.Kb=function(e){return df(),$o(Q(u(u(e,57).g,10),(ae(),_i)))},F(_s,"LGraphToCGraphTransformer/lambda$0$Type",1665),D(1666,1,{},DN),l.Kb=function(e){return df(),rie(u(u(e,57).g,145))},F(_s,"LGraphToCGraphTransformer/lambda$1$Type",1666),D(1675,1,li,AX),l.Mb=function(e){return df(),_t(u(e,57).g,10)},F(_s,"LGraphToCGraphTransformer/lambda$10$Type",1675),D(1676,1,Un,LX),l.td=function(e){yrn(u(e,57))},F(_s,"LGraphToCGraphTransformer/lambda$11$Type",1676),D(1677,1,li,MX),l.Mb=function(e){return df(),_t(u(e,57).g,145)},F(_s,"LGraphToCGraphTransformer/lambda$12$Type",1677),D(1681,1,Un,DX),l.td=function(e){Cln(u(e,57))},F(_s,"LGraphToCGraphTransformer/lambda$13$Type",1681),D(1678,1,Un,AC),l.td=function(e){KXe(this.a,u(e,8))},l.a=0,F(_s,"LGraphToCGraphTransformer/lambda$14$Type",1678),D(1679,1,Un,Yb),l.td=function(e){QXe(this.a,u(e,110))},l.a=0,F(_s,"LGraphToCGraphTransformer/lambda$15$Type",1679),D(1680,1,Un,dR),l.td=function(e){XXe(this.a,u(e,8))},l.a=0,F(_s,"LGraphToCGraphTransformer/lambda$16$Type",1680),D(1682,1,{},IX),l.Kb=function(e){return df(),new Tn(null,new jw(new ar(lr(Ds(u(e,10)).a.Kc(),new z))))},F(_s,"LGraphToCGraphTransformer/lambda$17$Type",1682),D(1683,1,li,OX),l.Mb=function(e){return df(),Ga(u(e,17))},F(_s,"LGraphToCGraphTransformer/lambda$18$Type",1683),D(1684,1,Un,Htt),l.td=function(e){Don(this.a,u(e,17))},F(_s,"LGraphToCGraphTransformer/lambda$19$Type",1684),D(1668,1,Un,Vtt),l.td=function(e){hsn(this.a,u(e,145))},F(_s,"LGraphToCGraphTransformer/lambda$2$Type",1668),D(1685,1,{},IN),l.Kb=function(e){return df(),new Tn(null,new _n(u(e,29).a,16))},F(_s,"LGraphToCGraphTransformer/lambda$20$Type",1685),D(1686,1,{},PX),l.Kb=function(e){return df(),new Tn(null,new jw(new ar(lr(Ds(u(e,10)).a.Kc(),new z))))},F(_s,"LGraphToCGraphTransformer/lambda$21$Type",1686),D(1687,1,{},ON),l.Kb=function(e){return df(),u(Q(u(e,17),(ae(),R2)),15)},F(_s,"LGraphToCGraphTransformer/lambda$22$Type",1687),D(1688,1,li,FX),l.Mb=function(e){return JQe(u(e,15))},F(_s,"LGraphToCGraphTransformer/lambda$23$Type",1688),D(1689,1,Un,Gtt),l.td=function(e){Apn(this.a,u(e,15))},F(_s,"LGraphToCGraphTransformer/lambda$24$Type",1689),D(1667,1,Un,aGt),l.td=function(e){Zsn(this.a,this.b,u(e,145))},F(_s,"LGraphToCGraphTransformer/lambda$3$Type",1667),D(1669,1,{},NX),l.Kb=function(e){return df(),new Tn(null,new _n(u(e,29).a,16))},F(_s,"LGraphToCGraphTransformer/lambda$4$Type",1669),D(1670,1,{},BX),l.Kb=function(e){return df(),new Tn(null,new jw(new ar(lr(Ds(u(e,10)).a.Kc(),new z))))},F(_s,"LGraphToCGraphTransformer/lambda$5$Type",1670),D(1671,1,{},HT),l.Kb=function(e){return df(),u(Q(u(e,17),(ae(),R2)),15)},F(_s,"LGraphToCGraphTransformer/lambda$6$Type",1671),D(1673,1,Un,Utt),l.td=function(e){abn(this.a,u(e,15))},F(_s,"LGraphToCGraphTransformer/lambda$8$Type",1673),D(1674,1,Un,oGt),l.td=function(e){mQe(this.a,this.b,u(e,145))},F(_s,"LGraphToCGraphTransformer/lambda$9$Type",1674),D(1663,1,{},RX),l.Le=function(e){var n,r,s,o,h;for(this.a=e,this.d=new eet,this.c=Nt(a7t,De,121,this.a.a.a.c.length,0,1),this.b=0,r=new S(this.a.a.a);r.a=tt&&(le(h,pe(M)),St=b.Math.max(St,Rt[M-1]-j),v+=K,gt+=Rt[M-1]-gt,j=Rt[M-1],K=k[M]),K=b.Math.max(K,k[M]),++M;v+=K}G=b.Math.min(1/St,1/n.b/v),G>s&&(s=G,r=h)}return r},l.Wf=function(){return!1},F(Cd,"MSDCutIndexHeuristic",802),D(1617,1,os,lQ),l.pf=function(e,n){Ryn(u(e,37),n)},F(Cd,"SingleEdgeGraphWrapper",1617),D(227,22,{3:1,35:1,22:1,227:1},ZC);var V4,g7,p7,Ny,bS,G4,b7=jr(kc,"CenterEdgeLabelPlacementStrategy",227,Hr,Kan,SJe),C2e;D(422,22,{3:1,35:1,22:1,422:1},Bbt);var ATt,Alt,LTt=jr(kc,"ConstraintCalculationStrategy",422,Hr,jrn,AJe),_2e;D(314,22,{3:1,35:1,22:1,314:1,246:1,234:1},Pet),l.Kf=function(){return Noe(this)},l.Xf=function(){return Noe(this)};var EO,P6,MTt,DTt=jr(kc,"CrossingMinimizationStrategy",314,Hr,Din,LJe),S2e;D(337,22,{3:1,35:1,22:1,337:1},Fet);var ITt,Llt,VV,OTt=jr(kc,"CuttingStrategy",337,Hr,Iin,IJe),A2e;D(335,22,{3:1,35:1,22:1,335:1,246:1,234:1},AM),l.Kf=function(){return kce(this)},l.Xf=function(){return kce(this)};var PTt,Mlt,wS,Dlt,vS,FTt=jr(kc,"CycleBreakingStrategy",335,Hr,xan,OJe),L2e;D(419,22,{3:1,35:1,22:1,419:1},Rbt);var GV,NTt,BTt=jr(kc,"DirectionCongruency",419,Hr,Rrn,PJe),M2e;D(450,22,{3:1,35:1,22:1,450:1},Net);var w7,Ilt,U4,D2e=jr(kc,"EdgeConstraint",450,Hr,Oin,FJe),I2e;D(276,22,{3:1,35:1,22:1,276:1},JC);var Olt,Plt,Flt,Nlt,UV,Blt,RTt=jr(kc,"EdgeLabelSideSelection",276,Hr,Jan,NJe),O2e;D(479,22,{3:1,35:1,22:1,479:1},jbt);var WV,jTt,$Tt=jr(kc,"EdgeStraighteningStrategy",479,Hr,Brn,BJe),P2e;D(274,22,{3:1,35:1,22:1,274:1},t9);var Rlt,zTt,qTt,YV,HTt,VTt,GTt=jr(kc,"FixedAlignment",274,Hr,Qan,RJe),F2e;D(275,22,{3:1,35:1,22:1,275:1},e9);var UTt,WTt,YTt,KTt,mS,XTt,QTt=jr(kc,"GraphCompactionStrategy",275,Hr,Xan,jJe),N2e;D(256,22,{3:1,35:1,22:1,256:1},Fm);var v7,KV,m7,vh,yS,XV,y7,W4,QV,xS,jlt=jr(kc,"GraphProperties",256,Hr,Rcn,$Je),B2e;D(292,22,{3:1,35:1,22:1,292:1},Bet);var TO,$lt,zlt,qlt=jr(kc,"GreedySwitchType",292,Hr,Nin,zJe),R2e;D(303,22,{3:1,35:1,22:1,303:1},Ret);var F6,CO,Y4,j2e=jr(kc,"InLayerConstraint",303,Hr,Fin,qJe),$2e;D(420,22,{3:1,35:1,22:1,420:1},$bt);var Hlt,ZTt,JTt=jr(kc,"InteractiveReferencePoint",420,Hr,$rn,HJe),z2e,tCt,N6,Iv,ZV,eCt,nCt,JV,rCt,_O,tG,kS,B6,By,Vlt,eG,oc,iCt,Ov,Vc,Glt,Ult,SO,B2,Pv,R6,sCt,j6,AO,Ry,r1,$h,Wlt,K4,Tc,_i,aCt,oCt,cCt,uCt,lCt,Ylt,nG,Ju,Fv,Klt,$6,LO,q1,X4,x7,Q4,Z4,k7,R2,hCt,Xlt,Qlt,z6;D(163,22,{3:1,35:1,22:1,163:1},MM);var ES,bb,TS,jy,MO,fCt=jr(kc,"LayerConstraint",163,Hr,Tan,VJe),q2e;D(848,1,Oh,rtt),l.Qe=function(e){an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,C6t),""),"Direction Congruency"),"Specifies how drawings of the same graph with different layout directions compare to each other: either a natural reading direction is preserved or the drawings are rotated versions of each other."),kCt),(Ug(),us)),BTt),un((Qf(),qn))))),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,_6t),""),"Feedback Edges"),"Whether feedback edges should be highlighted by routing around the nodes."),(Nn(),!1)),La),Rs),un(qn)))),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,sH),""),"Interactive Reference Point"),"Determines which point of a node is considered by interactive layout phases."),ACt),us),JTt),un(qn)))),ca(e,sH,Qot,Owe),ca(e,sH,H_,Iwe),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,S6t),""),"Merge Edges"),"Edges that have no ports are merged so they touch the connected nodes at the same points. When this option is disabled, one port is created for each edge directly connected to a node. When it is enabled, all such incoming edges share an input port, and all outgoing edges share an output port."),!1),La),Rs),un(qn)))),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,A6t),""),"Merge Hierarchy-Crossing Edges"),"If hierarchical layout is active, hierarchy-crossing edges use as few hierarchical ports as possible. They are broken by the algorithm, with hierarchical ports inserted as required. Usually, one such port is created for each edge at each hierarchy crossing point. With this option set to true, we try to create as few hierarchical ports as possible in the process. In particular, all edges that form a hyperedge can share a port."),!0),La),Rs),un(qn)))),an(e,new Xe(XKe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,L6t),""),"Allow Non-Flow Ports To Switch Sides"),"Specifies whether non-flow ports may switch sides if their node's port constraints are either FIXED_SIDE or FIXED_ORDER. A non-flow port is a port on a side that is not part of the currently configured layout flow. For instance, given a left-to-right layout direction, north and south ports would be considered non-flow ports. Further note that the underlying criterium whether to switch sides or not solely relies on the minimization of edge crossings. Hence, edge length and other aesthetics criteria are not addressed."),!1),La),Rs),un(V2)),lt(ct(Ae,1),ee,2,6,["org.eclipse.elk.layered.northOrSouthPort"])))),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,M6t),""),"Port Sorting Strategy"),"Only relevant for nodes with FIXED_SIDE port constraints. Determines the way a node's ports are distributed on the sides of a node if their order is not prescribed. The option is set on parent nodes."),NCt),us),V9t),un(qn)))),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,D6t),""),"Thoroughness"),"How much effort should be spent to produce a nice layout."),pe(7)),gc),ja),un(qn)))),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,I6t),""),"Add Unnecessary Bendpoints"),"Adds bend points even if an edge does not change direction. If true, each long edge dummy will contribute a bend point to its edges and hierarchy-crossing edges will always get a bend point where they cross hierarchy boundaries. By default, bend points are only added where an edge changes direction."),!1),La),Rs),un(qn)))),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,O6t),""),"Generate Position and Layer IDs"),"If enabled position id and layer id are generated, which are usually only used internally when setting the interactiveLayout option. This option should be specified on the root node."),!1),La),Rs),un(qn)))),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,Qot),"cycleBreaking"),"Cycle Breaking Strategy"),"Strategy for cycle breaking. Cycle breaking looks for cycles in the graph and determines which edges to reverse to break the cycles. Reversed edges will end up pointing to the opposite direction of regular edges (that is, reversed edges will point left if edges usually point right)."),xCt),us),FTt),un(qn)))),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,KI),xct),"Node Layering Strategy"),"Strategy for node layering."),DCt),us),I9t),un(qn)))),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,P6t),xct),"Layer Constraint"),"Determines a constraint on the placement of the node regarding the layering."),LCt),us),fCt),un(ea)))),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,F6t),xct),"Layer Choice Constraint"),"Allows to set a constraint regarding the layer placement of a node. Let i be the value of teh constraint. Assumed the drawing has n layers and i < n. If set to i, it expresses that the node should be placed in i-th layer. Should i>=n be true then the node is placed in the last layer of the drawing. Note that this option is not part of any of ELK Layered's default configurations but is only evaluated as part of the `InteractiveLayeredGraphVisitor`, which must be applied manually or used via the `DiagramLayoutEngine."),pe(-1)),gc),ja),un(ea)))),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,N6t),xct),"Layer ID"),"Layer identifier that was calculated by ELK Layered for a node. This is only generated if interactiveLayot or generatePositionAndLayerIds is set."),pe(-1)),gc),ja),un(ea)))),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,Zot),I1e),"Upper Bound On Width [MinWidth Layerer]"),"Defines a loose upper bound on the width of the MinWidth layerer. If set to '-1' multiple values are tested and the best result is selected."),pe(4)),gc),ja),un(qn)))),ca(e,Zot,KI,$we),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,Jot),I1e),"Upper Layer Estimation Scaling Factor [MinWidth Layerer]"),"Multiplied with Upper Bound On Width for defining an upper bound on the width of layers which haven't been determined yet, but whose maximum width had been (roughly) estimated by the MinWidth algorithm. Compensates for too high estimations. If set to '-1' multiple values are tested and the best result is selected."),pe(2)),gc),ja),un(qn)))),ca(e,Jot,KI,qwe),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,tct),O1e),"Node Promotion Strategy"),"Reduces number of dummy nodes after layering phase (if possible)."),MCt),us),z9t),un(qn)))),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,ect),O1e),"Max Node Promotion Iterations"),"Limits the number of iterations for node promotion."),pe(0)),gc),ja),un(qn)))),ca(e,ect,tct,null),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,nct),"layering.coffmanGraham"),"Layer Bound"),"The maximum number of nodes allowed per layer."),pe(wi)),gc),ja),un(qn)))),ca(e,nct,KI,Fwe),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,H_),XI),"Crossing Minimization Strategy"),"Strategy for crossing minimization."),yCt),us),DTt),un(qn)))),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,B6t),XI),"Force Node Model Order"),"The node order given by the model does not change to produce a better layout. E.g. if node A is before node B in the model this is not changed during crossing minimization. This assumes that the node model order is already respected before crossing minimization. This can be achieved by setting considerModelOrder.strategy to NODES_AND_EDGES."),!1),La),Rs),un(qn)))),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,rct),XI),"Hierarchical Sweepiness"),"How likely it is to use cross-hierarchy (1) vs bottom-up (-1)."),.1),Oo),la),un(qn)))),ca(e,rct,vH,owe),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,ict),XI),"Semi-Interactive Crossing Minimization"),"Preserves the order of nodes within a layer but still minimizes crossings between edges connecting long edge dummies. Derives the desired order from positions specified by the 'org.eclipse.elk.position' layout option. Requires a crossing minimization strategy that is able to process 'in-layer' constraints."),!1),La),Rs),un(qn)))),ca(e,ict,H_,hwe),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,R6t),XI),"Position Choice Constraint"),"Allows to set a constraint regarding the position placement of a node in a layer. Assumed the layer in which the node placed includes n other nodes and i < n. If set to i, it expresses that the node should be placed at the i-th position. Should i>=n be true then the node is placed at the last position in the layer. Note that this option is not part of any of ELK Layered's default configurations but is only evaluated as part of the `InteractiveLayeredGraphVisitor`, which must be applied manually or used via the `DiagramLayoutEngine."),pe(-1)),gc),ja),un(ea)))),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,j6t),XI),"Position ID"),"Position within a layer that was determined by ELK Layered for a node. This is only generated if interactiveLayot or generatePositionAndLayerIds is set."),pe(-1)),gc),ja),un(ea)))),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,$6t),P1e),"Greedy Switch Activation Threshold"),"By default it is decided automatically if the greedy switch is activated or not. The decision is based on whether the size of the input graph (without dummy nodes) is smaller than the value of this option. A '0' enforces the activation."),pe(40)),gc),ja),un(qn)))),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,sct),P1e),"Greedy Switch Crossing Minimization"),"Greedy Switch strategy for crossing minimization. The greedy switch heuristic is executed after the regular crossing minimization as a post-processor. Note that if 'hierarchyHandling' is set to 'INCLUDE_CHILDREN', the 'greedySwitchHierarchical.type' option must be used."),mCt),us),qlt),un(qn)))),ca(e,sct,H_,swe),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,aH),"crossingMinimization.greedySwitchHierarchical"),"Greedy Switch Crossing Minimization (hierarchical)"),"Activates the greedy switch heuristic in case hierarchical layout is used. The differences to the non-hierarchical case (see 'greedySwitch.type') are: 1) greedy switch is inactive by default, 3) only the option value set on the node at which hierarchical layout starts is relevant, and 2) if it's activated by the user, it properly addresses hierarchy-crossing edges."),vCt),us),qlt),un(qn)))),ca(e,aH,H_,nwe),ca(e,aH,vH,rwe),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,I4),F1e),"Node Placement Strategy"),"Strategy for node placement."),FCt),us),N9t),un(qn)))),an(e,new Xe(rn(nn(sn(Ze(en(Je(tn(new Ue,oH),F1e),"Favor Straight Edges Over Balancing"),"Favor straight edges over a balanced node placement. The default behavior is determined automatically based on the used 'edgeRouting'. For an orthogonal style it is set to true, for all other styles to false."),La),Rs),un(qn)))),ca(e,oH,I4,Jwe),ca(e,oH,I4,tve),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,act),N1e),"BK Edge Straightening"),"Specifies whether the Brandes Koepf node placer tries to increase the number of straight edges at the expense of diagram size. There is a subtle difference to the 'favorStraightEdges' option, which decides whether a balanced placement of the nodes is desired, or not. In bk terms this means combining the four alignments into a single balanced one, or not. This option on the other hand tries to straighten additional edges during the creation of each of the four alignments."),ICt),us),$Tt),un(qn)))),ca(e,act,I4,Kwe),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,oct),N1e),"BK Fixed Alignment"),"Tells the BK node placer to use a certain alignment (out of its four) instead of the one producing the smallest height, or the combination of all four."),OCt),us),GTt),un(qn)))),ca(e,oct,I4,Qwe),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,cct),"nodePlacement.linearSegments"),"Linear Segments Deflection Dampening"),"Dampens the movement of nodes to keep the diagram from getting too large."),.3),Oo),la),un(qn)))),ca(e,cct,I4,nve),an(e,new Xe(rn(nn(sn(Ze(en(Je(tn(new Ue,uct),"nodePlacement.networkSimplex"),"Node Flexibility"),"Aims at shorter and straighter edges. Two configurations are possible: (a) allow ports to move freely on the side they are assigned to (the order is always defined beforehand), (b) additionally allow to enlarge a node wherever it helps. If this option is not configured for a node, the 'nodeFlexibility.default' value is used, which is specified for the node's parent."),us),yht),un(ea)))),ca(e,uct,I4,ave),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,lct),"nodePlacement.networkSimplex.nodeFlexibility"),"Node Flexibility Default"),"Default value of the 'nodeFlexibility' option for the children of a hierarchical node."),PCt),us),yht),un(qn)))),ca(e,lct,I4,sve),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,z6t),B1e),"Self-Loop Distribution"),"Alter the distribution of the loops around the node. It only takes effect for PortConstraints.FREE."),CCt),us),W9t),un(ea)))),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,q6t),B1e),"Self-Loop Ordering"),"Alter the ordering of the loops they can either be stacked or sequenced. It only takes effect for PortConstraints.FREE."),_Ct),us),Y9t),un(ea)))),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,cH),"edgeRouting.splines"),"Spline Routing Mode"),"Specifies the way control points are assembled for each individual edge. CONSERVATIVE ensures that edges are properly routed around the nodes but feels rather orthogonal at times. SLOPPY uses fewer control points to obtain curvier edge routes but may result in edges overlapping nodes."),SCt),us),X9t),un(qn)))),ca(e,cH,QI,kwe),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,uH),"edgeRouting.splines.sloppy"),"Sloppy Spline Layer Spacing Factor"),"Spacing factor for routing area between layers when using sloppy spline routing."),.2),Oo),la),un(qn)))),ca(e,uH,QI,Twe),ca(e,uH,cH,Cwe),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,hct),"edgeRouting.polyline"),"Sloped Edge Zone Width"),"Width of the strip to the left and to the right of each layer where the polyline edge router is allowed to refrain from ensuring that edges are routed horizontally. This prevents awkward bend points for nodes that extent almost to the edge of their layer."),2),Oo),la),un(qn)))),ca(e,hct,QI,vwe),an(e,new Xe(rn(nn(sn(Ze(en(Je(tn(new Ue,H6t),R1),"Spacing Base Value"),"An optional base value for all other layout options of the 'spacing' group. It can be used to conveniently alter the overall 'spaciousness' of the drawing. Whenever an explicit value is set for the other layout options, this base value will have no effect. The base value is not inherited, i.e. it must be set for each hierarchical node."),Oo),la),un(qn)))),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,V6t),R1),"Edge Node Between Layers Spacing"),"The spacing to be preserved between nodes and edges that are routed next to the node's layer. For the spacing between nodes and edges that cross the node's layer 'spacing.edgeNode' is used."),10),Oo),la),un(qn)))),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,G6t),R1),"Edge Edge Between Layer Spacing"),"Spacing to be preserved between pairs of edges that are routed between the same pair of layers. Note that 'spacing.edgeEdge' is used for the spacing between pairs of edges crossing the same layer."),10),Oo),la),un(qn)))),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,U6t),R1),"Node Node Between Layers Spacing"),"The spacing to be preserved between any pair of nodes of two adjacent layers. Note that 'spacing.nodeNode' is used for the spacing between nodes within the layer itself."),20),Oo),la),un(qn)))),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,W6t),nkt),"Direction Priority"),"Defines how important it is to have a certain edge point into the direction of the overall layout. This option is evaluated during the cycle breaking phase."),pe(0)),gc),ja),un(Pd)))),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,Y6t),nkt),"Shortness Priority"),"Defines how important it is to keep an edge as short as possible. This option is evaluated during the layering phase."),pe(0)),gc),ja),un(Pd)))),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,K6t),nkt),"Straightness Priority"),"Defines how important it is to keep an edge straight, i.e. aligned with one of the two axes. This option is evaluated during node placement."),pe(0)),gc),ja),un(Pd)))),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,fct),rkt),Jfe),"Tries to further compact components (disconnected sub-graphs)."),!1),La),Rs),un(qn)))),ca(e,fct,R_,!0),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,X6t),R1e),"Post Compaction Strategy"),j1e),gCt),us),QTt),un(qn)))),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,Q6t),R1e),"Post Compaction Constraint Calculation"),j1e),dCt),us),LTt),un(qn)))),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,lH),ikt),"High Degree Node Treatment"),"Makes room around high degree nodes to place leafs and trees."),!1),La),Rs),un(qn)))),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,dct),ikt),"High Degree Node Threshold"),"Whether a node is considered to have a high degree."),pe(16)),gc),ja),un(qn)))),ca(e,dct,lH,!0),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,gct),ikt),"High Degree Node Maximum Tree Height"),"Maximum height of a subtree connected to a high degree node to be moved to separate layers."),pe(5)),gc),ja),un(qn)))),ca(e,gct,lH,!0),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,tg),skt),"Graph Wrapping Strategy"),"For certain graphs and certain prescribed drawing areas it may be desirable to split the laid out graph into chunks that are placed side by side. The edges that connect different chunks are 'wrapped' around from the end of one chunk to the start of the other chunk. The points between the chunks are referred to as 'cuts'."),jCt),us),t_t),un(qn)))),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,hH),skt),"Additional Wrapped Edges Spacing"),"To visually separate edges that are wrapped from regularly routed edges an additional spacing value can be specified in form of this layout option. The spacing is added to the regular edgeNode spacing."),10),Oo),la),un(qn)))),ca(e,hH,tg,mve),ca(e,hH,tg,yve),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,fH),skt),"Correction Factor for Wrapping"),"At times and for certain types of graphs the executed wrapping may produce results that are consistently biased in the same fashion: either wrapping to often or to rarely. This factor can be used to correct the bias. Internally, it is simply multiplied with the 'aspect ratio' layout option."),1),Oo),la),un(qn)))),ca(e,fH,tg,kve),ca(e,fH,tg,Eve),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,V_),$1e),"Cutting Strategy"),"The strategy by which the layer indexes are determined at which the layering crumbles into chunks."),RCt),us),OTt),un(qn)))),ca(e,V_,tg,Lve),ca(e,V_,tg,Mve),an(e,new Xe(rn(nn(sn(Ze(en(Je(tn(new Ue,pct),$1e),"Manually Specified Cuts"),"Allows the user to specify her own cuts for a certain graph."),V1),wh),un(qn)))),ca(e,pct,V_,Cve),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,bct),"wrapping.cutting.msd"),"MSD Freedom"),"The MSD cutting strategy starts with an initial guess on the number of chunks the graph should be split into. The freedom specifies how much the strategy may deviate from this guess. E.g. if an initial number of 3 is computed, a freedom of 1 allows 2, 3, and 4 cuts."),BCt),gc),ja),un(qn)))),ca(e,bct,V_,Sve),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,dH),z1e),"Validification Strategy"),"When wrapping graphs, one can specify indices that are not allowed as split points. The validification strategy makes sure every computed split point is allowed."),$Ct),us),J9t),un(qn)))),ca(e,dH,tg,qve),ca(e,dH,tg,Hve),an(e,new Xe(rn(nn(sn(Ze(en(Je(tn(new Ue,gH),z1e),"Valid Indices for Wrapping"),null),V1),wh),un(qn)))),ca(e,gH,tg,jve),ca(e,gH,tg,$ve),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,pH),akt),"Improve Cuts"),"For general graphs it is important that not too many edges wrap backwards. Thus a compromise between evenly-distributed cuts and the total number of cut edges is sought."),!0),La),Rs),un(qn)))),ca(e,pH,tg,Pve),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,bH),akt),"Distance Penalty When Improving Cuts"),null),2),Oo),la),un(qn)))),ca(e,bH,tg,Ive),ca(e,bH,pH,!0),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,wct),akt),"Improve Wrapped Edges"),"The initial wrapping is performed in a very simple way. As a consequence, edges that wrap from one chunk to another may be unnecessarily long. Activating this option tries to shorten such edges."),!0),La),Rs),un(qn)))),ca(e,wct,tg,Nve),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,Z6t),kct),"Edge Label Side Selection"),"Method to decide on edge label sides."),TCt),us),RTt),un(qn)))),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,J6t),kct),"Edge Center Label Placement Strategy"),"Determines in which layer center labels of long edges should be placed."),ECt),us),b7),ji(qn,lt(ct(ip,1),oe,175,0,[rp]))))),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,wH),ZI),"Consider Model Order"),"Preserves the order of nodes and edges in the model file if this does not lead to additional edge crossings. Depending on the strategy this is not always possible since the node and edge order might be conflicting."),wCt),us),H9t),un(qn)))),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,tkt),ZI),"No Model Order"),"Set on a node to not set a model order for this node even though it is a real node."),!1),La),Rs),un(ea)))),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,vct),ZI),"Consider Model Order for Components"),"If set to NONE the usual ordering strategy (by cumulative node priority and size of nodes) is used. INSIDE_PORT_SIDES orders the components with external ports only inside the groups with the same port side. FORCE_MODEL_ORDER enforces the mode order on components. This option might produce bad alignments and sub optimal drawings in terms of used area since the ordering should be respected."),pCt),us),F7t),un(qn)))),ca(e,vct,R_,null),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,ekt),ZI),"Long Edge Ordering Strategy"),"Indicates whether long edges are sorted under, over, or equal to nodes that have no connection to a previous layer in a left-to-right or right-to-left layout. Under and over changes to right and left in a vertical layout."),bCt),us),P9t),un(qn)))),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,mct),ZI),"Crossing Counter Node Order Influence"),"Indicates with what percentage (1 for 100%) violations of the node model order are weighted against the crossings e.g. a value of 0.5 means two model order violations are as important as on edge crossing. This allows some edge crossings in favor of preserving the model order. It is advised to set this value to a very small positive value (e.g. 0.001) to have minimal crossing and a optimal node order. Defaults to no influence (0)."),0),Oo),la),un(qn)))),ca(e,mct,wH,null),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,yct),ZI),"Crossing Counter Port Order Influence"),"Indicates with what percentage (1 for 100%) violations of the port model order are weighted against the crossings e.g. a value of 0.5 means two model order violations are as important as on edge crossing. This allows some edge crossings in favor of preserving the model order. It is advised to set this value to a very small positive value (e.g. 0.001) to have minimal crossing and a optimal port order. Defaults to no influence (0)."),0),Oo),la),un(qn)))),ca(e,yct,wH,null),ife((new HB,e))};var H2e,V2e,G2e,dCt,U2e,gCt,W2e,pCt,Y2e,K2e,X2e,bCt,Q2e,Z2e,wCt,J2e,twe,ewe,vCt,nwe,rwe,iwe,mCt,swe,awe,owe,cwe,uwe,lwe,hwe,fwe,yCt,dwe,xCt,gwe,kCt,pwe,ECt,bwe,TCt,wwe,vwe,mwe,CCt,ywe,_Ct,xwe,SCt,kwe,Ewe,Twe,Cwe,_we,Swe,Awe,Lwe,Mwe,Dwe,ACt,Iwe,Owe,Pwe,Fwe,Nwe,Bwe,LCt,Rwe,jwe,$we,zwe,qwe,Hwe,Vwe,MCt,Gwe,DCt,Uwe,Wwe,Ywe,ICt,Kwe,Xwe,OCt,Qwe,Zwe,Jwe,tve,eve,nve,rve,ive,PCt,sve,ave,ove,FCt,cve,NCt,uve,lve,hve,fve,dve,gve,pve,bve,wve,vve,mve,yve,xve,kve,Eve,Tve,Cve,_ve,BCt,Sve,Ave,RCt,Lve,Mve,Dve,Ive,Ove,Pve,Fve,Nve,Bve,jCt,Rve,jve,$ve,zve,$Ct,qve,Hve;F(kc,"LayeredMetaDataProvider",848),D(986,1,Oh,HB),l.Qe=function(e){ife(e)};var Id,Zlt,rG,CS,iG,zCt,sG,q6,aG,qCt,HCt,Jlt,wb,tht,$y,VCt,DO,eht,GCt,Vve,oG,nht,_S,zy,Gve,Wl,UCt,WCt,cG,rht,Od,uG,eg,YCt,KCt,XCt,iht,sht,QCt,Jg,aht,ZCt,qy,JCt,t9t,e9t,lG,Hy,j2,n9t,r9t,So,i9t,Uve,uu,hG,s9t,a9t,o9t,oht,c9t,fG,u9t,l9t,dG,Nv,h9t,cht,SS,f9t,Bv,AS,gG,$2,uht,E7,pG,z2,d9t,g9t,p9t,T7,b9t,Wve,Yve,Kve,Xve,Rv,Vy,cs,tp,Qve,Gy,w9t,C7,v9t,Uy,Zve,_7,m9t,H6,Jve,tme,IO,lht,y9t,OO,Tf,J4,V6,jv,q2,bG,Wy,hht,S7,A7,$v,t5,fht,PO,LS,MS,dht,x9t,k9t,E9t,T9t,ght,C9t,_9t,S9t,A9t,pht,wG;F(kc,"LayeredOptions",986),D(987,1,{},fQ),l.$e=function(){var e;return e=new gqt,e},l._e=function(e){},F(kc,"LayeredOptions/LayeredFactory",987),D(1372,1,{}),l.a=0;var eme;F(Ec,"ElkSpacings/AbstractSpacingsBuilder",1372),D(779,1372,{},w3t);var vG,nme;F(kc,"LayeredSpacings/LayeredSpacingsBuilder",779),D(313,22,{3:1,35:1,22:1,313:1,246:1,234:1},n9),l.Kf=function(){return Bce(this)},l.Xf=function(){return Bce(this)};var bht,L9t,M9t,mG,wht,D9t,I9t=jr(kc,"LayeringStrategy",313,Hr,Zan,GJe),rme;D(378,22,{3:1,35:1,22:1,378:1},jet);var vht,O9t,yG,P9t=jr(kc,"LongEdgeOrderingStrategy",378,Hr,Min,UJe),ime;D(197,22,{3:1,35:1,22:1,197:1},nj);var e5,n5,xG,mht,yht=jr(kc,"NodeFlexibility",197,Hr,Bsn,WJe),sme;D(315,22,{3:1,35:1,22:1,315:1,246:1,234:1},LM),l.Kf=function(){return xce(this)},l.Xf=function(){return xce(this)};var DS,xht,kht,IS,F9t,N9t=jr(kc,"NodePlacementStrategy",315,Hr,yan,JJe),ame;D(260,22,{3:1,35:1,22:1,260:1},Ix);var B9t,FO,R9t,j9t,NO,$9t,kG,EG,z9t=jr(kc,"NodePromotionStrategy",260,Hr,Qon,KJe),ome;D(339,22,{3:1,35:1,22:1,339:1},$et);var q9t,vb,Eht,H9t=jr(kc,"OrderingStrategy",339,Hr,Rin,XJe),cme;D(421,22,{3:1,35:1,22:1,421:1},zbt);var Tht,Cht,V9t=jr(kc,"PortSortingStrategy",421,Hr,zrn,QJe),ume;D(452,22,{3:1,35:1,22:1,452:1},zet);var tl,nu,OS,lme=jr(kc,"PortType",452,Hr,Bin,YJe),hme;D(375,22,{3:1,35:1,22:1,375:1},qet);var G9t,_ht,U9t,W9t=jr(kc,"SelfLoopDistributionStrategy",375,Hr,jin,ZJe),fme;D(376,22,{3:1,35:1,22:1,376:1},qbt);var BO,Sht,Y9t=jr(kc,"SelfLoopOrderingStrategy",376,Hr,Nrn,ttn),dme;D(304,1,{304:1},ahe),F(kc,"Spacings",304),D(336,22,{3:1,35:1,22:1,336:1},Het);var Aht,K9t,PS,X9t=jr(kc,"SplineRoutingMode",336,Hr,zin,etn),gme;D(338,22,{3:1,35:1,22:1,338:1},Vet);var Lht,Q9t,Z9t,J9t=jr(kc,"ValidifyStrategy",338,Hr,qin,ntn),pme;D(377,22,{3:1,35:1,22:1,377:1},Get);var Yy,Mht,L7,t_t=jr(kc,"WrappingStrategy",377,Hr,$in,rtn),bme;D(1383,1,zc,att),l.Yf=function(e){return u(e,37),wme},l.pf=function(e,n){I3n(this,u(e,37),n)};var wme;F(xH,"DepthFirstCycleBreaker",1383),D(782,1,zc,evt),l.Yf=function(e){return u(e,37),vme},l.pf=function(e,n){Mxn(this,u(e,37),n)},l.Zf=function(e){return u(Ne(e,Zz(this.d,e.c.length)),10)};var vme;F(xH,"GreedyCycleBreaker",782),D(1386,782,zc,WGt),l.Zf=function(e){var n,r,s,o;for(o=null,n=wi,s=new S(e);s.a1&&(je(Re(Q(Na((An(0,e.c.length),u(e.c[0],10))),(Te(),$y))))?Dce(e,this.d,u(this,660)):(wn(),Zs(e,this.d)),Qne(this.e,e))},l.Sf=function(e,n,r,s){var o,h,d,v,k,C,M;for(n!=kKt(r,e.length)&&(h=e[n-(r?1:-1)],_mt(this.f,h,r?(so(),nu):(so(),tl))),o=e[n][0],M=!s||o.k==(Vn(),ks),C=A1(e[n]),this.ag(C,M,!1,r),d=0,k=new S(C);k.a"),e0?Crt(this.a,e[n-1],e[n]):!r&&n1&&(je(Re(Q(Na((An(0,e.c.length),u(e.c[0],10))),(Te(),$y))))?Dce(e,this.d,this):(wn(),Zs(e,this.d)),je(Re(Q(Na((An(0,e.c.length),u(e.c[0],10))),$y)))||Qne(this.e,e))},F(qu,"ModelOrderBarycenterHeuristic",660),D(1803,1,Oi,D$t),l.ue=function(e,n){return Ugn(this.a,u(e,10),u(n,10))},l.Fb=function(e){return this===e},l.ve=function(){return new dt(this)},F(qu,"ModelOrderBarycenterHeuristic/lambda$0$Type",1803),D(1403,1,zc,ltt),l.Yf=function(e){var n;return u(e,37),n=pj(Dme),bi(n,(Wa(),cu),(ro(),IV)),n},l.pf=function(e,n){Drn((u(e,37),n))};var Dme;F(qu,"NoCrossingMinimizer",1403),D(796,402,qkt,hbt),l.$f=function(e,n,r){var s,o,h,d,v,k,C,M,j,H,G;switch(j=this.g,r.g){case 1:{for(o=0,h=0,M=new S(e.j);M.a1&&(o.j==(ve(),Hn)?this.b[e]=!0:o.j==Bn&&e>0&&(this.b[e-1]=!0))},l.f=0,F(c0,"AllCrossingsCounter",1798),D(587,1,{},gz),l.b=0,l.d=0,F(c0,"BinaryIndexedTree",587),D(524,1,{},YM);var r_t,CG;F(c0,"CrossingsCounter",524),D(1906,1,Oi,I$t),l.ue=function(e,n){return Pen(this.a,u(e,11),u(n,11))},l.Fb=function(e){return this===e},l.ve=function(){return new dt(this)},F(c0,"CrossingsCounter/lambda$0$Type",1906),D(1907,1,Oi,O$t),l.ue=function(e,n){return Fen(this.a,u(e,11),u(n,11))},l.Fb=function(e){return this===e},l.ve=function(){return new dt(this)},F(c0,"CrossingsCounter/lambda$1$Type",1907),D(1908,1,Oi,P$t),l.ue=function(e,n){return Nen(this.a,u(e,11),u(n,11))},l.Fb=function(e){return this===e},l.ve=function(){return new dt(this)},F(c0,"CrossingsCounter/lambda$2$Type",1908),D(1909,1,Oi,F$t),l.ue=function(e,n){return Ben(this.a,u(e,11),u(n,11))},l.Fb=function(e){return this===e},l.ve=function(){return new dt(this)},F(c0,"CrossingsCounter/lambda$3$Type",1909),D(1910,1,Un,N$t),l.td=function(e){von(this.a,u(e,11))},F(c0,"CrossingsCounter/lambda$4$Type",1910),D(1911,1,li,B$t),l.Mb=function(e){return IXe(this.a,u(e,11))},F(c0,"CrossingsCounter/lambda$5$Type",1911),D(1912,1,Un,R$t),l.td=function(e){HGt(this,e)},F(c0,"CrossingsCounter/lambda$6$Type",1912),D(1913,1,Un,pGt),l.td=function(e){var n;k8(),Up(this.b,(n=this.a,u(e,11),n))},F(c0,"CrossingsCounter/lambda$7$Type",1913),D(826,1,xd,YN),l.Lb=function(e){return k8(),Us(u(e,11),(ae(),Ju))},l.Fb=function(e){return this===e},l.Mb=function(e){return k8(),Us(u(e,11),(ae(),Ju))},F(c0,"CrossingsCounter/lambda$8$Type",826),D(1905,1,{},j$t),F(c0,"HyperedgeCrossingsCounter",1905),D(467,1,{35:1,467:1},sYt),l.wd=function(e){return pfn(this,u(e,467))},l.b=0,l.c=0,l.e=0,l.f=0;var h6n=F(c0,"HyperedgeCrossingsCounter/Hyperedge",467);D(362,1,{35:1,362:1},f$),l.wd=function(e){return d2n(this,u(e,362))},l.b=0,l.c=0;var Ime=F(c0,"HyperedgeCrossingsCounter/HyperedgeCorner",362);D(523,22,{3:1,35:1,22:1,523:1},Hbt);var NS,BS,Ome=jr(c0,"HyperedgeCrossingsCounter/HyperedgeCorner/Type",523,Hr,qrn,stn),Pme;D(1405,1,zc,stt),l.Yf=function(e){return u(Q(u(e,37),(ae(),Vc)),21).Hc((oo(),vh))?Fme:null},l.pf=function(e,n){Pdn(this,u(e,37),n)};var Fme;F(uo,"InteractiveNodePlacer",1405),D(1406,1,zc,itt),l.Yf=function(e){return u(Q(u(e,37),(ae(),Vc)),21).Hc((oo(),vh))?Nme:null},l.pf=function(e,n){v1n(this,u(e,37),n)};var Nme,_G,SG;F(uo,"LinearSegmentsNodePlacer",1406),D(257,1,{35:1,257:1},zpt),l.wd=function(e){return VKe(this,u(e,257))},l.Fb=function(e){var n;return _t(e,257)?(n=u(e,257),this.b==n.b):!1},l.Hb=function(){return this.b},l.Ib=function(){return"ls"+eb(this.e)},l.a=0,l.b=0,l.c=-1,l.d=-1,l.g=0;var Bme=F(uo,"LinearSegmentsNodePlacer/LinearSegment",257);D(1408,1,zc,IKt),l.Yf=function(e){return u(Q(u(e,37),(ae(),Vc)),21).Hc((oo(),vh))?Rme:null},l.pf=function(e,n){kxn(this,u(e,37),n)},l.b=0,l.g=0;var Rme;F(uo,"NetworkSimplexPlacer",1408),D(1427,1,Oi,wQ),l.ue=function(e,n){return pu(u(e,19).a,u(n,19).a)},l.Fb=function(e){return this===e},l.ve=function(){return new dt(this)},F(uo,"NetworkSimplexPlacer/0methodref$compare$Type",1427),D(1429,1,Oi,vQ),l.ue=function(e,n){return pu(u(e,19).a,u(n,19).a)},l.Fb=function(e){return this===e},l.ve=function(){return new dt(this)},F(uo,"NetworkSimplexPlacer/1methodref$compare$Type",1429),D(649,1,{649:1},bGt);var f6n=F(uo,"NetworkSimplexPlacer/EdgeRep",649);D(401,1,{401:1},Ovt),l.b=!1;var d6n=F(uo,"NetworkSimplexPlacer/NodeRep",401);D(508,12,{3:1,4:1,20:1,28:1,52:1,12:1,14:1,15:1,54:1,508:1},Cqt),F(uo,"NetworkSimplexPlacer/Path",508),D(1409,1,{},mQ),l.Kb=function(e){return u(e,17).d.i.k},F(uo,"NetworkSimplexPlacer/Path/lambda$0$Type",1409),D(1410,1,li,yQ),l.Mb=function(e){return u(e,267)==(Vn(),ta)},F(uo,"NetworkSimplexPlacer/Path/lambda$1$Type",1410),D(1411,1,{},xQ),l.Kb=function(e){return u(e,17).d.i},F(uo,"NetworkSimplexPlacer/Path/lambda$2$Type",1411),D(1412,1,li,$$t),l.Mb=function(e){return HWt(Aie(u(e,10)))},F(uo,"NetworkSimplexPlacer/Path/lambda$3$Type",1412),D(1413,1,li,kQ),l.Mb=function(e){return Een(u(e,11))},F(uo,"NetworkSimplexPlacer/lambda$0$Type",1413),D(1414,1,Un,wGt),l.td=function(e){yQe(this.a,this.b,u(e,11))},F(uo,"NetworkSimplexPlacer/lambda$1$Type",1414),D(1423,1,Un,z$t),l.td=function(e){$pn(this.a,u(e,17))},F(uo,"NetworkSimplexPlacer/lambda$10$Type",1423),D(1424,1,{},EQ),l.Kb=function(e){return Fl(),new Tn(null,new _n(u(e,29).a,16))},F(uo,"NetworkSimplexPlacer/lambda$11$Type",1424),D(1425,1,Un,q$t),l.td=function(e){Nvn(this.a,u(e,10))},F(uo,"NetworkSimplexPlacer/lambda$12$Type",1425),D(1426,1,{},TQ),l.Kb=function(e){return Fl(),pe(u(e,121).e)},F(uo,"NetworkSimplexPlacer/lambda$13$Type",1426),D(1428,1,{},CQ),l.Kb=function(e){return Fl(),pe(u(e,121).e)},F(uo,"NetworkSimplexPlacer/lambda$15$Type",1428),D(1430,1,li,_Q),l.Mb=function(e){return Fl(),u(e,401).c.k==(Vn(),Os)},F(uo,"NetworkSimplexPlacer/lambda$17$Type",1430),D(1431,1,li,SQ),l.Mb=function(e){return Fl(),u(e,401).c.j.c.length>1},F(uo,"NetworkSimplexPlacer/lambda$18$Type",1431),D(1432,1,Un,jXt),l.td=function(e){_hn(this.c,this.b,this.d,this.a,u(e,401))},l.c=0,l.d=0,F(uo,"NetworkSimplexPlacer/lambda$19$Type",1432),D(1415,1,{},AQ),l.Kb=function(e){return Fl(),new Tn(null,new _n(u(e,29).a,16))},F(uo,"NetworkSimplexPlacer/lambda$2$Type",1415),D(1433,1,Un,H$t),l.td=function(e){vQe(this.a,u(e,11))},l.a=0,F(uo,"NetworkSimplexPlacer/lambda$20$Type",1433),D(1434,1,{},nx),l.Kb=function(e){return Fl(),new Tn(null,new _n(u(e,29).a,16))},F(uo,"NetworkSimplexPlacer/lambda$21$Type",1434),D(1435,1,Un,V$t),l.td=function(e){OQe(this.a,u(e,10))},F(uo,"NetworkSimplexPlacer/lambda$22$Type",1435),D(1436,1,li,KN),l.Mb=function(e){return HWt(e)},F(uo,"NetworkSimplexPlacer/lambda$23$Type",1436),D(1437,1,{},LQ),l.Kb=function(e){return Fl(),new Tn(null,new _n(u(e,29).a,16))},F(uo,"NetworkSimplexPlacer/lambda$24$Type",1437),D(1438,1,li,G$t),l.Mb=function(e){return jXe(this.a,u(e,10))},F(uo,"NetworkSimplexPlacer/lambda$25$Type",1438),D(1439,1,Un,vGt),l.td=function(e){cpn(this.a,this.b,u(e,10))},F(uo,"NetworkSimplexPlacer/lambda$26$Type",1439),D(1440,1,li,MQ),l.Mb=function(e){return Fl(),!Ga(u(e,17))},F(uo,"NetworkSimplexPlacer/lambda$27$Type",1440),D(1441,1,li,DQ),l.Mb=function(e){return Fl(),!Ga(u(e,17))},F(uo,"NetworkSimplexPlacer/lambda$28$Type",1441),D(1442,1,{},U$t),l.Ce=function(e,n){return MQe(this.a,u(e,29),u(n,29))},F(uo,"NetworkSimplexPlacer/lambda$29$Type",1442),D(1416,1,{},XN),l.Kb=function(e){return Fl(),new Tn(null,new jw(new ar(lr(Ds(u(e,10)).a.Kc(),new z))))},F(uo,"NetworkSimplexPlacer/lambda$3$Type",1416),D(1417,1,li,IQ),l.Mb=function(e){return Fl(),wsn(u(e,17))},F(uo,"NetworkSimplexPlacer/lambda$4$Type",1417),D(1418,1,Un,W$t),l.td=function(e){Fyn(this.a,u(e,17))},F(uo,"NetworkSimplexPlacer/lambda$5$Type",1418),D(1419,1,{},WT),l.Kb=function(e){return Fl(),new Tn(null,new _n(u(e,29).a,16))},F(uo,"NetworkSimplexPlacer/lambda$6$Type",1419),D(1420,1,li,OQ),l.Mb=function(e){return Fl(),u(e,10).k==(Vn(),Os)},F(uo,"NetworkSimplexPlacer/lambda$7$Type",1420),D(1421,1,{},PQ),l.Kb=function(e){return Fl(),new Tn(null,new jw(new ar(lr(U0(u(e,10)).a.Kc(),new z))))},F(uo,"NetworkSimplexPlacer/lambda$8$Type",1421),D(1422,1,li,FQ),l.Mb=function(e){return Fl(),wen(u(e,17))},F(uo,"NetworkSimplexPlacer/lambda$9$Type",1422),D(1404,1,zc,vC),l.Yf=function(e){return u(Q(u(e,37),(ae(),Vc)),21).Hc((oo(),vh))?jme:null},l.pf=function(e,n){b3n(u(e,37),n)};var jme;F(uo,"SimpleNodePlacer",1404),D(180,1,{180:1},E4),l.Ib=function(){var e;return e="",this.c==(bd(),zv)?e+=x6:this.c==ep&&(e+=y6),this.o==(C1(),H2)?e+=Dot:this.o==H1?e+="UP":e+="BALANCED",e},F(ub,"BKAlignedLayout",180),D(516,22,{3:1,35:1,22:1,516:1},Gbt);var ep,zv,$me=jr(ub,"BKAlignedLayout/HDirection",516,Hr,Vrn,atn),zme;D(515,22,{3:1,35:1,22:1,515:1},Vbt);var H2,H1,qme=jr(ub,"BKAlignedLayout/VDirection",515,Hr,Grn,otn),Hme;D(1634,1,{},mGt),F(ub,"BKAligner",1634),D(1637,1,{},Zse),F(ub,"BKCompactor",1637),D(654,1,{654:1},NQ),l.a=0,F(ub,"BKCompactor/ClassEdge",654),D(458,1,{458:1},Eqt),l.a=null,l.b=0,F(ub,"BKCompactor/ClassNode",458),D(1407,1,zc,GGt),l.Yf=function(e){return u(Q(u(e,37),(ae(),Vc)),21).Hc((oo(),vh))?Vme:null},l.pf=function(e,n){Bxn(this,u(e,37),n)},l.d=!1;var Vme;F(ub,"BKNodePlacer",1407),D(1635,1,{},BQ),l.d=0,F(ub,"NeighborhoodInformation",1635),D(1636,1,Oi,Y$t),l.ue=function(e,n){return Von(this,u(e,46),u(n,46))},l.Fb=function(e){return this===e},l.ve=function(){return new dt(this)},F(ub,"NeighborhoodInformation/NeighborComparator",1636),D(808,1,{}),F(ub,"ThresholdStrategy",808),D(1763,808,{},Aqt),l.bg=function(e,n,r){return this.a.o==(C1(),H1)?as:Cs},l.cg=function(){},F(ub,"ThresholdStrategy/NullThresholdStrategy",1763),D(579,1,{579:1},yGt),l.c=!1,l.d=!1,F(ub,"ThresholdStrategy/Postprocessable",579),D(1764,808,{},Lqt),l.bg=function(e,n,r){var s,o,h;return o=n==r,s=this.a.a[r.p]==n,o||s?(h=e,this.a.c==(bd(),zv)?(o&&(h=Dat(this,n,!0)),!isNaN(h)&&!isFinite(h)&&s&&(h=Dat(this,r,!1))):(o&&(h=Dat(this,n,!0)),!isNaN(h)&&!isFinite(h)&&s&&(h=Dat(this,r,!1))),h):e},l.cg=function(){for(var e,n,r,s,o;this.d.b!=0;)o=u(oin(this.d),579),s=mle(this,o),s.a&&(e=s.a,r=je(this.a.f[this.a.g[o.b.p].p]),!(!r&&!Ga(e)&&e.c.i.c==e.d.i.c)&&(n=_ce(this,o),n||WXe(this.e,o)));for(;this.e.a.c.length!=0;)_ce(this,u(Nre(this.e),579))},F(ub,"ThresholdStrategy/SimpleThresholdStrategy",1764),D(635,1,{635:1,246:1,234:1},RQ),l.Kf=function(){return Une(this)},l.Xf=function(){return Une(this)};var Dht;F(Sct,"EdgeRouterFactory",635),D(1458,1,zc,od),l.Yf=function(e){return pvn(u(e,37))},l.pf=function(e,n){E3n(u(e,37),n)};var Gme,Ume,Wme,Yme,Kme,i_t,Xme,Qme;F(Sct,"OrthogonalEdgeRouter",1458),D(1451,1,zc,UGt),l.Yf=function(e){return jdn(u(e,37))},l.pf=function(e,n){H5n(this,u(e,37),n)};var Zme,Jme,tye,eye,jO,nye;F(Sct,"PolylineEdgeRouter",1451),D(1452,1,xd,jQ),l.Lb=function(e){return yyt(u(e,10))},l.Fb=function(e){return this===e},l.Mb=function(e){return yyt(u(e,10))},F(Sct,"PolylineEdgeRouter/1",1452),D(1809,1,li,$Q),l.Mb=function(e){return u(e,129).c==(Uf(),mb)},F(t1,"HyperEdgeCycleDetector/lambda$0$Type",1809),D(1810,1,{},zQ),l.Ge=function(e){return u(e,129).d},F(t1,"HyperEdgeCycleDetector/lambda$1$Type",1810),D(1811,1,li,qQ),l.Mb=function(e){return u(e,129).c==(Uf(),mb)},F(t1,"HyperEdgeCycleDetector/lambda$2$Type",1811),D(1812,1,{},rx),l.Ge=function(e){return u(e,129).d},F(t1,"HyperEdgeCycleDetector/lambda$3$Type",1812),D(1813,1,{},HQ),l.Ge=function(e){return u(e,129).d},F(t1,"HyperEdgeCycleDetector/lambda$4$Type",1813),D(1814,1,{},VQ),l.Ge=function(e){return u(e,129).d},F(t1,"HyperEdgeCycleDetector/lambda$5$Type",1814),D(112,1,{35:1,112:1},PD),l.wd=function(e){return GKe(this,u(e,112))},l.Fb=function(e){var n;return _t(e,112)?(n=u(e,112),this.g==n.g):!1},l.Hb=function(){return this.g},l.Ib=function(){var e,n,r,s;for(e=new Ol("{"),s=new S(this.n);s.a"+this.b+" ("+nZe(this.c)+")"},l.d=0,F(t1,"HyperEdgeSegmentDependency",129),D(520,22,{3:1,35:1,22:1,520:1},Ubt);var mb,Ky,rye=jr(t1,"HyperEdgeSegmentDependency/DependencyType",520,Hr,Hrn,ctn),iye;D(1815,1,{},K$t),F(t1,"HyperEdgeSegmentSplitter",1815),D(1816,1,{},_Ht),l.a=0,l.b=0,F(t1,"HyperEdgeSegmentSplitter/AreaRating",1816),D(329,1,{329:1},Dnt),l.a=0,l.b=0,l.c=0,F(t1,"HyperEdgeSegmentSplitter/FreeArea",329),D(1817,1,Oi,QQ),l.ue=function(e,n){return ZZe(u(e,112),u(n,112))},l.Fb=function(e){return this===e},l.ve=function(){return new dt(this)},F(t1,"HyperEdgeSegmentSplitter/lambda$0$Type",1817),D(1818,1,Un,$Xt),l.td=function(e){ran(this.a,this.d,this.c,this.b,u(e,112))},l.b=0,F(t1,"HyperEdgeSegmentSplitter/lambda$1$Type",1818),D(1819,1,{},ZQ),l.Kb=function(e){return new Tn(null,new _n(u(e,112).e,16))},F(t1,"HyperEdgeSegmentSplitter/lambda$2$Type",1819),D(1820,1,{},JQ),l.Kb=function(e){return new Tn(null,new _n(u(e,112).j,16))},F(t1,"HyperEdgeSegmentSplitter/lambda$3$Type",1820),D(1821,1,{},tZ),l.Fe=function(e){return Xt(ye(e))},F(t1,"HyperEdgeSegmentSplitter/lambda$4$Type",1821),D(655,1,{},ert),l.a=0,l.b=0,l.c=0,F(t1,"OrthogonalRoutingGenerator",655),D(1638,1,{},eZ),l.Kb=function(e){return new Tn(null,new _n(u(e,112).e,16))},F(t1,"OrthogonalRoutingGenerator/lambda$0$Type",1638),D(1639,1,{},nZ),l.Kb=function(e){return new Tn(null,new _n(u(e,112).j,16))},F(t1,"OrthogonalRoutingGenerator/lambda$1$Type",1639),D(661,1,{}),F(Act,"BaseRoutingDirectionStrategy",661),D(1807,661,{},Mqt),l.dg=function(e,n,r){var s,o,h,d,v,k,C,M,j,H,G,K,tt;if(!(e.r&&!e.q))for(M=n+e.o*r,C=new S(e.n);C.aEd&&(h=M,o=e,s=new $e(j,h),ri(d.a,s),pv(this,d,o,s,!1),H=e.r,H&&(G=Xt(ye(Zf(H.e,0))),s=new $e(G,h),ri(d.a,s),pv(this,d,o,s,!1),h=n+H.o*r,o=H,s=new $e(G,h),ri(d.a,s),pv(this,d,o,s,!1)),s=new $e(tt,h),ri(d.a,s),pv(this,d,o,s,!1)))},l.eg=function(e){return e.i.n.a+e.n.a+e.a.a},l.fg=function(){return ve(),mr},l.gg=function(){return ve(),Pn},F(Act,"NorthToSouthRoutingStrategy",1807),D(1808,661,{},Dqt),l.dg=function(e,n,r){var s,o,h,d,v,k,C,M,j,H,G,K,tt;if(!(e.r&&!e.q))for(M=n-e.o*r,C=new S(e.n);C.aEd&&(h=M,o=e,s=new $e(j,h),ri(d.a,s),pv(this,d,o,s,!1),H=e.r,H&&(G=Xt(ye(Zf(H.e,0))),s=new $e(G,h),ri(d.a,s),pv(this,d,o,s,!1),h=n-H.o*r,o=H,s=new $e(G,h),ri(d.a,s),pv(this,d,o,s,!1)),s=new $e(tt,h),ri(d.a,s),pv(this,d,o,s,!1)))},l.eg=function(e){return e.i.n.a+e.n.a+e.a.a},l.fg=function(){return ve(),Pn},l.gg=function(){return ve(),mr},F(Act,"SouthToNorthRoutingStrategy",1808),D(1806,661,{},Iqt),l.dg=function(e,n,r){var s,o,h,d,v,k,C,M,j,H,G,K,tt;if(!(e.r&&!e.q))for(M=n+e.o*r,C=new S(e.n);C.aEd&&(h=M,o=e,s=new $e(h,j),ri(d.a,s),pv(this,d,o,s,!0),H=e.r,H&&(G=Xt(ye(Zf(H.e,0))),s=new $e(h,G),ri(d.a,s),pv(this,d,o,s,!0),h=n+H.o*r,o=H,s=new $e(h,G),ri(d.a,s),pv(this,d,o,s,!0)),s=new $e(h,tt),ri(d.a,s),pv(this,d,o,s,!0)))},l.eg=function(e){return e.i.n.b+e.n.b+e.a.b},l.fg=function(){return ve(),Hn},l.gg=function(){return ve(),Bn},F(Act,"WestToEastRoutingStrategy",1806),D(813,1,{},fxt),l.Ib=function(){return eb(this.a)},l.b=0,l.c=!1,l.d=!1,l.f=0,F(Sy,"NubSpline",813),D(407,1,{407:1},eue,yQt),F(Sy,"NubSpline/PolarCP",407),D(1453,1,zc,Vse),l.Yf=function(e){return A0n(u(e,37))},l.pf=function(e,n){cxn(this,u(e,37),n)};var sye,aye,oye,cye,uye;F(Sy,"SplineEdgeRouter",1453),D(268,1,{268:1},R$),l.Ib=function(){return this.a+" ->("+this.c+") "+this.b},l.c=0,F(Sy,"SplineEdgeRouter/Dependency",268),D(455,22,{3:1,35:1,22:1,455:1},Wbt);var yb,r5,lye=jr(Sy,"SplineEdgeRouter/SideToProcess",455,Hr,Urn,utn),hye;D(1454,1,li,XQ),l.Mb=function(e){return m_(),!u(e,128).o},F(Sy,"SplineEdgeRouter/lambda$0$Type",1454),D(1455,1,{},KQ),l.Ge=function(e){return m_(),u(e,128).v+1},F(Sy,"SplineEdgeRouter/lambda$1$Type",1455),D(1456,1,Un,xGt),l.td=function(e){men(this.a,this.b,u(e,46))},F(Sy,"SplineEdgeRouter/lambda$2$Type",1456),D(1457,1,Un,kGt),l.td=function(e){yen(this.a,this.b,u(e,46))},F(Sy,"SplineEdgeRouter/lambda$3$Type",1457),D(128,1,{35:1,128:1},voe,vxt),l.wd=function(e){return UKe(this,u(e,128))},l.b=0,l.e=!1,l.f=0,l.g=0,l.j=!1,l.k=!1,l.n=0,l.o=!1,l.p=!1,l.q=!1,l.s=0,l.u=0,l.v=0,l.F=0,F(Sy,"SplineSegment",128),D(459,1,{459:1},YT),l.a=0,l.b=!1,l.c=!1,l.d=!1,l.e=!1,l.f=0,F(Sy,"SplineSegment/EdgeInformation",459),D(1234,1,{},GQ),F(G_,d6t,1234),D(1235,1,Oi,UQ),l.ue=function(e,n){return nbn(u(e,135),u(n,135))},l.Fb=function(e){return this===e},l.ve=function(){return new dt(this)},F(G_,n1e,1235),D(1233,1,{},qHt),F(G_,"MrTree",1233),D(393,22,{3:1,35:1,22:1,393:1,246:1,234:1},rj),l.Kf=function(){return Hoe(this)},l.Xf=function(){return Hoe(this)};var AG,RS,$O,jS,s_t=jr(G_,"TreeLayoutPhases",393,Hr,Rsn,ltn),fye;D(1130,209,S2,cYt),l.Ze=function(e,n){var r,s,o,h,d,v,k;for(je(Re(qe(e,(gv(),h_t))))||y$((r=new rr((Pm(),new Mm(e))),r)),d=(v=new j$,Mo(v,e),Jt(v,(fc(),qS),e),k=new _r,Wmn(e,v,k),lyn(e,v,k),v),h=ryn(this.a,d),o=new S(h);o.a"+S$(this.c):"e_"+Hi(this)},F(U_,"TEdge",188),D(135,134,{3:1,135:1,94:1,134:1},j$),l.Ib=function(){var e,n,r,s,o;for(o=null,s=ei(this.b,0);s.b!=s.d.c;)r=u(ti(s),86),o+=(r.c==null||r.c.length==0?"n_"+r.g:"n_"+r.c)+` +`;for(n=ei(this.a,0);n.b!=n.d.c;)e=u(ti(n),188),o+=(e.b&&e.c?S$(e.b)+"->"+S$(e.c):"e_"+Hi(e))+` +`;return o};var g6n=F(U_,"TGraph",135);D(633,502,{3:1,502:1,633:1,94:1,134:1}),F(U_,"TShape",633),D(86,633,{3:1,502:1,86:1,633:1,94:1,134:1},Dit),l.Ib=function(){return S$(this)};var p6n=F(U_,"TNode",86);D(255,1,r0,Lp),l.Jc=function(e){va(this,e)},l.Kc=function(){var e;return e=ei(this.a.d,0),new Ex(e)},F(U_,"TNode/2",255),D(358,1,sa,Ex),l.Nb=function(e){ba(this,e)},l.Pb=function(){return u(ti(this.a),188).c},l.Ob=function(){return OR(this.a)},l.Qb=function(){tz(this.a)},F(U_,"TNode/2/1",358),D(1840,1,os,oYt),l.pf=function(e,n){_yn(this,u(e,135),n)},F(A6,"FanProcessor",1840),D(327,22,{3:1,35:1,22:1,327:1,234:1},r9),l.Kf=function(){switch(this.g){case 0:return new Wqt;case 1:return new oYt;case 2:return new ix;case 3:return new rZ;case 4:return new sZ;case 5:return new RL;default:throw it(new Fn(Yot+(this.f!=null?this.f:""+this.g)))}};var Iht,Oht,Pht,Fht,Nht,LG,dye=jr(A6,T6t,327,Hr,ton,htn),gye;D(1843,1,os,rZ),l.pf=function(e,n){c2n(this,u(e,135),n)},l.a=0,F(A6,"LevelHeightProcessor",1843),D(1844,1,r0,iZ),l.Jc=function(e){va(this,e)},l.Kc=function(){return wn(),h8(),a7},F(A6,"LevelHeightProcessor/1",1844),D(1841,1,os,ix),l.pf=function(e,n){ppn(this,u(e,135),n)},l.a=0,F(A6,"NeighborsProcessor",1841),D(1842,1,r0,QN),l.Jc=function(e){va(this,e)},l.Kc=function(){return wn(),h8(),a7},F(A6,"NeighborsProcessor/1",1842),D(1845,1,os,sZ),l.pf=function(e,n){o2n(this,u(e,135),n)},l.a=0,F(A6,"NodePositionProcessor",1845),D(1839,1,os,Wqt),l.pf=function(e,n){O3n(this,u(e,135))},F(A6,"RootProcessor",1839),D(1846,1,os,RL),l.pf=function(e,n){qln(u(e,135))},F(A6,"Untreeifyer",1846);var zO,$S,pye,Bht,MG,zS,Rht,DG,IG,M7,qS,OG,np,a_t,bye,jht,Xy,$ht,o_t;D(851,1,Oh,D3),l.Qe=function(e){an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,Hkt),""),"Weighting of Nodes"),"Which weighting to use when computing a node order."),u_t),(Ug(),us)),b_t),un((Qf(),qn))))),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,Vkt),""),"Search Order"),"Which search order to use when computing a spanning tree."),c_t),us),v_t),un(qn)))),phe((new JL,e))};var wye,c_t,vye,u_t;F(EH,"MrTreeMetaDataProvider",851),D(994,1,Oh,JL),l.Qe=function(e){phe(e)};var mye,l_t,yye,xye,kye,Eye,h_t,Tye,f_t,Cye,PG,d_t,_ye,g_t,Sye;F(EH,"MrTreeOptions",994),D(995,1,{},aZ),l.$e=function(){var e;return e=new cYt,e},l._e=function(e){},F(EH,"MrTreeOptions/MrtreeFactory",995),D(480,22,{3:1,35:1,22:1,480:1},Ybt);var zht,p_t,b_t=jr(EH,"OrderWeighting",480,Hr,Yrn,ftn),Aye;D(425,22,{3:1,35:1,22:1,425:1},Kbt);var w_t,qht,v_t=jr(EH,"TreeifyingOrder",425,Hr,Wrn,gtn),Lye;D(1459,1,zc,ZL),l.Yf=function(e){return u(e,135),Mye},l.pf=function(e,n){zcn(this,u(e,135),n)};var Mye;F("org.eclipse.elk.alg.mrtree.p1treeify","DFSTreeifyer",1459),D(1460,1,zc,ctt),l.Yf=function(e){return u(e,135),Dye},l.pf=function(e,n){Cpn(this,u(e,135),n)};var Dye;F("org.eclipse.elk.alg.mrtree.p2order","NodeOrderer",1460),D(1461,1,zc,ott),l.Yf=function(e){return u(e,135),Iye},l.pf=function(e,n){qvn(this,u(e,135),n)},l.a=0;var Iye;F("org.eclipse.elk.alg.mrtree.p3place","NodePlacer",1461),D(1462,1,zc,GB),l.Yf=function(e){return u(e,135),Oye},l.pf=function(e,n){gdn(u(e,135),n)};var Oye;F("org.eclipse.elk.alg.mrtree.p4route","EdgeRouter",1462);var HS;D(495,22,{3:1,35:1,22:1,495:1,246:1,234:1},Xbt),l.Kf=function(){return xie(this)},l.Xf=function(){return xie(this)};var FG,D7,m_t=jr(Gkt,"RadialLayoutPhases",495,Hr,Krn,dtn),Pye;D(1131,209,S2,zHt),l.Ze=function(e,n){var r,s,o,h,d,v;if(r=Toe(this,e),vr(n,"Radial layout",r.c.length),je(Re(qe(e,(uy(),L_t))))||y$((s=new rr((Pm(),new Mm(e))),s)),v=D0n(e),wo(e,(m9(),HS),v),!v)throw it(new Fn("The given graph is not a tree!"));for(o=Xt(ye(qe(e,RG))),o==0&&(o=Roe(e)),wo(e,RG,o),d=new S(Toe(this,e));d.a0&&Ure((Rr(n-1,e.length),e.charCodeAt(n-1)),d1e);)--n;if(s>=n)throw it(new Fn("The given string does not contain any numbers."));if(o=vy(e.substr(s,n-s),`,|;|\r| +`),o.length!=2)throw it(new Fn("Exactly two numbers are expected, "+o.length+" were found."));try{this.a=dy(fy(o[0])),this.b=dy(fy(o[1]))}catch(h){throw h=Wi(h),_t(h,127)?(r=h,it(new Fn(g1e+r))):it(h)}},l.Ib=function(){return"("+this.a+","+this.b+")"},l.a=0,l.b=0;var Ws=F(WI,"KVector",8);D(74,68,{3:1,4:1,20:1,28:1,52:1,14:1,68:1,15:1,74:1,414:1},Pu,DR,MWt),l.Pc=function(){return tln(this)},l.Jf=function(e){var n,r,s,o,h,d;s=vy(e,`,|;|\\(|\\)|\\[|\\]|\\{|\\}| | | +`),Ah(this);try{for(r=0,h=0,o=0,d=0;r0&&(h%2==0?o=dy(s[r]):d=dy(s[r]),h>0&&h%2!=0&&ri(this,new $e(o,d)),++h),++r}catch(v){throw v=Wi(v),_t(v,127)?(n=v,it(new Fn("The given string does not match the expected format for vectors."+n))):it(v)}},l.Ib=function(){var e,n,r;for(e=new Ol("("),n=ei(this,0);n.b!=n.d.c;)r=u(ti(n),8),Gr(e,r.a+","+r.b),n.b!=n.d.c&&(e.a+="; ");return(e.a+=")",e).a};var ASt=F(WI,"KVectorChain",74);D(248,22,{3:1,35:1,22:1,248:1},i9);var uft,GG,UG,GO,UO,WG,LSt=jr(Fh,"Alignment",248,Hr,Yan,Dtn),J3e;D(979,1,Oh,htt),l.Qe=function(e){lle(e)};var MSt,lft,t4e,DSt,ISt,e4e,OSt,n4e,r4e,PSt,FSt,i4e;F(Fh,"BoxLayouterOptions",979),D(980,1,{},qZ),l.$e=function(){var e;return e=new YZ,e},l._e=function(e){},F(Fh,"BoxLayouterOptions/BoxFactory",980),D(291,22,{3:1,35:1,22:1,291:1},s9);var WO,hft,YO,KO,XO,fft,dft=jr(Fh,"ContentAlignment",291,Hr,Wan,Itn),s4e;D(684,1,Oh,Tp),l.Qe=function(e){an(e,new Xe(rn(nn(sn(Ze(en(Je(tn(new Ue,ude),""),"Layout Algorithm"),"Select a specific layout algorithm."),(Ug(),I7)),Ae),un((Qf(),qn))))),an(e,new Xe(rn(nn(sn(Ze(en(Je(tn(new Ue,lde),""),"Resolved Layout Algorithm"),"Meta data associated with the selected algorithm."),V1),v6n),un(qn)))),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,xkt),""),"Alignment"),"Alignment of the selected node relative to other nodes; the exact meaning depends on the used algorithm."),NSt),us),LSt),un(ea)))),an(e,new Xe(rn(nn(sn(Ze(en(Je(tn(new Ue,E6),""),"Aspect Ratio"),"The desired aspect ratio of the drawing, that is the quotient of width by height."),Oo),la),un(qn)))),an(e,new Xe(rn(nn(sn(Ze(en(Je(tn(new Ue,p8t),""),"Bend Points"),"A fixed list of bend points for the edge. This is used by the 'Fixed Layout' algorithm to specify a pre-defined routing for an edge. The vector chain must include the source point, any bend points, and the target point, so it must have at least two points."),V1),ASt),un(Pd)))),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,mH),""),"Content Alignment"),"Specifies how the content of a node are aligned. Each node can individually control the alignment of its contents. I.e. if a node should be aligned top left in its parent node, the parent node should specify that option."),RSt),U6),dft),un(qn)))),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,JI),""),"Debug Mode"),"Whether additional debug information shall be generated."),(Nn(),!1)),La),Rs),un(qn)))),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,Tkt),""),i6t),"Overall direction of edges: horizontal (right / left) or vertical (down / up)."),jSt),us),XS),un(qn)))),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,QI),""),"Edge Routing"),"What kind of edge routing style should be applied for the content of a parent node. Algorithms may also set this option to single edges in order to mark them as splines. The bend point list of edges with this option set to SPLINES must be interpreted as control points for a piecewise cubic spline."),qSt),us),_ft),un(qn)))),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,CH),""),"Expand Nodes"),"If active, nodes are expanded to fill the area of their parent."),!1),La),Rs),un(qn)))),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,vH),""),"Hierarchy Handling"),"Determines whether separate layout runs are triggered for different compound nodes in a hierarchical graph. Setting a node's hierarchy handling to `INCLUDE_CHILDREN` will lay out that node and all of its descendants in a single layout run, until a descendant is encountered which has its hierarchy handling set to `SEPARATE_CHILDREN`. In general, `SEPARATE_CHILDREN` will ensure that a new layout run is triggered for a node with that setting. Including multiple levels of hierarchy in a single layout run may allow cross-hierarchical edges to be laid out properly. If the root node is set to `INHERIT` (or not set at all), the default behavior is `SEPARATE_CHILDREN`."),USt),us),DAt),ji(qn,lt(ct(ip,1),oe,175,0,[ea]))))),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,xv),""),"Padding"),"The padding to be left to a parent element's border when placing child elements. This can also serve as an output option of a layout algorithm if node size calculation is setup appropriately."),nAt),V1),B7t),ji(qn,lt(ct(ip,1),oe,175,0,[ea]))))),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,GI),""),"Interactive"),"Whether the algorithm should be run in interactive mode for the content of a parent node. What this means exactly depends on how the specific algorithm interprets this option. Usually in the interactive mode algorithms try to modify the current layout as little as possible."),!1),La),Rs),un(qn)))),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,_ct),""),"interactive Layout"),"Whether the graph should be changeable interactively and by setting constraints"),!1),La),Rs),un(qn)))),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,j_),""),"Omit Node Micro Layout"),"Node micro layout comprises the computation of node dimensions (if requested), the placement of ports and their labels, and the placement of node labels. The functionality is implemented independent of any specific layout algorithm and shouldn't have any negative impact on the layout algorithm's performance itself. Yet, if any unforeseen behavior occurs, this option allows to deactivate the micro layout."),!1),La),Rs),un(qn)))),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,Got),""),"Port Constraints"),"Defines constraints of the position of the ports of a node."),oAt),us),PAt),un(ea)))),an(e,new Xe(rn(nn(sn(Ze(en(Je(tn(new Ue,yH),""),"Position"),"The position of a node, port, or label. This is used by the 'Fixed Layout' algorithm to specify a pre-defined position."),V1),Ws),ji(ea,lt(ct(ip,1),oe,175,0,[V2,rp]))))),an(e,new Xe(rn(nn(sn(Ze(en(Je(tn(new Ue,VI),""),"Priority"),"Defines the priority of an object; its meaning depends on the specific layout algorithm and the context where it is used."),gc),ja),ji(ea,lt(ct(ip,1),oe,175,0,[Pd]))))),an(e,new Xe(rn(nn(sn(Ze(en(Je(tn(new Ue,tH),""),"Randomization Seed"),"Seed used for pseudo-random number generators to control the layout algorithm. If the value is 0, the seed shall be determined pseudo-randomly (e.g. from the system time)."),gc),ja),un(qn)))),an(e,new Xe(rn(nn(sn(Ze(en(Je(tn(new Ue,R_),""),"Separate Connected Components"),"Whether each connected component should be processed separately."),La),Rs),un(qn)))),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,Okt),""),"Junction Points"),"This option is not used as option, but as output of the layout algorithms. It is attached to edges and determines the points where junction symbols should be drawn in order to represent hyperedges with orthogonal routing. Whether such points are computed depends on the chosen layout algorithm and edge routing style. The points are put into the vector chain with no specific order."),YSt),V1),ASt),un(Pd)))),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,Nkt),""),"Comment Box"),"Whether the node should be regarded as a comment box instead of a regular node. In that case its placement should be similar to how labels are handled. Any edges incident to a comment box specify to which graph elements the comment is related."),!1),La),Rs),un(ea)))),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,Bkt),""),"Hypernode"),"Whether the node should be handled as a hypernode."),!1),La),Rs),un(ea)))),an(e,new Xe(rn(nn(sn(Ze(en(Je(tn(new Ue,Uxn),""),"Label Manager"),"Label managers can shorten labels upon a layout algorithm's request."),V1),E6n),ji(qn,lt(ct(ip,1),oe,175,0,[rp]))))),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,jkt),""),"Margins"),"Margins define additional space around the actual bounds of a graph element. For instance, ports or labels being placed on the outside of a node's border might introduce such a margin. The margin is used to guarantee non-overlap of other graph elements with those ports or labels."),KSt),V1),N7t),un(ea)))),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,mkt),""),"No Layout"),"No layout is done for the associated element. This is used to mark parts of a diagram to avoid their inclusion in the layout graph, or to mark parts of the layout graph to prevent layout engines from processing them. If you wish to exclude the contents of a compound node from automatic layout, while the node itself is still considered on its own layer, use the 'Fixed Layout' algorithm for that node."),!1),La),Rs),ji(ea,lt(ct(ip,1),oe,175,0,[Pd,V2,rp]))))),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,hde),""),"Scale Factor"),"The scaling factor to be applied to the corresponding node in recursive layout. It causes the corresponding node's size to be adjusted, and its ports and labels to be sized and placed accordingly after the layout of that node has been determined (and before the node itself and its siblings are arranged). The scaling is not reverted afterwards, so the resulting layout graph contains the adjusted size and position data. This option is currently not supported if 'Layout Hierarchy' is set."),1),Oo),la),un(ea)))),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,fde),""),"Animate"),"Whether the shift from the old layout to the new computed layout shall be animated."),!0),La),Rs),un(qn)))),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,dde),""),"Animation Time Factor"),"Factor for computation of animation time. The higher the value, the longer the animation time. If the value is 0, the resulting time is always equal to the minimum defined by 'Minimal Animation Time'."),pe(100)),gc),ja),un(qn)))),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,gde),""),"Layout Ancestors"),"Whether the hierarchy levels on the path from the selected element to the root of the diagram shall be included in the layout process."),!1),La),Rs),un(qn)))),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,pde),""),"Maximal Animation Time"),"The maximal time for animations, in milliseconds."),pe(4e3)),gc),ja),un(qn)))),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,bde),""),"Minimal Animation Time"),"The minimal time for animations, in milliseconds."),pe(400)),gc),ja),un(qn)))),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,wde),""),"Progress Bar"),"Whether a progress bar shall be displayed during layout computations."),!1),La),Rs),un(qn)))),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,vde),""),"Validate Graph"),"Whether the graph shall be validated before any layout algorithm is applied. If this option is enabled and at least one error is found, the layout process is aborted and a message is shown to the user."),!1),La),Rs),un(qn)))),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,mde),""),"Validate Options"),"Whether layout options shall be validated before any layout algorithm is applied. If this option is enabled and at least one error is found, the layout process is aborted and a message is shown to the user."),!0),La),Rs),un(qn)))),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,yde),""),"Zoom to Fit"),"Whether the zoom level shall be set to view the whole diagram after layout."),!1),La),Rs),un(qn)))),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,g8t),"box"),"Box Layout Mode"),"Configures the packing mode used by the {@link BoxLayoutProvider}. If SIMPLE is not required (neither priorities are used nor the interactive mode), GROUP_DEC can improve the packing and decrease the area. GROUP_MIXED and GROUP_INC may, in very specific scenarios, work better."),BSt),us),$At),un(qn)))),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,okt),R1),"Comment Comment Spacing"),"Spacing to be preserved between a comment box and other comment boxes connected to the same node. The space left between comment boxes of different nodes is controlled by the node-node spacing."),10),Oo),la),un(qn)))),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,ckt),R1),"Comment Node Spacing"),"Spacing to be preserved between a node and its connected comment boxes. The space left between a node and the comments of another node is controlled by the node-node spacing."),10),Oo),la),un(qn)))),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,jot),R1),"Components Spacing"),"Spacing to be preserved between pairs of connected components. This option is only relevant if 'separateConnectedComponents' is activated."),20),Oo),la),un(qn)))),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,ukt),R1),"Edge Spacing"),"Spacing to be preserved between any two edges. Note that while this can somewhat easily be satisfied for the segments of orthogonally drawn edges, it is harder for general polylines or splines."),10),Oo),la),un(qn)))),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,Vot),R1),"Edge Label Spacing"),"The minimal distance to be preserved between a label and the edge it is associated with. Note that the placement of a label is influenced by the 'edgelabels.placement' option."),2),Oo),la),un(qn)))),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,lkt),R1),"Edge Node Spacing"),"Spacing to be preserved between nodes and edges."),10),Oo),la),un(qn)))),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,hkt),R1),"Label Spacing"),"Determines the amount of space to be left between two labels of the same graph element."),0),Oo),la),un(qn)))),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,gkt),R1),"Label Node Spacing"),"Spacing to be preserved between labels and the border of node they are associated with. Note that the placement of a label is influenced by the 'nodelabels.placement' option."),5),Oo),la),un(qn)))),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,fkt),R1),"Horizontal spacing between Label and Port"),"Horizontal spacing to be preserved between labels and the ports they are associated with. Note that the placement of a label is influenced by the 'portlabels.placement' option."),1),Oo),la),un(qn)))),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,dkt),R1),"Vertical spacing between Label and Port"),"Vertical spacing to be preserved between labels and the ports they are associated with. Note that the placement of a label is influenced by the 'portlabels.placement' option."),1),Oo),la),un(qn)))),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,Cy),R1),"Node Spacing"),"The minimal distance to be preserved between each two nodes."),20),Oo),la),un(qn)))),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,pkt),R1),"Node Self Loop Spacing"),"Spacing to be preserved between a node and its self loops."),10),Oo),la),un(qn)))),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,bkt),R1),"Port Spacing"),"Spacing between pairs of ports of the same node."),10),Oo),la),ji(qn,lt(ct(ip,1),oe,175,0,[ea]))))),an(e,new Xe(rn(nn(sn(Ze(en(Je(tn(new Ue,wkt),R1),"Individual Spacing"),"Allows to specify individual spacing values for graph elements that shall be different from the value specified for the element's parent."),V1),$4e),ji(ea,lt(ct(ip,1),oe,175,0,[Pd,V2,rp]))))),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,$kt),R1),"Additional Port Space"),"Additional space around the sets of ports on each node side. For each side of a node, this option can reserve additional space before and after the ports on each side. For example, a top spacing of 20 makes sure that the first port on the western and eastern side is 20 units away from the northern border."),wAt),V1),N7t),un(qn)))),an(e,new Xe(rn(nn(sn(Ze(en(Je(tn(new Ue,Cct),Ede),"Layout Partition"),"Partition to which the node belongs. This requires Layout Partitioning to be active. Nodes with lower partition IDs will appear to the left of nodes with higher partition IDs (assuming a left-to-right layout direction)."),gc),ja),ji(qn,lt(ct(ip,1),oe,175,0,[ea]))))),ca(e,Cct,Tct,d4e),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,Tct),Ede),"Layout Partitioning"),"Whether to activate partitioned layout. This will allow to group nodes through the Layout Partition option. a pair of nodes with different partition indices is then placed such that the node with lower index is placed to the left of the other node (with left-to-right layout direction). Depending on the layout algorithm, this may only be guaranteed to work if all nodes have a layout partition configured, or at least if edges that cross partitions are not part of a partition-crossing cycle."),rAt),La),Rs),un(qn)))),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,Ckt),Tde),"Node Label Padding"),"Define padding for node labels that are placed inside of a node."),QSt),V1),B7t),un(qn)))),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,UE),Tde),"Node Label Placement"),"Hints for where node labels are to be placed; if empty, the node label's position is not modified."),ZSt),U6),lo),ji(ea,lt(ct(ip,1),oe,175,0,[rp]))))),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,Akt),SH),"Port Alignment"),"Defines the default port distribution for a node. May be overridden for each side individually."),sAt),us),tA),un(ea)))),an(e,new Xe(rn(nn(sn(Ze(en(Je(tn(new Ue,Lkt),SH),"Port Alignment (North)"),"Defines how ports on the northern side are placed, overriding the node's general port alignment."),us),tA),un(ea)))),an(e,new Xe(rn(nn(sn(Ze(en(Je(tn(new Ue,Mkt),SH),"Port Alignment (South)"),"Defines how ports on the southern side are placed, overriding the node's general port alignment."),us),tA),un(ea)))),an(e,new Xe(rn(nn(sn(Ze(en(Je(tn(new Ue,Dkt),SH),"Port Alignment (West)"),"Defines how ports on the western side are placed, overriding the node's general port alignment."),us),tA),un(ea)))),an(e,new Xe(rn(nn(sn(Ze(en(Je(tn(new Ue,Ikt),SH),"Port Alignment (East)"),"Defines how ports on the eastern side are placed, overriding the node's general port alignment."),us),tA),un(ea)))),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,D4),Gct),"Node Size Constraints"),"What should be taken into account when calculating a node's size. Empty size constraints specify that a node's size is already fixed and should not be changed."),JSt),U6),rA),un(ea)))),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,T6),Gct),"Node Size Options"),"Options modifying the behavior of the size constraints set on a node. Each member of the set specifies something that should be taken into account when calculating node sizes. The empty set corresponds to no further modifications."),eAt),U6),NAt),un(ea)))),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,C6),Gct),"Node Size Minimum"),"The minimal size to which a node can be reduced."),tAt),V1),Ws),un(ea)))),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,Ect),Gct),"Fixed Graph Size"),"By default, the fixed layout provider will enlarge a graph until it is large enough to contain its children. If this option is set, it won't do so."),!1),La),Rs),un(qn)))),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,Pkt),kct),"Edge Label Placement"),"Gives a hint on where to put edge labels."),$St),us),mAt),un(rp)))),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,eH),kct),"Inline Edge Labels"),"If true, an edge label is placed directly on its edge. May only apply to center edge labels. This kind of label placement is only advisable if the label's rendering is such that it is not crossed by its edge and thus stays legible."),!1),La),Rs),un(rp)))),an(e,new Xe(rn(nn(sn(Ze(en(Je(tn(new Ue,Wxn),"font"),"Font Name"),"Font name used for a label."),I7),Ae),un(rp)))),an(e,new Xe(rn(nn(sn(Ze(en(Je(tn(new Ue,xde),"font"),"Font Size"),"Font size used for a label."),gc),ja),un(rp)))),an(e,new Xe(rn(nn(sn(Ze(en(Je(tn(new Ue,Rkt),Uct),"Port Anchor Offset"),"The offset to the port position where connections shall be attached."),V1),Ws),un(V2)))),an(e,new Xe(rn(nn(sn(Ze(en(Je(tn(new Ue,Fkt),Uct),"Port Index"),"The index of a port in the fixed order around a node. The order is assumed as clockwise, starting with the leftmost port on the top side. This option must be set if 'Port Constraints' is set to FIXED_ORDER and no specific positions are given for the ports. Additionally, the option 'Port Side' must be defined in this case."),gc),ja),un(V2)))),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,ykt),Uct),"Port Side"),"The side of a node on which a port is situated. This option must be set if 'Port Constraints' is set to FIXED_SIDE or FIXED_ORDER and no specific positions are given for the ports."),lAt),us),Xa),un(V2)))),an(e,new Xe(rn(nn(sn(Ze(en(Je(tn(new Ue,vkt),Uct),"Port Border Offset"),"The offset of ports on the node border. With a positive offset the port is moved outside of the node, while with a negative offset the port is moved towards the inside. An offset of 0 means that the port is placed directly on the node border, i.e. if the port side is north, the port's south border touches the nodes's north border; if the port side is east, the port's west border touches the nodes's east border; if the port side is south, the port's north border touches the node's south border; if the port side is west, the port's east border touches the node's west border."),Oo),la),un(V2)))),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,WE),b8t),"Port Label Placement"),"Decides on a placement method for port labels; if empty, the node label's position is not modified."),cAt),U6),eU),un(ea)))),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,_kt),b8t),"Port Labels Next to Port"),"Use 'portLabels.placement': NEXT_TO_PORT_OF_POSSIBLE."),!1),La),Rs),un(ea)))),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,Skt),b8t),"Treat Port Labels as Group"),"If this option is true (default), the labels of a port will be treated as a group when it comes to centering them next to their port. If this option is false, only the first label will be centered next to the port, with the others being placed below. This only applies to labels of eastern and western ports and will have no effect if labels are not placed next to their port."),!0),La),Rs),un(ea)))),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,kkt),Cde),"Activate Inside Self Loops"),"Whether this node allows to route self loops inside of it instead of around it. If set to true, this will make the node a compound node if it isn't already, and will require the layout algorithm to support compound nodes with hierarchical ports."),!1),La),Rs),un(ea)))),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,Ekt),Cde),"Inside Self Loop"),"Whether a self loop should be routed inside a node instead of around that node."),!1),La),Rs),un(Pd)))),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,$ot),"edge"),"Edge Thickness"),"The thickness of an edge. This is a hint on the line width used to draw an edge, possibly requiring more space to be reserved for it."),1),Oo),la),un(Pd)))),an(e,new Xe(rn(nn(sn(kn(Ze(en(Je(tn(new Ue,kde),"edge"),"Edge Type"),"The type of an edge. This is usually used for UML class diagrams, where associations must be handled differently from generalizations."),VSt),us),CAt),un(Pd)))),WC(e,new Yx(zC(o8(a8(new xm,Gn),"Layered"),'The layer-based method was introduced by Sugiyama, Tagawa and Toda in 1981. It emphasizes the direction of edges by pointing as many edges as possible into the same direction. The nodes are arranged in layers, which are sometimes called "hierarchies", and then reordered such that the number of edge crossings is minimized. Afterwards, concrete coordinates are computed for the nodes and edge bend points.'))),WC(e,new Yx(zC(o8(a8(new xm,"org.eclipse.elk.orthogonal"),"Orthogonal"),`Orthogonal methods that follow the "topology-shape-metrics" approach by Batini, Nardelli and Tamassia '86. The first phase determines the topology of the drawing by applying a planarization technique, which results in a planar representation of the graph. The orthogonal shape is computed in the second phase, which aims at minimizing the number of edge bends, and is called orthogonalization. The third phase leads to concrete coordinates for nodes and edge bend points by applying a compaction method, thus defining the metrics.`))),WC(e,new Yx(zC(o8(a8(new xm,Vl),"Force"),"Layout algorithms that follow physical analogies by simulating a system of attractive and repulsive forces. The first successful method of this kind was proposed by Eades in 1984."))),WC(e,new Yx(zC(o8(a8(new xm,"org.eclipse.elk.circle"),"Circle"),"Circular layout algorithms emphasize cycles or biconnected components of a graph by arranging them in circles. This is useful if a drawing is desired where such components are clearly grouped, or where cycles are shown as prominent OPTIONS of the graph."))),WC(e,new Yx(zC(o8(a8(new xm,K1e),"Tree"),"Specialized layout methods for trees, i.e. acyclic graphs. The regular structure of graphs that have no undirected cycles can be emphasized using an algorithm of this type."))),WC(e,new Yx(zC(o8(a8(new xm,"org.eclipse.elk.planar"),"Planar"),"Algorithms that require a planar or upward planar graph. Most of these algorithms are theoretically interesting, but not practically usable."))),WC(e,new Yx(zC(o8(a8(new xm,Sd),"Radial"),"Radial layout algorithms usually position the nodes of the graph on concentric circles."))),Kue((new QB,e)),lle((new htt,e)),Cue((new ZB,e))};var YS,a4e,NSt,W6,o4e,c4e,BSt,u4e,YG,RSt,QO,qv,jSt,gft,pft,$St,zSt,qSt,HSt,VSt,GSt,s5,USt,l4e,ZO,bft,KG,WSt,a5,YSt,JO,KSt,XSt,QSt,o5,ZSt,G2,JSt,XG,c5,tAt,xb,eAt,QG,tP,U2,nAt,h4e,rAt,f4e,d4e,iAt,sAt,wft,vft,mft,yft,aAt,dl,KS,oAt,xft,kft,Qy,cAt,uAt,u5,lAt,Y6,ZG,Eft,O7,g4e,Tft,p4e,b4e,hAt,w4e,fAt,v4e,K6,dAt,JG,gAt,pAt,W2,m4e,bAt,wAt,vAt;F(Fh,"CoreOptions",684),D(103,22,{3:1,35:1,22:1,103:1},PM);var ng,zh,Cf,h0,rg,XS=jr(Fh,i6t,103,Hr,ban,Ftn),y4e;D(272,22,{3:1,35:1,22:1,272:1},Zet);var P7,Zy,F7,mAt=jr(Fh,"EdgeLabelPlacement",272,Hr,Xin,Ntn),x4e;D(218,22,{3:1,35:1,22:1,218:1},sj);var N7,eP,X6,Cft,_ft=jr(Fh,"EdgeRouting",218,Hr,qsn,Btn),k4e;D(312,22,{3:1,35:1,22:1,312:1},a9);var yAt,xAt,kAt,EAt,Sft,TAt,CAt=jr(Fh,"EdgeType",312,Hr,non,Rtn),E4e;D(977,1,Oh,QB),l.Qe=function(e){Kue(e)};var _At,SAt,AAt,LAt,T4e,MAt,QS;F(Fh,"FixedLayouterOptions",977),D(978,1,{},qL),l.$e=function(){var e;return e=new UZ,e},l._e=function(e){},F(Fh,"FixedLayouterOptions/FixedFactory",978),D(334,22,{3:1,35:1,22:1,334:1},Jet);var sp,tU,ZS,DAt=jr(Fh,"HierarchyHandling",334,Hr,Kin,jtn),C4e;D(285,22,{3:1,35:1,22:1,285:1},aj);var f0,kb,nP,rP,_4e=jr(Fh,"LabelSide",285,Hr,zsn,$tn),S4e;D(93,22,{3:1,35:1,22:1,93:1},q3);var ig,_f,qh,Sf,Yl,Af,Hh,d0,Lf,lo=jr(Fh,"NodeLabelPlacement",93,Hr,scn,ztn),A4e;D(249,22,{3:1,35:1,22:1,249:1},FM);var IAt,JS,Eb,OAt,iP,tA=jr(Fh,"PortAlignment",249,Hr,wan,qtn),L4e;D(98,22,{3:1,35:1,22:1,98:1},o9);var Y2,Gc,g0,B7,G1,Tb,PAt=jr(Fh,"PortConstraints",98,Hr,jan,Htn),M4e;D(273,22,{3:1,35:1,22:1,273:1},c9);var eA,nA,sg,sP,Cb,Q6,eU=jr(Fh,"PortLabelPlacement",273,Hr,eon,Vtn),D4e;D(61,22,{3:1,35:1,22:1,61:1},NM);var Hn,Pn,mh,yh,Su,lu,U1,Mf,el,Vu,Uc,nl,Au,Lu,Df,Kl,Xl,Vh,mr,Zo,Bn,Xa=jr(Fh,"PortSide",61,Hr,dan,Wtn),I4e;D(981,1,Oh,ZB),l.Qe=function(e){Cue(e)};var O4e,P4e,FAt,F4e,N4e;F(Fh,"RandomLayouterOptions",981),D(982,1,{},ZZ),l.$e=function(){var e;return e=new tJ,e},l._e=function(e){},F(Fh,"RandomLayouterOptions/RandomFactory",982),D(374,22,{3:1,35:1,22:1,374:1},oj);var Jy,aP,oP,K2,rA=jr(Fh,"SizeConstraint",374,Hr,$sn,Gtn),B4e;D(259,22,{3:1,35:1,22:1,259:1},H3);var cP,nU,R7,Aft,uP,iA,rU,iU,sU,NAt=jr(Fh,"SizeOptions",259,Hr,fcn,Utn),R4e;D(370,1,{1949:1},r8),l.b=!1,l.c=0,l.d=-1,l.e=null,l.f=null,l.g=-1,l.j=!1,l.k=!1,l.n=!1,l.o=0,l.q=0,l.r=0,F(Ec,"BasicProgressMonitor",370),D(972,209,S2,YZ),l.Ze=function(e,n){var r,s,o,h,d,v,k,C,M;switch(vr(n,"Box layout",2),o=pM(ye(qe(e,(fq(),i4e)))),h=u(qe(e,r4e),116),r=je(Re(qe(e,DSt))),s=je(Re(qe(e,ISt))),u(qe(e,lft),311).g){case 0:d=(v=new Bu((!e.a&&(e.a=new fe(rs,e,10,11)),e.a)),wn(),Zs(v,new ozt(s)),v),k=Q4t(e),C=ye(qe(e,MSt)),(C==null||(On(C),C<=0))&&(C=1.3),M=Q5n(d,o,h,k.a,k.b,r,(On(C),C)),wv(e,M.a,M.b,!1,!0);break;default:W3n(e,o,h,r)}or(n)},F(Ec,"BoxLayoutProvider",972),D(973,1,Oi,ozt),l.ue=function(e,n){return pwn(this,u(e,33),u(n,33))},l.Fb=function(e){return this===e},l.ve=function(){return new dt(this)},l.a=!1,F(Ec,"BoxLayoutProvider/1",973),D(157,1,{157:1},rz,LWt),l.Ib=function(){return this.c?X5t(this.c):eb(this.b)},F(Ec,"BoxLayoutProvider/Group",157),D(311,22,{3:1,35:1,22:1,311:1},cj);var BAt,RAt,jAt,Lft,$At=jr(Ec,"BoxLayoutProvider/PackingMode",311,Hr,Hsn,Ytn),j4e;D(974,1,Oi,KZ),l.ue=function(e,n){return vrn(u(e,157),u(n,157))},l.Fb=function(e){return this===e},l.ve=function(){return new dt(this)},F(Ec,"BoxLayoutProvider/lambda$0$Type",974),D(975,1,Oi,sB),l.ue=function(e,n){return hrn(u(e,157),u(n,157))},l.Fb=function(e){return this===e},l.ve=function(){return new dt(this)},F(Ec,"BoxLayoutProvider/lambda$1$Type",975),D(976,1,Oi,XZ),l.ue=function(e,n){return frn(u(e,157),u(n,157))},l.Fb=function(e){return this===e},l.ve=function(){return new dt(this)},F(Ec,"BoxLayoutProvider/lambda$2$Type",976),D(1365,1,{831:1},QZ),l.qg=function(e,n){return HR(),!_t(n,160)||jHt((i6(),u(e,160)),n)},F(Ec,"ElkSpacings/AbstractSpacingsBuilder/lambda$0$Type",1365),D(1366,1,Un,czt),l.td=function(e){nln(this.a,u(e,146))},F(Ec,"ElkSpacings/AbstractSpacingsBuilder/lambda$1$Type",1366),D(1367,1,Un,WZ),l.td=function(e){u(e,94),HR()},F(Ec,"ElkSpacings/AbstractSpacingsBuilder/lambda$2$Type",1367),D(1371,1,Un,uzt),l.td=function(e){Scn(this.a,u(e,94))},F(Ec,"ElkSpacings/AbstractSpacingsBuilder/lambda$3$Type",1371),D(1369,1,li,CGt),l.Mb=function(e){return qun(this.a,this.b,u(e,146))},F(Ec,"ElkSpacings/AbstractSpacingsBuilder/lambda$4$Type",1369),D(1368,1,li,_Gt),l.Mb=function(e){return sZe(this.a,this.b,u(e,831))},F(Ec,"ElkSpacings/AbstractSpacingsBuilder/lambda$5$Type",1368),D(1370,1,Un,SGt),l.td=function(e){snn(this.a,this.b,u(e,146))},F(Ec,"ElkSpacings/AbstractSpacingsBuilder/lambda$6$Type",1370),D(935,1,{},GZ),l.Kb=function(e){return SUt(e)},l.Fb=function(e){return this===e},F(Ec,"ElkUtil/lambda$0$Type",935),D(936,1,Un,AGt),l.td=function(e){wbn(this.a,this.b,u(e,79))},l.a=0,l.b=0,F(Ec,"ElkUtil/lambda$1$Type",936),D(937,1,Un,LGt),l.td=function(e){wKe(this.a,this.b,u(e,202))},l.a=0,l.b=0,F(Ec,"ElkUtil/lambda$2$Type",937),D(938,1,Un,MGt),l.td=function(e){cQe(this.a,this.b,u(e,137))},l.a=0,l.b=0,F(Ec,"ElkUtil/lambda$3$Type",938),D(939,1,Un,lzt),l.td=function(e){xen(this.a,u(e,469))},F(Ec,"ElkUtil/lambda$4$Type",939),D(342,1,{35:1,342:1},WYe),l.wd=function(e){return NQe(this,u(e,236))},l.Fb=function(e){var n;return _t(e,342)?(n=u(e,342),this.a==n.a):!1},l.Hb=function(){return ps(this.a)},l.Ib=function(){return this.a+" (exclusive)"},l.a=0,F(Ec,"ExclusiveBounds/ExclusiveLowerBound",342),D(1138,209,S2,UZ),l.Ze=function(e,n){var r,s,o,h,d,v,k,C,M,j,H,G,K,tt,gt,Mt,St,Rt,Kt,ue,_e,We,Qe;for(vr(n,"Fixed Layout",1),h=u(qe(e,(ui(),zSt)),218),j=0,H=0,St=new nr((!e.a&&(e.a=new fe(rs,e,10,11)),e.a));St.e!=St.i.gc();){for(gt=u(dr(St),33),Qe=u(qe(gt,(Sz(),QS)),8),Qe&&(x1(gt,Qe.a,Qe.b),u(qe(gt,SAt),174).Hc((Al(),Jy))&&(G=u(qe(gt,LAt),8),G.a>0&&G.b>0&&wv(gt,G.a,G.b,!0,!0))),j=b.Math.max(j,gt.i+gt.g),H=b.Math.max(H,gt.j+gt.f),C=new nr((!gt.n&&(gt.n=new fe(qo,gt,1,7)),gt.n));C.e!=C.i.gc();)v=u(dr(C),137),Qe=u(qe(v,QS),8),Qe&&x1(v,Qe.a,Qe.b),j=b.Math.max(j,gt.i+v.i+v.g),H=b.Math.max(H,gt.j+v.j+v.f);for(ue=new nr((!gt.c&&(gt.c=new fe(gl,gt,9,9)),gt.c));ue.e!=ue.i.gc();)for(Kt=u(dr(ue),118),Qe=u(qe(Kt,QS),8),Qe&&x1(Kt,Qe.a,Qe.b),_e=gt.i+Kt.i,We=gt.j+Kt.j,j=b.Math.max(j,_e+Kt.g),H=b.Math.max(H,We+Kt.f),k=new nr((!Kt.n&&(Kt.n=new fe(qo,Kt,1,7)),Kt.n));k.e!=k.i.gc();)v=u(dr(k),137),Qe=u(qe(v,QS),8),Qe&&x1(v,Qe.a,Qe.b),j=b.Math.max(j,_e+v.i+v.g),H=b.Math.max(H,We+v.j+v.f);for(o=new ar(lr(K0(gt).a.Kc(),new z));zr(o);)r=u(Mr(o),79),M=$he(r),j=b.Math.max(j,M.a),H=b.Math.max(H,M.b);for(s=new ar(lr(wI(gt).a.Kc(),new z));zr(s);)r=u(Mr(s),79),es(e0(r))!=e&&(M=$he(r),j=b.Math.max(j,M.a),H=b.Math.max(H,M.b))}if(h==(W0(),N7))for(Mt=new nr((!e.a&&(e.a=new fe(rs,e,10,11)),e.a));Mt.e!=Mt.i.gc();)for(gt=u(dr(Mt),33),s=new ar(lr(K0(gt).a.Kc(),new z));zr(s);)r=u(Mr(s),79),d=gyn(r),d.b==0?wo(r,a5,null):wo(r,a5,d);je(Re(qe(e,(Sz(),AAt))))||(Rt=u(qe(e,T4e),116),tt=j+Rt.b+Rt.c,K=H+Rt.d+Rt.a,wv(e,tt,K,!0,!0)),or(n)},F(Ec,"FixedLayoutProvider",1138),D(373,134,{3:1,414:1,373:1,94:1,134:1},Yu,ree),l.Jf=function(e){var n,r,s,o,h,d,v,k,C;if(e)try{for(k=vy(e,";,;"),h=k,d=0,v=h.length;d>16&ys|n^s<<16},l.Kc=function(){return new hzt(this)},l.Ib=function(){return this.a==null&&this.b==null?"pair(null,null)":this.a==null?"pair(null,"+$o(this.b)+")":this.b==null?"pair("+$o(this.a)+",null)":"pair("+$o(this.a)+","+$o(this.b)+")"},F(Ec,"Pair",46),D(983,1,sa,hzt),l.Nb=function(e){ba(this,e)},l.Ob=function(){return!this.c&&(!this.b&&this.a.a!=null||this.a.b!=null)},l.Pb=function(){if(!this.c&&!this.b&&this.a.a!=null)return this.b=!0,this.a.a;if(!this.c&&this.a.b!=null)return this.c=!0,this.a.b;throw it(new lc)},l.Qb=function(){throw this.c&&this.a.b!=null?this.a.b=null:this.b&&this.a.a!=null&&(this.a.a=null),it(new Ou)},l.b=!1,l.c=!1,F(Ec,"Pair/1",983),D(448,1,{448:1},zXt),l.Fb=function(e){return Fc(this.a,u(e,448).a)&&Fc(this.c,u(e,448).c)&&Fc(this.d,u(e,448).d)&&Fc(this.b,u(e,448).b)},l.Hb=function(){return Az(lt(ct(Qn,1),De,1,5,[this.a,this.c,this.d,this.b]))},l.Ib=function(){return"("+this.a+Ya+this.c+Ya+this.d+Ya+this.b+")"},F(Ec,"Quadruple",448),D(1126,209,S2,tJ),l.Ze=function(e,n){var r,s,o,h,d;if(vr(n,"Random Layout",1),(!e.a&&(e.a=new fe(rs,e,10,11)),e.a).i==0){or(n);return}h=u(qe(e,(S3t(),F4e)),19),h&&h.a!=0?o=new F$(h.a):o=new Zit,r=pM(ye(qe(e,O4e))),d=pM(ye(qe(e,N4e))),s=u(qe(e,P4e),116),A5n(e,o,r,d,s),or(n)},F(Ec,"RandomLayoutProvider",1126);var H4e;D(553,1,{}),l.qf=function(){return new $e(this.f.i,this.f.j)},l.We=function(e){return dQt(e,(ui(),dl))?qe(this.f,V4e):qe(this.f,e)},l.rf=function(){return new $e(this.f.g,this.f.f)},l.sf=function(){return this.g},l.Xe=function(e){return o2(this.f,e)},l.tf=function(e){ku(this.f,e.a),Eu(this.f,e.b)},l.uf=function(e){tv(this.f,e.a),Jw(this.f,e.b)},l.vf=function(e){this.g=e},l.g=0;var V4e;F(K_,"ElkGraphAdapters/AbstractElkGraphElementAdapter",553),D(554,1,{839:1},wR),l.wf=function(){var e,n;if(!this.b)for(this.b=D$(u$(this.a).i),n=new nr(u$(this.a));n.e!=n.i.gc();)e=u(dr(n),137),le(this.b,new get(e));return this.b},l.b=null,F(K_,"ElkGraphAdapters/ElkEdgeAdapter",554),D(301,553,{},Mm),l.xf=function(){return zse(this)},l.a=null,F(K_,"ElkGraphAdapters/ElkGraphAdapter",301),D(630,553,{181:1},get),F(K_,"ElkGraphAdapters/ElkLabelAdapter",630),D(629,553,{680:1},gnt),l.wf=function(){return M1n(this)},l.Af=function(){var e;return e=u(qe(this.f,(ui(),JO)),142),!e&&(e=new OC),e},l.Cf=function(){return D1n(this)},l.Ef=function(e){var n;n=new Lnt(e),wo(this.f,(ui(),JO),n)},l.Ff=function(e){wo(this.f,(ui(),U2),new kwt(e))},l.yf=function(){return this.d},l.zf=function(){var e,n;if(!this.a)for(this.a=new he,n=new ar(lr(wI(u(this.f,33)).a.Kc(),new z));zr(n);)e=u(Mr(n),79),le(this.a,new wR(e));return this.a},l.Bf=function(){var e,n;if(!this.c)for(this.c=new he,n=new ar(lr(K0(u(this.f,33)).a.Kc(),new z));zr(n);)e=u(Mr(n),79),le(this.c,new wR(e));return this.c},l.Df=function(){return p$(u(this.f,33)).i!=0||je(Re(u(this.f,33).We((ui(),ZO))))},l.Gf=function(){xon(this,(Pm(),H4e))},l.a=null,l.b=null,l.c=null,l.d=null,l.e=null,F(K_,"ElkGraphAdapters/ElkNodeAdapter",629),D(1266,553,{838:1},$zt),l.wf=function(){return j1n(this)},l.zf=function(){var e,n;if(!this.a)for(this.a=Ud(u(this.f,118).xg().i),n=new nr(u(this.f,118).xg());n.e!=n.i.gc();)e=u(dr(n),79),le(this.a,new wR(e));return this.a},l.Bf=function(){var e,n;if(!this.c)for(this.c=Ud(u(this.f,118).yg().i),n=new nr(u(this.f,118).yg());n.e!=n.i.gc();)e=u(dr(n),79),le(this.c,new wR(e));return this.c},l.Hf=function(){return u(u(this.f,118).We((ui(),u5)),61)},l.If=function(){var e,n,r,s,o,h,d,v;for(s=T1(u(this.f,118)),r=new nr(u(this.f,118).yg());r.e!=r.i.gc();)for(e=u(dr(r),79),v=new nr((!e.c&&(e.c=new Cn(br,e,5,8)),e.c));v.e!=v.i.gc();){if(d=u(dr(v),82),ey(Do(d),s))return!0;if(Do(d)==s&&je(Re(qe(e,(ui(),bft)))))return!0}for(n=new nr(u(this.f,118).xg());n.e!=n.i.gc();)for(e=u(dr(n),79),h=new nr((!e.b&&(e.b=new Cn(br,e,4,7)),e.b));h.e!=h.i.gc();)if(o=u(dr(h),82),ey(Do(o),s))return!0;return!1},l.a=null,l.b=null,l.c=null,F(K_,"ElkGraphAdapters/ElkPortAdapter",1266),D(1267,1,Oi,eJ),l.ue=function(e,n){return omn(u(e,118),u(n,118))},l.Fb=function(e){return this===e},l.ve=function(){return new dt(this)},F(K_,"ElkGraphAdapters/PortComparator",1267);var _b=Ki(ph,"EObject"),j7=Ki(F4,Ade),Gh=Ki(F4,Lde),lP=Ki(F4,Mde),hP=Ki(F4,"ElkShape"),br=Ki(F4,Dde),Ys=Ki(F4,w8t),Ji=Ki(F4,Ide),fP=Ki(ph,Ode),sA=Ki(ph,"EFactory"),G4e,Mft=Ki(ph,Pde),i1=Ki(ph,"EPackage"),na,U4e,W4e,VAt,aU,Y4e,GAt,UAt,WAt,Sb,K4e,X4e,qo=Ki(F4,v8t),rs=Ki(F4,m8t),gl=Ki(F4,y8t);D(90,1,Fde),l.Jg=function(){return this.Kg(),null},l.Kg=function(){return null},l.Lg=function(){return this.Kg(),!1},l.Mg=function(){return!1},l.Ng=function(e){mi(this,e)},F(L6,"BasicNotifierImpl",90),D(97,90,jde),l.nh=function(){return xl(this)},l.Og=function(e,n){return e},l.Pg=function(){throw it(new Or)},l.Qg=function(e){var n;return n=no(u(yn(this.Tg(),this.Vg()),18)),this.eh().ih(this,n.n,n.f,e)},l.Rg=function(e,n){throw it(new Or)},l.Sg=function(e,n,r){return Hl(this,e,n,r)},l.Tg=function(){var e;return this.Pg()&&(e=this.Pg().ck(),e)?e:this.zh()},l.Ug=function(){return eat(this)},l.Vg=function(){throw it(new Or)},l.Wg=function(){var e,n;return n=this.ph().dk(),!n&&this.Pg().ik(n=(YC(),e=jvt(vd(this.Tg())),e==null?Rft:new jM(this,e))),n},l.Xg=function(e,n){return e},l.Yg=function(e){var n;return n=e.Gj(),n?e.aj():Gi(this.Tg(),e)},l.Zg=function(){var e;return e=this.Pg(),e?e.fk():null},l.$g=function(){return this.Pg()?this.Pg().ck():null},l._g=function(e,n,r){return Xz(this,e,n,r)},l.ah=function(e){return j8(this,e)},l.bh=function(e,n){return Urt(this,e,n)},l.dh=function(){var e;return e=this.Pg(),!!e&&e.gk()},l.eh=function(){throw it(new Or)},l.fh=function(){return Hz(this)},l.gh=function(e,n,r,s){return c6(this,e,n,s)},l.hh=function(e,n,r){var s;return s=u(yn(this.Tg(),n),66),s.Nj().Qj(this,this.yh(),n-this.Ah(),e,r)},l.ih=function(e,n,r,s){return m$(this,e,n,s)},l.jh=function(e,n,r){var s;return s=u(yn(this.Tg(),n),66),s.Nj().Rj(this,this.yh(),n-this.Ah(),e,r)},l.kh=function(){return!!this.Pg()&&!!this.Pg().ek()},l.lh=function(e){return fst(this,e)},l.mh=function(e){return MQt(this,e)},l.oh=function(e){return ehe(this,e)},l.ph=function(){throw it(new Or)},l.qh=function(){return this.Pg()?this.Pg().ek():null},l.rh=function(){return Hz(this)},l.sh=function(e,n){Xst(this,e,n)},l.th=function(e){this.ph().hk(e)},l.uh=function(e){this.ph().kk(e)},l.vh=function(e){this.ph().jk(e)},l.wh=function(e,n){var r,s,o,h;return h=this.Zg(),h&&e&&(n=Ba(h.Vk(),this,n),h.Zk(this)),s=this.eh(),s&&(wat(this,this.eh(),this.Vg()).Bb&Ka?(o=s.fh(),o&&(e?!h&&o.Zk(this):o.Yk(this))):(n=(r=this.Vg(),r>=0?this.Qg(n):this.eh().ih(this,-1-r,null,n)),n=this.Sg(null,-1,n))),this.uh(e),n},l.xh=function(e){var n,r,s,o,h,d,v,k;if(r=this.Tg(),h=Gi(r,e),n=this.Ah(),h>=n)return u(e,66).Nj().Uj(this,this.yh(),h-n);if(h<=-1)if(d=C4(($u(),ya),r,e),d){if(to(),u(d,66).Oj()||(d=Kx(To(ya,d))),o=(s=this.Yg(d),u(s>=0?this._g(s,!0,!0):dv(this,d,!0),153)),k=d.Zj(),k>1||k==-1)return u(u(o,215).hl(e,!1),76)}else throw it(new Fn(lb+e.ne()+Wct));else if(e.$j())return s=this.Yg(e),u(s>=0?this._g(s,!1,!0):dv(this,e,!1),76);return v=new XGt(this,e),v},l.yh=function(){return $mt(this)},l.zh=function(){return(Hp(),Ln).S},l.Ah=function(){return Jn(this.zh())},l.Bh=function(e){Gst(this,e)},l.Ib=function(){return mf(this)},F(Mn,"BasicEObjectImpl",97);var Q4e;D(114,97,{105:1,92:1,90:1,56:1,108:1,49:1,97:1,114:1}),l.Ch=function(e){var n;return n=zmt(this),n[e]},l.Dh=function(e,n){var r;r=zmt(this),ts(r,e,n)},l.Eh=function(e){var n;n=zmt(this),ts(n,e,null)},l.Jg=function(){return u(Dn(this,4),126)},l.Kg=function(){throw it(new Or)},l.Lg=function(){return(this.Db&4)!=0},l.Pg=function(){throw it(new Or)},l.Fh=function(e){o6(this,2,e)},l.Rg=function(e,n){this.Db=n<<16|this.Db&255,this.Fh(e)},l.Tg=function(){return vu(this)},l.Vg=function(){return this.Db>>16},l.Wg=function(){var e,n;return YC(),n=jvt(vd((e=u(Dn(this,16),26),e||this.zh()))),n==null?Rft:new jM(this,n)},l.Mg=function(){return(this.Db&1)==0},l.Zg=function(){return u(Dn(this,128),1935)},l.$g=function(){return u(Dn(this,16),26)},l.dh=function(){return(this.Db&32)!=0},l.eh=function(){return u(Dn(this,2),49)},l.kh=function(){return(this.Db&64)!=0},l.ph=function(){throw it(new Or)},l.qh=function(){return u(Dn(this,64),281)},l.th=function(e){o6(this,16,e)},l.uh=function(e){o6(this,128,e)},l.vh=function(e){o6(this,64,e)},l.yh=function(){return su(this)},l.Db=0,F(Mn,"MinimalEObjectImpl",114),D(115,114,{105:1,92:1,90:1,56:1,108:1,49:1,97:1,114:1,115:1}),l.Fh=function(e){this.Cb=e},l.eh=function(){return this.Cb},F(Mn,"MinimalEObjectImpl/Container",115),D(1985,115,{105:1,413:1,94:1,92:1,90:1,56:1,108:1,49:1,97:1,114:1,115:1}),l._g=function(e,n,r){return Z3t(this,e,n,r)},l.jh=function(e,n,r){return $4t(this,e,n,r)},l.lh=function(e){return Qvt(this,e)},l.sh=function(e,n){Byt(this,e,n)},l.zh=function(){return Jc(),X4e},l.Bh=function(e){_yt(this,e)},l.Ve=function(){return cse(this)},l.We=function(e){return qe(this,e)},l.Xe=function(e){return o2(this,e)},l.Ye=function(e,n){return wo(this,e,n)},F(M2,"EMapPropertyHolderImpl",1985),D(567,115,{105:1,469:1,92:1,90:1,56:1,108:1,49:1,97:1,114:1,115:1},xp),l._g=function(e,n,r){switch(e){case 0:return this.a;case 1:return this.b}return Xz(this,e,n,r)},l.lh=function(e){switch(e){case 0:return this.a!=0;case 1:return this.b!=0}return fst(this,e)},l.sh=function(e,n){switch(e){case 0:iz(this,Xt(ye(n)));return;case 1:sz(this,Xt(ye(n)));return}Xst(this,e,n)},l.zh=function(){return Jc(),U4e},l.Bh=function(e){switch(e){case 0:iz(this,0);return;case 1:sz(this,0);return}Gst(this,e)},l.Ib=function(){var e;return this.Db&64?mf(this):(e=new _h(mf(this)),e.a+=" (x: ",$3(e,this.a),e.a+=", y: ",$3(e,this.b),e.a+=")",e.a)},l.a=0,l.b=0,F(M2,"ElkBendPointImpl",567),D(723,1985,{105:1,413:1,160:1,94:1,92:1,90:1,56:1,108:1,49:1,97:1,114:1,115:1}),l._g=function(e,n,r){return n3t(this,e,n,r)},l.hh=function(e,n,r){return jst(this,e,n,r)},l.jh=function(e,n,r){return Eit(this,e,n,r)},l.lh=function(e){return vyt(this,e)},l.sh=function(e,n){w4t(this,e,n)},l.zh=function(){return Jc(),Y4e},l.Bh=function(e){Zyt(this,e)},l.zg=function(){return this.k},l.Ag=function(){return u$(this)},l.Ib=function(){return Xit(this)},l.k=null,F(M2,"ElkGraphElementImpl",723),D(724,723,{105:1,413:1,160:1,470:1,94:1,92:1,90:1,56:1,108:1,49:1,97:1,114:1,115:1}),l._g=function(e,n,r){return f3t(this,e,n,r)},l.lh=function(e){return m3t(this,e)},l.sh=function(e,n){v4t(this,e,n)},l.zh=function(){return Jc(),K4e},l.Bh=function(e){T3t(this,e)},l.Bg=function(){return this.f},l.Cg=function(){return this.g},l.Dg=function(){return this.i},l.Eg=function(){return this.j},l.Fg=function(e,n){bj(this,e,n)},l.Gg=function(e,n){x1(this,e,n)},l.Hg=function(e){ku(this,e)},l.Ig=function(e){Eu(this,e)},l.Ib=function(){return Vst(this)},l.f=0,l.g=0,l.i=0,l.j=0,F(M2,"ElkShapeImpl",724),D(725,724,{105:1,413:1,82:1,160:1,470:1,94:1,92:1,90:1,56:1,108:1,49:1,97:1,114:1,115:1}),l._g=function(e,n,r){return U3t(this,e,n,r)},l.hh=function(e,n,r){return h4t(this,e,n,r)},l.jh=function(e,n,r){return f4t(this,e,n,r)},l.lh=function(e){return Fyt(this,e)},l.sh=function(e,n){x5t(this,e,n)},l.zh=function(){return Jc(),W4e},l.Bh=function(e){R3t(this,e)},l.xg=function(){return!this.d&&(this.d=new Cn(Ys,this,8,5)),this.d},l.yg=function(){return!this.e&&(this.e=new Cn(Ys,this,7,4)),this.e},F(M2,"ElkConnectableShapeImpl",725),D(352,723,{105:1,413:1,79:1,160:1,352:1,94:1,92:1,90:1,56:1,108:1,49:1,97:1,114:1,115:1},pw),l.Qg=function(e){return o4t(this,e)},l._g=function(e,n,r){switch(e){case 3:return cD(this);case 4:return!this.b&&(this.b=new Cn(br,this,4,7)),this.b;case 5:return!this.c&&(this.c=new Cn(br,this,5,8)),this.c;case 6:return!this.a&&(this.a=new fe(Ji,this,6,6)),this.a;case 7:return Nn(),!this.b&&(this.b=new Cn(br,this,4,7)),!(this.b.i<=1&&(!this.c&&(this.c=new Cn(br,this,5,8)),this.c.i<=1));case 8:return Nn(),!!w_(this);case 9:return Nn(),!!fv(this);case 10:return Nn(),!this.b&&(this.b=new Cn(br,this,4,7)),this.b.i!=0&&(!this.c&&(this.c=new Cn(br,this,5,8)),this.c.i!=0)}return n3t(this,e,n,r)},l.hh=function(e,n,r){var s;switch(n){case 3:return this.Cb&&(r=(s=this.Db>>16,s>=0?o4t(this,r):this.Cb.ih(this,-1-s,null,r))),twt(this,u(e,33),r);case 4:return!this.b&&(this.b=new Cn(br,this,4,7)),Zc(this.b,e,r);case 5:return!this.c&&(this.c=new Cn(br,this,5,8)),Zc(this.c,e,r);case 6:return!this.a&&(this.a=new fe(Ji,this,6,6)),Zc(this.a,e,r)}return jst(this,e,n,r)},l.jh=function(e,n,r){switch(n){case 3:return twt(this,null,r);case 4:return!this.b&&(this.b=new Cn(br,this,4,7)),Ba(this.b,e,r);case 5:return!this.c&&(this.c=new Cn(br,this,5,8)),Ba(this.c,e,r);case 6:return!this.a&&(this.a=new fe(Ji,this,6,6)),Ba(this.a,e,r)}return Eit(this,e,n,r)},l.lh=function(e){switch(e){case 3:return!!cD(this);case 4:return!!this.b&&this.b.i!=0;case 5:return!!this.c&&this.c.i!=0;case 6:return!!this.a&&this.a.i!=0;case 7:return!this.b&&(this.b=new Cn(br,this,4,7)),!(this.b.i<=1&&(!this.c&&(this.c=new Cn(br,this,5,8)),this.c.i<=1));case 8:return w_(this);case 9:return fv(this);case 10:return!this.b&&(this.b=new Cn(br,this,4,7)),this.b.i!=0&&(!this.c&&(this.c=new Cn(br,this,5,8)),this.c.i!=0)}return vyt(this,e)},l.sh=function(e,n){switch(e){case 3:oat(this,u(n,33));return;case 4:!this.b&&(this.b=new Cn(br,this,4,7)),xr(this.b),!this.b&&(this.b=new Cn(br,this,4,7)),is(this.b,u(n,14));return;case 5:!this.c&&(this.c=new Cn(br,this,5,8)),xr(this.c),!this.c&&(this.c=new Cn(br,this,5,8)),is(this.c,u(n,14));return;case 6:!this.a&&(this.a=new fe(Ji,this,6,6)),xr(this.a),!this.a&&(this.a=new fe(Ji,this,6,6)),is(this.a,u(n,14));return}w4t(this,e,n)},l.zh=function(){return Jc(),VAt},l.Bh=function(e){switch(e){case 3:oat(this,null);return;case 4:!this.b&&(this.b=new Cn(br,this,4,7)),xr(this.b);return;case 5:!this.c&&(this.c=new Cn(br,this,5,8)),xr(this.c);return;case 6:!this.a&&(this.a=new fe(Ji,this,6,6)),xr(this.a);return}Zyt(this,e)},l.Ib=function(){return $le(this)},F(M2,"ElkEdgeImpl",352),D(439,1985,{105:1,413:1,202:1,439:1,94:1,92:1,90:1,56:1,108:1,49:1,97:1,114:1,115:1},ad),l.Qg=function(e){return r4t(this,e)},l._g=function(e,n,r){switch(e){case 1:return this.j;case 2:return this.k;case 3:return this.b;case 4:return this.c;case 5:return!this.a&&(this.a=new As(Gh,this,5)),this.a;case 6:return SQt(this);case 7:return n?wst(this):this.i;case 8:return n?bst(this):this.f;case 9:return!this.g&&(this.g=new Cn(Ji,this,9,10)),this.g;case 10:return!this.e&&(this.e=new Cn(Ji,this,10,9)),this.e;case 11:return this.d}return Z3t(this,e,n,r)},l.hh=function(e,n,r){var s,o,h;switch(n){case 6:return this.Cb&&(r=(o=this.Db>>16,o>=0?r4t(this,r):this.Cb.ih(this,-1-o,null,r))),ewt(this,u(e,79),r);case 9:return!this.g&&(this.g=new Cn(Ji,this,9,10)),Zc(this.g,e,r);case 10:return!this.e&&(this.e=new Cn(Ji,this,10,9)),Zc(this.e,e,r)}return h=u(yn((s=u(Dn(this,16),26),s||(Jc(),aU)),n),66),h.Nj().Qj(this,su(this),n-Jn((Jc(),aU)),e,r)},l.jh=function(e,n,r){switch(n){case 5:return!this.a&&(this.a=new As(Gh,this,5)),Ba(this.a,e,r);case 6:return ewt(this,null,r);case 9:return!this.g&&(this.g=new Cn(Ji,this,9,10)),Ba(this.g,e,r);case 10:return!this.e&&(this.e=new Cn(Ji,this,10,9)),Ba(this.e,e,r)}return $4t(this,e,n,r)},l.lh=function(e){switch(e){case 1:return this.j!=0;case 2:return this.k!=0;case 3:return this.b!=0;case 4:return this.c!=0;case 5:return!!this.a&&this.a.i!=0;case 6:return!!SQt(this);case 7:return!!this.i;case 8:return!!this.f;case 9:return!!this.g&&this.g.i!=0;case 10:return!!this.e&&this.e.i!=0;case 11:return this.d!=null}return Qvt(this,e)},l.sh=function(e,n){switch(e){case 1:G8(this,Xt(ye(n)));return;case 2:W8(this,Xt(ye(n)));return;case 3:V8(this,Xt(ye(n)));return;case 4:U8(this,Xt(ye(n)));return;case 5:!this.a&&(this.a=new As(Gh,this,5)),xr(this.a),!this.a&&(this.a=new As(Gh,this,5)),is(this.a,u(n,14));return;case 6:zce(this,u(n,79));return;case 7:lz(this,u(n,82));return;case 8:uz(this,u(n,82));return;case 9:!this.g&&(this.g=new Cn(Ji,this,9,10)),xr(this.g),!this.g&&(this.g=new Cn(Ji,this,9,10)),is(this.g,u(n,14));return;case 10:!this.e&&(this.e=new Cn(Ji,this,10,9)),xr(this.e),!this.e&&(this.e=new Cn(Ji,this,10,9)),is(this.e,u(n,14));return;case 11:uyt(this,Br(n));return}Byt(this,e,n)},l.zh=function(){return Jc(),aU},l.Bh=function(e){switch(e){case 1:G8(this,0);return;case 2:W8(this,0);return;case 3:V8(this,0);return;case 4:U8(this,0);return;case 5:!this.a&&(this.a=new As(Gh,this,5)),xr(this.a);return;case 6:zce(this,null);return;case 7:lz(this,null);return;case 8:uz(this,null);return;case 9:!this.g&&(this.g=new Cn(Ji,this,9,10)),xr(this.g);return;case 10:!this.e&&(this.e=new Cn(Ji,this,10,9)),xr(this.e);return;case 11:uyt(this,null);return}_yt(this,e)},l.Ib=function(){return sce(this)},l.b=0,l.c=0,l.d=null,l.j=0,l.k=0,F(M2,"ElkEdgeSectionImpl",439),D(150,115,{105:1,92:1,90:1,147:1,56:1,108:1,49:1,97:1,150:1,114:1,115:1}),l._g=function(e,n,r){var s;return e==0?(!this.Ab&&(this.Ab=new fe(Zr,this,0,3)),this.Ab):uh(this,e-Jn(this.zh()),yn((s=u(Dn(this,16),26),s||this.zh()),e),n,r)},l.hh=function(e,n,r){var s,o;return n==0?(!this.Ab&&(this.Ab=new fe(Zr,this,0,3)),Zc(this.Ab,e,r)):(o=u(yn((s=u(Dn(this,16),26),s||this.zh()),n),66),o.Nj().Qj(this,su(this),n-Jn(this.zh()),e,r))},l.jh=function(e,n,r){var s,o;return n==0?(!this.Ab&&(this.Ab=new fe(Zr,this,0,3)),Ba(this.Ab,e,r)):(o=u(yn((s=u(Dn(this,16),26),s||this.zh()),n),66),o.Nj().Rj(this,su(this),n-Jn(this.zh()),e,r))},l.lh=function(e){var n;return e==0?!!this.Ab&&this.Ab.i!=0:oh(this,e-Jn(this.zh()),yn((n=u(Dn(this,16),26),n||this.zh()),e))},l.oh=function(e){return Lxt(this,e)},l.sh=function(e,n){var r;switch(e){case 0:!this.Ab&&(this.Ab=new fe(Zr,this,0,3)),xr(this.Ab),!this.Ab&&(this.Ab=new fe(Zr,this,0,3)),is(this.Ab,u(n,14));return}gh(this,e-Jn(this.zh()),yn((r=u(Dn(this,16),26),r||this.zh()),e),n)},l.uh=function(e){o6(this,128,e)},l.zh=function(){return dn(),p5e},l.Bh=function(e){var n;switch(e){case 0:!this.Ab&&(this.Ab=new fe(Zr,this,0,3)),xr(this.Ab);return}fh(this,e-Jn(this.zh()),yn((n=u(Dn(this,16),26),n||this.zh()),e))},l.Gh=function(){this.Bb|=1},l.Hh=function(e){return k_(this,e)},l.Bb=0,F(Mn,"EModelElementImpl",150),D(704,150,{105:1,92:1,90:1,471:1,147:1,56:1,108:1,49:1,97:1,150:1,114:1,115:1},JB),l.Ih=function(e,n){return bhe(this,e,n)},l.Jh=function(e){var n,r,s,o,h;if(this.a!=Rl(e)||e.Bb&256)throw it(new Fn(Kct+e.zb+Cv));for(s=Ao(e);Lc(s.a).i!=0;){if(r=u(AI(s,0,(n=u(At(Lc(s.a),0),87),h=n.c,_t(h,88)?u(h,26):(dn(),Kh))),26),hv(r))return o=Rl(r).Nh().Jh(r),u(o,49).th(e),o;s=Ao(r)}return(e.D!=null?e.D:e.B)=="java.util.Map$Entry"?new hKt(e):new zwt(e)},l.Kh=function(e,n){return vv(this,e,n)},l._g=function(e,n,r){var s;switch(e){case 0:return!this.Ab&&(this.Ab=new fe(Zr,this,0,3)),this.Ab;case 1:return this.a}return uh(this,e-Jn((dn(),Db)),yn((s=u(Dn(this,16),26),s||Db),e),n,r)},l.hh=function(e,n,r){var s,o;switch(n){case 0:return!this.Ab&&(this.Ab=new fe(Zr,this,0,3)),Zc(this.Ab,e,r);case 1:return this.a&&(r=u(this.a,49).ih(this,4,i1,r)),Xyt(this,u(e,235),r)}return o=u(yn((s=u(Dn(this,16),26),s||(dn(),Db)),n),66),o.Nj().Qj(this,su(this),n-Jn((dn(),Db)),e,r)},l.jh=function(e,n,r){var s,o;switch(n){case 0:return!this.Ab&&(this.Ab=new fe(Zr,this,0,3)),Ba(this.Ab,e,r);case 1:return Xyt(this,null,r)}return o=u(yn((s=u(Dn(this,16),26),s||(dn(),Db)),n),66),o.Nj().Rj(this,su(this),n-Jn((dn(),Db)),e,r)},l.lh=function(e){var n;switch(e){case 0:return!!this.Ab&&this.Ab.i!=0;case 1:return!!this.a}return oh(this,e-Jn((dn(),Db)),yn((n=u(Dn(this,16),26),n||Db),e))},l.sh=function(e,n){var r;switch(e){case 0:!this.Ab&&(this.Ab=new fe(Zr,this,0,3)),xr(this.Ab),!this.Ab&&(this.Ab=new fe(Zr,this,0,3)),is(this.Ab,u(n,14));return;case 1:zae(this,u(n,235));return}gh(this,e-Jn((dn(),Db)),yn((r=u(Dn(this,16),26),r||Db),e),n)},l.zh=function(){return dn(),Db},l.Bh=function(e){var n;switch(e){case 0:!this.Ab&&(this.Ab=new fe(Zr,this,0,3)),xr(this.Ab);return;case 1:zae(this,null);return}fh(this,e-Jn((dn(),Db)),yn((n=u(Dn(this,16),26),n||Db),e))};var aA,YAt,Z4e;F(Mn,"EFactoryImpl",704),D(xf,704,{105:1,2014:1,92:1,90:1,471:1,147:1,56:1,108:1,49:1,97:1,150:1,114:1,115:1},ax),l.Ih=function(e,n){switch(e.yj()){case 12:return u(n,146).tg();case 13:return $o(n);default:throw it(new Fn(QE+e.ne()+Cv))}},l.Jh=function(e){var n,r,s,o,h,d,v,k;switch(e.G==-1&&(e.G=(n=Rl(e),n?Hg(n.Mh(),e):-1)),e.G){case 4:return h=new ZT,h;case 6:return d=new Vpt,d;case 7:return v=new Gpt,v;case 8:return s=new pw,s;case 9:return r=new xp,r;case 10:return o=new ad,o;case 11:return k=new aB,k;default:throw it(new Fn(Kct+e.zb+Cv))}},l.Kh=function(e,n){switch(e.yj()){case 13:case 12:return null;default:throw it(new Fn(QE+e.ne()+Cv))}},F(M2,"ElkGraphFactoryImpl",xf),D(438,150,{105:1,92:1,90:1,147:1,191:1,56:1,108:1,49:1,97:1,150:1,114:1,115:1}),l.Wg=function(){var e,n;return n=(e=u(Dn(this,16),26),jvt(vd(e||this.zh()))),n==null?(YC(),YC(),Rft):new IWt(this,n)},l._g=function(e,n,r){var s;switch(e){case 0:return!this.Ab&&(this.Ab=new fe(Zr,this,0,3)),this.Ab;case 1:return this.ne()}return uh(this,e-Jn(this.zh()),yn((s=u(Dn(this,16),26),s||this.zh()),e),n,r)},l.lh=function(e){var n;switch(e){case 0:return!!this.Ab&&this.Ab.i!=0;case 1:return this.zb!=null}return oh(this,e-Jn(this.zh()),yn((n=u(Dn(this,16),26),n||this.zh()),e))},l.sh=function(e,n){var r;switch(e){case 0:!this.Ab&&(this.Ab=new fe(Zr,this,0,3)),xr(this.Ab),!this.Ab&&(this.Ab=new fe(Zr,this,0,3)),is(this.Ab,u(n,14));return;case 1:this.Lh(Br(n));return}gh(this,e-Jn(this.zh()),yn((r=u(Dn(this,16),26),r||this.zh()),e),n)},l.zh=function(){return dn(),b5e},l.Bh=function(e){var n;switch(e){case 0:!this.Ab&&(this.Ab=new fe(Zr,this,0,3)),xr(this.Ab);return;case 1:this.Lh(null);return}fh(this,e-Jn(this.zh()),yn((n=u(Dn(this,16),26),n||this.zh()),e))},l.ne=function(){return this.zb},l.Lh=function(e){Qc(this,e)},l.Ib=function(){return J9(this)},l.zb=null,F(Mn,"ENamedElementImpl",438),D(179,438,{105:1,92:1,90:1,147:1,191:1,56:1,235:1,108:1,49:1,97:1,150:1,179:1,114:1,115:1,675:1},fQt),l.Qg=function(e){return eae(this,e)},l._g=function(e,n,r){var s;switch(e){case 0:return!this.Ab&&(this.Ab=new fe(Zr,this,0,3)),this.Ab;case 1:return this.zb;case 2:return this.yb;case 3:return this.xb;case 4:return this.sb;case 5:return!this.rb&&(this.rb=new Gm(this,s1,this)),this.rb;case 6:return!this.vb&&(this.vb=new Rx(i1,this,6,7)),this.vb;case 7:return n?this.Db>>16==7?u(this.Cb,235):null:AQt(this)}return uh(this,e-Jn((dn(),up)),yn((s=u(Dn(this,16),26),s||up),e),n,r)},l.hh=function(e,n,r){var s,o,h;switch(n){case 0:return!this.Ab&&(this.Ab=new fe(Zr,this,0,3)),Zc(this.Ab,e,r);case 4:return this.sb&&(r=u(this.sb,49).ih(this,1,sA,r)),t3t(this,u(e,471),r);case 5:return!this.rb&&(this.rb=new Gm(this,s1,this)),Zc(this.rb,e,r);case 6:return!this.vb&&(this.vb=new Rx(i1,this,6,7)),Zc(this.vb,e,r);case 7:return this.Cb&&(r=(o=this.Db>>16,o>=0?eae(this,r):this.Cb.ih(this,-1-o,null,r))),Hl(this,e,7,r)}return h=u(yn((s=u(Dn(this,16),26),s||(dn(),up)),n),66),h.Nj().Qj(this,su(this),n-Jn((dn(),up)),e,r)},l.jh=function(e,n,r){var s,o;switch(n){case 0:return!this.Ab&&(this.Ab=new fe(Zr,this,0,3)),Ba(this.Ab,e,r);case 4:return t3t(this,null,r);case 5:return!this.rb&&(this.rb=new Gm(this,s1,this)),Ba(this.rb,e,r);case 6:return!this.vb&&(this.vb=new Rx(i1,this,6,7)),Ba(this.vb,e,r);case 7:return Hl(this,null,7,r)}return o=u(yn((s=u(Dn(this,16),26),s||(dn(),up)),n),66),o.Nj().Rj(this,su(this),n-Jn((dn(),up)),e,r)},l.lh=function(e){var n;switch(e){case 0:return!!this.Ab&&this.Ab.i!=0;case 1:return this.zb!=null;case 2:return this.yb!=null;case 3:return this.xb!=null;case 4:return!!this.sb;case 5:return!!this.rb&&this.rb.i!=0;case 6:return!!this.vb&&this.vb.i!=0;case 7:return!!AQt(this)}return oh(this,e-Jn((dn(),up)),yn((n=u(Dn(this,16),26),n||up),e))},l.oh=function(e){var n;return n=Lwn(this,e),n||Lxt(this,e)},l.sh=function(e,n){var r;switch(e){case 0:!this.Ab&&(this.Ab=new fe(Zr,this,0,3)),xr(this.Ab),!this.Ab&&(this.Ab=new fe(Zr,this,0,3)),is(this.Ab,u(n,14));return;case 1:Qc(this,Br(n));return;case 2:wz(this,Br(n));return;case 3:bz(this,Br(n));return;case 4:Hst(this,u(n,471));return;case 5:!this.rb&&(this.rb=new Gm(this,s1,this)),xr(this.rb),!this.rb&&(this.rb=new Gm(this,s1,this)),is(this.rb,u(n,14));return;case 6:!this.vb&&(this.vb=new Rx(i1,this,6,7)),xr(this.vb),!this.vb&&(this.vb=new Rx(i1,this,6,7)),is(this.vb,u(n,14));return}gh(this,e-Jn((dn(),up)),yn((r=u(Dn(this,16),26),r||up),e),n)},l.vh=function(e){var n,r;if(e&&this.rb)for(r=new nr(this.rb);r.e!=r.i.gc();)n=dr(r),_t(n,351)&&(u(n,351).w=null);o6(this,64,e)},l.zh=function(){return dn(),up},l.Bh=function(e){var n;switch(e){case 0:!this.Ab&&(this.Ab=new fe(Zr,this,0,3)),xr(this.Ab);return;case 1:Qc(this,null);return;case 2:wz(this,null);return;case 3:bz(this,null);return;case 4:Hst(this,null);return;case 5:!this.rb&&(this.rb=new Gm(this,s1,this)),xr(this.rb);return;case 6:!this.vb&&(this.vb=new Rx(i1,this,6,7)),xr(this.vb);return}fh(this,e-Jn((dn(),up)),yn((n=u(Dn(this,16),26),n||up),e))},l.Gh=function(){Mst(this)},l.Mh=function(){return!this.rb&&(this.rb=new Gm(this,s1,this)),this.rb},l.Nh=function(){return this.sb},l.Oh=function(){return this.ub},l.Ph=function(){return this.xb},l.Qh=function(){return this.yb},l.Rh=function(e){this.ub=e},l.Ib=function(){var e;return this.Db&64?J9(this):(e=new _h(J9(this)),e.a+=" (nsURI: ",go(e,this.yb),e.a+=", nsPrefix: ",go(e,this.xb),e.a+=")",e.a)},l.xb=null,l.yb=null,F(Mn,"EPackageImpl",179),D(555,179,{105:1,2016:1,555:1,92:1,90:1,147:1,191:1,56:1,235:1,108:1,49:1,97:1,150:1,179:1,114:1,115:1,675:1},gce),l.q=!1,l.r=!1;var J4e=!1;F(M2,"ElkGraphPackageImpl",555),D(354,724,{105:1,413:1,160:1,137:1,470:1,354:1,94:1,92:1,90:1,56:1,108:1,49:1,97:1,114:1,115:1},ZT),l.Qg=function(e){return i4t(this,e)},l._g=function(e,n,r){switch(e){case 7:return LQt(this);case 8:return this.a}return f3t(this,e,n,r)},l.hh=function(e,n,r){var s;switch(n){case 7:return this.Cb&&(r=(s=this.Db>>16,s>=0?i4t(this,r):this.Cb.ih(this,-1-s,null,r))),nvt(this,u(e,160),r)}return jst(this,e,n,r)},l.jh=function(e,n,r){return n==7?nvt(this,null,r):Eit(this,e,n,r)},l.lh=function(e){switch(e){case 7:return!!LQt(this);case 8:return!hn("",this.a)}return m3t(this,e)},l.sh=function(e,n){switch(e){case 7:F5t(this,u(n,160));return;case 8:nyt(this,Br(n));return}v4t(this,e,n)},l.zh=function(){return Jc(),GAt},l.Bh=function(e){switch(e){case 7:F5t(this,null);return;case 8:nyt(this,"");return}T3t(this,e)},l.Ib=function(){return eoe(this)},l.a="",F(M2,"ElkLabelImpl",354),D(239,725,{105:1,413:1,82:1,160:1,33:1,470:1,239:1,94:1,92:1,90:1,56:1,108:1,49:1,97:1,114:1,115:1},Vpt),l.Qg=function(e){return c4t(this,e)},l._g=function(e,n,r){switch(e){case 9:return!this.c&&(this.c=new fe(gl,this,9,9)),this.c;case 10:return!this.a&&(this.a=new fe(rs,this,10,11)),this.a;case 11:return es(this);case 12:return!this.b&&(this.b=new fe(Ys,this,12,3)),this.b;case 13:return Nn(),!this.a&&(this.a=new fe(rs,this,10,11)),this.a.i>0}return U3t(this,e,n,r)},l.hh=function(e,n,r){var s;switch(n){case 9:return!this.c&&(this.c=new fe(gl,this,9,9)),Zc(this.c,e,r);case 10:return!this.a&&(this.a=new fe(rs,this,10,11)),Zc(this.a,e,r);case 11:return this.Cb&&(r=(s=this.Db>>16,s>=0?c4t(this,r):this.Cb.ih(this,-1-s,null,r))),lwt(this,u(e,33),r);case 12:return!this.b&&(this.b=new fe(Ys,this,12,3)),Zc(this.b,e,r)}return h4t(this,e,n,r)},l.jh=function(e,n,r){switch(n){case 9:return!this.c&&(this.c=new fe(gl,this,9,9)),Ba(this.c,e,r);case 10:return!this.a&&(this.a=new fe(rs,this,10,11)),Ba(this.a,e,r);case 11:return lwt(this,null,r);case 12:return!this.b&&(this.b=new fe(Ys,this,12,3)),Ba(this.b,e,r)}return f4t(this,e,n,r)},l.lh=function(e){switch(e){case 9:return!!this.c&&this.c.i!=0;case 10:return!!this.a&&this.a.i!=0;case 11:return!!es(this);case 12:return!!this.b&&this.b.i!=0;case 13:return!this.a&&(this.a=new fe(rs,this,10,11)),this.a.i>0}return Fyt(this,e)},l.sh=function(e,n){switch(e){case 9:!this.c&&(this.c=new fe(gl,this,9,9)),xr(this.c),!this.c&&(this.c=new fe(gl,this,9,9)),is(this.c,u(n,14));return;case 10:!this.a&&(this.a=new fe(rs,this,10,11)),xr(this.a),!this.a&&(this.a=new fe(rs,this,10,11)),is(this.a,u(n,14));return;case 11:I5t(this,u(n,33));return;case 12:!this.b&&(this.b=new fe(Ys,this,12,3)),xr(this.b),!this.b&&(this.b=new fe(Ys,this,12,3)),is(this.b,u(n,14));return}x5t(this,e,n)},l.zh=function(){return Jc(),UAt},l.Bh=function(e){switch(e){case 9:!this.c&&(this.c=new fe(gl,this,9,9)),xr(this.c);return;case 10:!this.a&&(this.a=new fe(rs,this,10,11)),xr(this.a);return;case 11:I5t(this,null);return;case 12:!this.b&&(this.b=new fe(Ys,this,12,3)),xr(this.b);return}R3t(this,e)},l.Ib=function(){return X5t(this)},F(M2,"ElkNodeImpl",239),D(186,725,{105:1,413:1,82:1,160:1,118:1,470:1,186:1,94:1,92:1,90:1,56:1,108:1,49:1,97:1,114:1,115:1},Gpt),l.Qg=function(e){return s4t(this,e)},l._g=function(e,n,r){return e==9?T1(this):U3t(this,e,n,r)},l.hh=function(e,n,r){var s;switch(n){case 9:return this.Cb&&(r=(s=this.Db>>16,s>=0?s4t(this,r):this.Cb.ih(this,-1-s,null,r))),nwt(this,u(e,33),r)}return h4t(this,e,n,r)},l.jh=function(e,n,r){return n==9?nwt(this,null,r):f4t(this,e,n,r)},l.lh=function(e){return e==9?!!T1(this):Fyt(this,e)},l.sh=function(e,n){switch(e){case 9:D5t(this,u(n,33));return}x5t(this,e,n)},l.zh=function(){return Jc(),WAt},l.Bh=function(e){switch(e){case 9:D5t(this,null);return}R3t(this,e)},l.Ib=function(){return zue(this)},F(M2,"ElkPortImpl",186);var t5e=Ki(Ra,"BasicEMap/Entry");D(1092,115,{105:1,42:1,92:1,90:1,133:1,56:1,108:1,49:1,97:1,114:1,115:1},aB),l.Fb=function(e){return this===e},l.cd=function(){return this.b},l.Hb=function(){return Pw(this)},l.Uh=function(e){ryt(this,u(e,146))},l._g=function(e,n,r){switch(e){case 0:return this.b;case 1:return this.c}return Xz(this,e,n,r)},l.lh=function(e){switch(e){case 0:return!!this.b;case 1:return this.c!=null}return fst(this,e)},l.sh=function(e,n){switch(e){case 0:ryt(this,u(n,146));return;case 1:ayt(this,n);return}Xst(this,e,n)},l.zh=function(){return Jc(),Sb},l.Bh=function(e){switch(e){case 0:ryt(this,null);return;case 1:ayt(this,null);return}Gst(this,e)},l.Sh=function(){var e;return this.a==-1&&(e=this.b,this.a=e?Hi(e):0),this.a},l.dd=function(){return this.c},l.Th=function(e){this.a=e},l.ed=function(e){var n;return n=this.c,ayt(this,e),n},l.Ib=function(){var e;return this.Db&64?mf(this):(e=new Mp,Gr(Gr(Gr(e,this.b?this.b.tg():_u),Uot),b9(this.c)),e.a)},l.a=-1,l.c=null;var Hv=F(M2,"ElkPropertyToValueMapEntryImpl",1092);D(984,1,{},oB),F(ma,"JsonAdapter",984),D(210,60,Q0,ud),F(ma,"JsonImportException",210),D(857,1,{},nae),F(ma,"JsonImporter",857),D(891,1,{},DGt),F(ma,"JsonImporter/lambda$0$Type",891),D(892,1,{},IGt),F(ma,"JsonImporter/lambda$1$Type",892),D(900,1,{},fzt),F(ma,"JsonImporter/lambda$10$Type",900),D(902,1,{},OGt),F(ma,"JsonImporter/lambda$11$Type",902),D(903,1,{},PGt),F(ma,"JsonImporter/lambda$12$Type",903),D(909,1,{},UXt),F(ma,"JsonImporter/lambda$13$Type",909),D(908,1,{},GXt),F(ma,"JsonImporter/lambda$14$Type",908),D(904,1,{},FGt),F(ma,"JsonImporter/lambda$15$Type",904),D(905,1,{},NGt),F(ma,"JsonImporter/lambda$16$Type",905),D(906,1,{},BGt),F(ma,"JsonImporter/lambda$17$Type",906),D(907,1,{},RGt),F(ma,"JsonImporter/lambda$18$Type",907),D(912,1,{},dzt),F(ma,"JsonImporter/lambda$19$Type",912),D(893,1,{},gzt),F(ma,"JsonImporter/lambda$2$Type",893),D(910,1,{},pzt),F(ma,"JsonImporter/lambda$20$Type",910),D(911,1,{},bzt),F(ma,"JsonImporter/lambda$21$Type",911),D(915,1,{},wzt),F(ma,"JsonImporter/lambda$22$Type",915),D(913,1,{},vzt),F(ma,"JsonImporter/lambda$23$Type",913),D(914,1,{},mzt),F(ma,"JsonImporter/lambda$24$Type",914),D(917,1,{},yzt),F(ma,"JsonImporter/lambda$25$Type",917),D(916,1,{},xzt),F(ma,"JsonImporter/lambda$26$Type",916),D(918,1,Un,jGt),l.td=function(e){ion(this.b,this.a,Br(e))},F(ma,"JsonImporter/lambda$27$Type",918),D(919,1,Un,$Gt),l.td=function(e){son(this.b,this.a,Br(e))},F(ma,"JsonImporter/lambda$28$Type",919),D(920,1,{},zGt),F(ma,"JsonImporter/lambda$29$Type",920),D(896,1,{},kzt),F(ma,"JsonImporter/lambda$3$Type",896),D(921,1,{},qGt),F(ma,"JsonImporter/lambda$30$Type",921),D(922,1,{},Ezt),F(ma,"JsonImporter/lambda$31$Type",922),D(923,1,{},Tzt),F(ma,"JsonImporter/lambda$32$Type",923),D(924,1,{},Czt),F(ma,"JsonImporter/lambda$33$Type",924),D(925,1,{},_zt),F(ma,"JsonImporter/lambda$34$Type",925),D(859,1,{},Szt),F(ma,"JsonImporter/lambda$35$Type",859),D(929,1,{},BYt),F(ma,"JsonImporter/lambda$36$Type",929),D(926,1,Un,Azt),l.td=function(e){can(this.a,u(e,469))},F(ma,"JsonImporter/lambda$37$Type",926),D(927,1,Un,YGt),l.td=function(e){NXe(this.a,this.b,u(e,202))},F(ma,"JsonImporter/lambda$38$Type",927),D(928,1,Un,KGt),l.td=function(e){BXe(this.a,this.b,u(e,202))},F(ma,"JsonImporter/lambda$39$Type",928),D(894,1,{},Lzt),F(ma,"JsonImporter/lambda$4$Type",894),D(930,1,Un,Mzt),l.td=function(e){uan(this.a,u(e,8))},F(ma,"JsonImporter/lambda$40$Type",930),D(895,1,{},Dzt),F(ma,"JsonImporter/lambda$5$Type",895),D(899,1,{},Izt),F(ma,"JsonImporter/lambda$6$Type",899),D(897,1,{},Ozt),F(ma,"JsonImporter/lambda$7$Type",897),D(898,1,{},Pzt),F(ma,"JsonImporter/lambda$8$Type",898),D(901,1,{},Fzt),F(ma,"JsonImporter/lambda$9$Type",901),D(948,1,Un,Nzt),l.td=function(e){Vx(this.a,new Um(Br(e)))},F(ma,"JsonMetaDataConverter/lambda$0$Type",948),D(949,1,Un,Bzt),l.td=function(e){Cnn(this.a,u(e,237))},F(ma,"JsonMetaDataConverter/lambda$1$Type",949),D(950,1,Un,Rzt),l.td=function(e){kin(this.a,u(e,149))},F(ma,"JsonMetaDataConverter/lambda$2$Type",950),D(951,1,Un,jzt),l.td=function(e){_nn(this.a,u(e,175))},F(ma,"JsonMetaDataConverter/lambda$3$Type",951),D(237,22,{3:1,35:1,22:1,237:1},Px);var oU,cU,Dft,uU,lU,hU,Ift,Oft,fU=jr(qI,"GraphFeature",237,Hr,Yon,Xtn),e5e;D(13,1,{35:1,146:1},Vi,Ps,mn,eo),l.wd=function(e){return FQe(this,u(e,146))},l.Fb=function(e){return dQt(this,e)},l.wg=function(){return Ie(this)},l.tg=function(){return this.b},l.Hb=function(){return Vg(this.b)},l.Ib=function(){return this.b},F(qI,"Property",13),D(818,1,Oi,Ept),l.ue=function(e,n){return Jln(this,u(e,94),u(n,94))},l.Fb=function(e){return this===e},l.ve=function(){return new dt(this)},F(qI,"PropertyHolderComparator",818),D(695,1,sa,Tpt),l.Nb=function(e){ba(this,e)},l.Pb=function(){return uon(this)},l.Qb=function(){IHt()},l.Ob=function(){return!!this.a},F(DH,"ElkGraphUtil/AncestorIterator",695);var KAt=Ki(Ra,"EList");D(67,52,{20:1,28:1,52:1,14:1,15:1,67:1,58:1}),l.Vc=function(e,n){n_(this,e,n)},l.Fc=function(e){return Dr(this,e)},l.Wc=function(e,n){return Syt(this,e,n)},l.Gc=function(e){return is(this,e)},l.Zh=function(){return new Bx(this)},l.$h=function(){return new $M(this)},l._h=function(e){return DD(this,e)},l.ai=function(){return!0},l.bi=function(e,n){},l.ci=function(){},l.di=function(e,n){Yrt(this,e,n)},l.ei=function(e,n,r){},l.fi=function(e,n){},l.gi=function(e,n,r){},l.Fb=function(e){return Sue(this,e)},l.Hb=function(){return kyt(this)},l.hi=function(){return!1},l.Kc=function(){return new nr(this)},l.Yc=function(){return new Nx(this)},l.Zc=function(e){var n;if(n=this.gc(),e<0||e>n)throw it(new qm(e,n));return new Jnt(this,e)},l.ji=function(e,n){this.ii(e,this.Xc(n))},l.Mc=function(e){return X$(this,e)},l.li=function(e,n){return n},l._c=function(e,n){return h4(this,e,n)},l.Ib=function(){return g3t(this)},l.ni=function(){return!0},l.oi=function(e,n){return sE(this,n)},F(Ra,"AbstractEList",67),D(63,67,Ld,ox,Qw,gyt),l.Vh=function(e,n){return $st(this,e,n)},l.Wh=function(e){return Lse(this,e)},l.Xh=function(e,n){UD(this,e,n)},l.Yh=function(e){gD(this,e)},l.pi=function(e){return Fmt(this,e)},l.$b=function(){z9(this)},l.Hc=function(e){return yE(this,e)},l.Xb=function(e){return At(this,e)},l.qi=function(e){var n,r,s;++this.j,r=this.g==null?0:this.g.length,e>r&&(s=this.g,n=r+(r/2|0)+4,n=0?(this.$c(n),!0):!1},l.mi=function(e,n){return this.Ui(e,this.oi(e,n))},l.gc=function(){return this.Vi()},l.Pc=function(){return this.Wi()},l.Qc=function(e){return this.Xi(e)},l.Ib=function(){return this.Yi()},F(Ra,"DelegatingEList",1995),D(1996,1995,E0e),l.Vh=function(e,n){return sxt(this,e,n)},l.Wh=function(e){return this.Vh(this.Vi(),e)},l.Xh=function(e,n){fce(this,e,n)},l.Yh=function(e){rce(this,e)},l.ai=function(){return!this.bj()},l.$b=function(){A_(this)},l.Zi=function(e,n,r,s,o){return new pQt(this,e,n,r,s,o)},l.$i=function(e){mi(this.Ai(),e)},l._i=function(){return null},l.aj=function(){return-1},l.Ai=function(){return null},l.bj=function(){return!1},l.cj=function(e,n){return n},l.dj=function(e,n){return n},l.ej=function(){return!1},l.fj=function(){return!this.Ri()},l.ii=function(e,n){var r,s;return this.ej()?(s=this.fj(),r=B4t(this,e,n),this.$i(this.Zi(7,pe(n),r,e,s)),r):B4t(this,e,n)},l.$c=function(e){var n,r,s,o;return this.ej()?(r=null,s=this.fj(),n=this.Zi(4,o=Hj(this,e),null,e,s),this.bj()&&o?(r=this.dj(o,r),r?(r.Ei(n),r.Fi()):this.$i(n)):r?(r.Ei(n),r.Fi()):this.$i(n),o):(o=Hj(this,e),this.bj()&&o&&(r=this.dj(o,null),r&&r.Fi()),o)},l.mi=function(e,n){return yle(this,e,n)},F(L6,"DelegatingNotifyingListImpl",1996),D(143,1,nO),l.Ei=function(e){return T4t(this,e)},l.Fi=function(){rit(this)},l.xi=function(){return this.d},l._i=function(){return null},l.gj=function(){return null},l.yi=function(e){return-1},l.zi=function(){return aue(this)},l.Ai=function(){return null},l.Bi=function(){return $5t(this)},l.Ci=function(){return this.o<0?this.o<-2?-2-this.o-1:-1:this.o},l.hj=function(){return!1},l.Di=function(e){var n,r,s,o,h,d,v,k,C,M,j;switch(this.d){case 1:case 2:switch(o=e.xi(),o){case 1:case 2:if(h=e.Ai(),Vt(h)===Vt(this.Ai())&&this.yi(null)==e.yi(null))return this.g=e.zi(),e.xi()==1&&(this.d=1),!0}case 4:{switch(o=e.xi(),o){case 4:{if(h=e.Ai(),Vt(h)===Vt(this.Ai())&&this.yi(null)==e.yi(null))return C=kxt(this),k=this.o<0?this.o<-2?-2-this.o-1:-1:this.o,d=e.Ci(),this.d=6,j=new Qw(2),k<=d?(Dr(j,this.n),Dr(j,e.Bi()),this.g=lt(ct(Cr,1),Xr,25,15,[this.o=k,d+1])):(Dr(j,e.Bi()),Dr(j,this.n),this.g=lt(ct(Cr,1),Xr,25,15,[this.o=d,k])),this.n=j,C||(this.o=-2-this.o-1),!0;break}}break}case 6:{switch(o=e.xi(),o){case 4:{if(h=e.Ai(),Vt(h)===Vt(this.Ai())&&this.yi(null)==e.yi(null)){for(C=kxt(this),d=e.Ci(),M=u(this.g,48),s=Nt(Cr,Xr,25,M.length+1,15,1),n=0;n>>0,n.toString(16))),s.a+=" (eventType: ",this.d){case 1:{s.a+="SET";break}case 2:{s.a+="UNSET";break}case 3:{s.a+="ADD";break}case 5:{s.a+="ADD_MANY";break}case 4:{s.a+="REMOVE";break}case 6:{s.a+="REMOVE_MANY";break}case 7:{s.a+="MOVE";break}case 8:{s.a+="REMOVING_ADAPTER";break}case 9:{s.a+="RESOLVE";break}default:{xet(s,this.d);break}}if(Yue(this)&&(s.a+=", touch: true"),s.a+=", position: ",xet(s,this.o<0?this.o<-2?-2-this.o-1:-1:this.o),s.a+=", notifier: ",l9(s,this.Ai()),s.a+=", feature: ",l9(s,this._i()),s.a+=", oldValue: ",l9(s,$5t(this)),s.a+=", newValue: ",this.d==6&&_t(this.g,48)){for(r=u(this.g,48),s.a+="[",e=0;e10?((!this.b||this.c.j!=this.a)&&(this.b=new E9(this),this.a=this.j),I0(this.b,e)):yE(this,e)},l.ni=function(){return!0},l.a=0,F(Ra,"AbstractEList/1",953),D(295,73,bot,qm),F(Ra,"AbstractEList/BasicIndexOutOfBoundsException",295),D(40,1,sa,nr),l.Nb=function(e){ba(this,e)},l.mj=function(){if(this.i.j!=this.f)throw it(new rh)},l.nj=function(){return dr(this)},l.Ob=function(){return this.e!=this.i.gc()},l.Pb=function(){return this.nj()},l.Qb=function(){f_(this)},l.e=0,l.f=0,l.g=-1,F(Ra,"AbstractEList/EIterator",40),D(278,40,n0,Nx,Jnt),l.Qb=function(){f_(this)},l.Rb=function(e){Die(this,e)},l.oj=function(){var e;try{return e=this.d.Xb(--this.e),this.mj(),this.g=this.e,e}catch(n){throw n=Wi(n),_t(n,73)?(this.mj(),it(new lc)):it(n)}},l.pj=function(e){Ise(this,e)},l.Sb=function(){return this.e!=0},l.Tb=function(){return this.e},l.Ub=function(){return this.oj()},l.Vb=function(){return this.e-1},l.Wb=function(e){this.pj(e)},F(Ra,"AbstractEList/EListIterator",278),D(341,40,sa,Bx),l.nj=function(){return dst(this)},l.Qb=function(){throw it(new Or)},F(Ra,"AbstractEList/NonResolvingEIterator",341),D(385,278,n0,$M,wwt),l.Rb=function(e){throw it(new Or)},l.nj=function(){var e;try{return e=this.c.ki(this.e),this.mj(),this.g=this.e++,e}catch(n){throw n=Wi(n),_t(n,73)?(this.mj(),it(new lc)):it(n)}},l.oj=function(){var e;try{return e=this.c.ki(--this.e),this.mj(),this.g=this.e,e}catch(n){throw n=Wi(n),_t(n,73)?(this.mj(),it(new lc)):it(n)}},l.Qb=function(){throw it(new Or)},l.Wb=function(e){throw it(new Or)},F(Ra,"AbstractEList/NonResolvingEListIterator",385),D(1982,67,T0e),l.Vh=function(e,n){var r,s,o,h,d,v,k,C,M,j,H;if(o=n.gc(),o!=0){for(C=u(Dn(this.a,4),126),M=C==null?0:C.length,H=M+o,s=Fit(this,H),j=M-e,j>0&&Dc(C,e,s,e+o,j),k=n.Kc(),d=0;dr)throw it(new qm(e,r));return new _Xt(this,e)},l.$b=function(){var e,n;++this.j,e=u(Dn(this.a,4),126),n=e==null?0:e.length,bE(this,null),Yrt(this,n,e)},l.Hc=function(e){var n,r,s,o,h;if(n=u(Dn(this.a,4),126),n!=null){if(e!=null){for(s=n,o=0,h=s.length;o=r)throw it(new qm(e,r));return n[e]},l.Xc=function(e){var n,r,s;if(n=u(Dn(this.a,4),126),n!=null){if(e!=null){for(r=0,s=n.length;rr)throw it(new qm(e,r));return new CXt(this,e)},l.ii=function(e,n){var r,s,o;if(r=jie(this),o=r==null?0:r.length,e>=o)throw it(new yo(iut+e+D2+o));if(n>=o)throw it(new yo(sut+n+D2+o));return s=r[n],e!=n&&(e0&&Dc(e,0,n,0,r),n},l.Qc=function(e){var n,r,s;return n=u(Dn(this.a,4),126),s=n==null?0:n.length,s>0&&(e.lengths&&ts(e,s,null),e};var n5e;F(Ra,"ArrayDelegatingEList",1982),D(1038,40,sa,FJt),l.mj=function(){if(this.b.j!=this.f||Vt(u(Dn(this.b.a,4),126))!==Vt(this.a))throw it(new rh)},l.Qb=function(){f_(this),this.a=u(Dn(this.b.a,4),126)},F(Ra,"ArrayDelegatingEList/EIterator",1038),D(706,278,n0,KKt,CXt),l.mj=function(){if(this.b.j!=this.f||Vt(u(Dn(this.b.a,4),126))!==Vt(this.a))throw it(new rh)},l.pj=function(e){Ise(this,e),this.a=u(Dn(this.b.a,4),126)},l.Qb=function(){f_(this),this.a=u(Dn(this.b.a,4),126)},F(Ra,"ArrayDelegatingEList/EListIterator",706),D(1039,341,sa,NJt),l.mj=function(){if(this.b.j!=this.f||Vt(u(Dn(this.b.a,4),126))!==Vt(this.a))throw it(new rh)},F(Ra,"ArrayDelegatingEList/NonResolvingEIterator",1039),D(707,385,n0,XKt,_Xt),l.mj=function(){if(this.b.j!=this.f||Vt(u(Dn(this.b.a,4),126))!==Vt(this.a))throw it(new rh)},F(Ra,"ArrayDelegatingEList/NonResolvingEListIterator",707),D(606,295,bot,nnt),F(Ra,"BasicEList/BasicIndexOutOfBoundsException",606),D(696,63,Ld,n2t),l.Vc=function(e,n){throw it(new Or)},l.Fc=function(e){throw it(new Or)},l.Wc=function(e,n){throw it(new Or)},l.Gc=function(e){throw it(new Or)},l.$b=function(){throw it(new Or)},l.qi=function(e){throw it(new Or)},l.Kc=function(){return this.Zh()},l.Yc=function(){return this.$h()},l.Zc=function(e){return this._h(e)},l.ii=function(e,n){throw it(new Or)},l.ji=function(e,n){throw it(new Or)},l.$c=function(e){throw it(new Or)},l.Mc=function(e){throw it(new Or)},l._c=function(e,n){throw it(new Or)},F(Ra,"BasicEList/UnmodifiableEList",696),D(705,1,{3:1,20:1,14:1,15:1,58:1,589:1}),l.Vc=function(e,n){CQe(this,e,u(n,42))},l.Fc=function(e){return hZe(this,u(e,42))},l.Jc=function(e){va(this,e)},l.Xb=function(e){return u(At(this.c,e),133)},l.ii=function(e,n){return u(this.c.ii(e,n),42)},l.ji=function(e,n){_Qe(this,e,u(n,42))},l.Lc=function(){return new Tn(null,new _n(this,16))},l.$c=function(e){return u(this.c.$c(e),42)},l._c=function(e,n){return mnn(this,e,u(n,42))},l.ad=function(e){r4(this,e)},l.Nc=function(){return new _n(this,16)},l.Oc=function(){return new Tn(null,new _n(this,16))},l.Wc=function(e,n){return this.c.Wc(e,n)},l.Gc=function(e){return this.c.Gc(e)},l.$b=function(){this.c.$b()},l.Hc=function(e){return this.c.Hc(e)},l.Ic=function(e){return ND(this.c,e)},l.qj=function(){var e,n,r;if(this.d==null){for(this.d=Nt(XAt,R8t,63,2*this.f+1,0,1),r=this.e,this.f=0,n=this.c.Kc();n.e!=n.i.gc();)e=u(n.nj(),133),Jz(this,e);this.e=r}},l.Fb=function(e){return xYt(this,e)},l.Hb=function(){return kyt(this.c)},l.Xc=function(e){return this.c.Xc(e)},l.rj=function(){this.c=new zzt(this)},l.dc=function(){return this.f==0},l.Kc=function(){return this.c.Kc()},l.Yc=function(){return this.c.Yc()},l.Zc=function(e){return this.c.Zc(e)},l.sj=function(){return wD(this)},l.tj=function(e,n,r){return new RYt(e,n,r)},l.uj=function(){return new kp},l.Mc=function(e){return tne(this,e)},l.gc=function(){return this.f},l.bd=function(e,n){return new Qd(this.c,e,n)},l.Pc=function(){return this.c.Pc()},l.Qc=function(e){return this.c.Qc(e)},l.Ib=function(){return g3t(this.c)},l.e=0,l.f=0,F(Ra,"BasicEMap",705),D(1033,63,Ld,zzt),l.bi=function(e,n){cKe(this,u(n,133))},l.ei=function(e,n,r){var s;++(s=this,u(n,133),s).a.e},l.fi=function(e,n){uKe(this,u(n,133))},l.gi=function(e,n,r){ZQe(this,u(n,133),u(r,133))},l.di=function(e,n){Vne(this.a)},F(Ra,"BasicEMap/1",1033),D(1034,63,Ld,kp),l.ri=function(e){return Nt(y6n,C0e,612,e,0,1)},F(Ra,"BasicEMap/2",1034),D(1035,N1,zu,qzt),l.$b=function(){this.a.c.$b()},l.Hc=function(e){return ist(this.a,e)},l.Kc=function(){return this.a.f==0?(y8(),pP.a):new EHt(this.a)},l.Mc=function(e){var n;return n=this.a.f,qz(this.a,e),this.a.f!=n},l.gc=function(){return this.a.f},F(Ra,"BasicEMap/3",1035),D(1036,28,xy,Hzt),l.$b=function(){this.a.c.$b()},l.Hc=function(e){return Aue(this.a,e)},l.Kc=function(){return this.a.f==0?(y8(),pP.a):new THt(this.a)},l.gc=function(){return this.a.f},F(Ra,"BasicEMap/4",1036),D(1037,N1,zu,Vzt),l.$b=function(){this.a.c.$b()},l.Hc=function(e){var n,r,s,o,h,d,v,k,C;if(this.a.f>0&&_t(e,42)&&(this.a.qj(),k=u(e,42),v=k.cd(),o=v==null?0:Hi(v),h=rwt(this.a,o),n=this.a.d[h],n)){for(r=u(n.g,367),C=n.i,d=0;d"+this.c},l.a=0;var y6n=F(Ra,"BasicEMap/EntryImpl",612);D(536,1,{},Ik),F(Ra,"BasicEMap/View",536);var pP;D(768,1,{}),l.Fb=function(e){return k5t((wn(),io),e)},l.Hb=function(){return Pyt((wn(),io))},l.Ib=function(){return eb((wn(),io))},F(Ra,"ECollections/BasicEmptyUnmodifiableEList",768),D(1312,1,n0,cB),l.Nb=function(e){ba(this,e)},l.Rb=function(e){throw it(new Or)},l.Ob=function(){return!1},l.Sb=function(){return!1},l.Pb=function(){throw it(new lc)},l.Tb=function(){return 0},l.Ub=function(){throw it(new lc)},l.Vb=function(){return-1},l.Qb=function(){throw it(new Or)},l.Wb=function(e){throw it(new Or)},F(Ra,"ECollections/BasicEmptyUnmodifiableEList/1",1312),D(1310,768,{20:1,14:1,15:1,58:1},Pqt),l.Vc=function(e,n){GHt()},l.Fc=function(e){return UHt()},l.Wc=function(e,n){return WHt()},l.Gc=function(e){return YHt()},l.$b=function(){KHt()},l.Hc=function(e){return!1},l.Ic=function(e){return!1},l.Jc=function(e){va(this,e)},l.Xb=function(e){return s2t((wn(),e)),null},l.Xc=function(e){return-1},l.dc=function(){return!0},l.Kc=function(){return this.a},l.Yc=function(){return this.a},l.Zc=function(e){return this.a},l.ii=function(e,n){return XHt()},l.ji=function(e,n){QHt()},l.Lc=function(){return new Tn(null,new _n(this,16))},l.$c=function(e){return ZHt()},l.Mc=function(e){return JHt()},l._c=function(e,n){return tVt()},l.gc=function(){return 0},l.ad=function(e){r4(this,e)},l.Nc=function(){return new _n(this,16)},l.Oc=function(){return new Tn(null,new _n(this,16))},l.bd=function(e,n){return wn(),new Qd(io,e,n)},l.Pc=function(){return svt((wn(),io))},l.Qc=function(e){return wn(),eI(io,e)},F(Ra,"ECollections/EmptyUnmodifiableEList",1310),D(1311,768,{20:1,14:1,15:1,58:1,589:1},Fqt),l.Vc=function(e,n){GHt()},l.Fc=function(e){return UHt()},l.Wc=function(e,n){return WHt()},l.Gc=function(e){return YHt()},l.$b=function(){KHt()},l.Hc=function(e){return!1},l.Ic=function(e){return!1},l.Jc=function(e){va(this,e)},l.Xb=function(e){return s2t((wn(),e)),null},l.Xc=function(e){return-1},l.dc=function(){return!0},l.Kc=function(){return this.a},l.Yc=function(){return this.a},l.Zc=function(e){return this.a},l.ii=function(e,n){return XHt()},l.ji=function(e,n){QHt()},l.Lc=function(){return new Tn(null,new _n(this,16))},l.$c=function(e){return ZHt()},l.Mc=function(e){return JHt()},l._c=function(e,n){return tVt()},l.gc=function(){return 0},l.ad=function(e){r4(this,e)},l.Nc=function(){return new _n(this,16)},l.Oc=function(){return new Tn(null,new _n(this,16))},l.bd=function(e,n){return wn(),new Qd(io,e,n)},l.Pc=function(){return svt((wn(),io))},l.Qc=function(e){return wn(),eI(io,e)},l.sj=function(){return wn(),wn(),u0},F(Ra,"ECollections/EmptyUnmodifiableEMap",1311);var ZAt=Ki(Ra,"Enumerator"),dU;D(281,1,{281:1},fat),l.Fb=function(e){var n;return this===e?!0:_t(e,281)?(n=u(e,281),this.f==n.f&&$en(this.i,n.i)&&jnt(this.a,this.f&256?n.f&256?n.a:null:n.f&256?null:n.a)&&jnt(this.d,n.d)&&jnt(this.g,n.g)&&jnt(this.e,n.e)&&Pfn(this,n)):!1},l.Hb=function(){return this.f},l.Ib=function(){return sle(this)},l.f=0;var r5e=0,i5e=0,s5e=0,a5e=0,JAt=0,tLt=0,eLt=0,nLt=0,rLt=0,o5e,oA=0,cA=0,c5e=0,u5e=0,gU,iLt;F(Ra,"URI",281),D(1091,43,A4,Nqt),l.zc=function(e,n){return u(ko(this,Br(e),u(n,281)),281)},F(Ra,"URI/URICache",1091),D(497,63,Ld,Ok,Gj),l.hi=function(){return!0},F(Ra,"UniqueEList",497),D(581,60,Q0,W$),F(Ra,"WrappedException",581);var Zr=Ki(ph,A0e),t3=Ki(ph,L0e),Mu=Ki(ph,M0e),e3=Ki(ph,D0e),s1=Ki(ph,I0e),Uh=Ki(ph,"EClass"),Nft=Ki(ph,"EDataType"),l5e;D(1183,43,A4,Bqt),l.xc=function(e){return ra(e)?Nc(this,e):ec(Lo(this.f,e))},F(ph,"EDataType/Internal/ConversionDelegate/Factory/Registry/Impl",1183);var pU=Ki(ph,"EEnum"),ag=Ki(ph,O0e),ho=Ki(ph,P0e),Wh=Ki(ph,F0e),Yh,Vv=Ki(ph,N0e),n3=Ki(ph,B0e);D(1029,1,{},nJ),l.Ib=function(){return"NIL"},F(ph,"EStructuralFeature/Internal/DynamicValueHolder/1",1029);var h5e;D(1028,43,A4,Rqt),l.xc=function(e){return ra(e)?Nc(this,e):ec(Lo(this.f,e))},F(ph,"EStructuralFeature/Internal/SettingDelegate/Factory/Registry/Impl",1028);var hu=Ki(ph,R0e),Z6=Ki(ph,"EValidator/PatternMatcher"),sLt,aLt,Ln,ap,r3,Lb,f5e,d5e,g5e,Mb,op,Db,Gv,W1,p5e,b5e,Kh,cp,w5e,up,i3,l5,Qa,v5e,m5e,Uv,bU=Ki($i,"FeatureMap/Entry");D(535,1,{72:1},lj),l.ak=function(){return this.a},l.dd=function(){return this.b},F(Mn,"BasicEObjectImpl/1",535),D(1027,1,hut,XGt),l.Wj=function(e){return Urt(this.a,this.b,e)},l.fj=function(){return MQt(this.a,this.b)},l.Wb=function(e){zvt(this.a,this.b,e)},l.Xj=function(){Nnn(this.a,this.b)},F(Mn,"BasicEObjectImpl/4",1027),D(1983,1,{108:1}),l.bk=function(e){this.e=e==0?y5e:Nt(Qn,De,1,e,5,1)},l.Ch=function(e){return this.e[e]},l.Dh=function(e,n){this.e[e]=n},l.Eh=function(e){this.e[e]=null},l.ck=function(){return this.c},l.dk=function(){throw it(new Or)},l.ek=function(){throw it(new Or)},l.fk=function(){return this.d},l.gk=function(){return this.e!=null},l.hk=function(e){this.c=e},l.ik=function(e){throw it(new Or)},l.jk=function(e){throw it(new Or)},l.kk=function(e){this.d=e};var y5e;F(Mn,"BasicEObjectImpl/EPropertiesHolderBaseImpl",1983),D(185,1983,{108:1},nh),l.dk=function(){return this.a},l.ek=function(){return this.b},l.ik=function(e){this.a=e},l.jk=function(e){this.b=e},F(Mn,"BasicEObjectImpl/EPropertiesHolderImpl",185),D(506,97,jde,Pk),l.Kg=function(){return this.f},l.Pg=function(){return this.k},l.Rg=function(e,n){this.g=e,this.i=n},l.Tg=function(){return this.j&2?this.ph().ck():this.zh()},l.Vg=function(){return this.i},l.Mg=function(){return(this.j&1)!=0},l.eh=function(){return this.g},l.kh=function(){return(this.j&4)!=0},l.ph=function(){return!this.k&&(this.k=new nh),this.k},l.th=function(e){this.ph().hk(e),e?this.j|=2:this.j&=-3},l.vh=function(e){this.ph().jk(e),e?this.j|=4:this.j&=-5},l.zh=function(){return(Hp(),Ln).S},l.i=0,l.j=1,F(Mn,"EObjectImpl",506),D(780,506,{105:1,92:1,90:1,56:1,108:1,49:1,97:1},zwt),l.Ch=function(e){return this.e[e]},l.Dh=function(e,n){this.e[e]=n},l.Eh=function(e){this.e[e]=null},l.Tg=function(){return this.d},l.Yg=function(e){return Gi(this.d,e)},l.$g=function(){return this.d},l.dh=function(){return this.e!=null},l.ph=function(){return!this.k&&(this.k=new uB),this.k},l.th=function(e){this.d=e},l.yh=function(){var e;return this.e==null&&(e=Jn(this.d),this.e=e==0?x5e:Nt(Qn,De,1,e,5,1)),this},l.Ah=function(){return 0};var x5e;F(Mn,"DynamicEObjectImpl",780),D(1376,780,{105:1,42:1,92:1,90:1,133:1,56:1,108:1,49:1,97:1},hKt),l.Fb=function(e){return this===e},l.Hb=function(){return Pw(this)},l.th=function(e){this.d=e,this.b=mI(e,"key"),this.c=mI(e,Z_)},l.Sh=function(){var e;return this.a==-1&&(e=iit(this,this.b),this.a=e==null?0:Hi(e)),this.a},l.cd=function(){return iit(this,this.b)},l.dd=function(){return iit(this,this.c)},l.Th=function(e){this.a=e},l.Uh=function(e){zvt(this,this.b,e)},l.ed=function(e){var n;return n=iit(this,this.c),zvt(this,this.c,e),n},l.a=0,F(Mn,"DynamicEObjectImpl/BasicEMapEntry",1376),D(1377,1,{108:1},uB),l.bk=function(e){throw it(new Or)},l.Ch=function(e){throw it(new Or)},l.Dh=function(e,n){throw it(new Or)},l.Eh=function(e){throw it(new Or)},l.ck=function(){throw it(new Or)},l.dk=function(){return this.a},l.ek=function(){return this.b},l.fk=function(){return this.c},l.gk=function(){throw it(new Or)},l.hk=function(e){throw it(new Or)},l.ik=function(e){this.a=e},l.jk=function(e){this.b=e},l.kk=function(e){this.c=e},F(Mn,"DynamicEObjectImpl/DynamicEPropertiesHolderImpl",1377),D(510,150,{105:1,92:1,90:1,590:1,147:1,56:1,108:1,49:1,97:1,510:1,150:1,114:1,115:1},lB),l.Qg=function(e){return a4t(this,e)},l._g=function(e,n,r){var s;switch(e){case 0:return!this.Ab&&(this.Ab=new fe(Zr,this,0,3)),this.Ab;case 1:return this.d;case 2:return r?(!this.b&&(this.b=new kl((dn(),Qa),cc,this)),this.b):(!this.b&&(this.b=new kl((dn(),Qa),cc,this)),wD(this.b));case 3:return FQt(this);case 4:return!this.a&&(this.a=new As(_b,this,4)),this.a;case 5:return!this.c&&(this.c=new Y3(_b,this,5)),this.c}return uh(this,e-Jn((dn(),ap)),yn((s=u(Dn(this,16),26),s||ap),e),n,r)},l.hh=function(e,n,r){var s,o,h;switch(n){case 0:return!this.Ab&&(this.Ab=new fe(Zr,this,0,3)),Zc(this.Ab,e,r);case 3:return this.Cb&&(r=(o=this.Db>>16,o>=0?a4t(this,r):this.Cb.ih(this,-1-o,null,r))),rvt(this,u(e,147),r)}return h=u(yn((s=u(Dn(this,16),26),s||(dn(),ap)),n),66),h.Nj().Qj(this,su(this),n-Jn((dn(),ap)),e,r)},l.jh=function(e,n,r){var s,o;switch(n){case 0:return!this.Ab&&(this.Ab=new fe(Zr,this,0,3)),Ba(this.Ab,e,r);case 2:return!this.b&&(this.b=new kl((dn(),Qa),cc,this)),Oj(this.b,e,r);case 3:return rvt(this,null,r);case 4:return!this.a&&(this.a=new As(_b,this,4)),Ba(this.a,e,r)}return o=u(yn((s=u(Dn(this,16),26),s||(dn(),ap)),n),66),o.Nj().Rj(this,su(this),n-Jn((dn(),ap)),e,r)},l.lh=function(e){var n;switch(e){case 0:return!!this.Ab&&this.Ab.i!=0;case 1:return this.d!=null;case 2:return!!this.b&&this.b.f!=0;case 3:return!!FQt(this);case 4:return!!this.a&&this.a.i!=0;case 5:return!!this.c&&this.c.i!=0}return oh(this,e-Jn((dn(),ap)),yn((n=u(Dn(this,16),26),n||ap),e))},l.sh=function(e,n){var r;switch(e){case 0:!this.Ab&&(this.Ab=new fe(Zr,this,0,3)),xr(this.Ab),!this.Ab&&(this.Ab=new fe(Zr,this,0,3)),is(this.Ab,u(n,14));return;case 1:Cen(this,Br(n));return;case 2:!this.b&&(this.b=new kl((dn(),Qa),cc,this)),xz(this.b,n);return;case 3:Kce(this,u(n,147));return;case 4:!this.a&&(this.a=new As(_b,this,4)),xr(this.a),!this.a&&(this.a=new As(_b,this,4)),is(this.a,u(n,14));return;case 5:!this.c&&(this.c=new Y3(_b,this,5)),xr(this.c),!this.c&&(this.c=new Y3(_b,this,5)),is(this.c,u(n,14));return}gh(this,e-Jn((dn(),ap)),yn((r=u(Dn(this,16),26),r||ap),e),n)},l.zh=function(){return dn(),ap},l.Bh=function(e){var n;switch(e){case 0:!this.Ab&&(this.Ab=new fe(Zr,this,0,3)),xr(this.Ab);return;case 1:oyt(this,null);return;case 2:!this.b&&(this.b=new kl((dn(),Qa),cc,this)),this.b.c.$b();return;case 3:Kce(this,null);return;case 4:!this.a&&(this.a=new As(_b,this,4)),xr(this.a);return;case 5:!this.c&&(this.c=new Y3(_b,this,5)),xr(this.c);return}fh(this,e-Jn((dn(),ap)),yn((n=u(Dn(this,16),26),n||ap),e))},l.Ib=function(){return lie(this)},l.d=null,F(Mn,"EAnnotationImpl",510),D(151,705,j8t,_l),l.Xh=function(e,n){oQe(this,e,u(n,42))},l.lk=function(e,n){return eJe(this,u(e,42),n)},l.pi=function(e){return u(u(this.c,69).pi(e),133)},l.Zh=function(){return u(this.c,69).Zh()},l.$h=function(){return u(this.c,69).$h()},l._h=function(e){return u(this.c,69)._h(e)},l.mk=function(e,n){return Oj(this,e,n)},l.Wj=function(e){return u(this.c,76).Wj(e)},l.rj=function(){},l.fj=function(){return u(this.c,76).fj()},l.tj=function(e,n,r){var s;return s=u(Rl(this.b).Nh().Jh(this.b),133),s.Th(e),s.Uh(n),s.ed(r),s},l.uj=function(){return new _pt(this)},l.Wb=function(e){xz(this,e)},l.Xj=function(){u(this.c,76).Xj()},F($i,"EcoreEMap",151),D(158,151,j8t,kl),l.qj=function(){var e,n,r,s,o,h;if(this.d==null){for(h=Nt(XAt,R8t,63,2*this.f+1,0,1),r=this.c.Kc();r.e!=r.i.gc();)n=u(r.nj(),133),s=n.Sh(),o=(s&wi)%h.length,e=h[o],!e&&(e=h[o]=new _pt(this)),e.Fc(n);this.d=h}},F(Mn,"EAnnotationImpl/1",158),D(284,438,{105:1,92:1,90:1,147:1,191:1,56:1,108:1,472:1,49:1,97:1,150:1,284:1,114:1,115:1}),l._g=function(e,n,r){var s,o;switch(e){case 0:return!this.Ab&&(this.Ab=new fe(Zr,this,0,3)),this.Ab;case 1:return this.zb;case 2:return Nn(),!!(this.Bb&256);case 3:return Nn(),!!(this.Bb&512);case 4:return pe(this.s);case 5:return pe(this.t);case 6:return Nn(),!!this.$j();case 7:return Nn(),o=this.s,o>=1;case 8:return n?Dh(this):this.r;case 9:return this.q}return uh(this,e-Jn(this.zh()),yn((s=u(Dn(this,16),26),s||this.zh()),e),n,r)},l.jh=function(e,n,r){var s,o;switch(n){case 0:return!this.Ab&&(this.Ab=new fe(Zr,this,0,3)),Ba(this.Ab,e,r);case 9:return nrt(this,r)}return o=u(yn((s=u(Dn(this,16),26),s||this.zh()),n),66),o.Nj().Rj(this,su(this),n-Jn(this.zh()),e,r)},l.lh=function(e){var n,r;switch(e){case 0:return!!this.Ab&&this.Ab.i!=0;case 1:return this.zb!=null;case 2:return(this.Bb&256)==0;case 3:return(this.Bb&512)==0;case 4:return this.s!=0;case 5:return this.t!=1;case 6:return this.$j();case 7:return r=this.s,r>=1;case 8:return!!this.r&&!this.q.e&&qw(this.q).i==0;case 9:return!!this.q&&!(this.r&&!this.q.e&&qw(this.q).i==0)}return oh(this,e-Jn(this.zh()),yn((n=u(Dn(this,16),26),n||this.zh()),e))},l.sh=function(e,n){var r,s;switch(e){case 0:!this.Ab&&(this.Ab=new fe(Zr,this,0,3)),xr(this.Ab),!this.Ab&&(this.Ab=new fe(Zr,this,0,3)),is(this.Ab,u(n,14));return;case 1:this.Lh(Br(n));return;case 2:zg(this,je(Re(n)));return;case 3:qg(this,je(Re(n)));return;case 4:Rg(this,u(n,19).a);return;case 5:this.ok(u(n,19).a);return;case 8:b2(this,u(n,138));return;case 9:s=F1(this,u(n,87),null),s&&s.Fi();return}gh(this,e-Jn(this.zh()),yn((r=u(Dn(this,16),26),r||this.zh()),e),n)},l.zh=function(){return dn(),m5e},l.Bh=function(e){var n,r;switch(e){case 0:!this.Ab&&(this.Ab=new fe(Zr,this,0,3)),xr(this.Ab);return;case 1:this.Lh(null);return;case 2:zg(this,!0);return;case 3:qg(this,!0);return;case 4:Rg(this,0);return;case 5:this.ok(1);return;case 8:b2(this,null);return;case 9:r=F1(this,null,null),r&&r.Fi();return}fh(this,e-Jn(this.zh()),yn((n=u(Dn(this,16),26),n||this.zh()),e))},l.Gh=function(){Dh(this),this.Bb|=1},l.Yj=function(){return Dh(this)},l.Zj=function(){return this.t},l.$j=function(){var e;return e=this.t,e>1||e==-1},l.hi=function(){return(this.Bb&512)!=0},l.nk=function(e,n){return e3t(this,e,n)},l.ok=function(e){ry(this,e)},l.Ib=function(){return f5t(this)},l.s=0,l.t=1,F(Mn,"ETypedElementImpl",284),D(449,284,{105:1,92:1,90:1,147:1,191:1,56:1,170:1,66:1,108:1,472:1,49:1,97:1,150:1,449:1,284:1,114:1,115:1,677:1}),l.Qg=function(e){return Use(this,e)},l._g=function(e,n,r){var s,o;switch(e){case 0:return!this.Ab&&(this.Ab=new fe(Zr,this,0,3)),this.Ab;case 1:return this.zb;case 2:return Nn(),!!(this.Bb&256);case 3:return Nn(),!!(this.Bb&512);case 4:return pe(this.s);case 5:return pe(this.t);case 6:return Nn(),!!this.$j();case 7:return Nn(),o=this.s,o>=1;case 8:return n?Dh(this):this.r;case 9:return this.q;case 10:return Nn(),!!(this.Bb&xf);case 11:return Nn(),!!(this.Bb&Dy);case 12:return Nn(),!!(this.Bb&Ey);case 13:return this.j;case 14:return SE(this);case 15:return Nn(),!!(this.Bb&Hu);case 16:return Nn(),!!(this.Bb&md);case 17:return Ym(this)}return uh(this,e-Jn(this.zh()),yn((s=u(Dn(this,16),26),s||this.zh()),e),n,r)},l.hh=function(e,n,r){var s,o,h;switch(n){case 0:return!this.Ab&&(this.Ab=new fe(Zr,this,0,3)),Zc(this.Ab,e,r);case 17:return this.Cb&&(r=(o=this.Db>>16,o>=0?Use(this,r):this.Cb.ih(this,-1-o,null,r))),Hl(this,e,17,r)}return h=u(yn((s=u(Dn(this,16),26),s||this.zh()),n),66),h.Nj().Qj(this,su(this),n-Jn(this.zh()),e,r)},l.jh=function(e,n,r){var s,o;switch(n){case 0:return!this.Ab&&(this.Ab=new fe(Zr,this,0,3)),Ba(this.Ab,e,r);case 9:return nrt(this,r);case 17:return Hl(this,null,17,r)}return o=u(yn((s=u(Dn(this,16),26),s||this.zh()),n),66),o.Nj().Rj(this,su(this),n-Jn(this.zh()),e,r)},l.lh=function(e){var n,r;switch(e){case 0:return!!this.Ab&&this.Ab.i!=0;case 1:return this.zb!=null;case 2:return(this.Bb&256)==0;case 3:return(this.Bb&512)==0;case 4:return this.s!=0;case 5:return this.t!=1;case 6:return this.$j();case 7:return r=this.s,r>=1;case 8:return!!this.r&&!this.q.e&&qw(this.q).i==0;case 9:return!!this.q&&!(this.r&&!this.q.e&&qw(this.q).i==0);case 10:return(this.Bb&xf)==0;case 11:return(this.Bb&Dy)!=0;case 12:return(this.Bb&Ey)!=0;case 13:return this.j!=null;case 14:return SE(this)!=null;case 15:return(this.Bb&Hu)!=0;case 16:return(this.Bb&md)!=0;case 17:return!!Ym(this)}return oh(this,e-Jn(this.zh()),yn((n=u(Dn(this,16),26),n||this.zh()),e))},l.sh=function(e,n){var r,s;switch(e){case 0:!this.Ab&&(this.Ab=new fe(Zr,this,0,3)),xr(this.Ab),!this.Ab&&(this.Ab=new fe(Zr,this,0,3)),is(this.Ab,u(n,14));return;case 1:Mrt(this,Br(n));return;case 2:zg(this,je(Re(n)));return;case 3:qg(this,je(Re(n)));return;case 4:Rg(this,u(n,19).a);return;case 5:this.ok(u(n,19).a);return;case 8:b2(this,u(n,138));return;case 9:s=F1(this,u(n,87),null),s&&s.Fi();return;case 10:lE(this,je(Re(n)));return;case 11:dE(this,je(Re(n)));return;case 12:hE(this,je(Re(n)));return;case 13:r2t(this,Br(n));return;case 15:fE(this,je(Re(n)));return;case 16:gE(this,je(Re(n)));return}gh(this,e-Jn(this.zh()),yn((r=u(Dn(this,16),26),r||this.zh()),e),n)},l.zh=function(){return dn(),v5e},l.Bh=function(e){var n,r;switch(e){case 0:!this.Ab&&(this.Ab=new fe(Zr,this,0,3)),xr(this.Ab);return;case 1:_t(this.Cb,88)&&gy(sl(u(this.Cb,88)),4),Qc(this,null);return;case 2:zg(this,!0);return;case 3:qg(this,!0);return;case 4:Rg(this,0);return;case 5:this.ok(1);return;case 8:b2(this,null);return;case 9:r=F1(this,null,null),r&&r.Fi();return;case 10:lE(this,!0);return;case 11:dE(this,!1);return;case 12:hE(this,!1);return;case 13:this.i=null,fz(this,null);return;case 15:fE(this,!1);return;case 16:gE(this,!1);return}fh(this,e-Jn(this.zh()),yn((n=u(Dn(this,16),26),n||this.zh()),e))},l.Gh=function(){M8(To(($u(),ya),this)),Dh(this),this.Bb|=1},l.Gj=function(){return this.f},l.zj=function(){return SE(this)},l.Hj=function(){return Ym(this)},l.Lj=function(){return null},l.pk=function(){return this.k},l.aj=function(){return this.n},l.Mj=function(){return cq(this)},l.Nj=function(){var e,n,r,s,o,h,d,v,k;return this.p||(r=Ym(this),(r.i==null&&vd(r),r.i).length,s=this.Lj(),s&&Jn(Ym(s)),o=Dh(this),d=o.Bj(),e=d?d.i&1?d==pl?Rs:d==Cr?ja:d==a3?i7:d==aa?la:d==Ob?Sv:d==g5?Av:d==Gu?M6:uS:d:null,n=SE(this),v=o.zj(),shn(this),this.Bb&md&&((h=d4t(($u(),ya),r))&&h!=this||(h=Kx(To(ya,this))))?this.p=new ZGt(this,h):this.$j()?this.rk()?s?this.Bb&Hu?e?this.sk()?this.p=new n2(47,e,this,s):this.p=new n2(5,e,this,s):this.sk()?this.p=new s2(46,this,s):this.p=new s2(4,this,s):e?this.sk()?this.p=new n2(49,e,this,s):this.p=new n2(7,e,this,s):this.sk()?this.p=new s2(48,this,s):this.p=new s2(6,this,s):this.Bb&Hu?e?e==P2?this.p=new Ig(50,t5e,this):this.sk()?this.p=new Ig(43,e,this):this.p=new Ig(1,e,this):this.sk()?this.p=new Pg(42,this):this.p=new Pg(0,this):e?e==P2?this.p=new Ig(41,t5e,this):this.sk()?this.p=new Ig(45,e,this):this.p=new Ig(3,e,this):this.sk()?this.p=new Pg(44,this):this.p=new Pg(2,this):_t(o,148)?e==bU?this.p=new Pg(40,this):this.Bb&512?this.Bb&Hu?e?this.p=new Ig(9,e,this):this.p=new Pg(8,this):e?this.p=new Ig(11,e,this):this.p=new Pg(10,this):this.Bb&Hu?e?this.p=new Ig(13,e,this):this.p=new Pg(12,this):e?this.p=new Ig(15,e,this):this.p=new Pg(14,this):s?(k=s.t,k>1||k==-1?this.sk()?this.Bb&Hu?e?this.p=new n2(25,e,this,s):this.p=new s2(24,this,s):e?this.p=new n2(27,e,this,s):this.p=new s2(26,this,s):this.Bb&Hu?e?this.p=new n2(29,e,this,s):this.p=new s2(28,this,s):e?this.p=new n2(31,e,this,s):this.p=new s2(30,this,s):this.sk()?this.Bb&Hu?e?this.p=new n2(33,e,this,s):this.p=new s2(32,this,s):e?this.p=new n2(35,e,this,s):this.p=new s2(34,this,s):this.Bb&Hu?e?this.p=new n2(37,e,this,s):this.p=new s2(36,this,s):e?this.p=new n2(39,e,this,s):this.p=new s2(38,this,s)):this.sk()?this.Bb&Hu?e?this.p=new Ig(17,e,this):this.p=new Pg(16,this):e?this.p=new Ig(19,e,this):this.p=new Pg(18,this):this.Bb&Hu?e?this.p=new Ig(21,e,this):this.p=new Pg(20,this):e?this.p=new Ig(23,e,this):this.p=new Pg(22,this):this.qk()?this.sk()?this.p=new jYt(u(o,26),this,s):this.p=new $vt(u(o,26),this,s):_t(o,148)?e==bU?this.p=new Pg(40,this):this.Bb&Hu?e?this.p=new BKt(n,v,this,(rst(),d==Cr?dLt:d==pl?cLt:d==Ob?gLt:d==a3?fLt:d==aa?hLt:d==g5?pLt:d==Gu?uLt:d==xh?lLt:jft)):this.p=new KXt(u(o,148),n,v,this):e?this.p=new NKt(n,v,this,(rst(),d==Cr?dLt:d==pl?cLt:d==Ob?gLt:d==a3?fLt:d==aa?hLt:d==g5?pLt:d==Gu?uLt:d==xh?lLt:jft)):this.p=new YXt(u(o,148),n,v,this):this.rk()?s?this.Bb&Hu?this.sk()?this.p=new zYt(u(o,26),this,s):this.p=new Dwt(u(o,26),this,s):this.sk()?this.p=new $Yt(u(o,26),this,s):this.p=new Int(u(o,26),this,s):this.Bb&Hu?this.sk()?this.p=new NWt(u(o,26),this):this.p=new G2t(u(o,26),this):this.sk()?this.p=new FWt(u(o,26),this):this.p=new vnt(u(o,26),this):this.sk()?s?this.Bb&Hu?this.p=new qYt(u(o,26),this,s):this.p=new Lwt(u(o,26),this,s):this.Bb&Hu?this.p=new BWt(u(o,26),this):this.p=new U2t(u(o,26),this):s?this.Bb&Hu?this.p=new HYt(u(o,26),this,s):this.p=new Mwt(u(o,26),this,s):this.Bb&Hu?this.p=new RWt(u(o,26),this):this.p=new Uj(u(o,26),this)),this.p},l.Ij=function(){return(this.Bb&xf)!=0},l.qk=function(){return!1},l.rk=function(){return!1},l.Jj=function(){return(this.Bb&md)!=0},l.Oj=function(){return ait(this)},l.sk=function(){return!1},l.Kj=function(){return(this.Bb&Hu)!=0},l.tk=function(e){this.k=e},l.Lh=function(e){Mrt(this,e)},l.Ib=function(){return _q(this)},l.e=!1,l.n=0,F(Mn,"EStructuralFeatureImpl",449),D(322,449,{105:1,92:1,90:1,34:1,147:1,191:1,56:1,170:1,66:1,108:1,472:1,49:1,97:1,322:1,150:1,449:1,284:1,114:1,115:1,677:1},ret),l._g=function(e,n,r){var s,o;switch(e){case 0:return!this.Ab&&(this.Ab=new fe(Zr,this,0,3)),this.Ab;case 1:return this.zb;case 2:return Nn(),!!(this.Bb&256);case 3:return Nn(),!!(this.Bb&512);case 4:return pe(this.s);case 5:return pe(this.t);case 6:return Nn(),!!c5t(this);case 7:return Nn(),o=this.s,o>=1;case 8:return n?Dh(this):this.r;case 9:return this.q;case 10:return Nn(),!!(this.Bb&xf);case 11:return Nn(),!!(this.Bb&Dy);case 12:return Nn(),!!(this.Bb&Ey);case 13:return this.j;case 14:return SE(this);case 15:return Nn(),!!(this.Bb&Hu);case 16:return Nn(),!!(this.Bb&md);case 17:return Ym(this);case 18:return Nn(),!!(this.Bb&dc);case 19:return n?Tit(this):KJt(this)}return uh(this,e-Jn((dn(),r3)),yn((s=u(Dn(this,16),26),s||r3),e),n,r)},l.lh=function(e){var n,r;switch(e){case 0:return!!this.Ab&&this.Ab.i!=0;case 1:return this.zb!=null;case 2:return(this.Bb&256)==0;case 3:return(this.Bb&512)==0;case 4:return this.s!=0;case 5:return this.t!=1;case 6:return c5t(this);case 7:return r=this.s,r>=1;case 8:return!!this.r&&!this.q.e&&qw(this.q).i==0;case 9:return!!this.q&&!(this.r&&!this.q.e&&qw(this.q).i==0);case 10:return(this.Bb&xf)==0;case 11:return(this.Bb&Dy)!=0;case 12:return(this.Bb&Ey)!=0;case 13:return this.j!=null;case 14:return SE(this)!=null;case 15:return(this.Bb&Hu)!=0;case 16:return(this.Bb&md)!=0;case 17:return!!Ym(this);case 18:return(this.Bb&dc)!=0;case 19:return!!KJt(this)}return oh(this,e-Jn((dn(),r3)),yn((n=u(Dn(this,16),26),n||r3),e))},l.sh=function(e,n){var r,s;switch(e){case 0:!this.Ab&&(this.Ab=new fe(Zr,this,0,3)),xr(this.Ab),!this.Ab&&(this.Ab=new fe(Zr,this,0,3)),is(this.Ab,u(n,14));return;case 1:Mrt(this,Br(n));return;case 2:zg(this,je(Re(n)));return;case 3:qg(this,je(Re(n)));return;case 4:Rg(this,u(n,19).a);return;case 5:SHt(this,u(n,19).a);return;case 8:b2(this,u(n,138));return;case 9:s=F1(this,u(n,87),null),s&&s.Fi();return;case 10:lE(this,je(Re(n)));return;case 11:dE(this,je(Re(n)));return;case 12:hE(this,je(Re(n)));return;case 13:r2t(this,Br(n));return;case 15:fE(this,je(Re(n)));return;case 16:gE(this,je(Re(n)));return;case 18:Kit(this,je(Re(n)));return}gh(this,e-Jn((dn(),r3)),yn((r=u(Dn(this,16),26),r||r3),e),n)},l.zh=function(){return dn(),r3},l.Bh=function(e){var n,r;switch(e){case 0:!this.Ab&&(this.Ab=new fe(Zr,this,0,3)),xr(this.Ab);return;case 1:_t(this.Cb,88)&&gy(sl(u(this.Cb,88)),4),Qc(this,null);return;case 2:zg(this,!0);return;case 3:qg(this,!0);return;case 4:Rg(this,0);return;case 5:this.b=0,ry(this,1);return;case 8:b2(this,null);return;case 9:r=F1(this,null,null),r&&r.Fi();return;case 10:lE(this,!0);return;case 11:dE(this,!1);return;case 12:hE(this,!1);return;case 13:this.i=null,fz(this,null);return;case 15:fE(this,!1);return;case 16:gE(this,!1);return;case 18:Kit(this,!1);return}fh(this,e-Jn((dn(),r3)),yn((n=u(Dn(this,16),26),n||r3),e))},l.Gh=function(){Tit(this),M8(To(($u(),ya),this)),Dh(this),this.Bb|=1},l.$j=function(){return c5t(this)},l.nk=function(e,n){return this.b=0,this.a=null,e3t(this,e,n)},l.ok=function(e){SHt(this,e)},l.Ib=function(){var e;return this.Db&64?_q(this):(e=new _h(_q(this)),e.a+=" (iD: ",Lg(e,(this.Bb&dc)!=0),e.a+=")",e.a)},l.b=0,F(Mn,"EAttributeImpl",322),D(351,438,{105:1,92:1,90:1,138:1,147:1,191:1,56:1,108:1,49:1,97:1,351:1,150:1,114:1,115:1,676:1}),l.uk=function(e){return e.Tg()==this},l.Qg=function(e){return Lst(this,e)},l.Rg=function(e,n){this.w=null,this.Db=n<<16|this.Db&255,this.Cb=e},l._g=function(e,n,r){var s;switch(e){case 0:return!this.Ab&&(this.Ab=new fe(Zr,this,0,3)),this.Ab;case 1:return this.zb;case 2:return this.D!=null?this.D:this.B;case 3:return hv(this);case 4:return this.zj();case 5:return this.F;case 6:return n?Rl(this):O8(this);case 7:return!this.A&&(this.A=new Fu(hu,this,7)),this.A}return uh(this,e-Jn(this.zh()),yn((s=u(Dn(this,16),26),s||this.zh()),e),n,r)},l.hh=function(e,n,r){var s,o,h;switch(n){case 0:return!this.Ab&&(this.Ab=new fe(Zr,this,0,3)),Zc(this.Ab,e,r);case 6:return this.Cb&&(r=(o=this.Db>>16,o>=0?Lst(this,r):this.Cb.ih(this,-1-o,null,r))),Hl(this,e,6,r)}return h=u(yn((s=u(Dn(this,16),26),s||this.zh()),n),66),h.Nj().Qj(this,su(this),n-Jn(this.zh()),e,r)},l.jh=function(e,n,r){var s,o;switch(n){case 0:return!this.Ab&&(this.Ab=new fe(Zr,this,0,3)),Ba(this.Ab,e,r);case 6:return Hl(this,null,6,r);case 7:return!this.A&&(this.A=new Fu(hu,this,7)),Ba(this.A,e,r)}return o=u(yn((s=u(Dn(this,16),26),s||this.zh()),n),66),o.Nj().Rj(this,su(this),n-Jn(this.zh()),e,r)},l.lh=function(e){var n;switch(e){case 0:return!!this.Ab&&this.Ab.i!=0;case 1:return this.zb!=null;case 2:return this.D!=null&&this.D==this.F;case 3:return!!hv(this);case 4:return this.zj()!=null;case 5:return this.F!=null&&this.F!=this.D&&this.F!=this.B;case 6:return!!O8(this);case 7:return!!this.A&&this.A.i!=0}return oh(this,e-Jn(this.zh()),yn((n=u(Dn(this,16),26),n||this.zh()),e))},l.sh=function(e,n){var r;switch(e){case 0:!this.Ab&&(this.Ab=new fe(Zr,this,0,3)),xr(this.Ab),!this.Ab&&(this.Ab=new fe(Zr,this,0,3)),is(this.Ab,u(n,14));return;case 1:_$(this,Br(n));return;case 2:snt(this,Br(n));return;case 5:OE(this,Br(n));return;case 7:!this.A&&(this.A=new Fu(hu,this,7)),xr(this.A),!this.A&&(this.A=new Fu(hu,this,7)),is(this.A,u(n,14));return}gh(this,e-Jn(this.zh()),yn((r=u(Dn(this,16),26),r||this.zh()),e),n)},l.zh=function(){return dn(),f5e},l.Bh=function(e){var n;switch(e){case 0:!this.Ab&&(this.Ab=new fe(Zr,this,0,3)),xr(this.Ab);return;case 1:_t(this.Cb,179)&&(u(this.Cb,179).tb=null),Qc(this,null);return;case 2:aE(this,null),Y8(this,this.D);return;case 5:OE(this,null);return;case 7:!this.A&&(this.A=new Fu(hu,this,7)),xr(this.A);return}fh(this,e-Jn(this.zh()),yn((n=u(Dn(this,16),26),n||this.zh()),e))},l.yj=function(){var e;return this.G==-1&&(this.G=(e=Rl(this),e?Hg(e.Mh(),this):-1)),this.G},l.zj=function(){return null},l.Aj=function(){return Rl(this)},l.vk=function(){return this.v},l.Bj=function(){return hv(this)},l.Cj=function(){return this.D!=null?this.D:this.B},l.Dj=function(){return this.F},l.wj=function(e){return xat(this,e)},l.wk=function(e){this.v=e},l.xk=function(e){Cne(this,e)},l.yk=function(e){this.C=e},l.Lh=function(e){_$(this,e)},l.Ib=function(){return Rz(this)},l.C=null,l.D=null,l.G=-1,F(Mn,"EClassifierImpl",351),D(88,351,{105:1,92:1,90:1,26:1,138:1,147:1,191:1,56:1,108:1,49:1,97:1,88:1,351:1,150:1,473:1,114:1,115:1,676:1},eM),l.uk=function(e){return zZe(this,e.Tg())},l._g=function(e,n,r){var s;switch(e){case 0:return!this.Ab&&(this.Ab=new fe(Zr,this,0,3)),this.Ab;case 1:return this.zb;case 2:return this.D!=null?this.D:this.B;case 3:return hv(this);case 4:return null;case 5:return this.F;case 6:return n?Rl(this):O8(this);case 7:return!this.A&&(this.A=new Fu(hu,this,7)),this.A;case 8:return Nn(),!!(this.Bb&256);case 9:return Nn(),!!(this.Bb&512);case 10:return Ao(this);case 11:return!this.q&&(this.q=new fe(Wh,this,11,10)),this.q;case 12:return T4(this);case 13:return C_(this);case 14:return C_(this),this.r;case 15:return T4(this),this.k;case 16:return Z4t(this);case 17:return _at(this);case 18:return vd(this);case 19:return mq(this);case 20:return T4(this),this.o;case 21:return!this.s&&(this.s=new fe(Mu,this,21,17)),this.s;case 22:return Lc(this);case 23:return hat(this)}return uh(this,e-Jn((dn(),Lb)),yn((s=u(Dn(this,16),26),s||Lb),e),n,r)},l.hh=function(e,n,r){var s,o,h;switch(n){case 0:return!this.Ab&&(this.Ab=new fe(Zr,this,0,3)),Zc(this.Ab,e,r);case 6:return this.Cb&&(r=(o=this.Db>>16,o>=0?Lst(this,r):this.Cb.ih(this,-1-o,null,r))),Hl(this,e,6,r);case 11:return!this.q&&(this.q=new fe(Wh,this,11,10)),Zc(this.q,e,r);case 21:return!this.s&&(this.s=new fe(Mu,this,21,17)),Zc(this.s,e,r)}return h=u(yn((s=u(Dn(this,16),26),s||(dn(),Lb)),n),66),h.Nj().Qj(this,su(this),n-Jn((dn(),Lb)),e,r)},l.jh=function(e,n,r){var s,o;switch(n){case 0:return!this.Ab&&(this.Ab=new fe(Zr,this,0,3)),Ba(this.Ab,e,r);case 6:return Hl(this,null,6,r);case 7:return!this.A&&(this.A=new Fu(hu,this,7)),Ba(this.A,e,r);case 11:return!this.q&&(this.q=new fe(Wh,this,11,10)),Ba(this.q,e,r);case 21:return!this.s&&(this.s=new fe(Mu,this,21,17)),Ba(this.s,e,r);case 22:return Ba(Lc(this),e,r)}return o=u(yn((s=u(Dn(this,16),26),s||(dn(),Lb)),n),66),o.Nj().Rj(this,su(this),n-Jn((dn(),Lb)),e,r)},l.lh=function(e){var n;switch(e){case 0:return!!this.Ab&&this.Ab.i!=0;case 1:return this.zb!=null;case 2:return this.D!=null&&this.D==this.F;case 3:return!!hv(this);case 4:return!1;case 5:return this.F!=null&&this.F!=this.D&&this.F!=this.B;case 6:return!!O8(this);case 7:return!!this.A&&this.A.i!=0;case 8:return(this.Bb&256)!=0;case 9:return(this.Bb&512)!=0;case 10:return!!this.u&&Lc(this.u.a).i!=0&&!(this.n&&vst(this.n));case 11:return!!this.q&&this.q.i!=0;case 12:return T4(this).i!=0;case 13:return C_(this).i!=0;case 14:return C_(this),this.r.i!=0;case 15:return T4(this),this.k.i!=0;case 16:return Z4t(this).i!=0;case 17:return _at(this).i!=0;case 18:return vd(this).i!=0;case 19:return mq(this).i!=0;case 20:return T4(this),!!this.o;case 21:return!!this.s&&this.s.i!=0;case 22:return!!this.n&&vst(this.n);case 23:return hat(this).i!=0}return oh(this,e-Jn((dn(),Lb)),yn((n=u(Dn(this,16),26),n||Lb),e))},l.oh=function(e){var n;return n=this.i==null||this.q&&this.q.i!=0?null:mI(this,e),n||Lxt(this,e)},l.sh=function(e,n){var r;switch(e){case 0:!this.Ab&&(this.Ab=new fe(Zr,this,0,3)),xr(this.Ab),!this.Ab&&(this.Ab=new fe(Zr,this,0,3)),is(this.Ab,u(n,14));return;case 1:_$(this,Br(n));return;case 2:snt(this,Br(n));return;case 5:OE(this,Br(n));return;case 7:!this.A&&(this.A=new Fu(hu,this,7)),xr(this.A),!this.A&&(this.A=new Fu(hu,this,7)),is(this.A,u(n,14));return;case 8:r3t(this,je(Re(n)));return;case 9:i3t(this,je(Re(n)));return;case 10:A_(Ao(this)),is(Ao(this),u(n,14));return;case 11:!this.q&&(this.q=new fe(Wh,this,11,10)),xr(this.q),!this.q&&(this.q=new fe(Wh,this,11,10)),is(this.q,u(n,14));return;case 21:!this.s&&(this.s=new fe(Mu,this,21,17)),xr(this.s),!this.s&&(this.s=new fe(Mu,this,21,17)),is(this.s,u(n,14));return;case 22:xr(Lc(this)),is(Lc(this),u(n,14));return}gh(this,e-Jn((dn(),Lb)),yn((r=u(Dn(this,16),26),r||Lb),e),n)},l.zh=function(){return dn(),Lb},l.Bh=function(e){var n;switch(e){case 0:!this.Ab&&(this.Ab=new fe(Zr,this,0,3)),xr(this.Ab);return;case 1:_t(this.Cb,179)&&(u(this.Cb,179).tb=null),Qc(this,null);return;case 2:aE(this,null),Y8(this,this.D);return;case 5:OE(this,null);return;case 7:!this.A&&(this.A=new Fu(hu,this,7)),xr(this.A);return;case 8:r3t(this,!1);return;case 9:i3t(this,!1);return;case 10:this.u&&A_(this.u);return;case 11:!this.q&&(this.q=new fe(Wh,this,11,10)),xr(this.q);return;case 21:!this.s&&(this.s=new fe(Mu,this,21,17)),xr(this.s);return;case 22:this.n&&xr(this.n);return}fh(this,e-Jn((dn(),Lb)),yn((n=u(Dn(this,16),26),n||Lb),e))},l.Gh=function(){var e,n;if(T4(this),C_(this),Z4t(this),_at(this),vd(this),mq(this),hat(this),z9(ien(sl(this))),this.s)for(e=0,n=this.s.i;e=0;--n)At(this,n);return _3t(this,e)},l.Xj=function(){xr(this)},l.oi=function(e,n){return Yee(this,e,n)},F($i,"EcoreEList",622),D(496,622,zo,ZM),l.ai=function(){return!1},l.aj=function(){return this.c},l.bj=function(){return!1},l.Fk=function(){return!0},l.hi=function(){return!0},l.li=function(e,n){return n},l.ni=function(){return!1},l.c=0,F($i,"EObjectEList",496),D(85,496,zo,As),l.bj=function(){return!0},l.Dk=function(){return!1},l.rk=function(){return!0},F($i,"EObjectContainmentEList",85),D(545,85,zo,kj),l.ci=function(){this.b=!0},l.fj=function(){return this.b},l.Xj=function(){var e;xr(this),xl(this.e)?(e=this.b,this.b=!1,mi(this.e,new bf(this.e,2,this.c,e,!1))):this.b=!1},l.b=!1,F($i,"EObjectContainmentEList/Unsettable",545),D(1140,545,zo,PKt),l.ii=function(e,n){var r,s;return r=u(r_(this,e,n),87),xl(this.e)&&n8(this,new mD(this.a,7,(dn(),d5e),pe(n),(s=r.c,_t(s,88)?u(s,26):Kh),e)),r},l.jj=function(e,n){return Uhn(this,u(e,87),n)},l.kj=function(e,n){return Ghn(this,u(e,87),n)},l.lj=function(e,n,r){return Wdn(this,u(e,87),u(n,87),r)},l.Zi=function(e,n,r,s,o){switch(e){case 3:return F9(this,e,n,r,s,this.i>1);case 5:return F9(this,e,n,r,s,this.i-u(r,15).gc()>0);default:return new z0(this.e,e,this.c,n,r,s,!0)}},l.ij=function(){return!0},l.fj=function(){return vst(this)},l.Xj=function(){xr(this)},F(Mn,"EClassImpl/1",1140),D(1154,1153,B8t),l.ui=function(e){var n,r,s,o,h,d,v;if(r=e.xi(),r!=8){if(s=Lfn(e),s==0)switch(r){case 1:case 9:{v=e.Bi(),v!=null&&(n=sl(u(v,473)),!n.c&&(n.c=new Tm),X$(n.c,e.Ai())),d=e.zi(),d!=null&&(o=u(d,473),o.Bb&1||(n=sl(o),!n.c&&(n.c=new Tm),Dr(n.c,u(e.Ai(),26))));break}case 3:{d=e.zi(),d!=null&&(o=u(d,473),o.Bb&1||(n=sl(o),!n.c&&(n.c=new Tm),Dr(n.c,u(e.Ai(),26))));break}case 5:{if(d=e.zi(),d!=null)for(h=u(d,14).Kc();h.Ob();)o=u(h.Pb(),473),o.Bb&1||(n=sl(o),!n.c&&(n.c=new Tm),Dr(n.c,u(e.Ai(),26)));break}case 4:{v=e.Bi(),v!=null&&(o=u(v,473),o.Bb&1||(n=sl(o),!n.c&&(n.c=new Tm),X$(n.c,e.Ai())));break}case 6:{if(v=e.Bi(),v!=null)for(h=u(v,14).Kc();h.Ob();)o=u(h.Pb(),473),o.Bb&1||(n=sl(o),!n.c&&(n.c=new Tm),X$(n.c,e.Ai()));break}}this.Hk(s)}},l.Hk=function(e){Oue(this,e)},l.b=63,F(Mn,"ESuperAdapter",1154),D(1155,1154,B8t,Uzt),l.Hk=function(e){gy(this,e)},F(Mn,"EClassImpl/10",1155),D(1144,696,zo),l.Vh=function(e,n){return $st(this,e,n)},l.Wh=function(e){return Lse(this,e)},l.Xh=function(e,n){UD(this,e,n)},l.Yh=function(e){gD(this,e)},l.pi=function(e){return Fmt(this,e)},l.mi=function(e,n){return sit(this,e,n)},l.lk=function(e,n){throw it(new Or)},l.Zh=function(){return new Bx(this)},l.$h=function(){return new $M(this)},l._h=function(e){return DD(this,e)},l.mk=function(e,n){throw it(new Or)},l.Wj=function(e){return this},l.fj=function(){return this.i!=0},l.Wb=function(e){throw it(new Or)},l.Xj=function(){throw it(new Or)},F($i,"EcoreEList/UnmodifiableEList",1144),D(319,1144,zo,V3),l.ni=function(){return!1},F($i,"EcoreEList/UnmodifiableEList/FastCompare",319),D(1147,319,zo,wre),l.Xc=function(e){var n,r,s;if(_t(e,170)&&(n=u(e,170),r=n.aj(),r!=-1)){for(s=this.i;r4)if(this.wj(e)){if(this.rk()){if(s=u(e,49),r=s.Ug(),v=r==this.b&&(this.Dk()?s.Og(s.Vg(),u(yn(vu(this.b),this.aj()).Yj(),26).Bj())==no(u(yn(vu(this.b),this.aj()),18)).n:-1-s.Vg()==this.aj()),this.Ek()&&!v&&!r&&s.Zg()){for(o=0;o1||s==-1)):!1},l.Dk=function(){var e,n,r;return n=yn(vu(this.b),this.aj()),_t(n,99)?(e=u(n,18),r=no(e),!!r):!1},l.Ek=function(){var e,n;return n=yn(vu(this.b),this.aj()),_t(n,99)?(e=u(n,18),(e.Bb&Ka)!=0):!1},l.Xc=function(e){var n,r,s,o;if(s=this.Qi(e),s>=0)return s;if(this.Fk()){for(r=0,o=this.Vi();r=0;--e)AI(this,e,this.Oi(e));return this.Wi()},l.Qc=function(e){var n;if(this.Ek())for(n=this.Vi()-1;n>=0;--n)AI(this,n,this.Oi(n));return this.Xi(e)},l.Xj=function(){A_(this)},l.oi=function(e,n){return Ite(this,e,n)},F($i,"DelegatingEcoreEList",742),D(1150,742,z8t,KWt),l.Hi=function(e,n){pZe(this,e,u(n,26))},l.Ii=function(e){uQe(this,u(e,26))},l.Oi=function(e){var n,r;return n=u(At(Lc(this.a),e),87),r=n.c,_t(r,88)?u(r,26):(dn(),Kh)},l.Ti=function(e){var n,r;return n=u(by(Lc(this.a),e),87),r=n.c,_t(r,88)?u(r,26):(dn(),Kh)},l.Ui=function(e,n){return b1n(this,e,u(n,26))},l.ai=function(){return!1},l.Zi=function(e,n,r,s,o){return null},l.Ji=function(){return new Yzt(this)},l.Ki=function(){xr(Lc(this.a))},l.Li=function(e){return cie(this,e)},l.Mi=function(e){var n,r;for(r=e.Kc();r.Ob();)if(n=r.Pb(),!cie(this,n))return!1;return!0},l.Ni=function(e){var n,r,s;if(_t(e,15)&&(s=u(e,15),s.gc()==Lc(this.a).i)){for(n=s.Kc(),r=new nr(this);n.Ob();)if(Vt(n.Pb())!==Vt(dr(r)))return!1;return!0}return!1},l.Pi=function(){var e,n,r,s,o;for(r=1,n=new nr(Lc(this.a));n.e!=n.i.gc();)e=u(dr(n),87),s=(o=e.c,_t(o,88)?u(o,26):(dn(),Kh)),r=31*r+(s?Pw(s):0);return r},l.Qi=function(e){var n,r,s,o;for(s=0,r=new nr(Lc(this.a));r.e!=r.i.gc();){if(n=u(dr(r),87),Vt(e)===Vt((o=n.c,_t(o,88)?u(o,26):(dn(),Kh))))return s;++s}return-1},l.Ri=function(){return Lc(this.a).i==0},l.Si=function(){return null},l.Vi=function(){return Lc(this.a).i},l.Wi=function(){var e,n,r,s,o,h;for(h=Lc(this.a).i,o=Nt(Qn,De,1,h,5,1),r=0,n=new nr(Lc(this.a));n.e!=n.i.gc();)e=u(dr(n),87),o[r++]=(s=e.c,_t(s,88)?u(s,26):(dn(),Kh));return o},l.Xi=function(e){var n,r,s,o,h,d,v;for(v=Lc(this.a).i,e.lengthv&&ts(e,v,null),s=0,r=new nr(Lc(this.a));r.e!=r.i.gc();)n=u(dr(r),87),h=(d=n.c,_t(d,88)?u(d,26):(dn(),Kh)),ts(e,s++,h);return e},l.Yi=function(){var e,n,r,s,o;for(o=new Ag,o.a+="[",e=Lc(this.a),n=0,s=Lc(this.a).i;n>16,o>=0?Lst(this,r):this.Cb.ih(this,-1-o,null,r))),Hl(this,e,6,r);case 9:return!this.a&&(this.a=new fe(ag,this,9,5)),Zc(this.a,e,r)}return h=u(yn((s=u(Dn(this,16),26),s||(dn(),Mb)),n),66),h.Nj().Qj(this,su(this),n-Jn((dn(),Mb)),e,r)},l.jh=function(e,n,r){var s,o;switch(n){case 0:return!this.Ab&&(this.Ab=new fe(Zr,this,0,3)),Ba(this.Ab,e,r);case 6:return Hl(this,null,6,r);case 7:return!this.A&&(this.A=new Fu(hu,this,7)),Ba(this.A,e,r);case 9:return!this.a&&(this.a=new fe(ag,this,9,5)),Ba(this.a,e,r)}return o=u(yn((s=u(Dn(this,16),26),s||(dn(),Mb)),n),66),o.Nj().Rj(this,su(this),n-Jn((dn(),Mb)),e,r)},l.lh=function(e){var n;switch(e){case 0:return!!this.Ab&&this.Ab.i!=0;case 1:return this.zb!=null;case 2:return this.D!=null&&this.D==this.F;case 3:return!!hv(this);case 4:return!!Hyt(this);case 5:return this.F!=null&&this.F!=this.D&&this.F!=this.B;case 6:return!!O8(this);case 7:return!!this.A&&this.A.i!=0;case 8:return(this.Bb&256)==0;case 9:return!!this.a&&this.a.i!=0}return oh(this,e-Jn((dn(),Mb)),yn((n=u(Dn(this,16),26),n||Mb),e))},l.sh=function(e,n){var r;switch(e){case 0:!this.Ab&&(this.Ab=new fe(Zr,this,0,3)),xr(this.Ab),!this.Ab&&(this.Ab=new fe(Zr,this,0,3)),is(this.Ab,u(n,14));return;case 1:_$(this,Br(n));return;case 2:snt(this,Br(n));return;case 5:OE(this,Br(n));return;case 7:!this.A&&(this.A=new Fu(hu,this,7)),xr(this.A),!this.A&&(this.A=new Fu(hu,this,7)),is(this.A,u(n,14));return;case 8:Iz(this,je(Re(n)));return;case 9:!this.a&&(this.a=new fe(ag,this,9,5)),xr(this.a),!this.a&&(this.a=new fe(ag,this,9,5)),is(this.a,u(n,14));return}gh(this,e-Jn((dn(),Mb)),yn((r=u(Dn(this,16),26),r||Mb),e),n)},l.zh=function(){return dn(),Mb},l.Bh=function(e){var n;switch(e){case 0:!this.Ab&&(this.Ab=new fe(Zr,this,0,3)),xr(this.Ab);return;case 1:_t(this.Cb,179)&&(u(this.Cb,179).tb=null),Qc(this,null);return;case 2:aE(this,null),Y8(this,this.D);return;case 5:OE(this,null);return;case 7:!this.A&&(this.A=new Fu(hu,this,7)),xr(this.A);return;case 8:Iz(this,!0);return;case 9:!this.a&&(this.a=new fe(ag,this,9,5)),xr(this.a);return}fh(this,e-Jn((dn(),Mb)),yn((n=u(Dn(this,16),26),n||Mb),e))},l.Gh=function(){var e,n;if(this.a)for(e=0,n=this.a.i;e>16==5?u(this.Cb,671):null}return uh(this,e-Jn((dn(),op)),yn((s=u(Dn(this,16),26),s||op),e),n,r)},l.hh=function(e,n,r){var s,o,h;switch(n){case 0:return!this.Ab&&(this.Ab=new fe(Zr,this,0,3)),Zc(this.Ab,e,r);case 5:return this.Cb&&(r=(o=this.Db>>16,o>=0?tae(this,r):this.Cb.ih(this,-1-o,null,r))),Hl(this,e,5,r)}return h=u(yn((s=u(Dn(this,16),26),s||(dn(),op)),n),66),h.Nj().Qj(this,su(this),n-Jn((dn(),op)),e,r)},l.jh=function(e,n,r){var s,o;switch(n){case 0:return!this.Ab&&(this.Ab=new fe(Zr,this,0,3)),Ba(this.Ab,e,r);case 5:return Hl(this,null,5,r)}return o=u(yn((s=u(Dn(this,16),26),s||(dn(),op)),n),66),o.Nj().Rj(this,su(this),n-Jn((dn(),op)),e,r)},l.lh=function(e){var n;switch(e){case 0:return!!this.Ab&&this.Ab.i!=0;case 1:return this.zb!=null;case 2:return this.d!=0;case 3:return!!this.b;case 4:return this.c!=null;case 5:return!!(this.Db>>16==5&&u(this.Cb,671))}return oh(this,e-Jn((dn(),op)),yn((n=u(Dn(this,16),26),n||op),e))},l.sh=function(e,n){var r;switch(e){case 0:!this.Ab&&(this.Ab=new fe(Zr,this,0,3)),xr(this.Ab),!this.Ab&&(this.Ab=new fe(Zr,this,0,3)),is(this.Ab,u(n,14));return;case 1:Qc(this,Br(n));return;case 2:hit(this,u(n,19).a);return;case 3:Koe(this,u(n,1940));return;case 4:dit(this,Br(n));return}gh(this,e-Jn((dn(),op)),yn((r=u(Dn(this,16),26),r||op),e),n)},l.zh=function(){return dn(),op},l.Bh=function(e){var n;switch(e){case 0:!this.Ab&&(this.Ab=new fe(Zr,this,0,3)),xr(this.Ab);return;case 1:Qc(this,null);return;case 2:hit(this,0);return;case 3:Koe(this,null);return;case 4:dit(this,null);return}fh(this,e-Jn((dn(),op)),yn((n=u(Dn(this,16),26),n||op),e))},l.Ib=function(){var e;return e=this.c,e??this.zb},l.b=null,l.c=null,l.d=0,F(Mn,"EEnumLiteralImpl",573);var x6n=Ki(Mn,"EFactoryImpl/InternalEDateTimeFormat");D(489,1,{2015:1},fM),F(Mn,"EFactoryImpl/1ClientInternalEDateTimeFormat",489),D(241,115,{105:1,92:1,90:1,87:1,56:1,108:1,49:1,97:1,241:1,114:1,115:1},xw),l.Sg=function(e,n,r){var s;return r=Hl(this,e,n,r),this.e&&_t(e,170)&&(s=vq(this,this.e),s!=this.c&&(r=PE(this,s,r))),r},l._g=function(e,n,r){var s;switch(e){case 0:return this.f;case 1:return!this.d&&(this.d=new As(ho,this,1)),this.d;case 2:return n?Lq(this):this.c;case 3:return this.b;case 4:return this.e;case 5:return n?xst(this):this.a}return uh(this,e-Jn((dn(),Gv)),yn((s=u(Dn(this,16),26),s||Gv),e),n,r)},l.jh=function(e,n,r){var s,o;switch(n){case 0:return Zre(this,null,r);case 1:return!this.d&&(this.d=new As(ho,this,1)),Ba(this.d,e,r);case 3:return Qre(this,null,r)}return o=u(yn((s=u(Dn(this,16),26),s||(dn(),Gv)),n),66),o.Nj().Rj(this,su(this),n-Jn((dn(),Gv)),e,r)},l.lh=function(e){var n;switch(e){case 0:return!!this.f;case 1:return!!this.d&&this.d.i!=0;case 2:return!!this.c;case 3:return!!this.b;case 4:return!!this.e;case 5:return!!this.a}return oh(this,e-Jn((dn(),Gv)),yn((n=u(Dn(this,16),26),n||Gv),e))},l.sh=function(e,n){var r;switch(e){case 0:vae(this,u(n,87));return;case 1:!this.d&&(this.d=new As(ho,this,1)),xr(this.d),!this.d&&(this.d=new As(ho,this,1)),is(this.d,u(n,14));return;case 3:k4t(this,u(n,87));return;case 4:j4t(this,u(n,836));return;case 5:H8(this,u(n,138));return}gh(this,e-Jn((dn(),Gv)),yn((r=u(Dn(this,16),26),r||Gv),e),n)},l.zh=function(){return dn(),Gv},l.Bh=function(e){var n;switch(e){case 0:vae(this,null);return;case 1:!this.d&&(this.d=new As(ho,this,1)),xr(this.d);return;case 3:k4t(this,null);return;case 4:j4t(this,null);return;case 5:H8(this,null);return}fh(this,e-Jn((dn(),Gv)),yn((n=u(Dn(this,16),26),n||Gv),e))},l.Ib=function(){var e;return e=new Ol(mf(this)),e.a+=" (expression: ",Mat(this,e),e.a+=")",e.a};var oLt;F(Mn,"EGenericTypeImpl",241),D(1969,1964,NH),l.Xh=function(e,n){UWt(this,e,n)},l.lk=function(e,n){return UWt(this,this.gc(),e),n},l.pi=function(e){return Zf(this.Gi(),e)},l.Zh=function(){return this.$h()},l.Gi=function(){return new Zzt(this)},l.$h=function(){return this._h(0)},l._h=function(e){return this.Gi().Zc(e)},l.mk=function(e,n){return ay(this,e,!0),n},l.ii=function(e,n){var r,s;return s=Dst(this,n),r=this.Zc(e),r.Rb(s),s},l.ji=function(e,n){var r;ay(this,n,!0),r=this.Zc(e),r.Rb(n)},F($i,"AbstractSequentialInternalEList",1969),D(486,1969,NH,jM),l.pi=function(e){return Zf(this.Gi(),e)},l.Zh=function(){return this.b==null?(Mg(),Mg(),bP):this.Jk()},l.Gi=function(){return new wUt(this.a,this.b)},l.$h=function(){return this.b==null?(Mg(),Mg(),bP):this.Jk()},l._h=function(e){var n,r;if(this.b==null){if(e<0||e>1)throw it(new yo(J_+e+", size=0"));return Mg(),Mg(),bP}for(r=this.Jk(),n=0;n0;)if(n=this.c[--this.d],(!this.e||n.Gj()!=j7||n.aj()!=0)&&(!this.Mk()||this.b.mh(n))){if(h=this.b.bh(n,this.Lk()),this.f=(to(),u(n,66).Oj()),this.f||n.$j()){if(this.Lk()?(s=u(h,15),this.k=s):(s=u(h,69),this.k=this.j=s),_t(this.k,54)?(this.o=this.k.gc(),this.n=this.o):this.p=this.j?this.j._h(this.k.gc()):this.k.Zc(this.k.gc()),this.p?loe(this,this.p):koe(this))return o=this.p?this.p.Ub():this.j?this.j.pi(--this.n):this.k.Xb(--this.n),this.f?(e=u(o,72),e.ak(),r=e.dd(),this.i=r):(r=o,this.i=r),this.g=-3,!0}else if(h!=null)return this.k=null,this.p=null,r=h,this.i=r,this.g=-2,!0}return this.k=null,this.p=null,this.g=-1,!1}else return o=this.p?this.p.Ub():this.j?this.j.pi(--this.n):this.k.Xb(--this.n),this.f?(e=u(o,72),e.ak(),r=e.dd(),this.i=r):(r=o,this.i=r),this.g=-3,!0}},l.Pb=function(){return kz(this)},l.Tb=function(){return this.a},l.Ub=function(){var e;if(this.g<-1||this.Sb())return--this.a,this.g=0,e=this.i,this.Sb(),e;throw it(new lc)},l.Vb=function(){return this.a-1},l.Qb=function(){throw it(new Or)},l.Lk=function(){return!1},l.Wb=function(e){throw it(new Or)},l.Mk=function(){return!0},l.a=0,l.d=0,l.f=!1,l.g=0,l.n=0,l.o=0;var bP;F($i,"EContentsEList/FeatureIteratorImpl",279),D(697,279,BH,V2t),l.Lk=function(){return!0},F($i,"EContentsEList/ResolvingFeatureIteratorImpl",697),D(1157,697,BH,PWt),l.Mk=function(){return!1},F(Mn,"ENamedElementImpl/1/1",1157),D(1158,279,BH,OWt),l.Mk=function(){return!1},F(Mn,"ENamedElementImpl/1/2",1158),D(36,143,nO,Qm,Rrt,Js,Jrt,z0,bf,Ymt,cZt,Kmt,uZt,mmt,lZt,Zmt,hZt,ymt,fZt,Xmt,dZt,A9,mD,brt,Qmt,gZt,xmt,pZt),l._i=function(){return Imt(this)},l.gj=function(){var e;return e=Imt(this),e?e.zj():null},l.yi=function(e){return this.b==-1&&this.a&&(this.b=this.c.Xg(this.a.aj(),this.a.Gj())),this.c.Og(this.b,e)},l.Ai=function(){return this.c},l.hj=function(){var e;return e=Imt(this),e?e.Kj():!1},l.b=-1,F(Mn,"ENotificationImpl",36),D(399,284,{105:1,92:1,90:1,147:1,191:1,56:1,59:1,108:1,472:1,49:1,97:1,150:1,399:1,284:1,114:1,115:1},iet),l.Qg=function(e){return rae(this,e)},l._g=function(e,n,r){var s,o,h;switch(e){case 0:return!this.Ab&&(this.Ab=new fe(Zr,this,0,3)),this.Ab;case 1:return this.zb;case 2:return Nn(),!!(this.Bb&256);case 3:return Nn(),!!(this.Bb&512);case 4:return pe(this.s);case 5:return pe(this.t);case 6:return Nn(),h=this.t,h>1||h==-1;case 7:return Nn(),o=this.s,o>=1;case 8:return n?Dh(this):this.r;case 9:return this.q;case 10:return this.Db>>16==10?u(this.Cb,26):null;case 11:return!this.d&&(this.d=new Fu(hu,this,11)),this.d;case 12:return!this.c&&(this.c=new fe(Vv,this,12,10)),this.c;case 13:return!this.a&&(this.a=new GM(this,this)),this.a;case 14:return al(this)}return uh(this,e-Jn((dn(),cp)),yn((s=u(Dn(this,16),26),s||cp),e),n,r)},l.hh=function(e,n,r){var s,o,h;switch(n){case 0:return!this.Ab&&(this.Ab=new fe(Zr,this,0,3)),Zc(this.Ab,e,r);case 10:return this.Cb&&(r=(o=this.Db>>16,o>=0?rae(this,r):this.Cb.ih(this,-1-o,null,r))),Hl(this,e,10,r);case 12:return!this.c&&(this.c=new fe(Vv,this,12,10)),Zc(this.c,e,r)}return h=u(yn((s=u(Dn(this,16),26),s||(dn(),cp)),n),66),h.Nj().Qj(this,su(this),n-Jn((dn(),cp)),e,r)},l.jh=function(e,n,r){var s,o;switch(n){case 0:return!this.Ab&&(this.Ab=new fe(Zr,this,0,3)),Ba(this.Ab,e,r);case 9:return nrt(this,r);case 10:return Hl(this,null,10,r);case 11:return!this.d&&(this.d=new Fu(hu,this,11)),Ba(this.d,e,r);case 12:return!this.c&&(this.c=new fe(Vv,this,12,10)),Ba(this.c,e,r);case 14:return Ba(al(this),e,r)}return o=u(yn((s=u(Dn(this,16),26),s||(dn(),cp)),n),66),o.Nj().Rj(this,su(this),n-Jn((dn(),cp)),e,r)},l.lh=function(e){var n,r,s;switch(e){case 0:return!!this.Ab&&this.Ab.i!=0;case 1:return this.zb!=null;case 2:return(this.Bb&256)==0;case 3:return(this.Bb&512)==0;case 4:return this.s!=0;case 5:return this.t!=1;case 6:return s=this.t,s>1||s==-1;case 7:return r=this.s,r>=1;case 8:return!!this.r&&!this.q.e&&qw(this.q).i==0;case 9:return!!this.q&&!(this.r&&!this.q.e&&qw(this.q).i==0);case 10:return!!(this.Db>>16==10&&u(this.Cb,26));case 11:return!!this.d&&this.d.i!=0;case 12:return!!this.c&&this.c.i!=0;case 13:return!!this.a&&al(this.a.a).i!=0&&!(this.b&&mst(this.b));case 14:return!!this.b&&mst(this.b)}return oh(this,e-Jn((dn(),cp)),yn((n=u(Dn(this,16),26),n||cp),e))},l.sh=function(e,n){var r,s;switch(e){case 0:!this.Ab&&(this.Ab=new fe(Zr,this,0,3)),xr(this.Ab),!this.Ab&&(this.Ab=new fe(Zr,this,0,3)),is(this.Ab,u(n,14));return;case 1:Qc(this,Br(n));return;case 2:zg(this,je(Re(n)));return;case 3:qg(this,je(Re(n)));return;case 4:Rg(this,u(n,19).a);return;case 5:ry(this,u(n,19).a);return;case 8:b2(this,u(n,138));return;case 9:s=F1(this,u(n,87),null),s&&s.Fi();return;case 11:!this.d&&(this.d=new Fu(hu,this,11)),xr(this.d),!this.d&&(this.d=new Fu(hu,this,11)),is(this.d,u(n,14));return;case 12:!this.c&&(this.c=new fe(Vv,this,12,10)),xr(this.c),!this.c&&(this.c=new fe(Vv,this,12,10)),is(this.c,u(n,14));return;case 13:!this.a&&(this.a=new GM(this,this)),A_(this.a),!this.a&&(this.a=new GM(this,this)),is(this.a,u(n,14));return;case 14:xr(al(this)),is(al(this),u(n,14));return}gh(this,e-Jn((dn(),cp)),yn((r=u(Dn(this,16),26),r||cp),e),n)},l.zh=function(){return dn(),cp},l.Bh=function(e){var n,r;switch(e){case 0:!this.Ab&&(this.Ab=new fe(Zr,this,0,3)),xr(this.Ab);return;case 1:Qc(this,null);return;case 2:zg(this,!0);return;case 3:qg(this,!0);return;case 4:Rg(this,0);return;case 5:ry(this,1);return;case 8:b2(this,null);return;case 9:r=F1(this,null,null),r&&r.Fi();return;case 11:!this.d&&(this.d=new Fu(hu,this,11)),xr(this.d);return;case 12:!this.c&&(this.c=new fe(Vv,this,12,10)),xr(this.c);return;case 13:this.a&&A_(this.a);return;case 14:this.b&&xr(this.b);return}fh(this,e-Jn((dn(),cp)),yn((n=u(Dn(this,16),26),n||cp),e))},l.Gh=function(){var e,n;if(this.c)for(e=0,n=this.c.i;ev&&ts(e,v,null),s=0,r=new nr(al(this.a));r.e!=r.i.gc();)n=u(dr(r),87),h=(d=n.c,d||(dn(),W1)),ts(e,s++,h);return e},l.Yi=function(){var e,n,r,s,o;for(o=new Ag,o.a+="[",e=al(this.a),n=0,s=al(this.a).i;n1);case 5:return F9(this,e,n,r,s,this.i-u(r,15).gc()>0);default:return new z0(this.e,e,this.c,n,r,s,!0)}},l.ij=function(){return!0},l.fj=function(){return mst(this)},l.Xj=function(){xr(this)},F(Mn,"EOperationImpl/2",1341),D(498,1,{1938:1,498:1},QGt),F(Mn,"EPackageImpl/1",498),D(16,85,zo,fe),l.zk=function(){return this.d},l.Ak=function(){return this.b},l.Dk=function(){return!0},l.b=0,F($i,"EObjectContainmentWithInverseEList",16),D(353,16,zo,Rx),l.Ek=function(){return!0},l.li=function(e,n){return g6(this,e,u(n,56))},F($i,"EObjectContainmentWithInverseEList/Resolving",353),D(298,353,zo,Gm),l.ci=function(){this.a.tb=null},F(Mn,"EPackageImpl/2",298),D(1228,1,{},hB),F(Mn,"EPackageImpl/3",1228),D(718,43,A4,Upt),l._b=function(e){return ra(e)?wrt(this,e):!!Lo(this.f,e)},F(Mn,"EPackageRegistryImpl",718),D(509,284,{105:1,92:1,90:1,147:1,191:1,56:1,2017:1,108:1,472:1,49:1,97:1,150:1,509:1,284:1,114:1,115:1},set),l.Qg=function(e){return iae(this,e)},l._g=function(e,n,r){var s,o,h;switch(e){case 0:return!this.Ab&&(this.Ab=new fe(Zr,this,0,3)),this.Ab;case 1:return this.zb;case 2:return Nn(),!!(this.Bb&256);case 3:return Nn(),!!(this.Bb&512);case 4:return pe(this.s);case 5:return pe(this.t);case 6:return Nn(),h=this.t,h>1||h==-1;case 7:return Nn(),o=this.s,o>=1;case 8:return n?Dh(this):this.r;case 9:return this.q;case 10:return this.Db>>16==10?u(this.Cb,59):null}return uh(this,e-Jn((dn(),i3)),yn((s=u(Dn(this,16),26),s||i3),e),n,r)},l.hh=function(e,n,r){var s,o,h;switch(n){case 0:return!this.Ab&&(this.Ab=new fe(Zr,this,0,3)),Zc(this.Ab,e,r);case 10:return this.Cb&&(r=(o=this.Db>>16,o>=0?iae(this,r):this.Cb.ih(this,-1-o,null,r))),Hl(this,e,10,r)}return h=u(yn((s=u(Dn(this,16),26),s||(dn(),i3)),n),66),h.Nj().Qj(this,su(this),n-Jn((dn(),i3)),e,r)},l.jh=function(e,n,r){var s,o;switch(n){case 0:return!this.Ab&&(this.Ab=new fe(Zr,this,0,3)),Ba(this.Ab,e,r);case 9:return nrt(this,r);case 10:return Hl(this,null,10,r)}return o=u(yn((s=u(Dn(this,16),26),s||(dn(),i3)),n),66),o.Nj().Rj(this,su(this),n-Jn((dn(),i3)),e,r)},l.lh=function(e){var n,r,s;switch(e){case 0:return!!this.Ab&&this.Ab.i!=0;case 1:return this.zb!=null;case 2:return(this.Bb&256)==0;case 3:return(this.Bb&512)==0;case 4:return this.s!=0;case 5:return this.t!=1;case 6:return s=this.t,s>1||s==-1;case 7:return r=this.s,r>=1;case 8:return!!this.r&&!this.q.e&&qw(this.q).i==0;case 9:return!!this.q&&!(this.r&&!this.q.e&&qw(this.q).i==0);case 10:return!!(this.Db>>16==10&&u(this.Cb,59))}return oh(this,e-Jn((dn(),i3)),yn((n=u(Dn(this,16),26),n||i3),e))},l.zh=function(){return dn(),i3},F(Mn,"EParameterImpl",509),D(99,449,{105:1,92:1,90:1,147:1,191:1,56:1,18:1,170:1,66:1,108:1,472:1,49:1,97:1,150:1,99:1,449:1,284:1,114:1,115:1,677:1},K2t),l._g=function(e,n,r){var s,o,h,d;switch(e){case 0:return!this.Ab&&(this.Ab=new fe(Zr,this,0,3)),this.Ab;case 1:return this.zb;case 2:return Nn(),!!(this.Bb&256);case 3:return Nn(),!!(this.Bb&512);case 4:return pe(this.s);case 5:return pe(this.t);case 6:return Nn(),d=this.t,d>1||d==-1;case 7:return Nn(),o=this.s,o>=1;case 8:return n?Dh(this):this.r;case 9:return this.q;case 10:return Nn(),!!(this.Bb&xf);case 11:return Nn(),!!(this.Bb&Dy);case 12:return Nn(),!!(this.Bb&Ey);case 13:return this.j;case 14:return SE(this);case 15:return Nn(),!!(this.Bb&Hu);case 16:return Nn(),!!(this.Bb&md);case 17:return Ym(this);case 18:return Nn(),!!(this.Bb&dc);case 19:return Nn(),h=no(this),!!(h&&h.Bb&dc);case 20:return Nn(),!!(this.Bb&Ka);case 21:return n?no(this):this.b;case 22:return n?Iyt(this):BJt(this);case 23:return!this.a&&(this.a=new Y3(e3,this,23)),this.a}return uh(this,e-Jn((dn(),l5)),yn((s=u(Dn(this,16),26),s||l5),e),n,r)},l.lh=function(e){var n,r,s,o;switch(e){case 0:return!!this.Ab&&this.Ab.i!=0;case 1:return this.zb!=null;case 2:return(this.Bb&256)==0;case 3:return(this.Bb&512)==0;case 4:return this.s!=0;case 5:return this.t!=1;case 6:return o=this.t,o>1||o==-1;case 7:return r=this.s,r>=1;case 8:return!!this.r&&!this.q.e&&qw(this.q).i==0;case 9:return!!this.q&&!(this.r&&!this.q.e&&qw(this.q).i==0);case 10:return(this.Bb&xf)==0;case 11:return(this.Bb&Dy)!=0;case 12:return(this.Bb&Ey)!=0;case 13:return this.j!=null;case 14:return SE(this)!=null;case 15:return(this.Bb&Hu)!=0;case 16:return(this.Bb&md)!=0;case 17:return!!Ym(this);case 18:return(this.Bb&dc)!=0;case 19:return s=no(this),!!s&&(s.Bb&dc)!=0;case 20:return(this.Bb&Ka)==0;case 21:return!!this.b;case 22:return!!BJt(this);case 23:return!!this.a&&this.a.i!=0}return oh(this,e-Jn((dn(),l5)),yn((n=u(Dn(this,16),26),n||l5),e))},l.sh=function(e,n){var r,s;switch(e){case 0:!this.Ab&&(this.Ab=new fe(Zr,this,0,3)),xr(this.Ab),!this.Ab&&(this.Ab=new fe(Zr,this,0,3)),is(this.Ab,u(n,14));return;case 1:Mrt(this,Br(n));return;case 2:zg(this,je(Re(n)));return;case 3:qg(this,je(Re(n)));return;case 4:Rg(this,u(n,19).a);return;case 5:ry(this,u(n,19).a);return;case 8:b2(this,u(n,138));return;case 9:s=F1(this,u(n,87),null),s&&s.Fi();return;case 10:lE(this,je(Re(n)));return;case 11:dE(this,je(Re(n)));return;case 12:hE(this,je(Re(n)));return;case 13:r2t(this,Br(n));return;case 15:fE(this,je(Re(n)));return;case 16:gE(this,je(Re(n)));return;case 18:xin(this,je(Re(n)));return;case 20:u3t(this,je(Re(n)));return;case 21:cyt(this,u(n,18));return;case 23:!this.a&&(this.a=new Y3(e3,this,23)),xr(this.a),!this.a&&(this.a=new Y3(e3,this,23)),is(this.a,u(n,14));return}gh(this,e-Jn((dn(),l5)),yn((r=u(Dn(this,16),26),r||l5),e),n)},l.zh=function(){return dn(),l5},l.Bh=function(e){var n,r;switch(e){case 0:!this.Ab&&(this.Ab=new fe(Zr,this,0,3)),xr(this.Ab);return;case 1:_t(this.Cb,88)&&gy(sl(u(this.Cb,88)),4),Qc(this,null);return;case 2:zg(this,!0);return;case 3:qg(this,!0);return;case 4:Rg(this,0);return;case 5:ry(this,1);return;case 8:b2(this,null);return;case 9:r=F1(this,null,null),r&&r.Fi();return;case 10:lE(this,!0);return;case 11:dE(this,!1);return;case 12:hE(this,!1);return;case 13:this.i=null,fz(this,null);return;case 15:fE(this,!1);return;case 16:gE(this,!1);return;case 18:c3t(this,!1),_t(this.Cb,88)&&gy(sl(u(this.Cb,88)),2);return;case 20:u3t(this,!0);return;case 21:cyt(this,null);return;case 23:!this.a&&(this.a=new Y3(e3,this,23)),xr(this.a);return}fh(this,e-Jn((dn(),l5)),yn((n=u(Dn(this,16),26),n||l5),e))},l.Gh=function(){Iyt(this),M8(To(($u(),ya),this)),Dh(this),this.Bb|=1},l.Lj=function(){return no(this)},l.qk=function(){var e;return e=no(this),!!e&&(e.Bb&dc)!=0},l.rk=function(){return(this.Bb&dc)!=0},l.sk=function(){return(this.Bb&Ka)!=0},l.nk=function(e,n){return this.c=null,e3t(this,e,n)},l.Ib=function(){var e;return this.Db&64?_q(this):(e=new _h(_q(this)),e.a+=" (containment: ",Lg(e,(this.Bb&dc)!=0),e.a+=", resolveProxies: ",Lg(e,(this.Bb&Ka)!=0),e.a+=")",e.a)},F(Mn,"EReferenceImpl",99),D(548,115,{105:1,42:1,92:1,90:1,133:1,56:1,108:1,49:1,97:1,548:1,114:1,115:1},iJ),l.Fb=function(e){return this===e},l.cd=function(){return this.b},l.dd=function(){return this.c},l.Hb=function(){return Pw(this)},l.Uh=function(e){_en(this,Br(e))},l.ed=function(e){return gen(this,Br(e))},l._g=function(e,n,r){var s;switch(e){case 0:return this.b;case 1:return this.c}return uh(this,e-Jn((dn(),Qa)),yn((s=u(Dn(this,16),26),s||Qa),e),n,r)},l.lh=function(e){var n;switch(e){case 0:return this.b!=null;case 1:return this.c!=null}return oh(this,e-Jn((dn(),Qa)),yn((n=u(Dn(this,16),26),n||Qa),e))},l.sh=function(e,n){var r;switch(e){case 0:Sen(this,Br(n));return;case 1:syt(this,Br(n));return}gh(this,e-Jn((dn(),Qa)),yn((r=u(Dn(this,16),26),r||Qa),e),n)},l.zh=function(){return dn(),Qa},l.Bh=function(e){var n;switch(e){case 0:iyt(this,null);return;case 1:syt(this,null);return}fh(this,e-Jn((dn(),Qa)),yn((n=u(Dn(this,16),26),n||Qa),e))},l.Sh=function(){var e;return this.a==-1&&(e=this.b,this.a=e==null?0:Vg(e)),this.a},l.Th=function(e){this.a=e},l.Ib=function(){var e;return this.Db&64?mf(this):(e=new _h(mf(this)),e.a+=" (key: ",go(e,this.b),e.a+=", value: ",go(e,this.c),e.a+=")",e.a)},l.a=-1,l.b=null,l.c=null;var cc=F(Mn,"EStringToStringMapEntryImpl",548),E5e=Ki($i,"FeatureMap/Entry/Internal");D(565,1,RH),l.Ok=function(e){return this.Pk(u(e,49))},l.Pk=function(e){return this.Ok(e)},l.Fb=function(e){var n,r;return this===e?!0:_t(e,72)?(n=u(e,72),n.ak()==this.c?(r=this.dd(),r==null?n.dd()==null:yi(r,n.dd())):!1):!1},l.ak=function(){return this.c},l.Hb=function(){var e;return e=this.dd(),Hi(this.c)^(e==null?0:Hi(e))},l.Ib=function(){var e,n;return e=this.c,n=Rl(e.Hj()).Ph(),e.ne(),(n!=null&&n.length!=0?n+":"+e.ne():e.ne())+"="+this.dd()},F(Mn,"EStructuralFeatureImpl/BasicFeatureMapEntry",565),D(776,565,RH,iwt),l.Pk=function(e){return new iwt(this.c,e)},l.dd=function(){return this.a},l.Qk=function(e,n,r){return Hcn(this,e,this.a,n,r)},l.Rk=function(e,n,r){return Vcn(this,e,this.a,n,r)},F(Mn,"EStructuralFeatureImpl/ContainmentUpdatingFeatureMapEntry",776),D(1314,1,{},ZGt),l.Pj=function(e,n,r,s,o){var h;return h=u(j8(e,this.b),215),h.nl(this.a).Wj(s)},l.Qj=function(e,n,r,s,o){var h;return h=u(j8(e,this.b),215),h.el(this.a,s,o)},l.Rj=function(e,n,r,s,o){var h;return h=u(j8(e,this.b),215),h.fl(this.a,s,o)},l.Sj=function(e,n,r){var s;return s=u(j8(e,this.b),215),s.nl(this.a).fj()},l.Tj=function(e,n,r,s){var o;o=u(j8(e,this.b),215),o.nl(this.a).Wb(s)},l.Uj=function(e,n,r){return u(j8(e,this.b),215).nl(this.a)},l.Vj=function(e,n,r){var s;s=u(j8(e,this.b),215),s.nl(this.a).Xj()},F(Mn,"EStructuralFeatureImpl/InternalSettingDelegateFeatureMapDelegator",1314),D(89,1,{},Ig,n2,Pg,s2),l.Pj=function(e,n,r,s,o){var h;if(h=n.Ch(r),h==null&&n.Dh(r,h=jq(this,e)),!o)switch(this.e){case 50:case 41:return u(h,589).sj();case 40:return u(h,215).kl()}return h},l.Qj=function(e,n,r,s,o){var h,d;return d=n.Ch(r),d==null&&n.Dh(r,d=jq(this,e)),h=u(d,69).lk(s,o),h},l.Rj=function(e,n,r,s,o){var h;return h=n.Ch(r),h!=null&&(o=u(h,69).mk(s,o)),o},l.Sj=function(e,n,r){var s;return s=n.Ch(r),s!=null&&u(s,76).fj()},l.Tj=function(e,n,r,s){var o;o=u(n.Ch(r),76),!o&&n.Dh(r,o=jq(this,e)),o.Wb(s)},l.Uj=function(e,n,r){var s,o;return o=n.Ch(r),o==null&&n.Dh(r,o=jq(this,e)),_t(o,76)?u(o,76):(s=u(n.Ch(r),15),new Qzt(s))},l.Vj=function(e,n,r){var s;s=u(n.Ch(r),76),!s&&n.Dh(r,s=jq(this,e)),s.Xj()},l.b=0,l.e=0,F(Mn,"EStructuralFeatureImpl/InternalSettingDelegateMany",89),D(504,1,{}),l.Qj=function(e,n,r,s,o){throw it(new Or)},l.Rj=function(e,n,r,s,o){throw it(new Or)},l.Uj=function(e,n,r){return new WXt(this,e,n,r)};var p0;F(Mn,"EStructuralFeatureImpl/InternalSettingDelegateSingle",504),D(1331,1,hut,WXt),l.Wj=function(e){return this.a.Pj(this.c,this.d,this.b,e,!0)},l.fj=function(){return this.a.Sj(this.c,this.d,this.b)},l.Wb=function(e){this.a.Tj(this.c,this.d,this.b,e)},l.Xj=function(){this.a.Vj(this.c,this.d,this.b)},l.b=0,F(Mn,"EStructuralFeatureImpl/InternalSettingDelegateSingle/1",1331),D(769,504,{},$vt),l.Pj=function(e,n,r,s,o){return wat(e,e.eh(),e.Vg())==this.b?this.sk()&&s?eat(e):e.eh():null},l.Qj=function(e,n,r,s,o){var h,d;return e.eh()&&(o=(h=e.Vg(),h>=0?e.Qg(o):e.eh().ih(e,-1-h,null,o))),d=Gi(e.Tg(),this.e),e.Sg(s,d,o)},l.Rj=function(e,n,r,s,o){var h;return h=Gi(e.Tg(),this.e),e.Sg(null,h,o)},l.Sj=function(e,n,r){var s;return s=Gi(e.Tg(),this.e),!!e.eh()&&e.Vg()==s},l.Tj=function(e,n,r,s){var o,h,d,v,k;if(s!=null&&!xat(this.a,s))throw it(new i8(jH+(_t(s,56)?y4t(u(s,56).Tg()):Vmt(ol(s)))+$H+this.a+"'"));if(o=e.eh(),d=Gi(e.Tg(),this.e),Vt(s)!==Vt(o)||e.Vg()!=d&&s!=null){if(vE(e,u(s,56)))throw it(new Fn(Q_+e.Ib()));k=null,o&&(k=(h=e.Vg(),h>=0?e.Qg(k):e.eh().ih(e,-1-h,null,k))),v=u(s,49),v&&(k=v.gh(e,Gi(v.Tg(),this.b),null,k)),k=e.Sg(v,d,k),k&&k.Fi()}else e.Lg()&&e.Mg()&&mi(e,new Js(e,1,d,s,s))},l.Vj=function(e,n,r){var s,o,h,d;s=e.eh(),s?(d=(o=e.Vg(),o>=0?e.Qg(null):e.eh().ih(e,-1-o,null,null)),h=Gi(e.Tg(),this.e),d=e.Sg(null,h,d),d&&d.Fi()):e.Lg()&&e.Mg()&&mi(e,new A9(e,1,this.e,null,null))},l.sk=function(){return!1},F(Mn,"EStructuralFeatureImpl/InternalSettingDelegateSingleContainer",769),D(1315,769,{},jYt),l.sk=function(){return!0},F(Mn,"EStructuralFeatureImpl/InternalSettingDelegateSingleContainerResolving",1315),D(563,504,{}),l.Pj=function(e,n,r,s,o){var h;return h=n.Ch(r),h==null?this.b:Vt(h)===Vt(p0)?null:h},l.Sj=function(e,n,r){var s;return s=n.Ch(r),s!=null&&(Vt(s)===Vt(p0)||!yi(s,this.b))},l.Tj=function(e,n,r,s){var o,h;e.Lg()&&e.Mg()?(o=(h=n.Ch(r),h==null?this.b:Vt(h)===Vt(p0)?null:h),s==null?this.c!=null?(n.Dh(r,null),s=this.b):this.b!=null?n.Dh(r,p0):n.Dh(r,null):(this.Sk(s),n.Dh(r,s)),mi(e,this.d.Tk(e,1,this.e,o,s))):s==null?this.c!=null?n.Dh(r,null):this.b!=null?n.Dh(r,p0):n.Dh(r,null):(this.Sk(s),n.Dh(r,s))},l.Vj=function(e,n,r){var s,o;e.Lg()&&e.Mg()?(s=(o=n.Ch(r),o==null?this.b:Vt(o)===Vt(p0)?null:o),n.Eh(r),mi(e,this.d.Tk(e,1,this.e,s,this.b))):n.Eh(r)},l.Sk=function(e){throw it(new oqt)},F(Mn,"EStructuralFeatureImpl/InternalSettingDelegateSingleData",563),D(R4,1,{},fB),l.Tk=function(e,n,r,s,o){return new A9(e,n,r,s,o)},l.Uk=function(e,n,r,s,o,h){return new brt(e,n,r,s,o,h)};var cLt,uLt,lLt,hLt,fLt,dLt,gLt,jft,pLt;F(Mn,"EStructuralFeatureImpl/InternalSettingDelegateSingleData/NotificationCreator",R4),D(1332,R4,{},dB),l.Tk=function(e,n,r,s,o){return new xmt(e,n,r,je(Re(s)),je(Re(o)))},l.Uk=function(e,n,r,s,o,h){return new pZt(e,n,r,je(Re(s)),je(Re(o)),h)},F(Mn,"EStructuralFeatureImpl/InternalSettingDelegateSingleData/NotificationCreator/1",1332),D(1333,R4,{},gB),l.Tk=function(e,n,r,s,o){return new Ymt(e,n,r,u(s,217).a,u(o,217).a)},l.Uk=function(e,n,r,s,o,h){return new cZt(e,n,r,u(s,217).a,u(o,217).a,h)},F(Mn,"EStructuralFeatureImpl/InternalSettingDelegateSingleData/NotificationCreator/2",1333),D(1334,R4,{},Nk),l.Tk=function(e,n,r,s,o){return new Kmt(e,n,r,u(s,172).a,u(o,172).a)},l.Uk=function(e,n,r,s,o,h){return new uZt(e,n,r,u(s,172).a,u(o,172).a,h)},F(Mn,"EStructuralFeatureImpl/InternalSettingDelegateSingleData/NotificationCreator/3",1334),D(1335,R4,{},pB),l.Tk=function(e,n,r,s,o){return new mmt(e,n,r,Xt(ye(s)),Xt(ye(o)))},l.Uk=function(e,n,r,s,o,h){return new lZt(e,n,r,Xt(ye(s)),Xt(ye(o)),h)},F(Mn,"EStructuralFeatureImpl/InternalSettingDelegateSingleData/NotificationCreator/4",1335),D(1336,R4,{},bB),l.Tk=function(e,n,r,s,o){return new Zmt(e,n,r,u(s,155).a,u(o,155).a)},l.Uk=function(e,n,r,s,o,h){return new hZt(e,n,r,u(s,155).a,u(o,155).a,h)},F(Mn,"EStructuralFeatureImpl/InternalSettingDelegateSingleData/NotificationCreator/5",1336),D(1337,R4,{},sJ),l.Tk=function(e,n,r,s,o){return new ymt(e,n,r,u(s,19).a,u(o,19).a)},l.Uk=function(e,n,r,s,o,h){return new fZt(e,n,r,u(s,19).a,u(o,19).a,h)},F(Mn,"EStructuralFeatureImpl/InternalSettingDelegateSingleData/NotificationCreator/6",1337),D(1338,R4,{},Bk),l.Tk=function(e,n,r,s,o){return new Xmt(e,n,r,u(s,162).a,u(o,162).a)},l.Uk=function(e,n,r,s,o,h){return new dZt(e,n,r,u(s,162).a,u(o,162).a,h)},F(Mn,"EStructuralFeatureImpl/InternalSettingDelegateSingleData/NotificationCreator/7",1338),D(1339,R4,{},Rk),l.Tk=function(e,n,r,s,o){return new Qmt(e,n,r,u(s,184).a,u(o,184).a)},l.Uk=function(e,n,r,s,o,h){return new gZt(e,n,r,u(s,184).a,u(o,184).a,h)},F(Mn,"EStructuralFeatureImpl/InternalSettingDelegateSingleData/NotificationCreator/8",1339),D(1317,563,{},YXt),l.Sk=function(e){if(!this.a.wj(e))throw it(new i8(jH+ol(e)+$H+this.a+"'"))},F(Mn,"EStructuralFeatureImpl/InternalSettingDelegateSingleDataDynamic",1317),D(1318,563,{},NKt),l.Sk=function(e){},F(Mn,"EStructuralFeatureImpl/InternalSettingDelegateSingleDataStatic",1318),D(770,563,{}),l.Sj=function(e,n,r){var s;return s=n.Ch(r),s!=null},l.Tj=function(e,n,r,s){var o,h;e.Lg()&&e.Mg()?(o=!0,h=n.Ch(r),h==null?(o=!1,h=this.b):Vt(h)===Vt(p0)&&(h=null),s==null?this.c!=null?(n.Dh(r,null),s=this.b):n.Dh(r,p0):(this.Sk(s),n.Dh(r,s)),mi(e,this.d.Uk(e,1,this.e,h,s,!o))):s==null?this.c!=null?n.Dh(r,null):n.Dh(r,p0):(this.Sk(s),n.Dh(r,s))},l.Vj=function(e,n,r){var s,o;e.Lg()&&e.Mg()?(s=!0,o=n.Ch(r),o==null?(s=!1,o=this.b):Vt(o)===Vt(p0)&&(o=null),n.Eh(r),mi(e,this.d.Uk(e,2,this.e,o,this.b,s))):n.Eh(r)},F(Mn,"EStructuralFeatureImpl/InternalSettingDelegateSingleDataUnsettable",770),D(1319,770,{},KXt),l.Sk=function(e){if(!this.a.wj(e))throw it(new i8(jH+ol(e)+$H+this.a+"'"))},F(Mn,"EStructuralFeatureImpl/InternalSettingDelegateSingleDataUnsettableDynamic",1319),D(1320,770,{},BKt),l.Sk=function(e){},F(Mn,"EStructuralFeatureImpl/InternalSettingDelegateSingleDataUnsettableStatic",1320),D(398,504,{},Uj),l.Pj=function(e,n,r,s,o){var h,d,v,k,C;if(C=n.Ch(r),this.Kj()&&Vt(C)===Vt(p0))return null;if(this.sk()&&s&&C!=null){if(v=u(C,49),v.kh()&&(k=Zp(e,v),v!=k)){if(!xat(this.a,k))throw it(new i8(jH+ol(k)+$H+this.a+"'"));n.Dh(r,C=k),this.rk()&&(h=u(k,49),d=v.ih(e,this.b?Gi(v.Tg(),this.b):-1-Gi(e.Tg(),this.e),null,null),!h.eh()&&(d=h.gh(e,this.b?Gi(h.Tg(),this.b):-1-Gi(e.Tg(),this.e),null,d)),d&&d.Fi()),e.Lg()&&e.Mg()&&mi(e,new A9(e,9,this.e,v,k))}return C}else return C},l.Qj=function(e,n,r,s,o){var h,d;return d=n.Ch(r),Vt(d)===Vt(p0)&&(d=null),n.Dh(r,s),this.bj()?Vt(d)!==Vt(s)&&d!=null&&(h=u(d,49),o=h.ih(e,Gi(h.Tg(),this.b),null,o)):this.rk()&&d!=null&&(o=u(d,49).ih(e,-1-Gi(e.Tg(),this.e),null,o)),e.Lg()&&e.Mg()&&(!o&&(o=new Dp(4)),o.Ei(new A9(e,1,this.e,d,s))),o},l.Rj=function(e,n,r,s,o){var h;return h=n.Ch(r),Vt(h)===Vt(p0)&&(h=null),n.Eh(r),e.Lg()&&e.Mg()&&(!o&&(o=new Dp(4)),this.Kj()?o.Ei(new A9(e,2,this.e,h,null)):o.Ei(new A9(e,1,this.e,h,null))),o},l.Sj=function(e,n,r){var s;return s=n.Ch(r),s!=null},l.Tj=function(e,n,r,s){var o,h,d,v,k;if(s!=null&&!xat(this.a,s))throw it(new i8(jH+(_t(s,56)?y4t(u(s,56).Tg()):Vmt(ol(s)))+$H+this.a+"'"));k=n.Ch(r),v=k!=null,this.Kj()&&Vt(k)===Vt(p0)&&(k=null),d=null,this.bj()?Vt(k)!==Vt(s)&&(k!=null&&(o=u(k,49),d=o.ih(e,Gi(o.Tg(),this.b),null,d)),s!=null&&(o=u(s,49),d=o.gh(e,Gi(o.Tg(),this.b),null,d))):this.rk()&&Vt(k)!==Vt(s)&&(k!=null&&(d=u(k,49).ih(e,-1-Gi(e.Tg(),this.e),null,d)),s!=null&&(d=u(s,49).gh(e,-1-Gi(e.Tg(),this.e),null,d))),s==null&&this.Kj()?n.Dh(r,p0):n.Dh(r,s),e.Lg()&&e.Mg()?(h=new brt(e,1,this.e,k,s,this.Kj()&&!v),d?(d.Ei(h),d.Fi()):mi(e,h)):d&&d.Fi()},l.Vj=function(e,n,r){var s,o,h,d,v;v=n.Ch(r),d=v!=null,this.Kj()&&Vt(v)===Vt(p0)&&(v=null),h=null,v!=null&&(this.bj()?(s=u(v,49),h=s.ih(e,Gi(s.Tg(),this.b),null,h)):this.rk()&&(h=u(v,49).ih(e,-1-Gi(e.Tg(),this.e),null,h))),n.Eh(r),e.Lg()&&e.Mg()?(o=new brt(e,this.Kj()?2:1,this.e,v,null,d),h?(h.Ei(o),h.Fi()):mi(e,o)):h&&h.Fi()},l.bj=function(){return!1},l.rk=function(){return!1},l.sk=function(){return!1},l.Kj=function(){return!1},F(Mn,"EStructuralFeatureImpl/InternalSettingDelegateSingleEObject",398),D(564,398,{},vnt),l.rk=function(){return!0},F(Mn,"EStructuralFeatureImpl/InternalSettingDelegateSingleEObjectContainment",564),D(1323,564,{},FWt),l.sk=function(){return!0},F(Mn,"EStructuralFeatureImpl/InternalSettingDelegateSingleEObjectContainmentResolving",1323),D(772,564,{},G2t),l.Kj=function(){return!0},F(Mn,"EStructuralFeatureImpl/InternalSettingDelegateSingleEObjectContainmentUnsettable",772),D(1325,772,{},NWt),l.sk=function(){return!0},F(Mn,"EStructuralFeatureImpl/InternalSettingDelegateSingleEObjectContainmentUnsettableResolving",1325),D(640,564,{},Int),l.bj=function(){return!0},F(Mn,"EStructuralFeatureImpl/InternalSettingDelegateSingleEObjectContainmentWithInverse",640),D(1324,640,{},$Yt),l.sk=function(){return!0},F(Mn,"EStructuralFeatureImpl/InternalSettingDelegateSingleEObjectContainmentWithInverseResolving",1324),D(773,640,{},Dwt),l.Kj=function(){return!0},F(Mn,"EStructuralFeatureImpl/InternalSettingDelegateSingleEObjectContainmentWithInverseUnsettable",773),D(1326,773,{},zYt),l.sk=function(){return!0},F(Mn,"EStructuralFeatureImpl/InternalSettingDelegateSingleEObjectContainmentWithInverseUnsettableResolving",1326),D(641,398,{},U2t),l.sk=function(){return!0},F(Mn,"EStructuralFeatureImpl/InternalSettingDelegateSingleEObjectResolving",641),D(1327,641,{},BWt),l.Kj=function(){return!0},F(Mn,"EStructuralFeatureImpl/InternalSettingDelegateSingleEObjectResolvingUnsettable",1327),D(774,641,{},Lwt),l.bj=function(){return!0},F(Mn,"EStructuralFeatureImpl/InternalSettingDelegateSingleEObjectResolvingWithInverse",774),D(1328,774,{},qYt),l.Kj=function(){return!0},F(Mn,"EStructuralFeatureImpl/InternalSettingDelegateSingleEObjectResolvingWithInverseUnsettable",1328),D(1321,398,{},RWt),l.Kj=function(){return!0},F(Mn,"EStructuralFeatureImpl/InternalSettingDelegateSingleEObjectUnsettable",1321),D(771,398,{},Mwt),l.bj=function(){return!0},F(Mn,"EStructuralFeatureImpl/InternalSettingDelegateSingleEObjectWithInverse",771),D(1322,771,{},HYt),l.Kj=function(){return!0},F(Mn,"EStructuralFeatureImpl/InternalSettingDelegateSingleEObjectWithInverseUnsettable",1322),D(775,565,RH,_vt),l.Pk=function(e){return new _vt(this.a,this.c,e)},l.dd=function(){return this.b},l.Qk=function(e,n,r){return Van(this,e,this.b,r)},l.Rk=function(e,n,r){return Gan(this,e,this.b,r)},F(Mn,"EStructuralFeatureImpl/InverseUpdatingFeatureMapEntry",775),D(1329,1,hut,Qzt),l.Wj=function(e){return this.a},l.fj=function(){return _t(this.a,95)?u(this.a,95).fj():!this.a.dc()},l.Wb=function(e){this.a.$b(),this.a.Gc(u(e,15))},l.Xj=function(){_t(this.a,95)?u(this.a,95).Xj():this.a.$b()},F(Mn,"EStructuralFeatureImpl/SettingMany",1329),D(1330,565,RH,rJt),l.Ok=function(e){return new xnt((Ii(),fA),this.b.Ih(this.a,e))},l.dd=function(){return null},l.Qk=function(e,n,r){return r},l.Rk=function(e,n,r){return r},F(Mn,"EStructuralFeatureImpl/SimpleContentFeatureMapEntry",1330),D(642,565,RH,xnt),l.Ok=function(e){return new xnt(this.c,e)},l.dd=function(){return this.a},l.Qk=function(e,n,r){return r},l.Rk=function(e,n,r){return r},F(Mn,"EStructuralFeatureImpl/SimpleFeatureMapEntry",642),D(391,497,Ld,Tm),l.ri=function(e){return Nt(Uh,De,26,e,0,1)},l.ni=function(){return!1},F(Mn,"ESuperAdapter/1",391),D(444,438,{105:1,92:1,90:1,147:1,191:1,56:1,108:1,836:1,49:1,97:1,150:1,444:1,114:1,115:1},HL),l._g=function(e,n,r){var s;switch(e){case 0:return!this.Ab&&(this.Ab=new fe(Zr,this,0,3)),this.Ab;case 1:return this.zb;case 2:return!this.a&&(this.a=new T9(this,ho,this)),this.a}return uh(this,e-Jn((dn(),Uv)),yn((s=u(Dn(this,16),26),s||Uv),e),n,r)},l.jh=function(e,n,r){var s,o;switch(n){case 0:return!this.Ab&&(this.Ab=new fe(Zr,this,0,3)),Ba(this.Ab,e,r);case 2:return!this.a&&(this.a=new T9(this,ho,this)),Ba(this.a,e,r)}return o=u(yn((s=u(Dn(this,16),26),s||(dn(),Uv)),n),66),o.Nj().Rj(this,su(this),n-Jn((dn(),Uv)),e,r)},l.lh=function(e){var n;switch(e){case 0:return!!this.Ab&&this.Ab.i!=0;case 1:return this.zb!=null;case 2:return!!this.a&&this.a.i!=0}return oh(this,e-Jn((dn(),Uv)),yn((n=u(Dn(this,16),26),n||Uv),e))},l.sh=function(e,n){var r;switch(e){case 0:!this.Ab&&(this.Ab=new fe(Zr,this,0,3)),xr(this.Ab),!this.Ab&&(this.Ab=new fe(Zr,this,0,3)),is(this.Ab,u(n,14));return;case 1:Qc(this,Br(n));return;case 2:!this.a&&(this.a=new T9(this,ho,this)),xr(this.a),!this.a&&(this.a=new T9(this,ho,this)),is(this.a,u(n,14));return}gh(this,e-Jn((dn(),Uv)),yn((r=u(Dn(this,16),26),r||Uv),e),n)},l.zh=function(){return dn(),Uv},l.Bh=function(e){var n;switch(e){case 0:!this.Ab&&(this.Ab=new fe(Zr,this,0,3)),xr(this.Ab);return;case 1:Qc(this,null);return;case 2:!this.a&&(this.a=new T9(this,ho,this)),xr(this.a);return}fh(this,e-Jn((dn(),Uv)),yn((n=u(Dn(this,16),26),n||Uv),e))},F(Mn,"ETypeParameterImpl",444),D(445,85,zo,T9),l.cj=function(e,n){return G0n(this,u(e,87),n)},l.dj=function(e,n){return U0n(this,u(e,87),n)},F(Mn,"ETypeParameterImpl/1",445),D(634,43,A4,aet),l.ec=function(){return new mR(this)},F(Mn,"ETypeParameterImpl/2",634),D(556,N1,zu,mR),l.Fc=function(e){return lYt(this,u(e,87))},l.Gc=function(e){var n,r,s;for(s=!1,r=e.Kc();r.Ob();)n=u(r.Pb(),87),ki(this.a,n,"")==null&&(s=!0);return s},l.$b=function(){Xu(this.a)},l.Hc=function(e){return Tl(this.a,e)},l.Kc=function(){var e;return e=new p2(new Cg(this.a).a),new yR(e)},l.Mc=function(e){return XJt(this,e)},l.gc=function(){return HC(this.a)},F(Mn,"ETypeParameterImpl/2/1",556),D(557,1,sa,yR),l.Nb=function(e){ba(this,e)},l.Pb=function(){return u(Zw(this.a).cd(),87)},l.Ob=function(){return this.a.b},l.Qb=function(){Ste(this.a)},F(Mn,"ETypeParameterImpl/2/1/1",557),D(1276,43,A4,zqt),l._b=function(e){return ra(e)?wrt(this,e):!!Lo(this.f,e)},l.xc=function(e){var n,r;return n=ra(e)?Nc(this,e):ec(Lo(this.f,e)),_t(n,837)?(r=u(n,837),n=r._j(),ki(this,u(e,235),n),n):n??(e==null?(Tet(),C5e):null)},F(Mn,"EValidatorRegistryImpl",1276),D(1313,704,{105:1,92:1,90:1,471:1,147:1,56:1,108:1,1941:1,49:1,97:1,150:1,114:1,115:1},aJ),l.Ih=function(e,n){switch(e.yj()){case 21:case 22:case 23:case 24:case 26:case 31:case 32:case 37:case 38:case 39:case 40:case 43:case 44:case 48:case 49:case 20:return n==null?null:$o(n);case 25:return Jon(n);case 27:return bon(n);case 28:return won(n);case 29:return n==null?null:VUt(aA[0],u(n,199));case 41:return n==null?"":Ip(u(n,290));case 42:return $o(n);case 50:return Br(n);default:throw it(new Fn(QE+e.ne()+Cv))}},l.Jh=function(e){var n,r,s,o,h,d,v,k,C,M,j,H,G,K,tt,gt;switch(e.G==-1&&(e.G=(H=Rl(e),H?Hg(H.Mh(),e):-1)),e.G){case 0:return r=new ret,r;case 1:return n=new lB,n;case 2:return s=new eM,s;case 4:return o=new xR,o;case 5:return h=new $qt,h;case 6:return d=new lqt,d;case 7:return v=new JB,v;case 10:return C=new Pk,C;case 11:return M=new iet,M;case 12:return j=new fQt,j;case 13:return G=new set,G;case 14:return K=new K2t,K;case 17:return tt=new iJ,tt;case 18:return k=new xw,k;case 19:return gt=new HL,gt;default:throw it(new Fn(Kct+e.zb+Cv))}},l.Kh=function(e,n){switch(e.yj()){case 20:return n==null?null:new gbt(n);case 21:return n==null?null:new Rp(n);case 23:case 22:return n==null?null:ifn(n);case 26:case 24:return n==null?null:AD(ql(n,-128,127)<<24>>24);case 25:return p2n(n);case 27:return z1n(n);case 28:return q1n(n);case 29:return lgn(n);case 32:case 31:return n==null?null:dy(n);case 38:case 37:return n==null?null:new Ppt(n);case 40:case 39:return n==null?null:pe(ql(n,Sa,wi));case 41:return null;case 42:return n==null,null;case 44:case 43:return n==null?null:v2(Rq(n));case 49:case 48:return n==null?null:uE(ql(n,zH,32767)<<16>>16);case 50:return n;default:throw it(new Fn(QE+e.ne()+Cv))}},F(Mn,"EcoreFactoryImpl",1313),D(547,179,{105:1,92:1,90:1,147:1,191:1,56:1,235:1,108:1,1939:1,49:1,97:1,150:1,179:1,547:1,114:1,115:1,675:1},LXt),l.gb=!1,l.hb=!1;var bLt,T5e=!1;F(Mn,"EcorePackageImpl",547),D(1184,1,{837:1},oJ),l._j=function(){return gWt(),_5e},F(Mn,"EcorePackageImpl/1",1184),D(1193,1,si,cJ),l.wj=function(e){return _t(e,147)},l.xj=function(e){return Nt(fP,De,147,e,0,1)},F(Mn,"EcorePackageImpl/10",1193),D(1194,1,si,uJ),l.wj=function(e){return _t(e,191)},l.xj=function(e){return Nt(Mft,De,191,e,0,1)},F(Mn,"EcorePackageImpl/11",1194),D(1195,1,si,lJ),l.wj=function(e){return _t(e,56)},l.xj=function(e){return Nt(_b,De,56,e,0,1)},F(Mn,"EcorePackageImpl/12",1195),D(1196,1,si,hJ),l.wj=function(e){return _t(e,399)},l.xj=function(e){return Nt(Wh,$8t,59,e,0,1)},F(Mn,"EcorePackageImpl/13",1196),D(1197,1,si,fJ),l.wj=function(e){return _t(e,235)},l.xj=function(e){return Nt(i1,De,235,e,0,1)},F(Mn,"EcorePackageImpl/14",1197),D(1198,1,si,dJ),l.wj=function(e){return _t(e,509)},l.xj=function(e){return Nt(Vv,De,2017,e,0,1)},F(Mn,"EcorePackageImpl/15",1198),D(1199,1,si,wB),l.wj=function(e){return _t(e,99)},l.xj=function(e){return Nt(n3,B4,18,e,0,1)},F(Mn,"EcorePackageImpl/16",1199),D(1200,1,si,gJ),l.wj=function(e){return _t(e,170)},l.xj=function(e){return Nt(Mu,B4,170,e,0,1)},F(Mn,"EcorePackageImpl/17",1200),D(1201,1,si,pJ),l.wj=function(e){return _t(e,472)},l.xj=function(e){return Nt(t3,De,472,e,0,1)},F(Mn,"EcorePackageImpl/18",1201),D(1202,1,si,bJ),l.wj=function(e){return _t(e,548)},l.xj=function(e){return Nt(cc,C0e,548,e,0,1)},F(Mn,"EcorePackageImpl/19",1202),D(1185,1,si,vB),l.wj=function(e){return _t(e,322)},l.xj=function(e){return Nt(e3,B4,34,e,0,1)},F(Mn,"EcorePackageImpl/2",1185),D(1203,1,si,jk),l.wj=function(e){return _t(e,241)},l.xj=function(e){return Nt(ho,q0e,87,e,0,1)},F(Mn,"EcorePackageImpl/20",1203),D(1204,1,si,eC),l.wj=function(e){return _t(e,444)},l.xj=function(e){return Nt(hu,De,836,e,0,1)},F(Mn,"EcorePackageImpl/21",1204),D(1205,1,si,mB),l.wj=function(e){return Nm(e)},l.xj=function(e){return Nt(Rs,ee,476,e,8,1)},F(Mn,"EcorePackageImpl/22",1205),D(1206,1,si,wJ),l.wj=function(e){return _t(e,190)},l.xj=function(e){return Nt(Gu,ee,190,e,0,2)},F(Mn,"EcorePackageImpl/23",1206),D(1207,1,si,yB),l.wj=function(e){return _t(e,217)},l.xj=function(e){return Nt(M6,ee,217,e,0,1)},F(Mn,"EcorePackageImpl/24",1207),D(1208,1,si,xB),l.wj=function(e){return _t(e,172)},l.xj=function(e){return Nt(uS,ee,172,e,0,1)},F(Mn,"EcorePackageImpl/25",1208),D(1209,1,si,vJ),l.wj=function(e){return _t(e,199)},l.xj=function(e){return Nt(tV,ee,199,e,0,1)},F(Mn,"EcorePackageImpl/26",1209),D(1210,1,si,nC),l.wj=function(e){return!1},l.xj=function(e){return Nt(PLt,De,2110,e,0,1)},F(Mn,"EcorePackageImpl/27",1210),D(1211,1,si,Cm),l.wj=function(e){return Bm(e)},l.xj=function(e){return Nt(la,ee,333,e,7,1)},F(Mn,"EcorePackageImpl/28",1211),D(1212,1,si,kB),l.wj=function(e){return _t(e,58)},l.xj=function(e){return Nt(KAt,Ty,58,e,0,1)},F(Mn,"EcorePackageImpl/29",1212),D(1186,1,si,EB),l.wj=function(e){return _t(e,510)},l.xj=function(e){return Nt(Zr,{3:1,4:1,5:1,1934:1},590,e,0,1)},F(Mn,"EcorePackageImpl/3",1186),D(1213,1,si,mJ),l.wj=function(e){return _t(e,573)},l.xj=function(e){return Nt(ZAt,De,1940,e,0,1)},F(Mn,"EcorePackageImpl/30",1213),D(1214,1,si,yJ),l.wj=function(e){return _t(e,153)},l.xj=function(e){return Nt(xLt,Ty,153,e,0,1)},F(Mn,"EcorePackageImpl/31",1214),D(1215,1,si,rC),l.wj=function(e){return _t(e,72)},l.xj=function(e){return Nt(bU,Q0e,72,e,0,1)},F(Mn,"EcorePackageImpl/32",1215),D(1216,1,si,TB),l.wj=function(e){return _t(e,155)},l.xj=function(e){return Nt(i7,ee,155,e,0,1)},F(Mn,"EcorePackageImpl/33",1216),D(1217,1,si,CB),l.wj=function(e){return _t(e,19)},l.xj=function(e){return Nt(ja,ee,19,e,0,1)},F(Mn,"EcorePackageImpl/34",1217),D(1218,1,si,uc),l.wj=function(e){return _t(e,290)},l.xj=function(e){return Nt(J8t,De,290,e,0,1)},F(Mn,"EcorePackageImpl/35",1218),D(1219,1,si,xJ),l.wj=function(e){return _t(e,162)},l.xj=function(e){return Nt(Sv,ee,162,e,0,1)},F(Mn,"EcorePackageImpl/36",1219),D(1220,1,si,_B),l.wj=function(e){return _t(e,83)},l.xj=function(e){return Nt(tEt,De,83,e,0,1)},F(Mn,"EcorePackageImpl/37",1220),D(1221,1,si,iC),l.wj=function(e){return _t(e,591)},l.xj=function(e){return Nt(wLt,De,591,e,0,1)},F(Mn,"EcorePackageImpl/38",1221),D(1222,1,si,kJ),l.wj=function(e){return!1},l.xj=function(e){return Nt(FLt,De,2111,e,0,1)},F(Mn,"EcorePackageImpl/39",1222),D(1187,1,si,EJ),l.wj=function(e){return _t(e,88)},l.xj=function(e){return Nt(Uh,De,26,e,0,1)},F(Mn,"EcorePackageImpl/4",1187),D(1223,1,si,sC),l.wj=function(e){return _t(e,184)},l.xj=function(e){return Nt(Av,ee,184,e,0,1)},F(Mn,"EcorePackageImpl/40",1223),D(1224,1,si,SB),l.wj=function(e){return ra(e)},l.xj=function(e){return Nt(Ae,ee,2,e,6,1)},F(Mn,"EcorePackageImpl/41",1224),D(1225,1,si,aC),l.wj=function(e){return _t(e,588)},l.xj=function(e){return Nt(QAt,De,588,e,0,1)},F(Mn,"EcorePackageImpl/42",1225),D(1226,1,si,oC),l.wj=function(e){return!1},l.xj=function(e){return Nt(NLt,ee,2112,e,0,1)},F(Mn,"EcorePackageImpl/43",1226),D(1227,1,si,jf),l.wj=function(e){return _t(e,42)},l.xj=function(e){return Nt(P2,Hq,42,e,0,1)},F(Mn,"EcorePackageImpl/44",1227),D(1188,1,si,VL),l.wj=function(e){return _t(e,138)},l.xj=function(e){return Nt(s1,De,138,e,0,1)},F(Mn,"EcorePackageImpl/5",1188),D(1189,1,si,GL),l.wj=function(e){return _t(e,148)},l.xj=function(e){return Nt(Nft,De,148,e,0,1)},F(Mn,"EcorePackageImpl/6",1189),D(1190,1,si,lx),l.wj=function(e){return _t(e,457)},l.xj=function(e){return Nt(pU,De,671,e,0,1)},F(Mn,"EcorePackageImpl/7",1190),D(1191,1,si,TJ),l.wj=function(e){return _t(e,573)},l.xj=function(e){return Nt(ag,De,678,e,0,1)},F(Mn,"EcorePackageImpl/8",1191),D(1192,1,si,CJ),l.wj=function(e){return _t(e,471)},l.xj=function(e){return Nt(sA,De,471,e,0,1)},F(Mn,"EcorePackageImpl/9",1192),D(1025,1982,T0e,sHt),l.bi=function(e,n){Mln(this,u(n,415))},l.fi=function(e,n){moe(this,e,u(n,415))},F(Mn,"MinimalEObjectImpl/1ArrayDelegatingAdapterList",1025),D(1026,143,nO,yXt),l.Ai=function(){return this.a.a},F(Mn,"MinimalEObjectImpl/1ArrayDelegatingAdapterList/1",1026),D(1053,1052,{},NUt),F("org.eclipse.emf.ecore.plugin","EcorePlugin",1053);var wLt=Ki(Z0e,"Resource");D(781,1378,J0e),l.Yk=function(e){},l.Zk=function(e){},l.Vk=function(){return!this.a&&(this.a=new Ztt(this)),this.a},l.Wk=function(e){var n,r,s,o,h;if(s=e.length,s>0)if(Rr(0,e.length),e.charCodeAt(0)==47){for(h=new Xc(4),o=1,n=1;n0&&(e=e.substr(0,r)));return Zpn(this,e)},l.Xk=function(){return this.c},l.Ib=function(){var e;return Ip(this.gm)+"@"+(e=Hi(this)>>>0,e.toString(16))+" uri='"+this.d+"'"},l.b=!1,F(fut,"ResourceImpl",781),D(1379,781,J0e,Jzt),F(fut,"BinaryResourceImpl",1379),D(1169,694,aut),l.si=function(e){return _t(e,56)?Orn(this,u(e,56)):_t(e,591)?new nr(u(e,591).Vk()):Vt(e)===Vt(this.f)?u(e,14).Kc():(y8(),pP.a)},l.Ob=function(){return h5t(this)},l.a=!1,F($i,"EcoreUtil/ContentTreeIterator",1169),D(1380,1169,aut,QKt),l.si=function(e){return Vt(e)===Vt(this.f)?u(e,15).Kc():new PZt(u(e,56))},F(fut,"ResourceImpl/5",1380),D(648,1994,z0e,Ztt),l.Hc=function(e){return this.i<=4?yE(this,e):_t(e,49)&&u(e,49).Zg()==this.a},l.bi=function(e,n){e==this.i-1&&(this.a.b||(this.a.b=!0))},l.di=function(e,n){e==0?this.a.b||(this.a.b=!0):Yrt(this,e,n)},l.fi=function(e,n){},l.gi=function(e,n,r){},l.aj=function(){return 2},l.Ai=function(){return this.a},l.bj=function(){return!0},l.cj=function(e,n){var r;return r=u(e,49),n=r.wh(this.a,n),n},l.dj=function(e,n){var r;return r=u(e,49),r.wh(null,n)},l.ej=function(){return!1},l.hi=function(){return!0},l.ri=function(e){return Nt(_b,De,56,e,0,1)},l.ni=function(){return!1},F(fut,"ResourceImpl/ContentsEList",648),D(957,1964,jE,Zzt),l.Zc=function(e){return this.a._h(e)},l.gc=function(){return this.a.gc()},F($i,"AbstractSequentialInternalEList/1",957);var vLt,mLt,ya,yLt;D(624,1,{},JYt);var wU,vU;F($i,"BasicExtendedMetaData",624),D(1160,1,{},JGt),l.$k=function(){return null},l._k=function(){return this.a==-2&&Tg(this,sgn(this.d,this.b)),this.a},l.al=function(){return null},l.bl=function(){return wn(),wn(),io},l.ne=function(){return this.c==t7&&O3(this,Xie(this.d,this.b)),this.c},l.cl=function(){return 0},l.a=-2,l.c=t7,F($i,"BasicExtendedMetaData/EClassExtendedMetaDataImpl",1160),D(1161,1,{},yZt),l.$k=function(){return this.a==(B8(),wU)&&ypt(this,xwn(this.f,this.b)),this.a},l._k=function(){return 0},l.al=function(){return this.c==(B8(),wU)&&Ftt(this,kwn(this.f,this.b)),this.c},l.bl=function(){return!this.d&&Ntt(this,xmn(this.f,this.b)),this.d},l.ne=function(){return this.e==t7&&cR(this,Xie(this.f,this.b)),this.e},l.cl=function(){return this.g==-2&&uR(this,T0n(this.f,this.b)),this.g},l.e=t7,l.g=-2,F($i,"BasicExtendedMetaData/EDataTypeExtendedMetaDataImpl",1161),D(1159,1,{},eUt),l.b=!1,l.c=!1,F($i,"BasicExtendedMetaData/EPackageExtendedMetaDataImpl",1159),D(1162,1,{},mZt),l.c=-2,l.e=t7,l.f=t7,F($i,"BasicExtendedMetaData/EStructuralFeatureExtendedMetaDataImpl",1162),D(585,622,zo,Rj),l.aj=function(){return this.c},l.Fk=function(){return!1},l.li=function(e,n){return n},l.c=0,F($i,"EDataTypeEList",585);var xLt=Ki($i,"FeatureMap");D(75,585,{3:1,4:1,20:1,28:1,52:1,14:1,15:1,54:1,67:1,63:1,58:1,76:1,153:1,215:1,1937:1,69:1,95:1},ss),l.Vc=function(e,n){wwn(this,e,u(n,72))},l.Fc=function(e){return N2n(this,u(e,72))},l.Yh=function(e){knn(this,u(e,72))},l.cj=function(e,n){return nJe(this,u(e,72),n)},l.dj=function(e,n){return vwt(this,u(e,72),n)},l.ii=function(e,n){return jmn(this,e,n)},l.li=function(e,n){return v4n(this,e,u(n,72))},l._c=function(e,n){return ovn(this,e,u(n,72))},l.jj=function(e,n){return rJe(this,u(e,72),n)},l.kj=function(e,n){return TYt(this,u(e,72),n)},l.lj=function(e,n,r){return o0n(this,u(e,72),u(n,72),r)},l.oi=function(e,n){return Rst(this,e,u(n,72))},l.dl=function(e,n){return J5t(this,e,n)},l.Wc=function(e,n){var r,s,o,h,d,v,k,C,M;for(C=new Qw(n.gc()),o=n.Kc();o.Ob();)if(s=u(o.Pb(),72),h=s.ak(),X0(this.e,h))(!h.hi()||!O$(this,h,s.dd())&&!yE(C,s))&&Dr(C,s);else{for(M=ou(this.e.Tg(),h),r=u(this.g,119),d=!0,v=0;v=0;)if(n=e[this.c],this.k.rl(n.ak()))return this.j=this.f?n:n.dd(),this.i=-2,!0;return this.i=-1,this.g=-1,!1},F($i,"BasicFeatureMap/FeatureEIterator",410),D(662,410,n0,rnt),l.Lk=function(){return!0},F($i,"BasicFeatureMap/ResolvingFeatureEIterator",662),D(955,486,NH,UUt),l.Gi=function(){return this},F($i,"EContentsEList/1",955),D(956,486,NH,wUt),l.Lk=function(){return!1},F($i,"EContentsEList/2",956),D(954,279,BH,WUt),l.Nk=function(e){},l.Ob=function(){return!1},l.Sb=function(){return!1},F($i,"EContentsEList/FeatureIteratorImpl/1",954),D(825,585,zo,E2t),l.ci=function(){this.a=!0},l.fj=function(){return this.a},l.Xj=function(){var e;xr(this),xl(this.e)?(e=this.a,this.a=!1,mi(this.e,new bf(this.e,2,this.c,e,!1))):this.a=!1},l.a=!1,F($i,"EDataTypeEList/Unsettable",825),D(1849,585,zo,eWt),l.hi=function(){return!0},F($i,"EDataTypeUniqueEList",1849),D(1850,825,zo,nWt),l.hi=function(){return!0},F($i,"EDataTypeUniqueEList/Unsettable",1850),D(139,85,zo,Fu),l.Ek=function(){return!0},l.li=function(e,n){return g6(this,e,u(n,56))},F($i,"EObjectContainmentEList/Resolving",139),D(1163,545,zo,tWt),l.Ek=function(){return!0},l.li=function(e,n){return g6(this,e,u(n,56))},F($i,"EObjectContainmentEList/Unsettable/Resolving",1163),D(748,16,zo,hwt),l.ci=function(){this.a=!0},l.fj=function(){return this.a},l.Xj=function(){var e;xr(this),xl(this.e)?(e=this.a,this.a=!1,mi(this.e,new bf(this.e,2,this.c,e,!1))):this.a=!1},l.a=!1,F($i,"EObjectContainmentWithInverseEList/Unsettable",748),D(1173,748,zo,hYt),l.Ek=function(){return!0},l.li=function(e,n){return g6(this,e,u(n,56))},F($i,"EObjectContainmentWithInverseEList/Unsettable/Resolving",1173),D(743,496,zo,k2t),l.ci=function(){this.a=!0},l.fj=function(){return this.a},l.Xj=function(){var e;xr(this),xl(this.e)?(e=this.a,this.a=!1,mi(this.e,new bf(this.e,2,this.c,e,!1))):this.a=!1},l.a=!1,F($i,"EObjectEList/Unsettable",743),D(328,496,zo,Y3),l.Ek=function(){return!0},l.li=function(e,n){return g6(this,e,u(n,56))},F($i,"EObjectResolvingEList",328),D(1641,743,zo,rWt),l.Ek=function(){return!0},l.li=function(e,n){return g6(this,e,u(n,56))},F($i,"EObjectResolvingEList/Unsettable",1641),D(1381,1,{},_J);var C5e;F($i,"EObjectValidator",1381),D(546,496,zo,r$),l.zk=function(){return this.d},l.Ak=function(){return this.b},l.bj=function(){return!0},l.Dk=function(){return!0},l.b=0,F($i,"EObjectWithInverseEList",546),D(1176,546,zo,fYt),l.Ck=function(){return!0},F($i,"EObjectWithInverseEList/ManyInverse",1176),D(625,546,zo,Ent),l.ci=function(){this.a=!0},l.fj=function(){return this.a},l.Xj=function(){var e;xr(this),xl(this.e)?(e=this.a,this.a=!1,mi(this.e,new bf(this.e,2,this.c,e,!1))):this.a=!1},l.a=!1,F($i,"EObjectWithInverseEList/Unsettable",625),D(1175,625,zo,dYt),l.Ck=function(){return!0},F($i,"EObjectWithInverseEList/Unsettable/ManyInverse",1175),D(749,546,zo,fwt),l.Ek=function(){return!0},l.li=function(e,n){return g6(this,e,u(n,56))},F($i,"EObjectWithInverseResolvingEList",749),D(31,749,zo,Cn),l.Ck=function(){return!0},F($i,"EObjectWithInverseResolvingEList/ManyInverse",31),D(750,625,zo,dwt),l.Ek=function(){return!0},l.li=function(e,n){return g6(this,e,u(n,56))},F($i,"EObjectWithInverseResolvingEList/Unsettable",750),D(1174,750,zo,gYt),l.Ck=function(){return!0},F($i,"EObjectWithInverseResolvingEList/Unsettable/ManyInverse",1174),D(1164,622,zo),l.ai=function(){return(this.b&1792)==0},l.ci=function(){this.b|=1},l.Bk=function(){return(this.b&4)!=0},l.bj=function(){return(this.b&40)!=0},l.Ck=function(){return(this.b&16)!=0},l.Dk=function(){return(this.b&8)!=0},l.Ek=function(){return(this.b&Dy)!=0},l.rk=function(){return(this.b&32)!=0},l.Fk=function(){return(this.b&xf)!=0},l.wj=function(e){return this.d?KZt(this.d,e):this.ak().Yj().wj(e)},l.fj=function(){return this.b&2?(this.b&1)!=0:this.i!=0},l.hi=function(){return(this.b&128)!=0},l.Xj=function(){var e;xr(this),this.b&2&&(xl(this.e)?(e=(this.b&1)!=0,this.b&=-2,n8(this,new bf(this.e,2,Gi(this.e.Tg(),this.ak()),e,!1))):this.b&=-2)},l.ni=function(){return(this.b&1536)==0},l.b=0,F($i,"EcoreEList/Generic",1164),D(1165,1164,zo,iQt),l.ak=function(){return this.a},F($i,"EcoreEList/Dynamic",1165),D(747,63,Ld,_pt),l.ri=function(e){return MD(this.a.a,e)},F($i,"EcoreEMap/1",747),D(746,85,zo,hvt),l.bi=function(e,n){Jz(this.b,u(n,133))},l.di=function(e,n){Vne(this.b)},l.ei=function(e,n,r){var s;++(s=this.b,u(n,133),s).e},l.fi=function(e,n){Wit(this.b,u(n,133))},l.gi=function(e,n,r){Wit(this.b,u(r,133)),Vt(r)===Vt(n)&&u(r,133).Th(hQe(u(n,133).cd())),Jz(this.b,u(n,133))},F($i,"EcoreEMap/DelegateEObjectContainmentEList",746),D(1171,151,j8t,rne),F($i,"EcoreEMap/Unsettable",1171),D(1172,746,zo,pYt),l.ci=function(){this.a=!0},l.fj=function(){return this.a},l.Xj=function(){var e;xr(this),xl(this.e)?(e=this.a,this.a=!1,mi(this.e,new bf(this.e,2,this.c,e,!1))):this.a=!1},l.a=!1,F($i,"EcoreEMap/Unsettable/UnsettableDelegateEObjectContainmentEList",1172),D(1168,228,A4,oXt),l.a=!1,l.b=!1,F($i,"EcoreUtil/Copier",1168),D(745,1,sa,PZt),l.Nb=function(e){ba(this,e)},l.Ob=function(){return Mie(this)},l.Pb=function(){var e;return Mie(this),e=this.b,this.b=null,e},l.Qb=function(){this.a.Qb()},F($i,"EcoreUtil/ProperContentIterator",745),D(1382,1381,{},tR);var _5e;F($i,"EcoreValidator",1382);var S5e;Ki($i,"FeatureMapUtil/Validator"),D(1260,1,{1942:1},SJ),l.rl=function(e){return!0},F($i,"FeatureMapUtil/1",1260),D(757,1,{1942:1},Axt),l.rl=function(e){var n;return this.c==e?!0:(n=Re(tr(this.a,e)),n==null?nmn(this,e)?(qJt(this.a,e,(Nn(),r7)),!0):(qJt(this.a,e,(Nn(),F2)),!1):n==(Nn(),r7))},l.e=!1;var $ft;F($i,"FeatureMapUtil/BasicValidator",757),D(758,43,A4,v2t),F($i,"FeatureMapUtil/BasicValidator/Cache",758),D(501,52,{20:1,28:1,52:1,14:1,15:1,58:1,76:1,69:1,95:1},BM),l.Vc=function(e,n){sue(this.c,this.b,e,n)},l.Fc=function(e){return J5t(this.c,this.b,e)},l.Wc=function(e,n){return w3n(this.c,this.b,e,n)},l.Gc=function(e){return g9(this,e)},l.Xh=function(e,n){Ron(this.c,this.b,e,n)},l.lk=function(e,n){return W5t(this.c,this.b,e,n)},l.pi=function(e){return Iq(this.c,this.b,e,!1)},l.Zh=function(){return AUt(this.c,this.b)},l.$h=function(){return ZXe(this.c,this.b)},l._h=function(e){return Han(this.c,this.b,e)},l.mk=function(e,n){return WWt(this,e,n)},l.$b=function(){Tx(this)},l.Hc=function(e){return O$(this.c,this.b,e)},l.Ic=function(e){return qcn(this.c,this.b,e)},l.Xb=function(e){return Iq(this.c,this.b,e,!0)},l.Wj=function(e){return this},l.Xc=function(e){return tan(this.c,this.b,e)},l.dc=function(){return hj(this)},l.fj=function(){return!XD(this.c,this.b)},l.Kc=function(){return _on(this.c,this.b)},l.Yc=function(){return Son(this.c,this.b)},l.Zc=function(e){return jln(this.c,this.b,e)},l.ii=function(e,n){return Ele(this.c,this.b,e,n)},l.ji=function(e,n){Ban(this.c,this.b,e,n)},l.$c=function(e){return noe(this.c,this.b,e)},l.Mc=function(e){return Emn(this.c,this.b,e)},l._c=function(e,n){return Lle(this.c,this.b,e,n)},l.Wb=function(e){pq(this.c,this.b),g9(this,u(e,15))},l.gc=function(){return Zln(this.c,this.b)},l.Pc=function(){return Qin(this.c,this.b)},l.Qc=function(e){return ean(this.c,this.b,e)},l.Ib=function(){var e,n;for(n=new Ag,n.a+="[",e=AUt(this.c,this.b);Bit(e);)go(n,b9(Qz(e))),Bit(e)&&(n.a+=Ya);return n.a+="]",n.a},l.Xj=function(){pq(this.c,this.b)},F($i,"FeatureMapUtil/FeatureEList",501),D(627,36,nO,jrt),l.yi=function(e){return e_(this,e)},l.Di=function(e){var n,r,s,o,h,d,v;switch(this.d){case 1:case 2:{if(h=e.Ai(),Vt(h)===Vt(this.c)&&e_(this,null)==e.yi(null))return this.g=e.zi(),e.xi()==1&&(this.d=1),!0;break}case 3:{switch(o=e.xi(),o){case 3:{if(h=e.Ai(),Vt(h)===Vt(this.c)&&e_(this,null)==e.yi(null))return this.d=5,n=new Qw(2),Dr(n,this.g),Dr(n,e.zi()),this.g=n,!0;break}}break}case 5:{switch(o=e.xi(),o){case 3:{if(h=e.Ai(),Vt(h)===Vt(this.c)&&e_(this,null)==e.yi(null))return r=u(this.g,14),r.Fc(e.zi()),!0;break}}break}case 4:{switch(o=e.xi(),o){case 3:{if(h=e.Ai(),Vt(h)===Vt(this.c)&&e_(this,null)==e.yi(null))return this.d=1,this.g=e.zi(),!0;break}case 4:{if(h=e.Ai(),Vt(h)===Vt(this.c)&&e_(this,null)==e.yi(null))return this.d=6,v=new Qw(2),Dr(v,this.n),Dr(v,e.Bi()),this.n=v,d=lt(ct(Cr,1),Xr,25,15,[this.o,e.Ci()]),this.g=d,!0;break}}break}case 6:{switch(o=e.xi(),o){case 4:{if(h=e.Ai(),Vt(h)===Vt(this.c)&&e_(this,null)==e.yi(null))return r=u(this.n,14),r.Fc(e.Bi()),d=u(this.g,48),s=Nt(Cr,Xr,25,d.length+1,15,1),Dc(d,0,s,0,d.length),s[d.length]=e.Ci(),this.g=s,!0;break}}break}}return!1},F($i,"FeatureMapUtil/FeatureENotificationImpl",627),D(552,501,{20:1,28:1,52:1,14:1,15:1,58:1,76:1,153:1,215:1,1937:1,69:1,95:1},qj),l.dl=function(e,n){return J5t(this.c,e,n)},l.el=function(e,n,r){return W5t(this.c,e,n,r)},l.fl=function(e,n,r){return bxt(this.c,e,n,r)},l.gl=function(){return this},l.hl=function(e,n){return SI(this.c,e,n)},l.il=function(e){return u(Iq(this.c,this.b,e,!1),72).ak()},l.jl=function(e){return u(Iq(this.c,this.b,e,!1),72).dd()},l.kl=function(){return this.a},l.ll=function(e){return!XD(this.c,e)},l.ml=function(e,n){Oq(this.c,e,n)},l.nl=function(e){return lne(this.c,e)},l.ol=function(e){Pse(this.c,e)},F($i,"FeatureMapUtil/FeatureFeatureMap",552),D(1259,1,hut,nUt),l.Wj=function(e){return Iq(this.b,this.a,-1,e)},l.fj=function(){return!XD(this.b,this.a)},l.Wb=function(e){Oq(this.b,this.a,e)},l.Xj=function(){pq(this.b,this.a)},F($i,"FeatureMapUtil/FeatureValue",1259);var J6,zft,qft,tk,A5e,wP=Ki(GH,"AnyType");D(666,60,Q0,pet),F(GH,"InvalidDatatypeValueException",666);var mU=Ki(GH,ege),vP=Ki(GH,nge),kLt=Ki(GH,rge),L5e,pc,ELt,X2,M5e,D5e,I5e,O5e,P5e,F5e,N5e,B5e,R5e,j5e,$5e,h5,z5e,f5,lA,q5e,Wv,mP,yP,H5e,hA,fA;D(830,506,{105:1,92:1,90:1,56:1,49:1,97:1,843:1},Wpt),l._g=function(e,n,r){switch(e){case 0:return r?(!this.c&&(this.c=new ss(this,0)),this.c):(!this.c&&(this.c=new ss(this,0)),this.c.b);case 1:return r?(!this.c&&(this.c=new ss(this,0)),u(Bc(this.c,(Ii(),X2)),153)):(!this.c&&(this.c=new ss(this,0)),u(u(Bc(this.c,(Ii(),X2)),153),215)).kl();case 2:return r?(!this.b&&(this.b=new ss(this,2)),this.b):(!this.b&&(this.b=new ss(this,2)),this.b.b)}return uh(this,e-Jn(this.zh()),yn(this.j&2?(!this.k&&(this.k=new nh),this.k).ck():this.zh(),e),n,r)},l.jh=function(e,n,r){var s;switch(n){case 0:return!this.c&&(this.c=new ss(this,0)),EI(this.c,e,r);case 1:return(!this.c&&(this.c=new ss(this,0)),u(u(Bc(this.c,(Ii(),X2)),153),69)).mk(e,r);case 2:return!this.b&&(this.b=new ss(this,2)),EI(this.b,e,r)}return s=u(yn(this.j&2?(!this.k&&(this.k=new nh),this.k).ck():this.zh(),n),66),s.Nj().Rj(this,$mt(this),n-Jn(this.zh()),e,r)},l.lh=function(e){switch(e){case 0:return!!this.c&&this.c.i!=0;case 1:return!(!this.c&&(this.c=new ss(this,0)),u(Bc(this.c,(Ii(),X2)),153)).dc();case 2:return!!this.b&&this.b.i!=0}return oh(this,e-Jn(this.zh()),yn(this.j&2?(!this.k&&(this.k=new nh),this.k).ck():this.zh(),e))},l.sh=function(e,n){switch(e){case 0:!this.c&&(this.c=new ss(this,0)),nD(this.c,n);return;case 1:(!this.c&&(this.c=new ss(this,0)),u(u(Bc(this.c,(Ii(),X2)),153),215)).Wb(n);return;case 2:!this.b&&(this.b=new ss(this,2)),nD(this.b,n);return}gh(this,e-Jn(this.zh()),yn(this.j&2?(!this.k&&(this.k=new nh),this.k).ck():this.zh(),e),n)},l.zh=function(){return Ii(),ELt},l.Bh=function(e){switch(e){case 0:!this.c&&(this.c=new ss(this,0)),xr(this.c);return;case 1:(!this.c&&(this.c=new ss(this,0)),u(Bc(this.c,(Ii(),X2)),153)).$b();return;case 2:!this.b&&(this.b=new ss(this,2)),xr(this.b);return}fh(this,e-Jn(this.zh()),yn(this.j&2?(!this.k&&(this.k=new nh),this.k).ck():this.zh(),e))},l.Ib=function(){var e;return this.j&4?mf(this):(e=new _h(mf(this)),e.a+=" (mixed: ",l9(e,this.c),e.a+=", anyAttribute: ",l9(e,this.b),e.a+=")",e.a)},F(xs,"AnyTypeImpl",830),D(667,506,{105:1,92:1,90:1,56:1,49:1,97:1,2021:1,667:1},AB),l._g=function(e,n,r){switch(e){case 0:return this.a;case 1:return this.b}return uh(this,e-Jn((Ii(),h5)),yn(this.j&2?(!this.k&&(this.k=new nh),this.k).ck():h5,e),n,r)},l.lh=function(e){switch(e){case 0:return this.a!=null;case 1:return this.b!=null}return oh(this,e-Jn((Ii(),h5)),yn(this.j&2?(!this.k&&(this.k=new nh),this.k).ck():h5,e))},l.sh=function(e,n){switch(e){case 0:$tt(this,Br(n));return;case 1:kpt(this,Br(n));return}gh(this,e-Jn((Ii(),h5)),yn(this.j&2?(!this.k&&(this.k=new nh),this.k).ck():h5,e),n)},l.zh=function(){return Ii(),h5},l.Bh=function(e){switch(e){case 0:this.a=null;return;case 1:this.b=null;return}fh(this,e-Jn((Ii(),h5)),yn(this.j&2?(!this.k&&(this.k=new nh),this.k).ck():h5,e))},l.Ib=function(){var e;return this.j&4?mf(this):(e=new _h(mf(this)),e.a+=" (data: ",go(e,this.a),e.a+=", target: ",go(e,this.b),e.a+=")",e.a)},l.a=null,l.b=null,F(xs,"ProcessingInstructionImpl",667),D(668,830,{105:1,92:1,90:1,56:1,49:1,97:1,843:1,2022:1,668:1},Hqt),l._g=function(e,n,r){switch(e){case 0:return r?(!this.c&&(this.c=new ss(this,0)),this.c):(!this.c&&(this.c=new ss(this,0)),this.c.b);case 1:return r?(!this.c&&(this.c=new ss(this,0)),u(Bc(this.c,(Ii(),X2)),153)):(!this.c&&(this.c=new ss(this,0)),u(u(Bc(this.c,(Ii(),X2)),153),215)).kl();case 2:return r?(!this.b&&(this.b=new ss(this,2)),this.b):(!this.b&&(this.b=new ss(this,2)),this.b.b);case 3:return!this.c&&(this.c=new ss(this,0)),Br(SI(this.c,(Ii(),lA),!0));case 4:return gwt(this.a,(!this.c&&(this.c=new ss(this,0)),Br(SI(this.c,(Ii(),lA),!0))));case 5:return this.a}return uh(this,e-Jn((Ii(),f5)),yn(this.j&2?(!this.k&&(this.k=new nh),this.k).ck():f5,e),n,r)},l.lh=function(e){switch(e){case 0:return!!this.c&&this.c.i!=0;case 1:return!(!this.c&&(this.c=new ss(this,0)),u(Bc(this.c,(Ii(),X2)),153)).dc();case 2:return!!this.b&&this.b.i!=0;case 3:return!this.c&&(this.c=new ss(this,0)),Br(SI(this.c,(Ii(),lA),!0))!=null;case 4:return gwt(this.a,(!this.c&&(this.c=new ss(this,0)),Br(SI(this.c,(Ii(),lA),!0))))!=null;case 5:return!!this.a}return oh(this,e-Jn((Ii(),f5)),yn(this.j&2?(!this.k&&(this.k=new nh),this.k).ck():f5,e))},l.sh=function(e,n){switch(e){case 0:!this.c&&(this.c=new ss(this,0)),nD(this.c,n);return;case 1:(!this.c&&(this.c=new ss(this,0)),u(u(Bc(this.c,(Ii(),X2)),153),215)).Wb(n);return;case 2:!this.b&&(this.b=new ss(this,2)),nD(this.b,n);return;case 3:Jvt(this,Br(n));return;case 4:Jvt(this,pwt(this.a,n));return;case 5:vc(this,u(n,148));return}gh(this,e-Jn((Ii(),f5)),yn(this.j&2?(!this.k&&(this.k=new nh),this.k).ck():f5,e),n)},l.zh=function(){return Ii(),f5},l.Bh=function(e){switch(e){case 0:!this.c&&(this.c=new ss(this,0)),xr(this.c);return;case 1:(!this.c&&(this.c=new ss(this,0)),u(Bc(this.c,(Ii(),X2)),153)).$b();return;case 2:!this.b&&(this.b=new ss(this,2)),xr(this.b);return;case 3:!this.c&&(this.c=new ss(this,0)),Oq(this.c,(Ii(),lA),null);return;case 4:Jvt(this,pwt(this.a,null));return;case 5:this.a=null;return}fh(this,e-Jn((Ii(),f5)),yn(this.j&2?(!this.k&&(this.k=new nh),this.k).ck():f5,e))},F(xs,"SimpleAnyTypeImpl",668),D(669,506,{105:1,92:1,90:1,56:1,49:1,97:1,2023:1,669:1},qqt),l._g=function(e,n,r){switch(e){case 0:return r?(!this.a&&(this.a=new ss(this,0)),this.a):(!this.a&&(this.a=new ss(this,0)),this.a.b);case 1:return r?(!this.b&&(this.b=new _l((dn(),Qa),cc,this,1)),this.b):(!this.b&&(this.b=new _l((dn(),Qa),cc,this,1)),wD(this.b));case 2:return r?(!this.c&&(this.c=new _l((dn(),Qa),cc,this,2)),this.c):(!this.c&&(this.c=new _l((dn(),Qa),cc,this,2)),wD(this.c));case 3:return!this.a&&(this.a=new ss(this,0)),Bc(this.a,(Ii(),mP));case 4:return!this.a&&(this.a=new ss(this,0)),Bc(this.a,(Ii(),yP));case 5:return!this.a&&(this.a=new ss(this,0)),Bc(this.a,(Ii(),hA));case 6:return!this.a&&(this.a=new ss(this,0)),Bc(this.a,(Ii(),fA))}return uh(this,e-Jn((Ii(),Wv)),yn(this.j&2?(!this.k&&(this.k=new nh),this.k).ck():Wv,e),n,r)},l.jh=function(e,n,r){var s;switch(n){case 0:return!this.a&&(this.a=new ss(this,0)),EI(this.a,e,r);case 1:return!this.b&&(this.b=new _l((dn(),Qa),cc,this,1)),Oj(this.b,e,r);case 2:return!this.c&&(this.c=new _l((dn(),Qa),cc,this,2)),Oj(this.c,e,r);case 5:return!this.a&&(this.a=new ss(this,0)),WWt(Bc(this.a,(Ii(),hA)),e,r)}return s=u(yn(this.j&2?(!this.k&&(this.k=new nh),this.k).ck():(Ii(),Wv),n),66),s.Nj().Rj(this,$mt(this),n-Jn((Ii(),Wv)),e,r)},l.lh=function(e){switch(e){case 0:return!!this.a&&this.a.i!=0;case 1:return!!this.b&&this.b.f!=0;case 2:return!!this.c&&this.c.f!=0;case 3:return!this.a&&(this.a=new ss(this,0)),!hj(Bc(this.a,(Ii(),mP)));case 4:return!this.a&&(this.a=new ss(this,0)),!hj(Bc(this.a,(Ii(),yP)));case 5:return!this.a&&(this.a=new ss(this,0)),!hj(Bc(this.a,(Ii(),hA)));case 6:return!this.a&&(this.a=new ss(this,0)),!hj(Bc(this.a,(Ii(),fA)))}return oh(this,e-Jn((Ii(),Wv)),yn(this.j&2?(!this.k&&(this.k=new nh),this.k).ck():Wv,e))},l.sh=function(e,n){switch(e){case 0:!this.a&&(this.a=new ss(this,0)),nD(this.a,n);return;case 1:!this.b&&(this.b=new _l((dn(),Qa),cc,this,1)),xz(this.b,n);return;case 2:!this.c&&(this.c=new _l((dn(),Qa),cc,this,2)),xz(this.c,n);return;case 3:!this.a&&(this.a=new ss(this,0)),Tx(Bc(this.a,(Ii(),mP))),!this.a&&(this.a=new ss(this,0)),g9(Bc(this.a,mP),u(n,14));return;case 4:!this.a&&(this.a=new ss(this,0)),Tx(Bc(this.a,(Ii(),yP))),!this.a&&(this.a=new ss(this,0)),g9(Bc(this.a,yP),u(n,14));return;case 5:!this.a&&(this.a=new ss(this,0)),Tx(Bc(this.a,(Ii(),hA))),!this.a&&(this.a=new ss(this,0)),g9(Bc(this.a,hA),u(n,14));return;case 6:!this.a&&(this.a=new ss(this,0)),Tx(Bc(this.a,(Ii(),fA))),!this.a&&(this.a=new ss(this,0)),g9(Bc(this.a,fA),u(n,14));return}gh(this,e-Jn((Ii(),Wv)),yn(this.j&2?(!this.k&&(this.k=new nh),this.k).ck():Wv,e),n)},l.zh=function(){return Ii(),Wv},l.Bh=function(e){switch(e){case 0:!this.a&&(this.a=new ss(this,0)),xr(this.a);return;case 1:!this.b&&(this.b=new _l((dn(),Qa),cc,this,1)),this.b.c.$b();return;case 2:!this.c&&(this.c=new _l((dn(),Qa),cc,this,2)),this.c.c.$b();return;case 3:!this.a&&(this.a=new ss(this,0)),Tx(Bc(this.a,(Ii(),mP)));return;case 4:!this.a&&(this.a=new ss(this,0)),Tx(Bc(this.a,(Ii(),yP)));return;case 5:!this.a&&(this.a=new ss(this,0)),Tx(Bc(this.a,(Ii(),hA)));return;case 6:!this.a&&(this.a=new ss(this,0)),Tx(Bc(this.a,(Ii(),fA)));return}fh(this,e-Jn((Ii(),Wv)),yn(this.j&2?(!this.k&&(this.k=new nh),this.k).ck():Wv,e))},l.Ib=function(){var e;return this.j&4?mf(this):(e=new _h(mf(this)),e.a+=" (mixed: ",l9(e,this.a),e.a+=")",e.a)},F(xs,"XMLTypeDocumentRootImpl",669),D(1919,704,{105:1,92:1,90:1,471:1,147:1,56:1,108:1,49:1,97:1,150:1,114:1,115:1,2024:1},_m),l.Ih=function(e,n){switch(e.yj()){case 7:case 8:case 9:case 10:case 16:case 22:case 23:case 24:case 25:case 26:case 32:case 33:case 34:case 36:case 37:case 44:case 45:case 50:case 51:case 53:case 55:case 56:case 57:case 58:case 60:case 61:case 4:return n==null?null:$o(n);case 19:case 28:case 29:case 35:case 38:case 39:case 41:case 46:case 52:case 54:case 5:return Br(n);case 6:return bZe(u(n,190));case 12:case 47:case 49:case 11:return bhe(this,e,n);case 13:return n==null?null:r3n(u(n,240));case 15:case 14:return n==null?null:dnn(Xt(ye(n)));case 17:return mae((Ii(),n));case 18:return mae(n);case 21:case 20:return n==null?null:gnn(u(n,155).a);case 27:return wZe(u(n,190));case 30:return Fse((Ii(),u(n,15)));case 31:return Fse(u(n,15));case 40:return mZe((Ii(),n));case 42:return yae((Ii(),n));case 43:return yae(n);case 59:case 48:return vZe((Ii(),n));default:throw it(new Fn(QE+e.ne()+Cv))}},l.Jh=function(e){var n,r,s,o,h;switch(e.G==-1&&(e.G=(r=Rl(e),r?Hg(r.Mh(),e):-1)),e.G){case 0:return n=new Wpt,n;case 1:return s=new AB,s;case 2:return o=new Hqt,o;case 3:return h=new qqt,h;default:throw it(new Fn(Kct+e.zb+Cv))}},l.Kh=function(e,n){var r,s,o,h,d,v,k,C,M,j,H,G,K,tt,gt,Mt;switch(e.yj()){case 5:case 52:case 4:return n;case 6:return Ofn(n);case 8:case 7:return n==null?null:y0n(n);case 9:return n==null?null:AD(ql((s=$c(n,!0),s.length>0&&(Rr(0,s.length),s.charCodeAt(0)==43)?s.substr(1):s),-128,127)<<24>>24);case 10:return n==null?null:AD(ql((o=$c(n,!0),o.length>0&&(Rr(0,o.length),o.charCodeAt(0)==43)?o.substr(1):o),-128,127)<<24>>24);case 11:return Br(vv(this,(Ii(),I5e),n));case 12:return Br(vv(this,(Ii(),O5e),n));case 13:return n==null?null:new gbt($c(n,!0));case 15:case 14:return z2n(n);case 16:return Br(vv(this,(Ii(),P5e),n));case 17:return zie((Ii(),n));case 18:return zie(n);case 28:case 29:case 35:case 38:case 39:case 41:case 54:case 19:return $c(n,!0);case 21:case 20:return X2n(n);case 22:return Br(vv(this,(Ii(),F5e),n));case 23:return Br(vv(this,(Ii(),N5e),n));case 24:return Br(vv(this,(Ii(),B5e),n));case 25:return Br(vv(this,(Ii(),R5e),n));case 26:return Br(vv(this,(Ii(),j5e),n));case 27:return Afn(n);case 30:return qie((Ii(),n));case 31:return qie(n);case 32:return n==null?null:pe(ql((M=$c(n,!0),M.length>0&&(Rr(0,M.length),M.charCodeAt(0)==43)?M.substr(1):M),Sa,wi));case 33:return n==null?null:new Rp((j=$c(n,!0),j.length>0&&(Rr(0,j.length),j.charCodeAt(0)==43)?j.substr(1):j));case 34:return n==null?null:pe(ql((H=$c(n,!0),H.length>0&&(Rr(0,H.length),H.charCodeAt(0)==43)?H.substr(1):H),Sa,wi));case 36:return n==null?null:v2(Rq((G=$c(n,!0),G.length>0&&(Rr(0,G.length),G.charCodeAt(0)==43)?G.substr(1):G)));case 37:return n==null?null:v2(Rq((K=$c(n,!0),K.length>0&&(Rr(0,K.length),K.charCodeAt(0)==43)?K.substr(1):K)));case 40:return Vhn((Ii(),n));case 42:return Hie((Ii(),n));case 43:return Hie(n);case 44:return n==null?null:new Rp((tt=$c(n,!0),tt.length>0&&(Rr(0,tt.length),tt.charCodeAt(0)==43)?tt.substr(1):tt));case 45:return n==null?null:new Rp((gt=$c(n,!0),gt.length>0&&(Rr(0,gt.length),gt.charCodeAt(0)==43)?gt.substr(1):gt));case 46:return $c(n,!1);case 47:return Br(vv(this,(Ii(),$5e),n));case 59:case 48:return Hhn((Ii(),n));case 49:return Br(vv(this,(Ii(),z5e),n));case 50:return n==null?null:uE(ql((Mt=$c(n,!0),Mt.length>0&&(Rr(0,Mt.length),Mt.charCodeAt(0)==43)?Mt.substr(1):Mt),zH,32767)<<16>>16);case 51:return n==null?null:uE(ql((h=$c(n,!0),h.length>0&&(Rr(0,h.length),h.charCodeAt(0)==43)?h.substr(1):h),zH,32767)<<16>>16);case 53:return Br(vv(this,(Ii(),q5e),n));case 55:return n==null?null:uE(ql((d=$c(n,!0),d.length>0&&(Rr(0,d.length),d.charCodeAt(0)==43)?d.substr(1):d),zH,32767)<<16>>16);case 56:return n==null?null:uE(ql((v=$c(n,!0),v.length>0&&(Rr(0,v.length),v.charCodeAt(0)==43)?v.substr(1):v),zH,32767)<<16>>16);case 57:return n==null?null:v2(Rq((k=$c(n,!0),k.length>0&&(Rr(0,k.length),k.charCodeAt(0)==43)?k.substr(1):k)));case 58:return n==null?null:v2(Rq((C=$c(n,!0),C.length>0&&(Rr(0,C.length),C.charCodeAt(0)==43)?C.substr(1):C)));case 60:return n==null?null:pe(ql((r=$c(n,!0),r.length>0&&(Rr(0,r.length),r.charCodeAt(0)==43)?r.substr(1):r),Sa,wi));case 61:return n==null?null:pe(ql($c(n,!0),Sa,wi));default:throw it(new Fn(QE+e.ne()+Cv))}};var V5e,TLt,G5e,CLt;F(xs,"XMLTypeFactoryImpl",1919),D(586,179,{105:1,92:1,90:1,147:1,191:1,56:1,235:1,108:1,49:1,97:1,150:1,179:1,114:1,115:1,675:1,1945:1,586:1},AXt),l.N=!1,l.O=!1;var U5e=!1;F(xs,"XMLTypePackageImpl",586),D(1852,1,{837:1},hx),l._j=function(){return oxt(),exe},F(xs,"XMLTypePackageImpl/1",1852),D(1861,1,si,d1),l.wj=function(e){return ra(e)},l.xj=function(e){return Nt(Ae,ee,2,e,6,1)},F(xs,"XMLTypePackageImpl/10",1861),D(1862,1,si,LB),l.wj=function(e){return ra(e)},l.xj=function(e){return Nt(Ae,ee,2,e,6,1)},F(xs,"XMLTypePackageImpl/11",1862),D(1863,1,si,MB),l.wj=function(e){return ra(e)},l.xj=function(e){return Nt(Ae,ee,2,e,6,1)},F(xs,"XMLTypePackageImpl/12",1863),D(1864,1,si,DB),l.wj=function(e){return Bm(e)},l.xj=function(e){return Nt(la,ee,333,e,7,1)},F(xs,"XMLTypePackageImpl/13",1864),D(1865,1,si,IB),l.wj=function(e){return ra(e)},l.xj=function(e){return Nt(Ae,ee,2,e,6,1)},F(xs,"XMLTypePackageImpl/14",1865),D(1866,1,si,OB),l.wj=function(e){return _t(e,15)},l.xj=function(e){return Nt(wh,Ty,15,e,0,1)},F(xs,"XMLTypePackageImpl/15",1866),D(1867,1,si,PB),l.wj=function(e){return _t(e,15)},l.xj=function(e){return Nt(wh,Ty,15,e,0,1)},F(xs,"XMLTypePackageImpl/16",1867),D(1868,1,si,$f),l.wj=function(e){return ra(e)},l.xj=function(e){return Nt(Ae,ee,2,e,6,1)},F(xs,"XMLTypePackageImpl/17",1868),D(1869,1,si,du),l.wj=function(e){return _t(e,155)},l.xj=function(e){return Nt(i7,ee,155,e,0,1)},F(xs,"XMLTypePackageImpl/18",1869),D(1870,1,si,AJ),l.wj=function(e){return ra(e)},l.xj=function(e){return Nt(Ae,ee,2,e,6,1)},F(xs,"XMLTypePackageImpl/19",1870),D(1853,1,si,LJ),l.wj=function(e){return _t(e,843)},l.xj=function(e){return Nt(wP,De,843,e,0,1)},F(xs,"XMLTypePackageImpl/2",1853),D(1871,1,si,MJ),l.wj=function(e){return ra(e)},l.xj=function(e){return Nt(Ae,ee,2,e,6,1)},F(xs,"XMLTypePackageImpl/20",1871),D(1872,1,si,gu),l.wj=function(e){return ra(e)},l.xj=function(e){return Nt(Ae,ee,2,e,6,1)},F(xs,"XMLTypePackageImpl/21",1872),D(1873,1,si,cC),l.wj=function(e){return ra(e)},l.xj=function(e){return Nt(Ae,ee,2,e,6,1)},F(xs,"XMLTypePackageImpl/22",1873),D(1874,1,si,FB),l.wj=function(e){return ra(e)},l.xj=function(e){return Nt(Ae,ee,2,e,6,1)},F(xs,"XMLTypePackageImpl/23",1874),D(1875,1,si,NB),l.wj=function(e){return _t(e,190)},l.xj=function(e){return Nt(Gu,ee,190,e,0,2)},F(xs,"XMLTypePackageImpl/24",1875),D(1876,1,si,fx),l.wj=function(e){return ra(e)},l.xj=function(e){return Nt(Ae,ee,2,e,6,1)},F(xs,"XMLTypePackageImpl/25",1876),D(1877,1,si,DJ),l.wj=function(e){return ra(e)},l.xj=function(e){return Nt(Ae,ee,2,e,6,1)},F(xs,"XMLTypePackageImpl/26",1877),D(1878,1,si,$k),l.wj=function(e){return _t(e,15)},l.xj=function(e){return Nt(wh,Ty,15,e,0,1)},F(xs,"XMLTypePackageImpl/27",1878),D(1879,1,si,IJ),l.wj=function(e){return _t(e,15)},l.xj=function(e){return Nt(wh,Ty,15,e,0,1)},F(xs,"XMLTypePackageImpl/28",1879),D(1880,1,si,BB),l.wj=function(e){return ra(e)},l.xj=function(e){return Nt(Ae,ee,2,e,6,1)},F(xs,"XMLTypePackageImpl/29",1880),D(1854,1,si,OJ),l.wj=function(e){return _t(e,667)},l.xj=function(e){return Nt(mU,De,2021,e,0,1)},F(xs,"XMLTypePackageImpl/3",1854),D(1881,1,si,PJ),l.wj=function(e){return _t(e,19)},l.xj=function(e){return Nt(ja,ee,19,e,0,1)},F(xs,"XMLTypePackageImpl/30",1881),D(1882,1,si,uC),l.wj=function(e){return ra(e)},l.xj=function(e){return Nt(Ae,ee,2,e,6,1)},F(xs,"XMLTypePackageImpl/31",1882),D(1883,1,si,RB),l.wj=function(e){return _t(e,162)},l.xj=function(e){return Nt(Sv,ee,162,e,0,1)},F(xs,"XMLTypePackageImpl/32",1883),D(1884,1,si,UL),l.wj=function(e){return ra(e)},l.xj=function(e){return Nt(Ae,ee,2,e,6,1)},F(xs,"XMLTypePackageImpl/33",1884),D(1885,1,si,lC),l.wj=function(e){return ra(e)},l.xj=function(e){return Nt(Ae,ee,2,e,6,1)},F(xs,"XMLTypePackageImpl/34",1885),D(1886,1,si,FJ),l.wj=function(e){return ra(e)},l.xj=function(e){return Nt(Ae,ee,2,e,6,1)},F(xs,"XMLTypePackageImpl/35",1886),D(1887,1,si,NJ),l.wj=function(e){return ra(e)},l.xj=function(e){return Nt(Ae,ee,2,e,6,1)},F(xs,"XMLTypePackageImpl/36",1887),D(1888,1,si,WL),l.wj=function(e){return _t(e,15)},l.xj=function(e){return Nt(wh,Ty,15,e,0,1)},F(xs,"XMLTypePackageImpl/37",1888),D(1889,1,si,hC),l.wj=function(e){return _t(e,15)},l.xj=function(e){return Nt(wh,Ty,15,e,0,1)},F(xs,"XMLTypePackageImpl/38",1889),D(1890,1,si,g1),l.wj=function(e){return ra(e)},l.xj=function(e){return Nt(Ae,ee,2,e,6,1)},F(xs,"XMLTypePackageImpl/39",1890),D(1855,1,si,zk),l.wj=function(e){return _t(e,668)},l.xj=function(e){return Nt(vP,De,2022,e,0,1)},F(xs,"XMLTypePackageImpl/4",1855),D(1891,1,si,BJ),l.wj=function(e){return ra(e)},l.xj=function(e){return Nt(Ae,ee,2,e,6,1)},F(xs,"XMLTypePackageImpl/40",1891),D(1892,1,si,qk),l.wj=function(e){return ra(e)},l.xj=function(e){return Nt(Ae,ee,2,e,6,1)},F(xs,"XMLTypePackageImpl/41",1892),D(1893,1,si,YL),l.wj=function(e){return ra(e)},l.xj=function(e){return Nt(Ae,ee,2,e,6,1)},F(xs,"XMLTypePackageImpl/42",1893),D(1894,1,si,Wb),l.wj=function(e){return ra(e)},l.xj=function(e){return Nt(Ae,ee,2,e,6,1)},F(xs,"XMLTypePackageImpl/43",1894),D(1895,1,si,fC),l.wj=function(e){return ra(e)},l.xj=function(e){return Nt(Ae,ee,2,e,6,1)},F(xs,"XMLTypePackageImpl/44",1895),D(1896,1,si,KL),l.wj=function(e){return _t(e,184)},l.xj=function(e){return Nt(Av,ee,184,e,0,1)},F(xs,"XMLTypePackageImpl/45",1896),D(1897,1,si,zf),l.wj=function(e){return ra(e)},l.xj=function(e){return Nt(Ae,ee,2,e,6,1)},F(xs,"XMLTypePackageImpl/46",1897),D(1898,1,si,dC),l.wj=function(e){return ra(e)},l.xj=function(e){return Nt(Ae,ee,2,e,6,1)},F(xs,"XMLTypePackageImpl/47",1898),D(1899,1,si,p1),l.wj=function(e){return ra(e)},l.xj=function(e){return Nt(Ae,ee,2,e,6,1)},F(xs,"XMLTypePackageImpl/48",1899),D(ab,1,si,b1),l.wj=function(e){return _t(e,184)},l.xj=function(e){return Nt(Av,ee,184,e,0,1)},F(xs,"XMLTypePackageImpl/49",ab),D(1856,1,si,RJ),l.wj=function(e){return _t(e,669)},l.xj=function(e){return Nt(kLt,De,2023,e,0,1)},F(xs,"XMLTypePackageImpl/5",1856),D(1901,1,si,jJ),l.wj=function(e){return _t(e,162)},l.xj=function(e){return Nt(Sv,ee,162,e,0,1)},F(xs,"XMLTypePackageImpl/50",1901),D(1902,1,si,M3),l.wj=function(e){return ra(e)},l.xj=function(e){return Nt(Ae,ee,2,e,6,1)},F(xs,"XMLTypePackageImpl/51",1902),D(1903,1,si,Hk),l.wj=function(e){return _t(e,19)},l.xj=function(e){return Nt(ja,ee,19,e,0,1)},F(xs,"XMLTypePackageImpl/52",1903),D(1857,1,si,Vk),l.wj=function(e){return ra(e)},l.xj=function(e){return Nt(Ae,ee,2,e,6,1)},F(xs,"XMLTypePackageImpl/6",1857),D(1858,1,si,gC),l.wj=function(e){return _t(e,190)},l.xj=function(e){return Nt(Gu,ee,190,e,0,2)},F(xs,"XMLTypePackageImpl/7",1858),D(1859,1,si,$J),l.wj=function(e){return Nm(e)},l.xj=function(e){return Nt(Rs,ee,476,e,8,1)},F(xs,"XMLTypePackageImpl/8",1859),D(1860,1,si,dx),l.wj=function(e){return _t(e,217)},l.xj=function(e){return Nt(M6,ee,217,e,0,1)},F(xs,"XMLTypePackageImpl/9",1860);var Y1,lp,dA,yU,wt;D(50,60,Q0,Nr),F(Zg,"RegEx/ParseException",50),D(820,1,{},XL),l.sl=function(e){return er*16)throw it(new Nr(qr((Pr(),g0e))));r=r*16+o}while(!0);if(this.a!=125)throw it(new Nr(qr((Pr(),p0e))));if(r>e7)throw it(new Nr(qr((Pr(),b0e))));e=r}else{if(o=0,this.c!=0||(o=y2(this.a))<0)throw it(new Nr(qr((Pr(),Qg))));if(r=o,fi(this),this.c!=0||(o=y2(this.a))<0)throw it(new Nr(qr((Pr(),Qg))));r=r*16+o,e=r}break;case 117:if(s=0,fi(this),this.c!=0||(s=y2(this.a))<0)throw it(new Nr(qr((Pr(),Qg))));if(n=s,fi(this),this.c!=0||(s=y2(this.a))<0)throw it(new Nr(qr((Pr(),Qg))));if(n=n*16+s,fi(this),this.c!=0||(s=y2(this.a))<0)throw it(new Nr(qr((Pr(),Qg))));if(n=n*16+s,fi(this),this.c!=0||(s=y2(this.a))<0)throw it(new Nr(qr((Pr(),Qg))));n=n*16+s,e=n;break;case 118:if(fi(this),this.c!=0||(s=y2(this.a))<0)throw it(new Nr(qr((Pr(),Qg))));if(n=s,fi(this),this.c!=0||(s=y2(this.a))<0)throw it(new Nr(qr((Pr(),Qg))));if(n=n*16+s,fi(this),this.c!=0||(s=y2(this.a))<0)throw it(new Nr(qr((Pr(),Qg))));if(n=n*16+s,fi(this),this.c!=0||(s=y2(this.a))<0)throw it(new Nr(qr((Pr(),Qg))));if(n=n*16+s,fi(this),this.c!=0||(s=y2(this.a))<0)throw it(new Nr(qr((Pr(),Qg))));if(n=n*16+s,fi(this),this.c!=0||(s=y2(this.a))<0)throw it(new Nr(qr((Pr(),Qg))));if(n=n*16+s,n>e7)throw it(new Nr(qr((Pr(),"parser.descappe.4"))));e=n;break;case 65:case 90:case 122:throw it(new Nr(qr((Pr(),w0e))))}return e},l.ul=function(e){var n,r;switch(e){case 100:r=(this.e&32)==32?ib("Nd",!0):(gi(),xU);break;case 68:r=(this.e&32)==32?ib("Nd",!1):(gi(),DLt);break;case 119:r=(this.e&32)==32?ib("IsWord",!0):(gi(),q7);break;case 87:r=(this.e&32)==32?ib("IsWord",!1):(gi(),OLt);break;case 115:r=(this.e&32)==32?ib("IsSpace",!0):(gi(),ek);break;case 83:r=(this.e&32)==32?ib("IsSpace",!1):(gi(),ILt);break;default:throw it(new Vo((n=e,wge+n.toString(16))))}return r},l.vl=function(e){var n,r,s,o,h,d,v,k,C,M,j,H;for(this.b=1,fi(this),n=null,this.c==0&&this.a==94?(fi(this),e?M=(gi(),gi(),new Nl(5)):(n=(gi(),gi(),new Nl(4)),jc(n,0,e7),M=new Nl(4))):M=(gi(),gi(),new Nl(4)),o=!0;(H=this.c)!=1&&!(H==0&&this.a==93&&!o);){if(o=!1,r=this.a,s=!1,H==10)switch(r){case 100:case 68:case 119:case 87:case 115:case 83:yy(M,this.ul(r)),s=!0;break;case 105:case 73:case 99:case 67:r=this.Ll(M,r),r<0&&(s=!0);break;case 112:case 80:if(j=u5t(this,r),!j)throw it(new Nr(qr((Pr(),cut))));yy(M,j),s=!0;break;default:r=this.tl()}else if(H==20){if(d=v8(this.i,58,this.d),d<0)throw it(new Nr(qr((Pr(),O8t))));if(v=!0,wa(this.i,this.d)==94&&(++this.d,v=!1),h=Pl(this.i,this.d,d),k=Lte(h,v,(this.e&512)==512),!k)throw it(new Nr(qr((Pr(),u0e))));if(yy(M,k),s=!0,d+1>=this.j||wa(this.i,d+1)!=93)throw it(new Nr(qr((Pr(),O8t))));this.d=d+2}if(fi(this),!s)if(this.c!=0||this.a!=45)jc(M,r,r);else{if(fi(this),(H=this.c)==1)throw it(new Nr(qr((Pr(),PH))));H==0&&this.a==93?(jc(M,r,r),jc(M,45,45)):(C=this.a,H==10&&(C=this.tl()),fi(this),jc(M,r,C))}(this.e&xf)==xf&&this.c==0&&this.a==44&&fi(this)}if(this.c==1)throw it(new Nr(qr((Pr(),PH))));return n&&(L_(n,M),M=n),v4(M),S_(M),this.b=0,fi(this),M},l.wl=function(){var e,n,r,s;for(r=this.vl(!1);(s=this.c)!=7;)if(e=this.a,s==0&&(e==45||e==38)||s==4){if(fi(this),this.c!=9)throw it(new Nr(qr((Pr(),h0e))));if(n=this.vl(!1),s==4)yy(r,n);else if(e==45)L_(r,n);else if(e==38)lhe(r,n);else throw it(new Vo("ASSERT"))}else throw it(new Nr(qr((Pr(),f0e))));return fi(this),r},l.xl=function(){var e,n;return e=this.a-48,n=(gi(),gi(),new krt(12,null,e)),!this.g&&(this.g=new ER),kR(this.g,new Spt(e)),fi(this),n},l.yl=function(){return fi(this),gi(),K5e},l.zl=function(){return fi(this),gi(),Y5e},l.Al=function(){throw it(new Nr(qr((Pr(),bh))))},l.Bl=function(){throw it(new Nr(qr((Pr(),bh))))},l.Cl=function(){return fi(this),Gun()},l.Dl=function(){return fi(this),gi(),Q5e},l.El=function(){return fi(this),gi(),J5e},l.Fl=function(){var e;if(this.d>=this.j||((e=wa(this.i,this.d++))&65504)!=64)throw it(new Nr(qr((Pr(),a0e))));return fi(this),gi(),gi(),new Yd(0,e-64)},l.Gl=function(){return fi(this),Ayn()},l.Hl=function(){return fi(this),gi(),txe},l.Il=function(){var e;return e=(gi(),gi(),new Yd(0,105)),fi(this),e},l.Jl=function(){return fi(this),gi(),Z5e},l.Kl=function(){return fi(this),gi(),X5e},l.Ll=function(e,n){return this.tl()},l.Ml=function(){return fi(this),gi(),LLt},l.Nl=function(){var e,n,r,s,o;if(this.d+1>=this.j)throw it(new Nr(qr((Pr(),r0e))));if(s=-1,n=null,e=wa(this.i,this.d),49<=e&&e<=57){if(s=e-48,!this.g&&(this.g=new ER),kR(this.g,new Spt(s)),++this.d,wa(this.i,this.d)!=41)throw it(new Nr(qr((Pr(),I2))));++this.d}else switch(e==63&&--this.d,fi(this),n=Ixt(this),n.e){case 20:case 21:case 22:case 23:break;case 8:if(this.c!=7)throw it(new Nr(qr((Pr(),I2))));break;default:throw it(new Nr(qr((Pr(),i0e))))}if(fi(this),o=cv(this),r=null,o.e==2){if(o.em()!=2)throw it(new Nr(qr((Pr(),s0e))));r=o.am(1),o=o.am(0)}if(this.c!=7)throw it(new Nr(qr((Pr(),I2))));return fi(this),gi(),gi(),new oee(s,n,o,r)},l.Ol=function(){return fi(this),gi(),MLt},l.Pl=function(){var e;if(fi(this),e=i$(24,cv(this)),this.c!=7)throw it(new Nr(qr((Pr(),I2))));return fi(this),e},l.Ql=function(){var e;if(fi(this),e=i$(20,cv(this)),this.c!=7)throw it(new Nr(qr((Pr(),I2))));return fi(this),e},l.Rl=function(){var e;if(fi(this),e=i$(22,cv(this)),this.c!=7)throw it(new Nr(qr((Pr(),I2))));return fi(this),e},l.Sl=function(){var e,n,r,s,o;for(e=0,r=0,n=-1;this.d=this.j)throw it(new Nr(qr((Pr(),D8t))));if(n==45){for(++this.d;this.d=this.j)throw it(new Nr(qr((Pr(),D8t))))}if(n==58){if(++this.d,fi(this),s=fXt(cv(this),e,r),this.c!=7)throw it(new Nr(qr((Pr(),I2))));fi(this)}else if(n==41)++this.d,fi(this),s=fXt(cv(this),e,r);else throw it(new Nr(qr((Pr(),n0e))));return s},l.Tl=function(){var e;if(fi(this),e=i$(21,cv(this)),this.c!=7)throw it(new Nr(qr((Pr(),I2))));return fi(this),e},l.Ul=function(){var e;if(fi(this),e=i$(23,cv(this)),this.c!=7)throw it(new Nr(qr((Pr(),I2))));return fi(this),e},l.Vl=function(){var e,n;if(fi(this),e=this.f++,n=Knt(cv(this),e),this.c!=7)throw it(new Nr(qr((Pr(),I2))));return fi(this),n},l.Wl=function(){var e;if(fi(this),e=Knt(cv(this),0),this.c!=7)throw it(new Nr(qr((Pr(),I2))));return fi(this),e},l.Xl=function(e){return fi(this),this.c==5?(fi(this),Yj(e,(gi(),gi(),new Xm(9,e)))):Yj(e,(gi(),gi(),new Xm(3,e)))},l.Yl=function(e){var n;return fi(this),n=(gi(),gi(),new d9(2)),this.c==5?(fi(this),E2(n,pA),E2(n,e)):(E2(n,e),E2(n,pA)),n},l.Zl=function(e){return fi(this),this.c==5?(fi(this),gi(),gi(),new Xm(9,e)):(gi(),gi(),new Xm(3,e))},l.a=0,l.b=0,l.c=0,l.d=0,l.e=0,l.f=1,l.g=null,l.j=0,F(Zg,"RegEx/RegexParser",820),D(1824,820,{},Vqt),l.sl=function(e){return!1},l.tl=function(){return H5t(this)},l.ul=function(e){return ME(e)},l.vl=function(e){return nfe(this)},l.wl=function(){throw it(new Nr(qr((Pr(),bh))))},l.xl=function(){throw it(new Nr(qr((Pr(),bh))))},l.yl=function(){throw it(new Nr(qr((Pr(),bh))))},l.zl=function(){throw it(new Nr(qr((Pr(),bh))))},l.Al=function(){return fi(this),ME(67)},l.Bl=function(){return fi(this),ME(73)},l.Cl=function(){throw it(new Nr(qr((Pr(),bh))))},l.Dl=function(){throw it(new Nr(qr((Pr(),bh))))},l.El=function(){throw it(new Nr(qr((Pr(),bh))))},l.Fl=function(){return fi(this),ME(99)},l.Gl=function(){throw it(new Nr(qr((Pr(),bh))))},l.Hl=function(){throw it(new Nr(qr((Pr(),bh))))},l.Il=function(){return fi(this),ME(105)},l.Jl=function(){throw it(new Nr(qr((Pr(),bh))))},l.Kl=function(){throw it(new Nr(qr((Pr(),bh))))},l.Ll=function(e,n){return yy(e,ME(n)),-1},l.Ml=function(){return fi(this),gi(),gi(),new Yd(0,94)},l.Nl=function(){throw it(new Nr(qr((Pr(),bh))))},l.Ol=function(){return fi(this),gi(),gi(),new Yd(0,36)},l.Pl=function(){throw it(new Nr(qr((Pr(),bh))))},l.Ql=function(){throw it(new Nr(qr((Pr(),bh))))},l.Rl=function(){throw it(new Nr(qr((Pr(),bh))))},l.Sl=function(){throw it(new Nr(qr((Pr(),bh))))},l.Tl=function(){throw it(new Nr(qr((Pr(),bh))))},l.Ul=function(){throw it(new Nr(qr((Pr(),bh))))},l.Vl=function(){var e;if(fi(this),e=Knt(cv(this),0),this.c!=7)throw it(new Nr(qr((Pr(),I2))));return fi(this),e},l.Wl=function(){throw it(new Nr(qr((Pr(),bh))))},l.Xl=function(e){return fi(this),Yj(e,(gi(),gi(),new Xm(3,e)))},l.Yl=function(e){var n;return fi(this),n=(gi(),gi(),new d9(2)),E2(n,e),E2(n,pA),n},l.Zl=function(e){return fi(this),gi(),gi(),new Xm(3,e)};var d5=null,$7=null;F(Zg,"RegEx/ParserForXMLSchema",1824),D(117,1,n7,yw),l.$l=function(e){throw it(new Vo("Not supported."))},l._l=function(){return-1},l.am=function(e){return null},l.bm=function(){return null},l.cm=function(e){},l.dm=function(e){},l.em=function(){return 0},l.Ib=function(){return this.fm(0)},l.fm=function(e){return this.e==11?".":""},l.e=0;var _Lt,z7,gA,W5e,SLt,s3=null,xU,Hft=null,ALt,pA,Vft=null,LLt,MLt,DLt,ILt,OLt,Y5e,ek,K5e,X5e,Q5e,Z5e,q7,J5e,txe,k6n=F(Zg,"RegEx/Token",117);D(136,117,{3:1,136:1,117:1},Nl),l.fm=function(e){var n,r,s;if(this.e==4)if(this==ALt)r=".";else if(this==xU)r="\\d";else if(this==q7)r="\\w";else if(this==ek)r="\\s";else{for(s=new Ag,s.a+="[",n=0;n0&&(s.a+=","),this.b[n]===this.b[n+1]?go(s,_I(this.b[n])):(go(s,_I(this.b[n])),s.a+="-",go(s,_I(this.b[n+1])));s.a+="]",r=s.a}else if(this==DLt)r="\\D";else if(this==OLt)r="\\W";else if(this==ILt)r="\\S";else{for(s=new Ag,s.a+="[^",n=0;n0&&(s.a+=","),this.b[n]===this.b[n+1]?go(s,_I(this.b[n])):(go(s,_I(this.b[n])),s.a+="-",go(s,_I(this.b[n+1])));s.a+="]",r=s.a}return r},l.a=!1,l.c=!1,F(Zg,"RegEx/RangeToken",136),D(584,1,{584:1},Spt),l.a=0,F(Zg,"RegEx/RegexParser/ReferencePosition",584),D(583,1,{3:1,583:1},eVt),l.Fb=function(e){var n;return e==null||!_t(e,583)?!1:(n=u(e,583),hn(this.b,n.b)&&this.a==n.a)},l.Hb=function(){return Vg(this.b+"/"+B5t(this.a))},l.Ib=function(){return this.c.fm(this.a)},l.a=0,F(Zg,"RegEx/RegularExpression",583),D(223,117,n7,Yd),l._l=function(){return this.a},l.fm=function(e){var n,r,s;switch(this.e){case 0:switch(this.a){case 124:case 42:case 43:case 63:case 40:case 41:case 46:case 91:case 123:case 92:s="\\"+knt(this.a&ys);break;case 12:s="\\f";break;case 10:s="\\n";break;case 13:s="\\r";break;case 9:s="\\t";break;case 27:s="\\e";break;default:this.a>=Ka?(r=(n=this.a>>>0,"0"+n.toString(16)),s="\\v"+Pl(r,r.length-6,r.length)):s=""+knt(this.a&ys)}break;case 8:this==LLt||this==MLt?s=""+knt(this.a&ys):s="\\"+knt(this.a&ys);break;default:s=null}return s},l.a=0,F(Zg,"RegEx/Token/CharToken",223),D(309,117,n7,Xm),l.am=function(e){return this.a},l.cm=function(e){this.b=e},l.dm=function(e){this.c=e},l.em=function(){return 1},l.fm=function(e){var n;if(this.e==3)if(this.c<0&&this.b<0)n=this.a.fm(e)+"*";else if(this.c==this.b)n=this.a.fm(e)+"{"+this.c+"}";else if(this.c>=0&&this.b>=0)n=this.a.fm(e)+"{"+this.c+","+this.b+"}";else if(this.c>=0&&this.b<0)n=this.a.fm(e)+"{"+this.c+",}";else throw it(new Vo("Token#toString(): CLOSURE "+this.c+Ya+this.b));else if(this.c<0&&this.b<0)n=this.a.fm(e)+"*?";else if(this.c==this.b)n=this.a.fm(e)+"{"+this.c+"}?";else if(this.c>=0&&this.b>=0)n=this.a.fm(e)+"{"+this.c+","+this.b+"}?";else if(this.c>=0&&this.b<0)n=this.a.fm(e)+"{"+this.c+",}?";else throw it(new Vo("Token#toString(): NONGREEDYCLOSURE "+this.c+Ya+this.b));return n},l.b=0,l.c=0,F(Zg,"RegEx/Token/ClosureToken",309),D(821,117,n7,mvt),l.am=function(e){return e==0?this.a:this.b},l.em=function(){return 2},l.fm=function(e){var n;return this.b.e==3&&this.b.am(0)==this.a?n=this.a.fm(e)+"+":this.b.e==9&&this.b.am(0)==this.a?n=this.a.fm(e)+"+?":n=this.a.fm(e)+(""+this.b.fm(e)),n},F(Zg,"RegEx/Token/ConcatToken",821),D(1822,117,n7,oee),l.am=function(e){if(e==0)return this.d;if(e==1)return this.b;throw it(new Vo("Internal Error: "+e))},l.em=function(){return this.b?2:1},l.fm=function(e){var n;return this.c>0?n="(?("+this.c+")":this.a.e==8?n="(?("+this.a+")":n="(?"+this.a,this.b?n+=this.d+"|"+this.b+")":n+=this.d+")",n},l.c=0,F(Zg,"RegEx/Token/ConditionToken",1822),D(1823,117,n7,oZt),l.am=function(e){return this.b},l.em=function(){return 1},l.fm=function(e){return"(?"+(this.a==0?"":B5t(this.a))+(this.c==0?"":B5t(this.c))+":"+this.b.fm(e)+")"},l.a=0,l.c=0,F(Zg,"RegEx/Token/ModifierToken",1823),D(822,117,n7,Cvt),l.am=function(e){return this.a},l.em=function(){return 1},l.fm=function(e){var n;switch(n=null,this.e){case 6:this.b==0?n="(?:"+this.a.fm(e)+")":n="("+this.a.fm(e)+")";break;case 20:n="(?="+this.a.fm(e)+")";break;case 21:n="(?!"+this.a.fm(e)+")";break;case 22:n="(?<="+this.a.fm(e)+")";break;case 23:n="(?"+this.a.fm(e)+")"}return n},l.b=0,F(Zg,"RegEx/Token/ParenToken",822),D(521,117,{3:1,117:1,521:1},krt),l.bm=function(){return this.b},l.fm=function(e){return this.e==12?"\\"+this.a:Nbn(this.b)},l.a=0,F(Zg,"RegEx/Token/StringToken",521),D(465,117,n7,d9),l.$l=function(e){E2(this,e)},l.am=function(e){return u(zw(this.a,e),117)},l.em=function(){return this.a?this.a.a.c.length:0},l.fm=function(e){var n,r,s,o,h;if(this.e==1){if(this.a.a.c.length==2)n=u(zw(this.a,0),117),r=u(zw(this.a,1),117),r.e==3&&r.am(0)==n?o=n.fm(e)+"+":r.e==9&&r.am(0)==n?o=n.fm(e)+"+?":o=n.fm(e)+(""+r.fm(e));else{for(h=new Ag,s=0;s=this.c.b:this.a<=this.c.b},l.Sb=function(){return this.b>0},l.Tb=function(){return this.b},l.Vb=function(){return this.b-1},l.Qb=function(){throw it(new Sg(Tge))},l.a=0,l.b=0,F(Z8t,"ExclusiveRange/RangeIterator",254);var xh=A8(FH,"C"),Cr=A8(rS,"I"),pl=A8(b6,"Z"),Ob=A8(iS,"J"),Gu=A8(tS,"B"),aa=A8(eS,"D"),a3=A8(nS,"F"),g5=A8(sS,"S"),E6n=Ki("org.eclipse.elk.core.labels","ILabelManager"),PLt=Ki(Ra,"DiagnosticChain"),FLt=Ki(Z0e,"ResourceSet"),NLt=F(Ra,"InvocationTargetException",null),nxe=(AR(),gan),rxe=rxe=r0n;ucn(nKe),Fcn("permProps",[[[YH,KH],[XH,"gecko1_8"]],[[YH,KH],[XH,"ie10"]],[[YH,KH],[XH,"ie8"]],[[YH,KH],[XH,"ie9"]],[[YH,KH],[XH,"safari"]]]),rxe(null,"elk",null)}).call(this)}).call(this,typeof b0<"u"?b0:typeof self<"u"?self:typeof window<"u"?window:{})},{}],3:[function(f,p,w){function m(I,B){if(!(I instanceof B))throw new TypeError("Cannot call a class as a function")}function b(I,B){if(!I)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return B&&(typeof B=="object"||typeof B=="function")?B:I}function E(I,B){if(typeof B!="function"&&B!==null)throw new TypeError("Super expression must either be null or a function, not "+typeof B);I.prototype=Object.create(B&&B.prototype,{constructor:{value:I,enumerable:!1,writable:!0,configurable:!0}}),B&&(Object.setPrototypeOf?Object.setPrototypeOf(I,B):I.__proto__=B)}var _=f("./elk-api.js").default,A=function(I){E(B,I);function B(){var N=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{};m(this,B);var R=Object.assign({},N),z=!1;try{f.resolve("web-worker"),z=!0}catch{}if(N.workerUrl)if(z){var W=f("web-worker");R.workerFactory=function(at){return new W(at)}}else console.warn(`Web worker requested but 'web-worker' package not installed. +Consider installing the package or pass your own 'workerFactory' to ELK's constructor. +... Falling back to non-web worker version.`);if(!R.workerFactory){var et=f("./elk-worker.min.js"),st=et.Worker;R.workerFactory=function(at){return new st(at)}}return b(this,(B.__proto__||Object.getPrototypeOf(B)).call(this,R))}return B}(_);Object.defineProperty(p.exports,"__esModule",{value:!0}),p.exports=A,A.default=A},{"./elk-api.js":1,"./elk-worker.min.js":2,"web-worker":4}],4:[function(f,p,w){p.exports=Worker},{}]},{},[3])(3)})})(Bjt);var oWe=Bjt.exports;const cWe=G7(oWe),Rjt=new cWe;let ow={};const uWe={};let q5={};const lWe=async function(i,a,f,p,w,m,b){const _=f.select(`[id="${a}"]`).insert("g").attr("class","nodes"),A=Object.keys(i);return await Promise.all(A.map(async function(I){const B=i[I];let N="default";B.classes.length>0&&(N=B.classes.join(" ")),N=N+" flowchart-label";const R=im(B.styles);let z=B.text!==void 0?B.text:B.id;const W={width:0,height:0},et=[{id:B.id+"-west",layoutOptions:{"port.side":"WEST"}},{id:B.id+"-east",layoutOptions:{"port.side":"EAST"}},{id:B.id+"-south",layoutOptions:{"port.side":"SOUTH"}},{id:B.id+"-north",layoutOptions:{"port.side":"NORTH"}}];let st=0,at="",bt={};switch(B.type){case"round":st=5,at="rect";break;case"square":at="rect";break;case"diamond":at="question",bt={portConstraints:"FIXED_SIDE"};break;case"hexagon":at="hexagon";break;case"odd":at="rect_left_inv_arrow";break;case"lean_right":at="lean_right";break;case"lean_left":at="lean_left";break;case"trapezoid":at="trapezoid";break;case"inv_trapezoid":at="inv_trapezoid";break;case"odd_right":at="rect_left_inv_arrow";break;case"circle":at="circle";break;case"ellipse":at="ellipse";break;case"stadium":at="stadium";break;case"subroutine":at="subroutine";break;case"cylinder":at="cylinder";break;case"group":at="rect";break;case"doublecircle":at="doublecircle";break;default:at="rect"}const mt={labelStyle:R.labelStyle,shape:at,labelText:z,labelType:B.labelType,rx:st,ry:st,class:N,style:R.style,id:B.id,link:B.link,linkTarget:B.linkTarget,tooltip:w.db.getTooltip(B.id)||"",domId:w.db.lookUpDomId(B.id),haveCallback:B.haveCallback,width:B.type==="group"?500:void 0,dir:B.dir,type:B.type,props:B.props,padding:Fd().flowchart.padding};let yt,ft;if(mt.type!=="group")ft=await kBt(_,mt,B.dir),yt=ft.node().getBBox();else{p.createElementNS("http://www.w3.org/2000/svg","text");const{shapeSvg:vt,bbox:X}=await Nd(_,mt,void 0,!0);W.width=X.width,W.wrappingWidth=Fd().flowchart.wrappingWidth,W.height=X.height,W.labelNode=vt.node(),mt.labelData=W}const ut={id:B.id,ports:B.type==="diamond"?et:[],layoutOptions:bt,labelText:z,labelData:W,domId:w.db.lookUpDomId(B.id),width:yt==null?void 0:yt.width,height:yt==null?void 0:yt.height,type:B.type,el:ft,parent:m.parentById[B.id]};q5[mt.id]=ut})),b},jjt=(i,a,f)=>{const p={TB:{in:{north:"north"},out:{south:"west",west:"east",east:"south"}},LR:{in:{west:"west"},out:{east:"south",south:"north",north:"east"}},RL:{in:{east:"east"},out:{west:"north",north:"south",south:"west"}},BT:{in:{south:"south"},out:{north:"east",east:"west",west:"north"}}};return p.TD=p.TB,Ut.info("abc88",f,a,i),p[f][a][i]},$jt=(i,a,f)=>{if(Ut.info("getNextPort abc88",{node:i,edgeDirection:a,graphDirection:f}),!ow[i])switch(f){case"TB":case"TD":ow[i]={inPosition:"north",outPosition:"south"};break;case"BT":ow[i]={inPosition:"south",outPosition:"north"};break;case"RL":ow[i]={inPosition:"east",outPosition:"west"};break;case"LR":ow[i]={inPosition:"west",outPosition:"east"};break}const p=a==="in"?ow[i].inPosition:ow[i].outPosition;return a==="in"?ow[i].inPosition=jjt(ow[i].inPosition,a,f):ow[i].outPosition=jjt(ow[i].outPosition,a,f),p},hWe=(i,a)=>{let f=i.start,p=i.end;const w=f,m=p,b=q5[f],E=q5[p];return!b||!E?{source:f,target:p}:(b.type==="diamond"&&(f=`${f}-${$jt(f,"out",a)}`),E.type==="diamond"&&(p=`${p}-${$jt(p,"in",a)}`),{source:f,target:p,sourceId:w,targetId:m})},fWe=function(i,a,f,p){Ut.info("abc78 edges = ",i);const w=p.insert("g").attr("class","edgeLabels");let m={},b=a.db.getDirection(),E,_;if(i.defaultStyle!==void 0){const A=im(i.defaultStyle);E=A.style,_=A.labelStyle}return i.forEach(function(A){const I="L-"+A.start+"-"+A.end;m[I]===void 0?(m[I]=0,Ut.info("abc78 new entry",I,m[I])):(m[I]++,Ut.info("abc78 new entry",I,m[I]));let B=I+"-"+m[I];Ut.info("abc78 new link id to be used is",I,B,m[I]);const N="LS-"+A.start,R="LE-"+A.end,z={style:"",labelStyle:""};switch(z.minlen=A.length||1,A.type==="arrow_open"?z.arrowhead="none":z.arrowhead="normal",z.arrowTypeStart="arrow_open",z.arrowTypeEnd="arrow_open",A.type){case"double_arrow_cross":z.arrowTypeStart="arrow_cross";case"arrow_cross":z.arrowTypeEnd="arrow_cross";break;case"double_arrow_point":z.arrowTypeStart="arrow_point";case"arrow_point":z.arrowTypeEnd="arrow_point";break;case"double_arrow_circle":z.arrowTypeStart="arrow_circle";case"arrow_circle":z.arrowTypeEnd="arrow_circle";break}let W="",et="";switch(A.stroke){case"normal":W="fill:none;",E!==void 0&&(W=E),_!==void 0&&(et=_),z.thickness="normal",z.pattern="solid";break;case"dotted":z.thickness="normal",z.pattern="dotted",z.style="fill:none;stroke-width:2px;stroke-dasharray:3;";break;case"thick":z.thickness="thick",z.pattern="solid",z.style="stroke-width: 3.5px;fill:none;";break}if(A.style!==void 0){const ft=im(A.style);W=ft.style,et=ft.labelStyle}z.style=z.style+=W,z.labelStyle=z.labelStyle+=et,A.interpolate!==void 0?z.curve=ew(A.interpolate,cg):i.defaultInterpolate!==void 0?z.curve=ew(i.defaultInterpolate,cg):z.curve=ew(uWe.curve,cg),A.text===void 0?A.style!==void 0&&(z.arrowheadStyle="fill: #333"):(z.arrowheadStyle="fill: #333",z.labelpos="c"),z.labelType=A.labelType,z.label=A.text.replace(Kr.lineBreakRegex,` +`),A.style===void 0&&(z.style=z.style||"stroke: #333; stroke-width: 1.5px;fill:none;"),z.labelStyle=z.labelStyle.replace("color:","fill:"),z.id=B,z.classes="flowchart-link "+N+" "+R;const st=_Bt(w,z),{source:at,target:bt,sourceId:mt,targetId:yt}=hWe(A,b);Ut.debug("abc78 source and target",at,bt),f.edges.push({id:"e"+A.start+A.end,sources:[at],targets:[bt],sourceId:mt,targetId:yt,labelEl:st,labels:[{width:z.width,height:z.height,orgWidth:z.width,orgHeight:z.height,text:z.label,layoutOptions:{"edgeLabels.inline":"true","edgeLabels.placement":"CENTER"}}],edgeData:z})}),f},dWe=function(i,a,f,p,w){let m="";switch(p&&(m=window.location.protocol+"//"+window.location.host+window.location.pathname+window.location.search,m=m.replace(/\(/g,"\\("),m=m.replace(/\)/g,"\\)")),a.arrowTypeStart){case"arrow_cross":i.attr("marker-start","url("+m+"#"+w+"_"+f+"-crossStart)");break;case"arrow_point":i.attr("marker-start","url("+m+"#"+w+"_"+f+"-pointStart)");break;case"arrow_barb":i.attr("marker-start","url("+m+"#"+w+"_"+f+"-barbStart)");break;case"arrow_circle":i.attr("marker-start","url("+m+"#"+w+"_"+f+"-circleStart)");break;case"aggregation":i.attr("marker-start","url("+m+"#"+w+"_"+f+"-aggregationStart)");break;case"extension":i.attr("marker-start","url("+m+"#"+w+"_"+f+"-extensionStart)");break;case"composition":i.attr("marker-start","url("+m+"#"+w+"_"+f+"-compositionStart)");break;case"dependency":i.attr("marker-start","url("+m+"#"+w+"_"+f+"-dependencyStart)");break;case"lollipop":i.attr("marker-start","url("+m+"#"+w+"_"+f+"-lollipopStart)");break}switch(a.arrowTypeEnd){case"arrow_cross":i.attr("marker-end","url("+m+"#"+w+"_"+f+"-crossEnd)");break;case"arrow_point":i.attr("marker-end","url("+m+"#"+w+"_"+f+"-pointEnd)");break;case"arrow_barb":i.attr("marker-end","url("+m+"#"+w+"_"+f+"-barbEnd)");break;case"arrow_circle":i.attr("marker-end","url("+m+"#"+w+"_"+f+"-circleEnd)");break;case"aggregation":i.attr("marker-end","url("+m+"#"+w+"_"+f+"-aggregationEnd)");break;case"extension":i.attr("marker-end","url("+m+"#"+w+"_"+f+"-extensionEnd)");break;case"composition":i.attr("marker-end","url("+m+"#"+w+"_"+f+"-compositionEnd)");break;case"dependency":i.attr("marker-end","url("+m+"#"+w+"_"+f+"-dependencyEnd)");break;case"lollipop":i.attr("marker-end","url("+m+"#"+w+"_"+f+"-lollipopEnd)");break}},gWe=function(i,a){return Ut.info("Extracting classes"),a.db.getClasses()},pWe=function(i){const a={parentById:{},childrenById:{}},f=i.getSubGraphs();return Ut.info("Subgraphs - ",f),f.forEach(function(p){p.nodes.forEach(function(w){a.parentById[w]=p.id,a.childrenById[p.id]===void 0&&(a.childrenById[p.id]=[]),a.childrenById[p.id].push(w)})}),f.forEach(function(p){p.id,a.parentById[p.id]!==void 0&&a.parentById[p.id]}),a},bWe=function(i,a,f){const p=aWe(i,a,f);if(p===void 0||p==="root")return{x:0,y:0};const w=q5[p].offset;return{x:w.posX,y:w.posY}},wWe=function(i,a,f,p,w,m){const b=bWe(a.sourceId,a.targetId,w),E=a.sections[0].startPoint,_=a.sections[0].endPoint,I=(a.sections[0].bendPoints?a.sections[0].bendPoints:[]).map(bt=>[bt.x+b.x,bt.y+b.y]),B=[[E.x+b.x,E.y+b.y],...I,[_.x+b.x,_.y+b.y]],{x:N,y:R}=CBt(a.edgeData),z=E5().x(N).y(R).curve(cg),W=i.insert("path").attr("d",z(B)).attr("class","path "+f.classes).attr("fill","none"),et=i.insert("g").attr("class","edgeLabel"),st=yr(et.node().appendChild(a.labelEl)),at=st.node().firstChild.getBoundingClientRect();st.attr("width",at.width),st.attr("height",at.height),et.attr("transform",`translate(${a.labels[0].x+b.x}, ${a.labels[0].y+b.y})`),dWe(W,f,p.type,p.arrowMarkerAbsolute,m)},zjt=(i,a)=>{i.forEach(f=>{f.children||(f.children=[]);const p=a.childrenById[f.id];p&&p.forEach(w=>{f.children.push(q5[w])}),zjt(f.children,a)})},vWe=async function(i,a,f,p){var ut;p.db.clear(),q5={},ow={},p.db.setGen("gen-2"),p.parser.parse(i);const w=yr("body").append("div").attr("style","height:400px").attr("id","cy");let m={id:"root",layoutOptions:{"elk.hierarchyHandling":"INCLUDE_CHILDREN","org.eclipse.elk.padding":"[top=100, left=100, bottom=110, right=110]","elk.layered.spacing.edgeNodeBetweenLayers":"30","elk.direction":"DOWN"},children:[],edges:[]};switch(Ut.info("Drawing flowchart using v3 renderer",Rjt),p.db.getDirection()){case"BT":m.layoutOptions["elk.direction"]="UP";break;case"TB":m.layoutOptions["elk.direction"]="DOWN";break;case"LR":m.layoutOptions["elk.direction"]="RIGHT";break;case"RL":m.layoutOptions["elk.direction"]="LEFT";break}const{securityLevel:E,flowchart:_}=Fd();let A;E==="sandbox"&&(A=yr("#i"+a));const I=yr(E==="sandbox"?A.nodes()[0].contentDocument.body:"body"),B=E==="sandbox"?A.nodes()[0].contentDocument:document,N=I.select(`[id="${a}"]`);PNt(N,["point","circle","cross"],p.type,a);const z=p.db.getVertices();let W;const et=p.db.getSubGraphs();Ut.info("Subgraphs - ",et);for(let vt=et.length-1;vt>=0;vt--)W=et[vt],p.db.addVertex(W.id,{text:W.title,type:W.labelType},"group",void 0,W.classes,W.dir);const st=N.insert("g").attr("class","subgraphs"),at=pWe(p.db);m=await lWe(z,a,I,B,p,at,m);const bt=N.insert("g").attr("class","edges edgePath"),mt=p.db.getEdges();m=fWe(mt,p,m,N),Object.keys(q5).forEach(vt=>{const X=q5[vt];X.parent||m.children.push(X),at.childrenById[vt]!==void 0&&(X.labels=[{text:X.labelText,layoutOptions:{"nodeLabels.placement":"[H_CENTER, V_TOP, INSIDE]"},width:X.labelData.width,height:X.labelData.height}],delete X.x,delete X.y,delete X.width,delete X.height)}),zjt(m.children,at),Ut.info("after layout",JSON.stringify(m,null,2));const ft=await Rjt.layout(m);qjt(0,0,ft.children,N,st,p,0),Ut.info("after layout",ft),(ut=ft.edges)==null||ut.map(vt=>{wWe(bt,vt,vt.edgeData,p,at,a)}),fT({},N,_.diagramPadding,_.useMaxWidth),w.remove()},qjt=(i,a,f,p,w,m,b)=>{f.forEach(function(E){if(E)if(q5[E.id].offset={posX:E.x+i,posY:E.y+a,x:i,y:a,depth:b,width:E.width,height:E.height},E.type==="group"){const _=w.insert("g").attr("class","subgraph");_.insert("rect").attr("class","subgraph subgraph-lvl-"+b%5+" node").attr("x",E.x+i).attr("y",E.y+a).attr("width",E.width).attr("height",E.height);const A=_.insert("g").attr("class","label"),I=Fd().flowchart.htmlLabels?E.labelData.width/2:0;A.attr("transform",`translate(${E.labels[0].x+i+E.x+I}, ${E.labels[0].y+a+E.y+3})`),A.node().appendChild(E.labelData.labelNode),Ut.info("Id (UGH)= ",E.type,E.labels)}else Ut.info("Id (UGH)= ",E.id),E.el.attr("transform",`translate(${E.x+i+E.width/2}, ${E.y+a+E.height/2})`)}),f.forEach(function(E){E&&E.type==="group"&&qjt(i+E.x,a+E.y,E.children,p,w,m,b+1)})},mWe={getClasses:gWe,draw:vWe},yWe=i=>{let a="";for(let f=0;f<5;f++)a+=` + .subgraph-lvl-${f} { + fill: ${i[`surface${f}`]}; + stroke: ${i[`surfacePeer${f}`]}; + } + `;return a},xWe=Object.freeze(Object.defineProperty({__proto__:null,diagram:{db:lIe,renderer:mWe,parser:Hdt,styles:i=>`.label { + font-family: ${i.fontFamily}; + color: ${i.nodeTextColor||i.textColor}; + } + .cluster-label text { + fill: ${i.titleColor}; + } + .cluster-label span { + color: ${i.titleColor}; + } + + .label text,span { + fill: ${i.nodeTextColor||i.textColor}; + color: ${i.nodeTextColor||i.textColor}; + } + + .node rect, + .node circle, + .node ellipse, + .node polygon, + .node path { + fill: ${i.mainBkg}; + stroke: ${i.nodeBorder}; + stroke-width: 1px; + } + + .node .label { + text-align: center; + } + .node.clickable { + cursor: pointer; + } + + .arrowheadPath { + fill: ${i.arrowheadColor}; + } + + .edgePath .path { + stroke: ${i.lineColor}; + stroke-width: 2.0px; + } + + .flowchart-link { + stroke: ${i.lineColor}; + fill: none; + } + + .edgeLabel { + background-color: ${i.edgeLabelBackground}; + rect { + opacity: 0.85; + background-color: ${i.edgeLabelBackground}; + fill: ${i.edgeLabelBackground}; + } + text-align: center; + } + + .cluster rect { + fill: ${i.clusterBkg}; + stroke: ${i.clusterBorder}; + stroke-width: 1px; + } + + .cluster text { + fill: ${i.titleColor}; + } + + .cluster span { + color: ${i.titleColor}; + } + /* .cluster div { + color: ${i.titleColor}; + } */ + + div.mermaidTooltip { + position: absolute; + text-align: center; + max-width: 200px; + padding: 2px; + font-family: ${i.fontFamily}; + font-size: 12px; + background: ${i.tertiaryColor}; + border: 1px solid ${i.border2}; + border-radius: 2px; + pointer-events: none; + z-index: 100; + } + + .flowchartTitleText { + text-anchor: middle; + font-size: 18px; + fill: ${i.textColor}; + } + .subgraph { + stroke-width:2; + rx:3; + } + // .subgraph-lvl-1 { + // fill:#ccc; + // // stroke:black; + // } + + .flowchart-label text { + text-anchor: middle; + } + + ${yWe(i)} +`}},Symbol.toStringTag,{value:"Module"}));var Ygt=function(){var i=function(N,R,z,W){for(z=z||{},W=N.length;W--;z[N[W]]=R);return z},a=[6,8,10,11,12,14,16,17,20,21],f=[1,9],p=[1,10],w=[1,11],m=[1,12],b=[1,13],E=[1,16],_=[1,17],A={trace:function(){},yy:{},symbols_:{error:2,start:3,timeline:4,document:5,EOF:6,line:7,SPACE:8,statement:9,NEWLINE:10,title:11,acc_title:12,acc_title_value:13,acc_descr:14,acc_descr_value:15,acc_descr_multiline_value:16,section:17,period_statement:18,event_statement:19,period:20,event:21,$accept:0,$end:1},terminals_:{2:"error",4:"timeline",6:"EOF",8:"SPACE",10:"NEWLINE",11:"title",12:"acc_title",13:"acc_title_value",14:"acc_descr",15:"acc_descr_value",16:"acc_descr_multiline_value",17:"section",20:"period",21:"event"},productions_:[0,[3,3],[5,0],[5,2],[7,2],[7,1],[7,1],[7,1],[9,1],[9,2],[9,2],[9,1],[9,1],[9,1],[9,1],[18,1],[19,1]],performAction:function(R,z,W,et,st,at,bt){var mt=at.length-1;switch(st){case 1:return at[mt-1];case 2:this.$=[];break;case 3:at[mt-1].push(at[mt]),this.$=at[mt-1];break;case 4:case 5:this.$=at[mt];break;case 6:case 7:this.$=[];break;case 8:et.getCommonDb().setDiagramTitle(at[mt].substr(6)),this.$=at[mt].substr(6);break;case 9:this.$=at[mt].trim(),et.getCommonDb().setAccTitle(this.$);break;case 10:case 11:this.$=at[mt].trim(),et.getCommonDb().setAccDescription(this.$);break;case 12:et.addSection(at[mt].substr(8)),this.$=at[mt].substr(8);break;case 15:et.addTask(at[mt],0,""),this.$=at[mt];break;case 16:et.addEvent(at[mt].substr(2)),this.$=at[mt];break}},table:[{3:1,4:[1,2]},{1:[3]},i(a,[2,2],{5:3}),{6:[1,4],7:5,8:[1,6],9:7,10:[1,8],11:f,12:p,14:w,16:m,17:b,18:14,19:15,20:E,21:_},i(a,[2,7],{1:[2,1]}),i(a,[2,3]),{9:18,11:f,12:p,14:w,16:m,17:b,18:14,19:15,20:E,21:_},i(a,[2,5]),i(a,[2,6]),i(a,[2,8]),{13:[1,19]},{15:[1,20]},i(a,[2,11]),i(a,[2,12]),i(a,[2,13]),i(a,[2,14]),i(a,[2,15]),i(a,[2,16]),i(a,[2,4]),i(a,[2,9]),i(a,[2,10])],defaultActions:{},parseError:function(R,z){if(z.recoverable)this.trace(R);else{var W=new Error(R);throw W.hash=z,W}},parse:function(R){var z=this,W=[0],et=[],st=[null],at=[],bt=this.table,mt="",yt=0,ft=0,ut=2,vt=1,X=at.slice.call(arguments,1),pt=Object.create(this.lexer),U={yy:{}};for(var Tt in this.yy)Object.prototype.hasOwnProperty.call(this.yy,Tt)&&(U.yy[Tt]=this.yy[Tt]);pt.setInput(R,U.yy),U.yy.lexer=pt,U.yy.parser=this,typeof pt.yylloc>"u"&&(pt.yylloc={});var nt=pt.yylloc;at.push(nt);var It=pt.options&&pt.options.ranges;typeof U.yy.parseError=="function"?this.parseError=U.yy.parseError:this.parseError=Object.getPrototypeOf(this).parseError;function Ot(){var me;return me=et.pop()||pt.lex()||vt,typeof me!="number"&&(me instanceof Array&&(et=me,me=et.pop()),me=z.symbols_[me]||me),me}for(var Bt,Et,Z,Ct,xt={},Ht,Le,Ft,gn;;){if(Et=W[W.length-1],this.defaultActions[Et]?Z=this.defaultActions[Et]:((Bt===null||typeof Bt>"u")&&(Bt=Ot()),Z=bt[Et]&&bt[Et][Bt]),typeof Z>"u"||!Z.length||!Z[0]){var Se="";gn=[];for(Ht in bt[Et])this.terminals_[Ht]&&Ht>ut&&gn.push("'"+this.terminals_[Ht]+"'");pt.showPosition?Se="Parse error on line "+(yt+1)+`: +`+pt.showPosition()+` +Expecting `+gn.join(", ")+", got '"+(this.terminals_[Bt]||Bt)+"'":Se="Parse error on line "+(yt+1)+": Unexpected "+(Bt==vt?"end of input":"'"+(this.terminals_[Bt]||Bt)+"'"),this.parseError(Se,{text:pt.match,token:this.terminals_[Bt]||Bt,line:pt.yylineno,loc:nt,expected:gn})}if(Z[0]instanceof Array&&Z.length>1)throw new Error("Parse Error: multiple actions possible at state: "+Et+", token: "+Bt);switch(Z[0]){case 1:W.push(Bt),st.push(pt.yytext),at.push(pt.yylloc),W.push(Z[1]),Bt=null,ft=pt.yyleng,mt=pt.yytext,yt=pt.yylineno,nt=pt.yylloc;break;case 2:if(Le=this.productions_[Z[1]][1],xt.$=st[st.length-Le],xt._$={first_line:at[at.length-(Le||1)].first_line,last_line:at[at.length-1].last_line,first_column:at[at.length-(Le||1)].first_column,last_column:at[at.length-1].last_column},It&&(xt._$.range=[at[at.length-(Le||1)].range[0],at[at.length-1].range[1]]),Ct=this.performAction.apply(xt,[mt,ft,yt,U.yy,Z[1],st,at].concat(X)),typeof Ct<"u")return Ct;Le&&(W=W.slice(0,-1*Le*2),st=st.slice(0,-1*Le),at=at.slice(0,-1*Le)),W.push(this.productions_[Z[1]][0]),st.push(xt.$),at.push(xt._$),Ft=bt[W[W.length-2]][W[W.length-1]],W.push(Ft);break;case 3:return!0}}return!0}},I=function(){var N={EOF:1,parseError:function(z,W){if(this.yy.parser)this.yy.parser.parseError(z,W);else throw new Error(z)},setInput:function(R,z){return this.yy=z||this.yy||{},this._input=R,this._more=this._backtrack=this.done=!1,this.yylineno=this.yyleng=0,this.yytext=this.matched=this.match="",this.conditionStack=["INITIAL"],this.yylloc={first_line:1,first_column:0,last_line:1,last_column:0},this.options.ranges&&(this.yylloc.range=[0,0]),this.offset=0,this},input:function(){var R=this._input[0];this.yytext+=R,this.yyleng++,this.offset++,this.match+=R,this.matched+=R;var z=R.match(/(?:\r\n?|\n).*/g);return z?(this.yylineno++,this.yylloc.last_line++):this.yylloc.last_column++,this.options.ranges&&this.yylloc.range[1]++,this._input=this._input.slice(1),R},unput:function(R){var z=R.length,W=R.split(/(?:\r\n?|\n)/g);this._input=R+this._input,this.yytext=this.yytext.substr(0,this.yytext.length-z),this.offset-=z;var et=this.match.split(/(?:\r\n?|\n)/g);this.match=this.match.substr(0,this.match.length-1),this.matched=this.matched.substr(0,this.matched.length-1),W.length-1&&(this.yylineno-=W.length-1);var st=this.yylloc.range;return this.yylloc={first_line:this.yylloc.first_line,last_line:this.yylineno+1,first_column:this.yylloc.first_column,last_column:W?(W.length===et.length?this.yylloc.first_column:0)+et[et.length-W.length].length-W[0].length:this.yylloc.first_column-z},this.options.ranges&&(this.yylloc.range=[st[0],st[0]+this.yyleng-z]),this.yyleng=this.yytext.length,this},more:function(){return this._more=!0,this},reject:function(){if(this.options.backtrack_lexer)this._backtrack=!0;else return this.parseError("Lexical error on line "+(this.yylineno+1)+`. You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true). +`+this.showPosition(),{text:"",token:null,line:this.yylineno});return this},less:function(R){this.unput(this.match.slice(R))},pastInput:function(){var R=this.matched.substr(0,this.matched.length-this.match.length);return(R.length>20?"...":"")+R.substr(-20).replace(/\n/g,"")},upcomingInput:function(){var R=this.match;return R.length<20&&(R+=this._input.substr(0,20-R.length)),(R.substr(0,20)+(R.length>20?"...":"")).replace(/\n/g,"")},showPosition:function(){var R=this.pastInput(),z=new Array(R.length+1).join("-");return R+this.upcomingInput()+` +`+z+"^"},test_match:function(R,z){var W,et,st;if(this.options.backtrack_lexer&&(st={yylineno:this.yylineno,yylloc:{first_line:this.yylloc.first_line,last_line:this.last_line,first_column:this.yylloc.first_column,last_column:this.yylloc.last_column},yytext:this.yytext,match:this.match,matches:this.matches,matched:this.matched,yyleng:this.yyleng,offset:this.offset,_more:this._more,_input:this._input,yy:this.yy,conditionStack:this.conditionStack.slice(0),done:this.done},this.options.ranges&&(st.yylloc.range=this.yylloc.range.slice(0))),et=R[0].match(/(?:\r\n?|\n).*/g),et&&(this.yylineno+=et.length),this.yylloc={first_line:this.yylloc.last_line,last_line:this.yylineno+1,first_column:this.yylloc.last_column,last_column:et?et[et.length-1].length-et[et.length-1].match(/\r?\n?/)[0].length:this.yylloc.last_column+R[0].length},this.yytext+=R[0],this.match+=R[0],this.matches=R,this.yyleng=this.yytext.length,this.options.ranges&&(this.yylloc.range=[this.offset,this.offset+=this.yyleng]),this._more=!1,this._backtrack=!1,this._input=this._input.slice(R[0].length),this.matched+=R[0],W=this.performAction.call(this,this.yy,this,z,this.conditionStack[this.conditionStack.length-1]),this.done&&this._input&&(this.done=!1),W)return W;if(this._backtrack){for(var at in st)this[at]=st[at];return!1}return!1},next:function(){if(this.done)return this.EOF;this._input||(this.done=!0);var R,z,W,et;this._more||(this.yytext="",this.match="");for(var st=this._currentRules(),at=0;atz[0].length)){if(z=W,et=at,this.options.backtrack_lexer){if(R=this.test_match(W,st[at]),R!==!1)return R;if(this._backtrack){z=!1;continue}else return!1}else if(!this.options.flex)break}return z?(R=this.test_match(z,st[et]),R!==!1?R:!1):this._input===""?this.EOF:this.parseError("Lexical error on line "+(this.yylineno+1)+`. Unrecognized text. +`+this.showPosition(),{text:"",token:null,line:this.yylineno})},lex:function(){var z=this.next();return z||this.lex()},begin:function(z){this.conditionStack.push(z)},popState:function(){var z=this.conditionStack.length-1;return z>0?this.conditionStack.pop():this.conditionStack[0]},_currentRules:function(){return this.conditionStack.length&&this.conditionStack[this.conditionStack.length-1]?this.conditions[this.conditionStack[this.conditionStack.length-1]].rules:this.conditions.INITIAL.rules},topState:function(z){return z=this.conditionStack.length-1-Math.abs(z||0),z>=0?this.conditionStack[z]:"INITIAL"},pushState:function(z){this.begin(z)},stateStackSize:function(){return this.conditionStack.length},options:{"case-insensitive":!0},performAction:function(z,W,et,st){switch(et){case 0:break;case 1:break;case 2:return 10;case 3:break;case 4:break;case 5:return 4;case 6:return 11;case 7:return this.begin("acc_title"),12;case 8:return this.popState(),"acc_title_value";case 9:return this.begin("acc_descr"),14;case 10:return this.popState(),"acc_descr_value";case 11:this.begin("acc_descr_multiline");break;case 12:this.popState();break;case 13:return"acc_descr_multiline_value";case 14:return 17;case 15:return 21;case 16:return 20;case 17:return 6;case 18:return"INVALID"}},rules:[/^(?:%(?!\{)[^\n]*)/i,/^(?:[^\}]%%[^\n]*)/i,/^(?:[\n]+)/i,/^(?:\s+)/i,/^(?:#[^\n]*)/i,/^(?:timeline\b)/i,/^(?:title\s[^#\n;]+)/i,/^(?:accTitle\s*:\s*)/i,/^(?:(?!\n||)*[^\n]*)/i,/^(?:accDescr\s*:\s*)/i,/^(?:(?!\n||)*[^\n]*)/i,/^(?:accDescr\s*\{\s*)/i,/^(?:[\}])/i,/^(?:[^\}]*)/i,/^(?:section\s[^#:\n;]+)/i,/^(?::\s[^#:\n;]+)/i,/^(?:[^#:\n;]+)/i,/^(?:$)/i,/^(?:.)/i],conditions:{acc_descr_multiline:{rules:[12,13],inclusive:!1},acc_descr:{rules:[10],inclusive:!1},acc_title:{rules:[8],inclusive:!1},INITIAL:{rules:[0,1,2,3,4,5,6,7,9,11,14,15,16,17,18],inclusive:!0}}};return N}();A.lexer=I;function B(){this.yy={}}return B.prototype=A,A.Parser=B,new B}();Ygt.parser=Ygt;const kWe=Ygt;let yL="",Hjt=0;const Kgt=[],eK=[],xL=[],Vjt=()=>_Ot,Gjt=function(){Kgt.length=0,eK.length=0,yL="",xL.length=0,hg()},Ujt=function(i){yL=i,Kgt.push(i)},Wjt=function(){return Kgt},Yjt=function(){let i=Zjt();const a=100;let f=0;for(;!i&&ff.id===Hjt-1).events.push(i)},Qjt=function(i){const a={section:yL,type:yL,description:i,task:i,classes:[]};eK.push(a)},Zjt=function(){const i=function(f){return xL[f].processed};let a=!0;for(const[f,p]of xL.entries())i(f),a=a&&p.processed;return a},EWe=Object.freeze(Object.defineProperty({__proto__:null,addEvent:Xjt,addSection:Ujt,addTask:Kjt,addTaskOrg:Qjt,clear:Gjt,default:{clear:Gjt,getCommonDb:Vjt,addSection:Ujt,getSections:Wjt,getTasks:Yjt,addTask:Kjt,addTaskOrg:Qjt,addEvent:Xjt},getCommonDb:Vjt,getSections:Wjt,getTasks:Yjt},Symbol.toStringTag,{value:"Module"})),TWe=12,nK=function(i,a){const f=i.append("rect");return f.attr("x",a.x),f.attr("y",a.y),f.attr("fill",a.fill),f.attr("stroke",a.stroke),f.attr("width",a.width),f.attr("height",a.height),f.attr("rx",a.rx),f.attr("ry",a.ry),a.class!==void 0&&f.attr("class",a.class),f},CWe=function(i,a){const p=i.append("circle").attr("cx",a.cx).attr("cy",a.cy).attr("class","face").attr("r",15).attr("stroke-width",2).attr("overflow","visible"),w=i.append("g");w.append("circle").attr("cx",a.cx-15/3).attr("cy",a.cy-15/3).attr("r",1.5).attr("stroke-width",2).attr("fill","#666").attr("stroke","#666"),w.append("circle").attr("cx",a.cx+15/3).attr("cy",a.cy-15/3).attr("r",1.5).attr("stroke-width",2).attr("fill","#666").attr("stroke","#666");function m(_){const A=OA().startAngle(Math.PI/2).endAngle(3*(Math.PI/2)).innerRadius(7.5).outerRadius(6.8181818181818175);_.append("path").attr("class","mouth").attr("d",A).attr("transform","translate("+a.cx+","+(a.cy+2)+")")}function b(_){const A=OA().startAngle(3*Math.PI/2).endAngle(5*(Math.PI/2)).innerRadius(7.5).outerRadius(6.8181818181818175);_.append("path").attr("class","mouth").attr("d",A).attr("transform","translate("+a.cx+","+(a.cy+7)+")")}function E(_){_.append("line").attr("class","mouth").attr("stroke",2).attr("x1",a.cx-5).attr("y1",a.cy+7).attr("x2",a.cx+5).attr("y2",a.cy+7).attr("class","mouth").attr("stroke-width","1px").attr("stroke","#666")}return a.score>3?m(w):a.score<3?b(w):E(w),p},_We=function(i,a){const f=i.append("circle");return f.attr("cx",a.cx),f.attr("cy",a.cy),f.attr("class","actor-"+a.pos),f.attr("fill",a.fill),f.attr("stroke",a.stroke),f.attr("r",a.r),f.class!==void 0&&f.attr("class",f.class),a.title!==void 0&&f.append("title").text(a.title),f},Jjt=function(i,a){const f=a.text.replace(//gi," "),p=i.append("text");p.attr("x",a.x),p.attr("y",a.y),p.attr("class","legend"),p.style("text-anchor",a.anchor),a.class!==void 0&&p.attr("class",a.class);const w=p.append("tspan");return w.attr("x",a.x+a.textMargin*2),w.text(f),p},SWe=function(i,a){function f(w,m,b,E,_){return w+","+m+" "+(w+b)+","+m+" "+(w+b)+","+(m+E-_)+" "+(w+b-_*1.2)+","+(m+E)+" "+w+","+(m+E)}const p=i.append("polygon");p.attr("points",f(a.x,a.y,50,20,7)),p.attr("class","labelBox"),a.y=a.y+a.labelMargin,a.x=a.x+.5*a.labelMargin,Jjt(i,a)},AWe=function(i,a,f){const p=i.append("g"),w=Xgt();w.x=a.x,w.y=a.y,w.fill=a.fill,w.width=f.width,w.height=f.height,w.class="journey-section section-type-"+a.num,w.rx=3,w.ry=3,nK(p,w),e$t(f)(a.text,p,w.x,w.y,w.width,w.height,{class:"journey-section section-type-"+a.num},f,a.colour)};let t$t=-1;const LWe=function(i,a,f){const p=a.x+f.width/2,w=i.append("g");t$t++;const m=300+5*30;w.append("line").attr("id","task"+t$t).attr("x1",p).attr("y1",a.y).attr("x2",p).attr("y2",m).attr("class","task-line").attr("stroke-width","1px").attr("stroke-dasharray","4 2").attr("stroke","#666"),CWe(w,{cx:p,cy:300+(5-a.score)*30,score:a.score});const b=Xgt();b.x=a.x,b.y=a.y,b.fill=a.fill,b.width=f.width,b.height=f.height,b.class="task task-type-"+a.num,b.rx=3,b.ry=3,nK(w,b),a.x+14,e$t(f)(a.task,w,b.x,b.y,b.width,b.height,{class:"task"},f,a.colour)},MWe=function(i,a){nK(i,{x:a.startx,y:a.starty,width:a.stopx-a.startx,height:a.stopy-a.starty,fill:a.fill,class:"rect"}).lower()},DWe=function(){return{x:0,y:0,fill:void 0,"text-anchor":"start",width:100,height:100,textMargin:0,rx:0,ry:0}},Xgt=function(){return{x:0,y:0,width:100,anchor:"start",height:100,rx:0,ry:0}},e$t=function(){function i(w,m,b,E,_,A,I,B){const N=m.append("text").attr("x",b+_/2).attr("y",E+A/2+5).style("font-color",B).style("text-anchor","middle").text(w);p(N,I)}function a(w,m,b,E,_,A,I,B,N){const{taskFontSize:R,taskFontFamily:z}=B,W=w.split(//gi);for(let et=0;et)/).reverse(),w,m=[],b=1.1,E=f.attr("y"),_=parseFloat(f.attr("dy")),A=f.text(null).append("tspan").attr("x",0).attr("y",E).attr("dy",_+"em");for(let I=0;Ia||w==="
            ")&&(m.pop(),A.text(m.join(" ").trim()),w==="
            "?m=[""]:m=[w],A=f.append("tspan").attr("x",0).attr("y",E).attr("dy",b+"em").text(w))})}const OWe=function(i,a,f,p){const w=f%TWe-1,m=i.append("g");a.section=w,m.attr("class",(a.class?a.class+" ":"")+"timeline-node "+("section-"+w));const b=m.append("g"),E=m.append("g"),A=E.append("text").text(a.descr).attr("dy","1em").attr("alignment-baseline","middle").attr("dominant-baseline","middle").attr("text-anchor","middle").call(n$t,a.width).node().getBBox(),I=p.fontSize&&p.fontSize.replace?p.fontSize.replace("px",""):p.fontSize;return a.height=A.height+I*1.1*.5+a.padding,a.height=Math.max(a.height,a.maxHeight),a.width=a.width+2*a.padding,E.attr("transform","translate("+a.width/2+", "+a.padding/2+")"),FWe(b,a,w),a},PWe=function(i,a,f){const p=i.append("g"),m=p.append("text").text(a.descr).attr("dy","1em").attr("alignment-baseline","middle").attr("dominant-baseline","middle").attr("text-anchor","middle").call(n$t,a.width).node().getBBox(),b=f.fontSize&&f.fontSize.replace?f.fontSize.replace("px",""):f.fontSize;return p.remove(),m.height+b*1.1*.5+a.padding},FWe=function(i,a,f){i.append("path").attr("id","node-"+a.id).attr("class","node-bkg node-"+a.type).attr("d",`M0 ${a.height-5} v${-a.height+2*5} q0,-5 5,-5 h${a.width-2*5} q5,0 5,5 v${a.height-5} H0 Z`),i.append("line").attr("class","node-line-"+f).attr("x1",0).attr("y1",a.height).attr("x2",a.width).attr("y2",a.height)},DT={drawRect:nK,drawCircle:_We,drawSection:AWe,drawText:Jjt,drawLabel:SWe,drawTask:LWe,drawBackgroundRect:MWe,getTextObj:DWe,getNoteRect:Xgt,initGraphics:IWe,drawNode:OWe,getVirtualNodeHeight:PWe},NWe=function(i,a,f,p){var X,pt;const w=Oe(),m=w.leftMargin??50;Ut.debug("timeline",p.db);const b=w.securityLevel;let E;b==="sandbox"&&(E=yr("#i"+a));const A=yr(b==="sandbox"?E.nodes()[0].contentDocument.body:"body").select("#"+a);A.append("g");const I=p.db.getTasks(),B=p.db.getCommonDb().getDiagramTitle();Ut.debug("task",I),DT.initGraphics(A);const N=p.db.getSections();Ut.debug("sections",N);let R=0,z=0,W=0,et=0,st=50+m,at=50;et=50;let bt=0,mt=!0;N.forEach(function(U){const Tt={number:bt,descr:U,section:bt,width:150,padding:20,maxHeight:R},nt=DT.getVirtualNodeHeight(A,Tt,w);Ut.debug("sectionHeight before draw",nt),R=Math.max(R,nt+20)});let yt=0,ft=0;Ut.debug("tasks.length",I.length);for(const[U,Tt]of I.entries()){const nt={number:U,descr:Tt,section:Tt.section,width:150,padding:20,maxHeight:z},It=DT.getVirtualNodeHeight(A,nt,w);Ut.debug("taskHeight before draw",It),z=Math.max(z,It+20),yt=Math.max(yt,Tt.events.length);let Ot=0;for(let Bt=0;Bt0?N.forEach(U=>{const Tt=I.filter(Bt=>Bt.section===U),nt={number:bt,descr:U,section:bt,width:200*Math.max(Tt.length,1)-50,padding:20,maxHeight:R};Ut.debug("sectionNode",nt);const It=A.append("g"),Ot=DT.drawNode(It,nt,bt,w);Ut.debug("sectionNode output",Ot),It.attr("transform",`translate(${st}, ${et})`),at+=R+50,Tt.length>0&&r$t(A,Tt,bt,st,at,z,w,yt,ft,R,!1),st+=200*Math.max(Tt.length,1),at=et,bt++}):(mt=!1,r$t(A,I,bt,st,at,z,w,yt,ft,R,!0));const ut=A.node().getBBox();Ut.debug("bounds",ut),B&&A.append("text").text(B).attr("x",ut.width/2-m).attr("font-size","4ex").attr("font-weight","bold").attr("y",20),W=mt?R+z+150:z+100,A.append("g").attr("class","lineWrapper").append("line").attr("x1",m).attr("y1",W).attr("x2",ut.width+3*m).attr("y2",W).attr("stroke-width",4).attr("stroke","black").attr("marker-end","url(#arrowhead)"),fT(void 0,A,((X=w.timeline)==null?void 0:X.padding)??50,((pt=w.timeline)==null?void 0:pt.useMaxWidth)??!1)},r$t=function(i,a,f,p,w,m,b,E,_,A,I){var B;for(const N of a){const R={descr:N.task,section:f,number:f,width:150,padding:20,maxHeight:m};Ut.debug("taskNode",R);const z=i.append("g").attr("class","taskWrapper"),et=DT.drawNode(z,R,f,b).height;if(Ut.debug("taskHeight after draw",et),z.attr("transform",`translate(${p}, ${w})`),m=Math.max(m,et),N.events){const st=i.append("g").attr("class","lineWrapper");let at=m;w+=100,at=at+BWe(i,N.events,f,p,w,b),w-=100,st.append("line").attr("x1",p+190/2).attr("y1",w+m).attr("x2",p+190/2).attr("y2",w+m+(I?m:A)+_+120).attr("stroke-width",2).attr("stroke","black").attr("marker-end","url(#arrowhead)").attr("stroke-dasharray","5,5")}p=p+200,I&&!((B=b.timeline)!=null&&B.disableMulticolor)&&f++}w=w-10},BWe=function(i,a,f,p,w,m){let b=0;const E=w;w=w+100;for(const _ of a){const A={descr:_,section:f,number:f,width:150,padding:20,maxHeight:50};Ut.debug("eventNode",A);const I=i.append("g").attr("class","eventWrapper"),N=DT.drawNode(I,A,f,m).height;b=b+N,I.attr("transform",`translate(${p}, ${w})`),w=w+10+N}return w=E,b},RWe={setConf:()=>{},draw:NWe},jWe=i=>{let a="";for(let f=0;f` + .edge { + stroke-width: 3; + } + ${jWe(i)} + .section-root rect, .section-root path, .section-root circle { + fill: ${i.git0}; + } + .section-root text { + fill: ${i.gitBranchLabel0}; + } + .icon-container { + height:100%; + display: flex; + justify-content: center; + align-items: center; + } + .edge { + fill: none; + } + .eventWrapper { + filter: brightness(120%); + } +`}},Symbol.toStringTag,{value:"Module"}));var Qgt=function(){var i=function(mt,yt,ft,ut){for(ft=ft||{},ut=mt.length;ut--;ft[mt[ut]]=yt);return ft},a=[1,4],f=[1,13],p=[1,12],w=[1,15],m=[1,16],b=[1,20],E=[1,19],_=[6,7,8],A=[1,26],I=[1,24],B=[1,25],N=[6,7,11],R=[1,6,13,15,16,19,22],z=[1,33],W=[1,34],et=[1,6,7,11,13,15,16,19,22],st={trace:function(){},yy:{},symbols_:{error:2,start:3,mindMap:4,spaceLines:5,SPACELINE:6,NL:7,MINDMAP:8,document:9,stop:10,EOF:11,statement:12,SPACELIST:13,node:14,ICON:15,CLASS:16,nodeWithId:17,nodeWithoutId:18,NODE_DSTART:19,NODE_DESCR:20,NODE_DEND:21,NODE_ID:22,$accept:0,$end:1},terminals_:{2:"error",6:"SPACELINE",7:"NL",8:"MINDMAP",11:"EOF",13:"SPACELIST",15:"ICON",16:"CLASS",19:"NODE_DSTART",20:"NODE_DESCR",21:"NODE_DEND",22:"NODE_ID"},productions_:[0,[3,1],[3,2],[5,1],[5,2],[5,2],[4,2],[4,3],[10,1],[10,1],[10,1],[10,2],[10,2],[9,3],[9,2],[12,2],[12,2],[12,2],[12,1],[12,1],[12,1],[12,1],[12,1],[14,1],[14,1],[18,3],[17,1],[17,4]],performAction:function(yt,ft,ut,vt,X,pt,U){var Tt=pt.length-1;switch(X){case 6:case 7:return vt;case 8:vt.getLogger().trace("Stop NL ");break;case 9:vt.getLogger().trace("Stop EOF ");break;case 11:vt.getLogger().trace("Stop NL2 ");break;case 12:vt.getLogger().trace("Stop EOF2 ");break;case 15:vt.getLogger().info("Node: ",pt[Tt].id),vt.addNode(pt[Tt-1].length,pt[Tt].id,pt[Tt].descr,pt[Tt].type);break;case 16:vt.getLogger().trace("Icon: ",pt[Tt]),vt.decorateNode({icon:pt[Tt]});break;case 17:case 21:vt.decorateNode({class:pt[Tt]});break;case 18:vt.getLogger().trace("SPACELIST");break;case 19:vt.getLogger().trace("Node: ",pt[Tt].id),vt.addNode(0,pt[Tt].id,pt[Tt].descr,pt[Tt].type);break;case 20:vt.decorateNode({icon:pt[Tt]});break;case 25:vt.getLogger().trace("node found ..",pt[Tt-2]),this.$={id:pt[Tt-1],descr:pt[Tt-1],type:vt.getType(pt[Tt-2],pt[Tt])};break;case 26:this.$={id:pt[Tt],descr:pt[Tt],type:vt.nodeType.DEFAULT};break;case 27:vt.getLogger().trace("node found ..",pt[Tt-3]),this.$={id:pt[Tt-3],descr:pt[Tt-1],type:vt.getType(pt[Tt-2],pt[Tt])};break}},table:[{3:1,4:2,5:3,6:[1,5],8:a},{1:[3]},{1:[2,1]},{4:6,6:[1,7],7:[1,8],8:a},{6:f,7:[1,10],9:9,12:11,13:p,14:14,15:w,16:m,17:17,18:18,19:b,22:E},i(_,[2,3]),{1:[2,2]},i(_,[2,4]),i(_,[2,5]),{1:[2,6],6:f,12:21,13:p,14:14,15:w,16:m,17:17,18:18,19:b,22:E},{6:f,9:22,12:11,13:p,14:14,15:w,16:m,17:17,18:18,19:b,22:E},{6:A,7:I,10:23,11:B},i(N,[2,22],{17:17,18:18,14:27,15:[1,28],16:[1,29],19:b,22:E}),i(N,[2,18]),i(N,[2,19]),i(N,[2,20]),i(N,[2,21]),i(N,[2,23]),i(N,[2,24]),i(N,[2,26],{19:[1,30]}),{20:[1,31]},{6:A,7:I,10:32,11:B},{1:[2,7],6:f,12:21,13:p,14:14,15:w,16:m,17:17,18:18,19:b,22:E},i(R,[2,14],{7:z,11:W}),i(et,[2,8]),i(et,[2,9]),i(et,[2,10]),i(N,[2,15]),i(N,[2,16]),i(N,[2,17]),{20:[1,35]},{21:[1,36]},i(R,[2,13],{7:z,11:W}),i(et,[2,11]),i(et,[2,12]),{21:[1,37]},i(N,[2,25]),i(N,[2,27])],defaultActions:{2:[2,1],6:[2,2]},parseError:function(yt,ft){if(ft.recoverable)this.trace(yt);else{var ut=new Error(yt);throw ut.hash=ft,ut}},parse:function(yt){var ft=this,ut=[0],vt=[],X=[null],pt=[],U=this.table,Tt="",nt=0,It=0,Ot=2,Bt=1,Et=pt.slice.call(arguments,1),Z=Object.create(this.lexer),Ct={yy:{}};for(var xt in this.yy)Object.prototype.hasOwnProperty.call(this.yy,xt)&&(Ct.yy[xt]=this.yy[xt]);Z.setInput(yt,Ct.yy),Ct.yy.lexer=Z,Ct.yy.parser=this,typeof Z.yylloc>"u"&&(Z.yylloc={});var Ht=Z.yylloc;pt.push(Ht);var Le=Z.options&&Z.options.ranges;typeof Ct.yy.parseError=="function"?this.parseError=Ct.yy.parseError:this.parseError=Object.getPrototypeOf(this).parseError;function Ft(){var Pe;return Pe=vt.pop()||Z.lex()||Bt,typeof Pe!="number"&&(Pe instanceof Array&&(vt=Pe,Pe=vt.pop()),Pe=ft.symbols_[Pe]||Pe),Pe}for(var gn,Se,me,Ve,Ye={},ce,ke,zt,re;;){if(Se=ut[ut.length-1],this.defaultActions[Se]?me=this.defaultActions[Se]:((gn===null||typeof gn>"u")&&(gn=Ft()),me=U[Se]&&U[Se][gn]),typeof me>"u"||!me.length||!me[0]){var se="";re=[];for(ce in U[Se])this.terminals_[ce]&&ce>Ot&&re.push("'"+this.terminals_[ce]+"'");Z.showPosition?se="Parse error on line "+(nt+1)+`: +`+Z.showPosition()+` +Expecting `+re.join(", ")+", got '"+(this.terminals_[gn]||gn)+"'":se="Parse error on line "+(nt+1)+": Unexpected "+(gn==Bt?"end of input":"'"+(this.terminals_[gn]||gn)+"'"),this.parseError(se,{text:Z.match,token:this.terminals_[gn]||gn,line:Z.yylineno,loc:Ht,expected:re})}if(me[0]instanceof Array&&me.length>1)throw new Error("Parse Error: multiple actions possible at state: "+Se+", token: "+gn);switch(me[0]){case 1:ut.push(gn),X.push(Z.yytext),pt.push(Z.yylloc),ut.push(me[1]),gn=null,It=Z.yyleng,Tt=Z.yytext,nt=Z.yylineno,Ht=Z.yylloc;break;case 2:if(ke=this.productions_[me[1]][1],Ye.$=X[X.length-ke],Ye._$={first_line:pt[pt.length-(ke||1)].first_line,last_line:pt[pt.length-1].last_line,first_column:pt[pt.length-(ke||1)].first_column,last_column:pt[pt.length-1].last_column},Le&&(Ye._$.range=[pt[pt.length-(ke||1)].range[0],pt[pt.length-1].range[1]]),Ve=this.performAction.apply(Ye,[Tt,It,nt,Ct.yy,me[1],X,pt].concat(Et)),typeof Ve<"u")return Ve;ke&&(ut=ut.slice(0,-1*ke*2),X=X.slice(0,-1*ke),pt=pt.slice(0,-1*ke)),ut.push(this.productions_[me[1]][0]),X.push(Ye.$),pt.push(Ye._$),zt=U[ut[ut.length-2]][ut[ut.length-1]],ut.push(zt);break;case 3:return!0}}return!0}},at=function(){var mt={EOF:1,parseError:function(ft,ut){if(this.yy.parser)this.yy.parser.parseError(ft,ut);else throw new Error(ft)},setInput:function(yt,ft){return this.yy=ft||this.yy||{},this._input=yt,this._more=this._backtrack=this.done=!1,this.yylineno=this.yyleng=0,this.yytext=this.matched=this.match="",this.conditionStack=["INITIAL"],this.yylloc={first_line:1,first_column:0,last_line:1,last_column:0},this.options.ranges&&(this.yylloc.range=[0,0]),this.offset=0,this},input:function(){var yt=this._input[0];this.yytext+=yt,this.yyleng++,this.offset++,this.match+=yt,this.matched+=yt;var ft=yt.match(/(?:\r\n?|\n).*/g);return ft?(this.yylineno++,this.yylloc.last_line++):this.yylloc.last_column++,this.options.ranges&&this.yylloc.range[1]++,this._input=this._input.slice(1),yt},unput:function(yt){var ft=yt.length,ut=yt.split(/(?:\r\n?|\n)/g);this._input=yt+this._input,this.yytext=this.yytext.substr(0,this.yytext.length-ft),this.offset-=ft;var vt=this.match.split(/(?:\r\n?|\n)/g);this.match=this.match.substr(0,this.match.length-1),this.matched=this.matched.substr(0,this.matched.length-1),ut.length-1&&(this.yylineno-=ut.length-1);var X=this.yylloc.range;return this.yylloc={first_line:this.yylloc.first_line,last_line:this.yylineno+1,first_column:this.yylloc.first_column,last_column:ut?(ut.length===vt.length?this.yylloc.first_column:0)+vt[vt.length-ut.length].length-ut[0].length:this.yylloc.first_column-ft},this.options.ranges&&(this.yylloc.range=[X[0],X[0]+this.yyleng-ft]),this.yyleng=this.yytext.length,this},more:function(){return this._more=!0,this},reject:function(){if(this.options.backtrack_lexer)this._backtrack=!0;else return this.parseError("Lexical error on line "+(this.yylineno+1)+`. You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true). +`+this.showPosition(),{text:"",token:null,line:this.yylineno});return this},less:function(yt){this.unput(this.match.slice(yt))},pastInput:function(){var yt=this.matched.substr(0,this.matched.length-this.match.length);return(yt.length>20?"...":"")+yt.substr(-20).replace(/\n/g,"")},upcomingInput:function(){var yt=this.match;return yt.length<20&&(yt+=this._input.substr(0,20-yt.length)),(yt.substr(0,20)+(yt.length>20?"...":"")).replace(/\n/g,"")},showPosition:function(){var yt=this.pastInput(),ft=new Array(yt.length+1).join("-");return yt+this.upcomingInput()+` +`+ft+"^"},test_match:function(yt,ft){var ut,vt,X;if(this.options.backtrack_lexer&&(X={yylineno:this.yylineno,yylloc:{first_line:this.yylloc.first_line,last_line:this.last_line,first_column:this.yylloc.first_column,last_column:this.yylloc.last_column},yytext:this.yytext,match:this.match,matches:this.matches,matched:this.matched,yyleng:this.yyleng,offset:this.offset,_more:this._more,_input:this._input,yy:this.yy,conditionStack:this.conditionStack.slice(0),done:this.done},this.options.ranges&&(X.yylloc.range=this.yylloc.range.slice(0))),vt=yt[0].match(/(?:\r\n?|\n).*/g),vt&&(this.yylineno+=vt.length),this.yylloc={first_line:this.yylloc.last_line,last_line:this.yylineno+1,first_column:this.yylloc.last_column,last_column:vt?vt[vt.length-1].length-vt[vt.length-1].match(/\r?\n?/)[0].length:this.yylloc.last_column+yt[0].length},this.yytext+=yt[0],this.match+=yt[0],this.matches=yt,this.yyleng=this.yytext.length,this.options.ranges&&(this.yylloc.range=[this.offset,this.offset+=this.yyleng]),this._more=!1,this._backtrack=!1,this._input=this._input.slice(yt[0].length),this.matched+=yt[0],ut=this.performAction.call(this,this.yy,this,ft,this.conditionStack[this.conditionStack.length-1]),this.done&&this._input&&(this.done=!1),ut)return ut;if(this._backtrack){for(var pt in X)this[pt]=X[pt];return!1}return!1},next:function(){if(this.done)return this.EOF;this._input||(this.done=!0);var yt,ft,ut,vt;this._more||(this.yytext="",this.match="");for(var X=this._currentRules(),pt=0;ptft[0].length)){if(ft=ut,vt=pt,this.options.backtrack_lexer){if(yt=this.test_match(ut,X[pt]),yt!==!1)return yt;if(this._backtrack){ft=!1;continue}else return!1}else if(!this.options.flex)break}return ft?(yt=this.test_match(ft,X[vt]),yt!==!1?yt:!1):this._input===""?this.EOF:this.parseError("Lexical error on line "+(this.yylineno+1)+`. Unrecognized text. +`+this.showPosition(),{text:"",token:null,line:this.yylineno})},lex:function(){var ft=this.next();return ft||this.lex()},begin:function(ft){this.conditionStack.push(ft)},popState:function(){var ft=this.conditionStack.length-1;return ft>0?this.conditionStack.pop():this.conditionStack[0]},_currentRules:function(){return this.conditionStack.length&&this.conditionStack[this.conditionStack.length-1]?this.conditions[this.conditionStack[this.conditionStack.length-1]].rules:this.conditions.INITIAL.rules},topState:function(ft){return ft=this.conditionStack.length-1-Math.abs(ft||0),ft>=0?this.conditionStack[ft]:"INITIAL"},pushState:function(ft){this.begin(ft)},stateStackSize:function(){return this.conditionStack.length},options:{"case-insensitive":!0},performAction:function(ft,ut,vt,X){switch(vt){case 0:return ft.getLogger().trace("Found comment",ut.yytext),6;case 1:return 8;case 2:this.begin("CLASS");break;case 3:return this.popState(),16;case 4:this.popState();break;case 5:ft.getLogger().trace("Begin icon"),this.begin("ICON");break;case 6:return ft.getLogger().trace("SPACELINE"),6;case 7:return 7;case 8:return 15;case 9:ft.getLogger().trace("end icon"),this.popState();break;case 10:return ft.getLogger().trace("Exploding node"),this.begin("NODE"),19;case 11:return ft.getLogger().trace("Cloud"),this.begin("NODE"),19;case 12:return ft.getLogger().trace("Explosion Bang"),this.begin("NODE"),19;case 13:return ft.getLogger().trace("Cloud Bang"),this.begin("NODE"),19;case 14:return this.begin("NODE"),19;case 15:return this.begin("NODE"),19;case 16:return this.begin("NODE"),19;case 17:return this.begin("NODE"),19;case 18:return 13;case 19:return 22;case 20:return 11;case 21:this.begin("NSTR2");break;case 22:return"NODE_DESCR";case 23:this.popState();break;case 24:ft.getLogger().trace("Starting NSTR"),this.begin("NSTR");break;case 25:return ft.getLogger().trace("description:",ut.yytext),"NODE_DESCR";case 26:this.popState();break;case 27:return this.popState(),ft.getLogger().trace("node end ))"),"NODE_DEND";case 28:return this.popState(),ft.getLogger().trace("node end )"),"NODE_DEND";case 29:return this.popState(),ft.getLogger().trace("node end ...",ut.yytext),"NODE_DEND";case 30:return this.popState(),ft.getLogger().trace("node end (("),"NODE_DEND";case 31:return this.popState(),ft.getLogger().trace("node end (-"),"NODE_DEND";case 32:return this.popState(),ft.getLogger().trace("node end (-"),"NODE_DEND";case 33:return this.popState(),ft.getLogger().trace("node end (("),"NODE_DEND";case 34:return this.popState(),ft.getLogger().trace("node end (("),"NODE_DEND";case 35:return ft.getLogger().trace("Long description:",ut.yytext),20;case 36:return ft.getLogger().trace("Long description:",ut.yytext),20}},rules:[/^(?:\s*%%.*)/i,/^(?:mindmap\b)/i,/^(?::::)/i,/^(?:.+)/i,/^(?:\n)/i,/^(?:::icon\()/i,/^(?:[\s]+[\n])/i,/^(?:[\n]+)/i,/^(?:[^\)]+)/i,/^(?:\))/i,/^(?:-\))/i,/^(?:\(-)/i,/^(?:\)\))/i,/^(?:\))/i,/^(?:\(\()/i,/^(?:\{\{)/i,/^(?:\()/i,/^(?:\[)/i,/^(?:[\s]+)/i,/^(?:[^\(\[\n\)\{\}]+)/i,/^(?:$)/i,/^(?:["][`])/i,/^(?:[^`"]+)/i,/^(?:[`]["])/i,/^(?:["])/i,/^(?:[^"]+)/i,/^(?:["])/i,/^(?:[\)]\))/i,/^(?:[\)])/i,/^(?:[\]])/i,/^(?:\}\})/i,/^(?:\(-)/i,/^(?:-\))/i,/^(?:\(\()/i,/^(?:\()/i,/^(?:[^\)\]\(\}]+)/i,/^(?:.+(?!\(\())/i],conditions:{CLASS:{rules:[3,4],inclusive:!1},ICON:{rules:[8,9],inclusive:!1},NSTR2:{rules:[22,23],inclusive:!1},NSTR:{rules:[25,26],inclusive:!1},NODE:{rules:[21,24,27,28,29,30,31,32,33,34,35,36],inclusive:!1},INITIAL:{rules:[0,1,2,5,6,7,10,11,12,13,14,15,16,17,18,19,20],inclusive:!0}}};return mt}();st.lexer=at;function bt(){this.yy={}}return bt.prototype=st,st.Parser=bt,new bt}();Qgt.parser=Qgt;const zWe=Qgt,rN=i=>Q1(i,Oe());let cw=[],i$t=0,Zgt={};const qWe=()=>{cw=[],i$t=0,Zgt={}},HWe=function(i){for(let a=cw.length-1;a>=0;a--)if(cw[a].levelcw.length>0?cw[0]:null,GWe=(i,a,f,p)=>{Ut.info("addNode",i,a,f,p);const w=Oe(),m={id:i$t++,nodeId:rN(a),level:i,descr:rN(f),type:p,children:[],width:Oe().mindmap.maxNodeWidth};switch(m.type){case Uu.ROUNDED_RECT:m.padding=2*w.mindmap.padding;break;case Uu.RECT:m.padding=2*w.mindmap.padding;break;case Uu.HEXAGON:m.padding=2*w.mindmap.padding;break;default:m.padding=w.mindmap.padding}const b=HWe(i);if(b)b.children.push(m),cw.push(m);else if(cw.length===0)cw.push(m);else{let E=new Error('There can be only one root. No parent could be found for ("'+m.descr+'")');throw E.hash={text:"branch "+name,token:"branch "+name,line:"1",loc:{first_line:1,last_line:1,first_column:1,last_column:1},expected:['"checkout '+name+'"']},E}},Uu={DEFAULT:0,NO_BORDER:0,ROUNDED_RECT:1,RECT:2,CIRCLE:3,CLOUD:4,BANG:5,HEXAGON:6},UWe=(i,a)=>{switch(Ut.debug("In get type",i,a),i){case"[":return Uu.RECT;case"(":return a===")"?Uu.ROUNDED_RECT:Uu.CLOUD;case"((":return Uu.CIRCLE;case")":return Uu.CLOUD;case"))":return Uu.BANG;case"{{":return Uu.HEXAGON;default:return Uu.DEFAULT}},s$t=(i,a)=>{Zgt[i]=a},WWe=i=>{const a=cw[cw.length-1];i&&i.icon&&(a.icon=rN(i.icon)),i&&i.class&&(a.class=rN(i.class))},IT=i=>{switch(i){case Uu.DEFAULT:return"no-border";case Uu.RECT:return"rect";case Uu.ROUNDED_RECT:return"rounded-rect";case Uu.CIRCLE:return"circle";case Uu.CLOUD:return"cloud";case Uu.BANG:return"bang";case Uu.HEXAGON:return"hexgon";default:return"no-border"}};let a$t;const YWe=i=>{a$t=i},KWe=()=>Ut,XWe=i=>cw[i],Jgt=i=>Zgt[i],QWe=Object.freeze(Object.defineProperty({__proto__:null,addNode:GWe,clear:qWe,decorateNode:WWe,getElementById:Jgt,getLogger:KWe,getMindmap:VWe,getNodeById:XWe,getType:UWe,nodeType:Uu,get parseError(){return a$t},sanitizeText:rN,setElementForId:s$t,setErrorHandler:YWe,type2Str:IT},Symbol.toStringTag,{value:"Module"})),o$t=12,ZWe=function(i,a,f){i.append("path").attr("id","node-"+a.id).attr("class","node-bkg node-"+IT(a.type)).attr("d",`M0 ${a.height-5} v${-a.height+2*5} q0,-5 5,-5 h${a.width-2*5} q5,0 5,5 v${a.height-5} H0 Z`),i.append("line").attr("class","node-line-"+f).attr("x1",0).attr("y1",a.height).attr("x2",a.width).attr("y2",a.height)},JWe=function(i,a){i.append("rect").attr("id","node-"+a.id).attr("class","node-bkg node-"+IT(a.type)).attr("height",a.height).attr("width",a.width)},tYe=function(i,a){const f=a.width,p=a.height,w=.15*f,m=.25*f,b=.35*f,E=.2*f;i.append("path").attr("id","node-"+a.id).attr("class","node-bkg node-"+IT(a.type)).attr("d",`M0 0 a${w},${w} 0 0,1 ${f*.25},${-1*f*.1} + a${b},${b} 1 0,1 ${f*.4},${-1*f*.1} + a${m},${m} 1 0,1 ${f*.35},${1*f*.2} + + a${w},${w} 1 0,1 ${f*.15},${1*p*.35} + a${E},${E} 1 0,1 ${-1*f*.15},${1*p*.65} + + a${m},${w} 1 0,1 ${-1*f*.25},${f*.15} + a${b},${b} 1 0,1 ${-1*f*.5},0 + a${w},${w} 1 0,1 ${-1*f*.25},${-1*f*.15} + + a${w},${w} 1 0,1 ${-1*f*.1},${-1*p*.35} + a${E},${E} 1 0,1 ${f*.1},${-1*p*.65} + + H0 V0 Z`)},eYe=function(i,a){const f=a.width,p=a.height,w=.15*f;i.append("path").attr("id","node-"+a.id).attr("class","node-bkg node-"+IT(a.type)).attr("d",`M0 0 a${w},${w} 1 0,0 ${f*.25},${-1*p*.1} + a${w},${w} 1 0,0 ${f*.25},0 + a${w},${w} 1 0,0 ${f*.25},0 + a${w},${w} 1 0,0 ${f*.25},${1*p*.1} + + a${w},${w} 1 0,0 ${f*.15},${1*p*.33} + a${w*.8},${w*.8} 1 0,0 0,${1*p*.34} + a${w},${w} 1 0,0 ${-1*f*.15},${1*p*.33} + + a${w},${w} 1 0,0 ${-1*f*.25},${p*.15} + a${w},${w} 1 0,0 ${-1*f*.25},0 + a${w},${w} 1 0,0 ${-1*f*.25},0 + a${w},${w} 1 0,0 ${-1*f*.25},${-1*p*.15} + + a${w},${w} 1 0,0 ${-1*f*.1},${-1*p*.33} + a${w*.8},${w*.8} 1 0,0 0,${-1*p*.34} + a${w},${w} 1 0,0 ${f*.1},${-1*p*.33} + + H0 V0 Z`)},nYe=function(i,a){i.append("circle").attr("id","node-"+a.id).attr("class","node-bkg node-"+IT(a.type)).attr("r",a.width/2)};function rYe(i,a,f,p,w){return i.insert("polygon",":first-child").attr("points",p.map(function(m){return m.x+","+m.y}).join(" ")).attr("transform","translate("+(w.width-a)/2+", "+f+")")}const iYe=function(i,a){const f=a.height,w=f/4,m=a.width-a.padding+2*w,b=[{x:w,y:0},{x:m-w,y:0},{x:m,y:-f/2},{x:m-w,y:-f},{x:w,y:-f},{x:0,y:-f/2}];rYe(i,m,f,b,a)},sYe=function(i,a){i.append("rect").attr("id","node-"+a.id).attr("class","node-bkg node-"+IT(a.type)).attr("height",a.height).attr("rx",a.padding).attr("ry",a.padding).attr("width",a.width)},c$t={drawNode:function(i,a,f,p){const w=p.htmlLabels,m=f%(o$t-1),b=i.append("g");a.section=m;let E="section-"+m;m<0&&(E+=" section-root"),b.attr("class",(a.class?a.class+" ":"")+"mindmap-node "+E);const _=b.append("g"),A=b.append("g"),I=a.descr.replace(/()/g,` +`);EY(A,I,{useHtmlLabels:w,width:a.width,classes:"mindmap-node-label"}),w||A.attr("dy","1em").attr("alignment-baseline","middle").attr("dominant-baseline","middle").attr("text-anchor","middle");const B=A.node().getBBox(),N=p.fontSize.replace?p.fontSize.replace("px",""):p.fontSize;if(a.height=B.height+N*1.1*.5+a.padding,a.width=B.width+2*a.padding,a.icon)if(a.type===Uu.CIRCLE)a.height+=50,a.width+=50,b.append("foreignObject").attr("height","50px").attr("width",a.width).attr("style","text-align: center;").append("div").attr("class","icon-container").append("i").attr("class","node-icon-"+m+" "+a.icon),A.attr("transform","translate("+a.width/2+", "+(a.height/2-1.5*a.padding)+")");else{a.width+=50;const R=a.height;a.height=Math.max(R,60);const z=Math.abs(a.height-R);b.append("foreignObject").attr("width","60px").attr("height",a.height).attr("style","text-align: center;margin-top:"+z/2+"px;").append("div").attr("class","icon-container").append("i").attr("class","node-icon-"+m+" "+a.icon),A.attr("transform","translate("+(25+a.width/2)+", "+(z/2+a.padding/2)+")")}else if(w){const R=(a.width-B.width)/2,z=(a.height-B.height)/2;A.attr("transform","translate("+R+", "+z+")")}else{const R=a.width/2,z=a.padding/2;A.attr("transform","translate("+R+", "+z+")")}switch(a.type){case Uu.DEFAULT:ZWe(_,a,m);break;case Uu.ROUNDED_RECT:sYe(_,a);break;case Uu.RECT:JWe(_,a);break;case Uu.CIRCLE:_.attr("transform","translate("+a.width/2+", "+ +a.height/2+")"),nYe(_,a);break;case Uu.CLOUD:tYe(_,a);break;case Uu.BANG:eYe(_,a);break;case Uu.HEXAGON:iYe(_,a);break}return s$t(a.id,b),a.height},positionNode:function(i){const a=Jgt(i.id),f=i.x||0,p=i.y||0;a.attr("transform","translate("+f+","+p+")")},drawEdge:function(a,f,p,w,m){const b=m%(o$t-1),E=p.x+p.width/2,_=p.y+p.height/2,A=f.x+f.width/2,I=f.y+f.height/2,B=A>E?E+Math.abs(E-A)/2:E-Math.abs(E-A)/2,N=I>_?_+Math.abs(_-I)/2:_-Math.abs(_-I)/2,R=A>E?Math.abs(E-B)/2+E:-Math.abs(E-B)/2+E,z=I>_?Math.abs(_-N)/2+_:-Math.abs(_-N)/2+_;a.append("path").attr("d",p.direction==="TB"||p.direction==="BT"?`M${E},${_} Q${E},${z} ${B},${N} T${A},${I}`:`M${E},${_} Q${R},${_} ${B},${N} T${A},${I}`).attr("class","edge section-edge-"+b+" edge-depth-"+w)}};var u$t={exports:{}};(function(i,a){(function(f,p){i.exports=p()})(b0,function(){function f(y){"@babel/helpers - typeof";return f=typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?function(g){return typeof g}:function(g){return g&&typeof Symbol=="function"&&g.constructor===Symbol&&g!==Symbol.prototype?"symbol":typeof g},f(y)}function p(y,g){if(!(y instanceof g))throw new TypeError("Cannot call a class as a function")}function w(y,g){for(var x=0;xy.length)&&(g=y.length);for(var x=0,T=new Array(g);x"u"?null:window,z=R?R.navigator:null;R&&R.document;var W=f(""),et=f({}),st=f(function(){}),at=typeof HTMLElement>"u"?"undefined":f(HTMLElement),bt=function(g){return g&&g.instanceString&&yt(g.instanceString)?g.instanceString():null},mt=function(g){return g!=null&&f(g)==W},yt=function(g){return g!=null&&f(g)===st},ft=function(g){return!Tt(g)&&(Array.isArray?Array.isArray(g):g!=null&&g instanceof Array)},ut=function(g){return g!=null&&f(g)===et&&!ft(g)&&g.constructor===Object},vt=function(g){return g!=null&&f(g)===et},X=function(g){return g!=null&&f(g)===f(1)&&!isNaN(g)},pt=function(g){return X(g)&&Math.floor(g)===g},U=function(g){if(at!=="undefined")return g!=null&&g instanceof HTMLElement},Tt=function(g){return nt(g)||It(g)},nt=function(g){return bt(g)==="collection"&&g._private.single},It=function(g){return bt(g)==="collection"&&!g._private.single},Ot=function(g){return bt(g)==="core"},Bt=function(g){return bt(g)==="stylesheet"},Et=function(g){return bt(g)==="event"},Z=function(g){return g==null?!0:!!(g===""||g.match(/^\s+$/))},Ct=function(g){return typeof HTMLElement>"u"?!1:g instanceof HTMLElement},xt=function(g){return ut(g)&&X(g.x1)&&X(g.x2)&&X(g.y1)&&X(g.y2)},Ht=function(g){return vt(g)&&yt(g.then)},Le=function(){return z&&z.userAgent.match(/msie|trident|edge/i)},Ft=function(g,x){x||(x=function(){if(arguments.length===1)return arguments[0];if(arguments.length===0)return"undefined";for(var O=[],P=0;Px?1:0},Me=function(g,x){return-1*te(g,x)},de=Object.assign!=null?Object.assign.bind(Object):function(y){for(var g=arguments,x=1;x1&&(Lt-=1),Lt<1/6?ht+(dt-ht)*6*Lt:Lt<1/2?dt:Lt<2/3?ht+(dt-ht)*(2/3-Lt)*6:ht}var Y=new RegExp("^"+zt+"$").exec(g);if(Y){if(T=parseInt(Y[1]),T<0?T=(360- -1*T%360)%360:T>360&&(T=T%360),T/=360,L=parseFloat(Y[2]),L<0||L>100||(L=L/100,O=parseFloat(Y[3]),O<0||O>100)||(O=O/100,P=Y[4],P!==void 0&&(P=parseFloat(P),P<0||P>1)))return;if(L===0)$=q=S=Math.round(O*255);else{var rt=O<.5?O*(1+L):O+L-O*L,ot=2*O-rt;$=Math.round(255*V(ot,rt,T+1/3)),q=Math.round(255*V(ot,rt,T)),S=Math.round(255*V(ot,rt,T-1/3))}x=[$,q,S,P]}return x},Ks=function(g){var x,T=new RegExp("^"+ce+"$").exec(g);if(T){x=[];for(var L=[],O=1;O<=3;O++){var P=T[O];if(P[P.length-1]==="%"&&(L[O]=!0),P=parseFloat(P),L[O]&&(P=P/100*255),P<0||P>255)return;x.push(Math.floor(P))}var $=L[1]||L[2]||L[3],q=L[1]&&L[2]&&L[3];if($&&!q)return;var S=T[4];if(S!==void 0){if(S=parseFloat(S),S<0||S>1)return;x.push(S)}}return x},ws=function(g){return Xi[g.toLowerCase()]},fo=function(g){return(ft(g)?g:null)||ws(g)||on(g)||Ks(g)||ni(g)},Xi={transparent:[0,0,0,0],aliceblue:[240,248,255],antiquewhite:[250,235,215],aqua:[0,255,255],aquamarine:[127,255,212],azure:[240,255,255],beige:[245,245,220],bisque:[255,228,196],black:[0,0,0],blanchedalmond:[255,235,205],blue:[0,0,255],blueviolet:[138,43,226],brown:[165,42,42],burlywood:[222,184,135],cadetblue:[95,158,160],chartreuse:[127,255,0],chocolate:[210,105,30],coral:[255,127,80],cornflowerblue:[100,149,237],cornsilk:[255,248,220],crimson:[220,20,60],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgoldenrod:[184,134,11],darkgray:[169,169,169],darkgreen:[0,100,0],darkgrey:[169,169,169],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkseagreen:[143,188,143],darkslateblue:[72,61,139],darkslategray:[47,79,79],darkslategrey:[47,79,79],darkturquoise:[0,206,209],darkviolet:[148,0,211],deeppink:[255,20,147],deepskyblue:[0,191,255],dimgray:[105,105,105],dimgrey:[105,105,105],dodgerblue:[30,144,255],firebrick:[178,34,34],floralwhite:[255,250,240],forestgreen:[34,139,34],fuchsia:[255,0,255],gainsboro:[220,220,220],ghostwhite:[248,248,255],gold:[255,215,0],goldenrod:[218,165,32],gray:[128,128,128],grey:[128,128,128],green:[0,128,0],greenyellow:[173,255,47],honeydew:[240,255,240],hotpink:[255,105,180],indianred:[205,92,92],indigo:[75,0,130],ivory:[255,255,240],khaki:[240,230,140],lavender:[230,230,250],lavenderblush:[255,240,245],lawngreen:[124,252,0],lemonchiffon:[255,250,205],lightblue:[173,216,230],lightcoral:[240,128,128],lightcyan:[224,255,255],lightgoldenrodyellow:[250,250,210],lightgray:[211,211,211],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightsalmon:[255,160,122],lightseagreen:[32,178,170],lightskyblue:[135,206,250],lightslategray:[119,136,153],lightslategrey:[119,136,153],lightsteelblue:[176,196,222],lightyellow:[255,255,224],lime:[0,255,0],limegreen:[50,205,50],linen:[250,240,230],magenta:[255,0,255],maroon:[128,0,0],mediumaquamarine:[102,205,170],mediumblue:[0,0,205],mediumorchid:[186,85,211],mediumpurple:[147,112,219],mediumseagreen:[60,179,113],mediumslateblue:[123,104,238],mediumspringgreen:[0,250,154],mediumturquoise:[72,209,204],mediumvioletred:[199,21,133],midnightblue:[25,25,112],mintcream:[245,255,250],mistyrose:[255,228,225],moccasin:[255,228,181],navajowhite:[255,222,173],navy:[0,0,128],oldlace:[253,245,230],olive:[128,128,0],olivedrab:[107,142,35],orange:[255,165,0],orangered:[255,69,0],orchid:[218,112,214],palegoldenrod:[238,232,170],palegreen:[152,251,152],paleturquoise:[175,238,238],palevioletred:[219,112,147],papayawhip:[255,239,213],peachpuff:[255,218,185],peru:[205,133,63],pink:[255,192,203],plum:[221,160,221],powderblue:[176,224,230],purple:[128,0,128],red:[255,0,0],rosybrown:[188,143,143],royalblue:[65,105,225],saddlebrown:[139,69,19],salmon:[250,128,114],sandybrown:[244,164,96],seagreen:[46,139,87],seashell:[255,245,238],sienna:[160,82,45],silver:[192,192,192],skyblue:[135,206,235],slateblue:[106,90,205],slategray:[112,128,144],slategrey:[112,128,144],snow:[255,250,250],springgreen:[0,255,127],steelblue:[70,130,180],tan:[210,180,140],teal:[0,128,128],thistle:[216,191,216],tomato:[255,99,71],turquoise:[64,224,208],violet:[238,130,238],wheat:[245,222,179],white:[255,255,255],whitesmoke:[245,245,245],yellow:[255,255,0],yellowgreen:[154,205,50]},Er=function(g){for(var x=g.map,T=g.keys,L=T.length,O=0;O=g||qt<0||Y&&ne>=O}function kt(){var Yt=Po();if(Lt(Yt))return Dt(Yt);$=setTimeout(kt,dt(Yt))}function Dt(Yt){return $=void 0,rt&&T?ot(Yt):(T=L=void 0,P)}function Pt(){$!==void 0&&clearTimeout($),S=0,T=q=L=$=void 0}function $t(){return $===void 0?P:Dt(Po())}function Zt(){var Yt=Po(),qt=Lt(Yt);if(T=arguments,L=this,q=Yt,qt){if($===void 0)return ht(q);if(Y)return clearTimeout($),$=setTimeout(kt,g),ot(q)}return $===void 0&&($=setTimeout(kt,g)),P}return Zt.cancel=Pt,Zt.flush=$t,Zt}var Yc=xi,Ce=R?R.performance:null,vp=Ce&&Ce.now?function(){return Ce.now()}:function(){return Date.now()},Be=function(){if(R){if(R.requestAnimationFrame)return function(y){R.requestAnimationFrame(y)};if(R.mozRequestAnimationFrame)return function(y){R.mozRequestAnimationFrame(y)};if(R.webkitRequestAnimationFrame)return function(y){R.webkitRequestAnimationFrame(y)};if(R.msRequestAnimationFrame)return function(y){R.msRequestAnimationFrame(y)}}return function(y){y&&setTimeout(function(){y(vp())},1e3/60)}}(),Bf=function(g){return Be(g)},yg=vp,bm=9261,Ek=65599,E3=5381,Il=function(g){for(var x=arguments.length>1&&arguments[1]!==void 0?arguments[1]:bm,T=x,L;L=g.next(),!L.done;)T=T*Ek+L.value|0;return T},L0=function(g){var x=arguments.length>1&&arguments[1]!==void 0?arguments[1]:bm;return x*Ek+g|0},hw=function(g){var x=arguments.length>1&&arguments[1]!==void 0?arguments[1]:E3;return(x<<5)+x+g|0},H5=function(g,x){return g*2097152+x},Hb=function(g){return g[0]*2097152+g[1]},V5=function(g,x){return[L0(g[0],x[0]),hw(g[1],x[1])]},f1=function(g,x){var T={value:0,done:!1},L=0,O=g.length,P={next:function(){return L=0&&!(g[L]===x&&(g.splice(L,1),T));L--);},TL=function(g){g.splice(0,g.length)},aN=function(g,x){for(var T=0;T"u"?"undefined":f(Set))!==fK?Set:dK,FT=function(g,x){var T=arguments.length>2&&arguments[2]!==void 0?arguments[2]:!0;if(g===void 0||x===void 0||!Ot(g)){vl("An element must have a core reference and parameters set");return}var L=x.group;if(L==null&&(x.data&&x.data.source!=null&&x.data.target!=null?L="edges":L="nodes"),L!=="nodes"&&L!=="edges"){vl("An element must be of type `nodes` or `edges`; you specified `"+L+"`");return}this.length=1,this[0]=this;var O=this._private={cy:g,single:!0,data:x.data||{},position:x.position||{x:0,y:0},autoWidth:void 0,autoHeight:void 0,autoPadding:void 0,compoundBoundsClean:!1,listeners:[],group:L,style:{},rstyle:{},styleCxts:[],styleKeys:{},removed:!0,selected:!!x.selected,selectable:x.selectable===void 0?!0:!!x.selectable,locked:!!x.locked,grabbed:!1,grabbable:x.grabbable===void 0?!0:!!x.grabbable,pannable:x.pannable===void 0?L==="edges":!!x.pannable,active:!1,classes:new Y5,animation:{current:[],queue:[]},rscratch:{},scratch:x.scratch||{},edges:[],children:[],parent:x.parent&&x.parent.isNode()?x.parent:null,traversalCache:{},backgrounding:!1,bbCache:null,bbCacheShift:{x:0,y:0},bodyBounds:null,overlayBounds:null,labelBounds:{all:null,source:null,target:null,main:null},arrowBounds:{source:null,target:null,"mid-source":null,"mid-target":null}};if(O.position.x==null&&(O.position.x=0),O.position.y==null&&(O.position.y=0),x.renderedPosition){var P=x.renderedPosition,$=g.pan(),q=g.zoom();O.position={x:(P.x-$.x)/q,y:(P.y-$.y)/q}}var S=[];ft(x.classes)?S=x.classes:mt(x.classes)&&(S=x.classes.split(/\s+/));for(var V=0,Y=S.length;VDt?1:0},V=function(kt,Dt,Pt,$t,Zt){var Yt;if(Pt==null&&(Pt=0),Zt==null&&(Zt=T),Pt<0)throw new Error("lo must be non-negative");for($t==null&&($t=kt.length);Pt<$t;)Yt=L((Pt+$t)/2),Zt(Dt,kt[Yt])<0?$t=Yt:Pt=Yt+1;return[].splice.apply(kt,[Pt,Pt-Pt].concat(Dt)),Dt},$=function(kt,Dt,Pt){return Pt==null&&(Pt=T),kt.push(Dt),dt(kt,0,kt.length-1,Pt)},P=function(kt,Dt){var Pt,$t;return Dt==null&&(Dt=T),Pt=kt.pop(),kt.length?($t=kt[0],kt[0]=Pt,Lt(kt,0,Dt)):$t=Pt,$t},S=function(kt,Dt,Pt){var $t;return Pt==null&&(Pt=T),$t=kt[0],kt[0]=Dt,Lt(kt,0,Pt),$t},q=function(kt,Dt,Pt){var $t;return Pt==null&&(Pt=T),kt.length&&Pt(kt[0],Dt)<0&&($t=[kt[0],Dt],Dt=$t[0],kt[0]=$t[1],Lt(kt,0,Pt)),Dt},O=function(kt,Dt){var Pt,$t,Zt,Yt,qt,ne;for(Dt==null&&(Dt=T),Yt=(function(){ne=[];for(var Gt=0,ge=L(kt.length/2);0<=ge?Gtge;0<=ge?Gt++:Gt--)ne.push(Gt);return ne}).apply(this).reverse(),qt=[],$t=0,Zt=Yt.length;$tbe;0<=be?++ne:--ne)ie.push(P(kt,Pt));return ie},dt=function(kt,Dt,Pt,$t){var Zt,Yt,qt;for($t==null&&($t=T),Zt=kt[Pt];Pt>Dt;){if(qt=Pt-1>>1,Yt=kt[qt],$t(Zt,Yt)<0){kt[Pt]=Yt,Pt=qt;continue}break}return kt[Pt]=Zt},Lt=function(kt,Dt,Pt){var $t,Zt,Yt,qt,ne;for(Pt==null&&(Pt=T),Zt=kt.length,ne=Dt,Yt=kt[Dt],$t=2*Dt+1;$t0;){var Yt=Dt.pop(),qt=Lt(Yt),ne=Yt.id();if(rt[ne]=qt,qt!==1/0)for(var Gt=Yt.neighborhood().intersect(ht),ge=0;ge0)for(En.unshift(Ge);Y[Yn];){var Sn=Y[Yn];En.unshift(Sn.edge),En.unshift(Sn.node),In=Sn.node,Yn=In.id()}return $.spawn(En)}}}},wK={kruskal:function(g){g=g||function(Pt){return 1};for(var x=this.byGroup(),T=x.nodes,L=x.edges,O=T.length,P=new Array(O),$=T,q=function($t){for(var Zt=0;Zt0;){if(Zt(),qt++,$t===V){for(var ne=[],Gt=O,ge=V,be=kt[ge];ne.unshift(Gt),be!=null&&ne.unshift(be),Gt=Lt[ge],Gt!=null;)ge=Gt.id(),be=kt[ge];return{found:!0,distance:Y[$t],path:this.spawn(ne),steps:qt}}ot[$t]=!0;for(var ie=Pt._private.edges,Fe=0;Febe&&(ht[ge]=be,Dt[ge]=Gt,Pt[ge]=Zt),!O){var ie=Gt*V+ne;!O&&ht[ie]>be&&(ht[ie]=be,Dt[ie]=ne,Pt[ie]=Zt)}}}for(var Fe=0;Fe1&&arguments[1]!==void 0?arguments[1]:P,Va=Pt(Si),Qs=[],qs=Va;;){if(qs==null)return x.spawn();var Tr=Dt(qs),Qt=Tr.edge,jn=Tr.pred;if(Qs.unshift(qs[0]),qs.same(Ui)&&Qs.length>0)break;Qt!=null&&Qs.unshift(Qt),qs=jn}return q.spawn(Qs)},Yt=0;Yt=0;V--){var Y=S[V],rt=Y[1],ot=Y[2];(x[rt]===$&&x[ot]===q||x[rt]===q&&x[ot]===$)&&S.splice(V,1)}for(var ht=0;htL;){var O=Math.floor(Math.random()*x.length);x=CK(O,g,x),T--}return x},_K={kargerStein:function(){var g=this,x=this.byGroup(),T=x.nodes,L=x.edges;L.unmergeBy(function(En){return En.isLoop()});var O=T.length,P=L.length,$=Math.ceil(Math.pow(Math.log(O)/Math.LN2,2)),q=Math.floor(O/TK);if(O<2){vl("At least 2 nodes are required for Karger-Stein algorithm");return}for(var S=[],V=0;V1&&arguments[1]!==void 0?arguments[1]:0,T=arguments.length>2&&arguments[2]!==void 0?arguments[2]:g.length,L=1/0,O=x;O1&&arguments[1]!==void 0?arguments[1]:0,T=arguments.length>2&&arguments[2]!==void 0?arguments[2]:g.length,L=-1/0,O=x;O1&&arguments[1]!==void 0?arguments[1]:0,T=arguments.length>2&&arguments[2]!==void 0?arguments[2]:g.length,L=0,O=0,P=x;P1&&arguments[1]!==void 0?arguments[1]:0,T=arguments.length>2&&arguments[2]!==void 0?arguments[2]:g.length,L=arguments.length>3&&arguments[3]!==void 0?arguments[3]:!0,O=arguments.length>4&&arguments[4]!==void 0?arguments[4]:!0,P=arguments.length>5&&arguments[5]!==void 0?arguments[5]:!0;L?g=g.slice(x,T):(T0&&g.splice(0,x));for(var $=0,q=g.length-1;q>=0;q--){var S=g[q];P?isFinite(S)||(g[q]=-1/0,$++):g.splice(q,1)}O&&g.sort(function(rt,ot){return rt-ot});var V=g.length,Y=Math.floor(V/2);return V%2!==0?g[Y+1+$]:(g[Y-1+$]+g[Y+$])/2},IK=function(g){return Math.PI*g/180},BT=function(g,x){return Math.atan2(x,g)-Math.PI/2},_L=Math.log2||function(y){return Math.log(y)/Math.log(2)},uN=function(g){return g>0?1:g<0?-1:0},C3=function(g,x){return Math.sqrt(_3(g,x))},_3=function(g,x){var T=x.x-g.x,L=x.y-g.y;return T*T+L*L},OK=function(g){for(var x=g.length,T=0,L=0;L=g.x1&&g.y2>=g.y1)return{x1:g.x1,y1:g.y1,x2:g.x2,y2:g.y2,w:g.x2-g.x1,h:g.y2-g.y1};if(g.w!=null&&g.h!=null&&g.w>=0&&g.h>=0)return{x1:g.x1,y1:g.y1,x2:g.x1+g.w,y2:g.y1+g.h,w:g.w,h:g.h}}},FK=function(g){return{x1:g.x1,x2:g.x2,w:g.w,y1:g.y1,y2:g.y2,h:g.h}},NK=function(g){g.x1=1/0,g.y1=1/0,g.x2=-1/0,g.y2=-1/0,g.w=0,g.h=0},BK=function(g,x){g.x1=Math.min(g.x1,x.x1),g.x2=Math.max(g.x2,x.x2),g.w=g.x2-g.x1,g.y1=Math.min(g.y1,x.y1),g.y2=Math.max(g.y2,x.y2),g.h=g.y2-g.y1},RK=function(g,x,T){g.x1=Math.min(g.x1,x),g.x2=Math.max(g.x2,x),g.w=g.x2-g.x1,g.y1=Math.min(g.y1,T),g.y2=Math.max(g.y2,T),g.h=g.y2-g.y1},RT=function(g){var x=arguments.length>1&&arguments[1]!==void 0?arguments[1]:0;return g.x1-=x,g.x2+=x,g.y1-=x,g.y2+=x,g.w=g.x2-g.x1,g.h=g.y2-g.y1,g},SL=function(g){var x=arguments.length>1&&arguments[1]!==void 0?arguments[1]:[0],T,L,O,P;if(x.length===1)T=L=O=P=x[0];else if(x.length===2)T=O=x[0],P=L=x[1];else if(x.length===4){var $=E(x,4);T=$[0],L=$[1],O=$[2],P=$[3]}return g.x1-=P,g.x2+=L,g.y1-=T,g.y2+=O,g.w=g.x2-g.x1,g.h=g.y2-g.y1,g},lN=function(g,x){g.x1=x.x1,g.y1=x.y1,g.x2=x.x2,g.y2=x.y2,g.w=g.x2-g.x1,g.h=g.y2-g.y1},AL=function(g,x){return!(g.x1>x.x2||x.x1>g.x2||g.x2x.y2||x.y1>g.y2)},Q5=function(g,x,T){return g.x1<=x&&x<=g.x2&&g.y1<=T&&T<=g.y2},jK=function(g,x){return Q5(g,x.x,x.y)},hN=function(g,x){return Q5(g,x.x1,x.y1)&&Q5(g,x.x2,x.y2)},fN=function(g,x,T,L,O,P,$){var q=Lk(O,P),S=O/2,V=P/2,Y;{var rt=T-S+q-$,ot=L-V-$,ht=T+S-q+$,dt=ot;if(Y=ym(g,x,T,L,rt,ot,ht,dt,!1),Y.length>0)return Y}{var Lt=T+S+$,kt=L-V+q-$,Dt=Lt,Pt=L+V-q+$;if(Y=ym(g,x,T,L,Lt,kt,Dt,Pt,!1),Y.length>0)return Y}{var $t=T-S+q-$,Zt=L+V+$,Yt=T+S-q+$,qt=Zt;if(Y=ym(g,x,T,L,$t,Zt,Yt,qt,!1),Y.length>0)return Y}{var ne=T-S-$,Gt=L-V+q-$,ge=ne,be=L+V-q+$;if(Y=ym(g,x,T,L,ne,Gt,ge,be,!1),Y.length>0)return Y}var ie;{var Fe=T-S+q,we=L-V+q;if(ie=Sk(g,x,T,L,Fe,we,q+$),ie.length>0&&ie[0]<=Fe&&ie[1]<=we)return[ie[0],ie[1]]}{var bn=T+S-q,ze=L-V+q;if(ie=Sk(g,x,T,L,bn,ze,q+$),ie.length>0&&ie[0]>=bn&&ie[1]<=ze)return[ie[0],ie[1]]}{var Ge=T+S-q,En=L+V-q;if(ie=Sk(g,x,T,L,Ge,En,q+$),ie.length>0&&ie[0]>=Ge&&ie[1]>=En)return[ie[0],ie[1]]}{var In=T-S+q,Yn=L+V-q;if(ie=Sk(g,x,T,L,In,Yn,q+$),ie.length>0&&ie[0]<=In&&ie[1]>=Yn)return[ie[0],ie[1]]}return[]},$K=function(g,x,T,L,O,P,$){var q=$,S=Math.min(T,O),V=Math.max(T,O),Y=Math.min(L,P),rt=Math.max(L,P);return S-q<=g&&g<=V+q&&Y-q<=x&&x<=rt+q},zK=function(g,x,T,L,O,P,$,q,S){var V={x1:Math.min(T,$,O)-S,x2:Math.max(T,$,O)+S,y1:Math.min(L,q,P)-S,y2:Math.max(L,q,P)+S};return!(gV.x2||xV.y2)},qK=function(g,x,T,L){T-=L;var O=x*x-4*g*T;if(O<0)return[];var P=Math.sqrt(O),$=2*g,q=(-x+P)/$,S=(-x-P)/$;return[q,S]},HK=function(g,x,T,L,O){var P=1e-5;g===0&&(g=P),x/=g,T/=g,L/=g;var $,q,S,V,Y,rt,ot,ht;if(q=(3*T-x*x)/9,S=-(27*L)+x*(9*T-2*(x*x)),S/=54,$=q*q*q+S*S,O[1]=0,ot=x/3,$>0){Y=S+Math.sqrt($),Y=Y<0?-Math.pow(-Y,1/3):Math.pow(Y,1/3),rt=S-Math.sqrt($),rt=rt<0?-Math.pow(-rt,1/3):Math.pow(rt,1/3),O[0]=-ot+Y+rt,ot+=(Y+rt)/2,O[4]=O[2]=-ot,ot=Math.sqrt(3)*(-rt+Y)/2,O[3]=ot,O[5]=-ot;return}if(O[5]=O[3]=0,$===0){ht=S<0?-Math.pow(-S,1/3):Math.pow(S,1/3),O[0]=-ot+2*ht,O[4]=O[2]=-(ht+ot);return}q=-q,V=q*q*q,V=Math.acos(S/Math.sqrt(V)),ht=2*Math.sqrt(q),O[0]=-ot+ht*Math.cos(V/3),O[2]=-ot+ht*Math.cos((V+2*Math.PI)/3),O[4]=-ot+ht*Math.cos((V+4*Math.PI)/3)},VK=function(g,x,T,L,O,P,$,q){var S=1*T*T-4*T*O+2*T*$+4*O*O-4*O*$+$*$+L*L-4*L*P+2*L*q+4*P*P-4*P*q+q*q,V=1*9*T*O-3*T*T-3*T*$-6*O*O+3*O*$+9*L*P-3*L*L-3*L*q-6*P*P+3*P*q,Y=1*3*T*T-6*T*O+T*$-T*g+2*O*O+2*O*g-$*g+3*L*L-6*L*P+L*q-L*x+2*P*P+2*P*x-q*x,rt=1*T*O-T*T+T*g-O*g+L*P-L*L+L*x-P*x,ot=[];HK(S,V,Y,rt,ot);for(var ht=1e-7,dt=[],Lt=0;Lt<6;Lt+=2)Math.abs(ot[Lt+1])=0&&ot[Lt]<=1&&dt.push(ot[Lt]);dt.push(1),dt.push(0);for(var kt=-1,Dt,Pt,$t,Zt=0;Zt=0?$tS?(g-O)*(g-O)+(x-P)*(x-P):V-rt},qd=function(g,x,T){for(var L,O,P,$,q,S=0,V=0;V=g&&g>=P||L<=g&&g<=P)q=(g-L)/(P-L)*($-O)+O,q>x&&S++;else continue;return S%2!==0},dw=function(g,x,T,L,O,P,$,q,S){var V=new Array(T.length),Y;q[0]!=null?(Y=Math.atan(q[1]/q[0]),q[0]<0?Y=Y+Math.PI/2:Y=-Y-Math.PI/2):Y=q;for(var rt=Math.cos(-Y),ot=Math.sin(-Y),ht=0;ht0){var Lt=gN(V,-S);dt=dN(Lt)}else dt=V;return qd(g,x,dt)},UK=function(g,x,T,L,O,P,$){for(var q=new Array(T.length),S=P/2,V=$/2,Y=DL(P,$),rt=Y*Y,ot=0;ot=0&&Lt<=1&&Dt.push(Lt),kt>=0&&kt<=1&&Dt.push(kt),Dt.length===0)return[];var Pt=Dt[0]*q[0]+g,$t=Dt[0]*q[1]+x;if(Dt.length>1){if(Dt[0]==Dt[1])return[Pt,$t];var Zt=Dt[1]*q[0]+g,Yt=Dt[1]*q[1]+x;return[Pt,$t,Zt,Yt]}else return[Pt,$t]},LL=function(g,x,T){return x<=g&&g<=T||T<=g&&g<=x?g:g<=x&&x<=T||T<=x&&x<=g?x:T},ym=function(g,x,T,L,O,P,$,q,S){var V=g-O,Y=T-g,rt=$-O,ot=x-P,ht=L-x,dt=q-P,Lt=rt*ot-dt*V,kt=Y*ot-ht*V,Dt=dt*Y-rt*ht;if(Dt!==0){var Pt=Lt/Dt,$t=kt/Dt,Zt=.001,Yt=0-Zt,qt=1+Zt;return Yt<=Pt&&Pt<=qt&&Yt<=$t&&$t<=qt?[g+Pt*Y,x+Pt*ht]:S?[g+Pt*Y,x+Pt*ht]:[]}else return Lt===0||kt===0?LL(g,T,$)===$?[$,q]:LL(g,T,O)===O?[O,P]:LL(O,$,T)===T?[T,L]:[]:[]},Ak=function(g,x,T,L,O,P,$,q){var S=[],V,Y=new Array(T.length),rt=!0;P==null&&(rt=!1);var ot;if(rt){for(var ht=0;ht0){var dt=gN(Y,-q);ot=dN(dt)}else ot=Y}else ot=T;for(var Lt,kt,Dt,Pt,$t=0;$t2){for(var ze=[S[0],S[1]],Ge=Math.pow(ze[0]-g,2)+Math.pow(ze[1]-x,2),En=1;EnV&&(V=$t)},get:function(Pt){return S[Pt]}},rt=0;rt<$.length;rt++){var ot=$[rt],ht=ot.id();T?q[ht]=ot.outgoers().nodes():q[ht]=ot.openNeighborhood().nodes(),Y.set(ht,0)}for(var dt=function(Pt){for(var $t=$[Pt].id(),Zt=[],Yt={},qt={},ne={},Gt=new Ck(function(ur,er){return ne[ur]-ne[er]}),ge=0;ge<$.length;ge++){var be=$[ge].id();Yt[be]=[],qt[be]=0,ne[be]=1/0}for(qt[$t]=1,ne[$t]=0,Gt.push($t);!Gt.empty();){var ie=Gt.pop();if(Zt.push(ie),O)for(var Fe=0;Fe0?ze=bn.edgesTo(we)[0]:ze=we.edgesTo(bn)[0];var Ge=L(ze);we=we.id(),ne[we]>ne[ie]+Ge&&(ne[we]=ne[ie]+Ge,Gt.nodes.indexOf(we)<0?Gt.push(we):Gt.updateItem(we),qt[we]=0,Yt[we]=[]),ne[we]==ne[ie]+Ge&&(qt[we]=qt[we]+qt[ie],Yt[we].push(ie))}else for(var En=0;En0;){for(var Wn=Zt.pop(),rr=0;rr0&&$.push(T[q]);$.length!==0&&O.push(L.collection($))}return O},oX=function(g,x){for(var T=0;T5&&arguments[5]!==void 0?arguments[5]:lX,$=L,q,S,V=0;V=2?Mk(g,x,T,0,TN,hX):Mk(g,x,T,0,EN)},squaredEuclidean:function(g,x,T){return Mk(g,x,T,0,TN)},manhattan:function(g,x,T){return Mk(g,x,T,0,EN)},max:function(g,x,T){return Mk(g,x,T,-1/0,fX)}};tx["squared-euclidean"]=tx.squaredEuclidean,tx.squaredeuclidean=tx.squaredEuclidean;function $T(y,g,x,T,L,O){var P;return yt(y)?P=y:P=tx[y]||tx.euclidean,g===0&&yt(y)?P(L,O):P(g,x,T,L,O)}var dX=Rf({k:2,m:2,sensitivityThreshold:1e-4,distance:"euclidean",maxIterations:10,attributes:[],testMode:!1,testCentroids:null}),PL=function(g){return dX(g)},zT=function(g,x,T,L,O){var P=O!=="kMedoids",$=P?function(Y){return T[Y]}:function(Y){return L[Y](T)},q=function(rt){return L[rt](x)},S=T,V=x;return $T(g,L.length,$,q,S,V)},FL=function(g,x,T){for(var L=T.length,O=new Array(L),P=new Array(L),$=new Array(x),q=null,S=0;ST)return!1}return!0},bX=function(g,x,T){for(var L=0;L$&&($=x[S][V],q=V);O[q].push(g[S])}for(var Y=0;Y=O.threshold||O.mode==="dendrogram"&&g.length===1)return!1;var ht=x[P],dt=x[L[P]],Lt;O.mode==="dendrogram"?Lt={left:ht,right:dt,key:ht.key}:Lt={value:ht.value.concat(dt.value),key:ht.key},g[ht.index]=Lt,g.splice(dt.index,1),x[ht.key]=Lt;for(var kt=0;ktT[dt.key][Dt.key]&&(q=T[dt.key][Dt.key])):O.linkage==="max"?(q=T[ht.key][Dt.key],T[ht.key][Dt.key]0&&L.push(O);return L},IN=function(g,x,T){for(var L=[],O=0;O$&&(P=S,$=x[O*g+S])}P>0&&L.push(P)}for(var V=0;VS&&(q=V,S=Y)}T[O]=P[q]}return L=IN(g,x,T),L},ON=function(g){for(var x=this.cy(),T=this.nodes(),L=MX(g),O={},P=0;P=be?(ie=be,be=we,Fe=bn):we>ie&&(ie=we);for(var ze=0;ze<$;ze++)Y[ge*$+ze]=(1-L.damping)*(S[ge*$+ze]-be)+L.damping*Pt[ze];Y[ge*$+Fe]=(1-L.damping)*(S[ge*$+Fe]-ie)+L.damping*Pt[Fe]}for(var Ge=0;Ge<$;Ge++){for(var En=0,In=0;In<$;In++)Pt[In]=rt[In*$+Ge],$t[In]=Math.max(0,Y[In*$+Ge]),En+=$t[In];En-=$t[Ge],$t[Ge]=Y[Ge*$+Ge],En+=$t[Ge];for(var Yn=0;Yn<$;Yn++)rt[Yn*$+Ge]=(1-L.damping)*Math.min(0,En-$t[Yn])+L.damping*Pt[Yn];rt[Ge*$+Ge]=(1-L.damping)*(En-$t[Ge])+L.damping*Pt[Ge]}for(var Sn=0,Wn=0;Wn<$;Wn++){var rr=rt[Wn*$+Wn]+Y[Wn*$+Wn]>0?1:0;qt[Gt%L.minIterations*$+Wn]=rr,Sn+=rr}if(Sn>0&&(Gt>=L.minIterations-1||Gt==L.maxIterations-1)){for(var wr=0,ur=0;ur<$;ur++){Zt[ur]=0;for(var er=0;er1||Yt>1)&&($=!0),Y[Pt]=[],Dt.outgoers().forEach(function(ne){ne.isEdge()&&Y[Pt].push(ne.id())})}else rt[Pt]=[void 0,Dt.target().id()]}):P.forEach(function(Dt){var Pt=Dt.id();if(Dt.isNode()){var $t=Dt.degree(!0);$t%2&&(q?S?$=!0:S=Pt:q=Pt),Y[Pt]=[],Dt.connectedEdges().forEach(function(Zt){return Y[Pt].push(Zt.id())})}else rt[Pt]=[Dt.source().id(),Dt.target().id()]});var ot={found:!1,trail:void 0};if($)return ot;if(S&&q)if(O){if(V&&S!=V)return ot;V=S}else{if(V&&S!=V&&q!=V)return ot;V||(V=S)}else V||(V=P[0].id());var ht=function(Pt){for(var $t=Pt,Zt=[Pt],Yt,qt,ne;Y[$t].length;)Yt=Y[$t].shift(),qt=rt[Yt][0],ne=rt[Yt][1],$t!=ne?(Y[ne]=Y[ne].filter(function(Gt){return Gt!=Yt}),$t=ne):!O&&$t!=qt&&(Y[qt]=Y[qt].filter(function(Gt){return Gt!=Yt}),$t=qt),Zt.unshift(Yt),Zt.unshift($t);return Zt},dt=[],Lt=[];for(Lt=ht(V);Lt.length!=1;)Y[Lt[0]].length==0?(dt.unshift(P.getElementById(Lt.shift())),dt.unshift(P.getElementById(Lt.shift()))):Lt=ht(Lt.shift()).concat(Lt);dt.unshift(P.getElementById(Lt.shift()));for(var kt in Y)if(Y[kt].length)return ot;return ot.found=!0,ot.trail=this.spawn(dt,!0),ot}},HT=function(){var g=this,x={},T=0,L=0,O=[],P=[],$={},q=function(rt,ot){for(var ht=P.length-1,dt=[],Lt=g.spawn();P[ht].x!=rt||P[ht].y!=ot;)dt.push(P.pop().edge),ht--;dt.push(P.pop().edge),dt.forEach(function(kt){var Dt=kt.connectedNodes().intersection(g);Lt.merge(kt),Dt.forEach(function(Pt){var $t=Pt.id(),Zt=Pt.connectedEdges().intersection(g);Lt.merge(Pt),x[$t].cutVertex?Lt.merge(Zt.filter(function(Yt){return Yt.isLoop()})):Lt.merge(Zt)})}),O.push(Lt)},S=function Y(rt,ot,ht){rt===ht&&(L+=1),x[ot]={id:T,low:T++,cutVertex:!1};var dt=g.getElementById(ot).connectedEdges().intersection(g);if(dt.size()===0)O.push(g.spawn(g.getElementById(ot)));else{var Lt,kt,Dt,Pt;dt.forEach(function($t){Lt=$t.source().id(),kt=$t.target().id(),Dt=Lt===ot?kt:Lt,Dt!==ht&&(Pt=$t.id(),$[Pt]||($[Pt]=!0,P.push({x:ot,y:Dt,edge:$t})),Dt in x?x[ot].low=Math.min(x[ot].low,x[Dt].id):(Y(rt,Dt,ot),x[ot].low=Math.min(x[ot].low,x[Dt].low),x[ot].id<=x[Dt].low&&(x[ot].cutVertex=!0,q(ot,Dt))))})}};g.forEach(function(Y){if(Y.isNode()){var rt=Y.id();rt in x||(L=0,S(rt,rt),x[rt].cutVertex=L>1)}});var V=Object.keys(x).filter(function(Y){return x[Y].cutVertex}).map(function(Y){return g.getElementById(Y)});return{cut:g.spawn(V),components:O}},RX={hopcroftTarjanBiconnected:HT,htbc:HT,htb:HT,hopcroftTarjanBiconnectedComponents:HT},VT=function(){var g=this,x={},T=0,L=[],O=[],P=g.spawn(g),$=function q(S){O.push(S),x[S]={index:T,low:T++,explored:!1};var V=g.getElementById(S).connectedEdges().intersection(g);if(V.forEach(function(dt){var Lt=dt.target().id();Lt!==S&&(Lt in x||q(Lt),x[Lt].explored||(x[S].low=Math.min(x[S].low,x[Lt].low)))}),x[S].index===x[S].low){for(var Y=g.spawn();;){var rt=O.pop();if(Y.merge(g.getElementById(rt)),x[rt].low=x[S].index,x[rt].explored=!0,rt===S)break}var ot=Y.edgesWith(Y),ht=Y.merge(ot);L.push(ht),P=P.difference(ht)}};return g.forEach(function(q){if(q.isNode()){var S=q.id();S in x||$(S)}}),{cut:P,components:L}},jX={tarjanStronglyConnected:VT,tsc:VT,tscc:VT,tarjanStronglyConnectedComponents:VT},PN={};[Tk,bK,wK,mK,xK,EK,_K,QK,Z5,J5,OL,uX,kX,AX,FX,BX,RX,jX].forEach(function(y){de(PN,y)});/*! +Embeddable Minimum Strictly-Compliant Promises/A+ 1.1.1 Thenable +Copyright (c) 2013-2014 Ralf S. Engelschall (http://engelschall.com) +Licensed under The MIT License (http://opensource.org/licenses/MIT) +*/var FN=0,NN=1,BN=2,gw=function y(g){if(!(this instanceof y))return new y(g);this.id="Thenable/1.0.7",this.state=FN,this.fulfillValue=void 0,this.rejectReason=void 0,this.onFulfilled=[],this.onRejected=[],this.proxy={then:this.then.bind(this)},typeof g=="function"&&g.call(this,this.fulfill.bind(this),this.reject.bind(this))};gw.prototype={fulfill:function(g){return RN(this,NN,"fulfillValue",g)},reject:function(g){return RN(this,BN,"rejectReason",g)},then:function(g,x){var T=this,L=new gw;return T.onFulfilled.push(zN(g,L,"fulfill")),T.onRejected.push(zN(x,L,"reject")),jN(T),L.proxy}};var RN=function(g,x,T,L){return g.state===FN&&(g.state=x,g[T]=L,jN(g)),g},jN=function(g){g.state===NN?$N(g,"onFulfilled",g.fulfillValue):g.state===BN&&$N(g,"onRejected",g.rejectReason)},$N=function(g,x,T){if(g[x].length!==0){var L=g[x];g[x]=[];var O=function(){for(var $=0;$0}},clearQueue:function(){return function(){var x=this,T=x.length!==void 0,L=T?x:[x],O=this._private.cy||this;if(!O.styleEnabled())return this;for(var P=0;P-1}var $Q=jQ;function zQ(y,g){var x=this.__data__,T=WT(x,y);return T<0?(++this.size,x.push([y,g])):x[T][1]=g,this}var qQ=zQ;function rx(y){var g=-1,x=y==null?0:y.length;for(this.clear();++g-1&&y%1==0&&y0&&this.spawn(L).updateStyle().emit("class"),x},addClass:function(g){return this.toggleClass(g,!0)},hasClass:function(g){var x=this[0];return x!=null&&x._private.classes.has(g)},toggleClass:function(g,x){ft(g)||(g=g.match(/\S+/g)||[]);for(var T=this,L=x===void 0,O=[],P=0,$=T.length;P<$;P++)for(var q=T[P],S=q._private.classes,V=!1,Y=0;Y0&&this.spawn(O).updateStyle().emit("class"),T},removeClass:function(g){return this.toggleClass(g,!1)},flashClass:function(g,x){var T=this;if(x==null)x=250;else if(x===0)return T;return T.addClass(g),setTimeout(function(){T.removeClass(g)},x),T}};QT.className=QT.classNames=QT.classes;var tc={metaChar:"[\\!\\\"\\#\\$\\%\\&\\'\\(\\)\\*\\+\\,\\.\\/\\:\\;\\<\\=\\>\\?\\@\\[\\]\\^\\`\\{\\|\\}\\~]",comparatorOp:"=|\\!=|>|>=|<|<=|\\$=|\\^=|\\*=",boolOp:"\\?|\\!|\\^",string:`"(?:\\\\"|[^"])*"|'(?:\\\\'|[^'])*'`,number:Ye,meta:"degree|indegree|outdegree",separator:"\\s*,\\s*",descendant:"\\s+",child:"\\s+>\\s+",subject:"\\$",group:"node|edge|\\*",directedEdge:"\\s+->\\s+",undirectedEdge:"\\s+<->\\s+"};tc.variable="(?:[\\w-.]|(?:\\\\"+tc.metaChar+"))+",tc.className="(?:[\\w-]|(?:\\\\"+tc.metaChar+"))+",tc.value=tc.string+"|"+tc.number,tc.id=tc.variable,function(){var y,g,x;for(y=tc.comparatorOp.split("|"),x=0;x=0)&&g!=="="&&(tc.comparatorOp+="|\\!"+g)}();var Kc=function(){return{checks:[]}},zi={GROUP:0,COLLECTION:1,FILTER:2,DATA_COMPARE:3,DATA_EXIST:4,DATA_BOOL:5,META_COMPARE:6,STATE:7,ID:8,CLASS:9,UNDIRECTED_EDGE:10,DIRECTED_EDGE:11,NODE_SOURCE:12,NODE_TARGET:13,NODE_NEIGHBOR:14,CHILD:15,DESCENDANT:16,PARENT:17,ANCESTOR:18,COMPOUND_SPLIT:19,TRUE:20},zL=[{selector:":selected",matches:function(g){return g.selected()}},{selector:":unselected",matches:function(g){return!g.selected()}},{selector:":selectable",matches:function(g){return g.selectable()}},{selector:":unselectable",matches:function(g){return!g.selectable()}},{selector:":locked",matches:function(g){return g.locked()}},{selector:":unlocked",matches:function(g){return!g.locked()}},{selector:":visible",matches:function(g){return g.visible()}},{selector:":hidden",matches:function(g){return!g.visible()}},{selector:":transparent",matches:function(g){return g.transparent()}},{selector:":grabbed",matches:function(g){return g.grabbed()}},{selector:":free",matches:function(g){return!g.grabbed()}},{selector:":removed",matches:function(g){return g.removed()}},{selector:":inside",matches:function(g){return!g.removed()}},{selector:":grabbable",matches:function(g){return g.grabbable()}},{selector:":ungrabbable",matches:function(g){return!g.grabbable()}},{selector:":animated",matches:function(g){return g.animated()}},{selector:":unanimated",matches:function(g){return!g.animated()}},{selector:":parent",matches:function(g){return g.isParent()}},{selector:":childless",matches:function(g){return g.isChildless()}},{selector:":child",matches:function(g){return g.isChild()}},{selector:":orphan",matches:function(g){return g.isOrphan()}},{selector:":nonorphan",matches:function(g){return g.isChild()}},{selector:":compound",matches:function(g){return g.isNode()?g.isParent():g.source().isParent()||g.target().isParent()}},{selector:":loop",matches:function(g){return g.isLoop()}},{selector:":simple",matches:function(g){return g.isSimple()}},{selector:":active",matches:function(g){return g.active()}},{selector:":inactive",matches:function(g){return!g.active()}},{selector:":backgrounding",matches:function(g){return g.backgrounding()}},{selector:":nonbackgrounding",matches:function(g){return!g.backgrounding()}}].sort(function(y,g){return Me(y.selector,g.selector)}),qZ=function(){for(var y={},g,x=0;x0&&V.edgeCount>0)return Sc("The selector `"+g+"` is invalid because it uses both a compound selector and an edge selector"),!1;if(V.edgeCount>1)return Sc("The selector `"+g+"` is invalid because it uses multiple edge selectors"),!1;V.edgeCount===1&&Sc("The selector `"+g+"` is deprecated. Edge selectors do not take effect on changes to source and target nodes after an edge is added, for performance reasons. Use a class or data selector on edges instead, updating the class or data of an edge when your app detects a change in source or target nodes.")}return!0},YZ=function(){if(this.toStringCache!=null)return this.toStringCache;for(var g=function(V){return V??""},x=function(V){return mt(V)?'"'+V+'"':g(V)},T=function(V){return" "+V+" "},L=function(V,Y){var rt=V.type,ot=V.value;switch(rt){case zi.GROUP:{var ht=g(ot);return ht.substring(0,ht.length-1)}case zi.DATA_COMPARE:{var dt=V.field,Lt=V.operator;return"["+dt+T(g(Lt))+x(ot)+"]"}case zi.DATA_BOOL:{var kt=V.operator,Dt=V.field;return"["+g(kt)+Dt+"]"}case zi.DATA_EXIST:{var Pt=V.field;return"["+Pt+"]"}case zi.META_COMPARE:{var $t=V.operator,Zt=V.field;return"[["+Zt+T(g($t))+x(ot)+"]]"}case zi.STATE:return ot;case zi.ID:return"#"+ot;case zi.CLASS:return"."+ot;case zi.PARENT:case zi.CHILD:return O(V.parent,Y)+T(">")+O(V.child,Y);case zi.ANCESTOR:case zi.DESCENDANT:return O(V.ancestor,Y)+" "+O(V.descendant,Y);case zi.COMPOUND_SPLIT:{var Yt=O(V.left,Y),qt=O(V.subject,Y),ne=O(V.right,Y);return Yt+(Yt.length>0?" ":"")+qt+ne}case zi.TRUE:return""}},O=function(V,Y){return V.checks.reduce(function(rt,ot,ht){return rt+(Y===V&&ht===0?"$":"")+L(ot,Y)},"")},P="",$=0;$1&&$=0&&(x=x.replace("!",""),Y=!0),x.indexOf("@")>=0&&(x=x.replace("@",""),V=!0),(O||$||V)&&(q=!O&&!P?"":""+g,S=""+T),V&&(g=q=q.toLowerCase(),T=S=S.toLowerCase()),x){case"*=":L=q.indexOf(S)>=0;break;case"$=":L=q.indexOf(S,q.length-S.length)>=0;break;case"^=":L=q.indexOf(S)===0;break;case"=":L=g===T;break;case">":rt=!0,L=g>T;break;case">=":rt=!0,L=g>=T;break;case"<":rt=!0,L=g0;){var V=L.shift();g(V),O.add(V.id()),$&&T(L,O,V)}return y}function Ik(y,g,x){if(x.isParent())for(var T=x._private.children,L=0;L1&&arguments[1]!==void 0?arguments[1]:!0;return ZT(this,y,g,Ik)};function aB(y,g,x){if(x.isChild()){var T=x._private.parent;g.has(T.id())||y.push(T)}}ax.forEachUp=function(y){var g=arguments.length>1&&arguments[1]!==void 0?arguments[1]:!0;return ZT(this,y,g,aB)};function nJ(y,g,x){aB(y,g,x),Ik(y,g,x)}ax.forEachUpAndDown=function(y){var g=arguments.length>1&&arguments[1]!==void 0?arguments[1]:!0;return ZT(this,y,g,nJ)},ax.ancestors=ax.parents;var Ok,oB;Ok=oB={data:Ac.data({field:"data",bindingEvent:"data",allowBinding:!0,allowSetting:!0,settingEvent:"data",settingTriggersEvent:!0,triggerFnName:"trigger",allowGetting:!0,immutableKeys:{id:!0,source:!0,target:!0,parent:!0},updateStyle:!0}),removeData:Ac.removeData({field:"data",event:"data",triggerFnName:"trigger",triggerEvent:!0,immutableKeys:{id:!0,source:!0,target:!0,parent:!0},updateStyle:!0}),scratch:Ac.data({field:"scratch",bindingEvent:"scratch",allowBinding:!0,allowSetting:!0,settingEvent:"scratch",settingTriggersEvent:!0,triggerFnName:"trigger",allowGetting:!0,updateStyle:!0}),removeScratch:Ac.removeData({field:"scratch",event:"scratch",triggerFnName:"trigger",triggerEvent:!0,updateStyle:!0}),rscratch:Ac.data({field:"rscratch",allowBinding:!1,allowSetting:!0,settingTriggersEvent:!1,allowGetting:!0}),removeRscratch:Ac.removeData({field:"rscratch",triggerEvent:!1}),id:function(){var g=this[0];if(g)return g._private.data.id}},Ok.attr=Ok.data,Ok.removeAttr=Ok.removeData;var rJ=oB,JT={};function ox(y){return function(g){var x=this;if(g===void 0&&(g=!0),x.length!==0)if(x.isNode()&&!x.removed()){for(var T=0,L=x[0],O=L._private.edges,P=0;Pg}),minIndegree:cx("indegree",function(y,g){return yg}),minOutdegree:cx("outdegree",function(y,g){return yg})}),de(JT,{totalDegree:function(g){for(var x=0,T=this.nodes(),L=0;L0,rt=Y;Y&&(V=V[0]);var ot=rt?V.position():{x:0,y:0};x!==void 0?S.position(g,x+ot[g]):O!==void 0&&S.position({x:O.x+ot.x,y:O.y+ot.y})}else{var ht=T.position(),dt=$?T.parent():null,Lt=dt&&dt.length>0,kt=Lt;Lt&&(dt=dt[0]);var Dt=kt?dt.position():{x:0,y:0};return O={x:ht.x-Dt.x,y:ht.y-Dt.y},g===void 0?O:O[g]}else if(!P)return;return this}},kp.modelPosition=kp.point=kp.position,kp.modelPositions=kp.points=kp.positions,kp.renderedPoint=kp.renderedPosition,kp.relativePoint=kp.relativePosition;var lB=cB,ux,Ub;ux=Ub={},Ub.renderedBoundingBox=function(y){var g=this.boundingBox(y),x=this.cy(),T=x.zoom(),L=x.pan(),O=g.x1*T+L.x,P=g.x2*T+L.x,$=g.y1*T+L.y,q=g.y2*T+L.y;return{x1:O,x2:P,y1:$,y2:q,w:P-O,h:q-$}},Ub.dirtyCompoundBoundsCache=function(){var y=arguments.length>0&&arguments[0]!==void 0?arguments[0]:!1,g=this.cy();return!g.styleEnabled()||!g.hasCompoundNodes()?this:(this.forEachUp(function(x){if(x.isParent()){var T=x._private;T.compoundBoundsClean=!1,T.bbCache=null,y||x.emitAndNotify("bounds")}}),this)},Ub.updateCompoundBounds=function(){var y=arguments.length>0&&arguments[0]!==void 0?arguments[0]:!1,g=this.cy();if(!g.styleEnabled()||!g.hasCompoundNodes())return this;if(!y&&g.batching())return this;function x(P){if(!P.isParent())return;var $=P._private,q=P.children(),S=P.pstyle("compound-sizing-wrt-labels").value==="include",V={width:{val:P.pstyle("min-width").pfValue,left:P.pstyle("min-width-bias-left"),right:P.pstyle("min-width-bias-right")},height:{val:P.pstyle("min-height").pfValue,top:P.pstyle("min-height-bias-top"),bottom:P.pstyle("min-height-bias-bottom")}},Y=q.boundingBox({includeLabels:S,includeOverlays:!1,useCache:!1}),rt=$.position;(Y.w===0||Y.h===0)&&(Y={w:P.pstyle("width").pfValue,h:P.pstyle("height").pfValue},Y.x1=rt.x-Y.w/2,Y.x2=rt.x+Y.w/2,Y.y1=rt.y-Y.h/2,Y.y2=rt.y+Y.h/2);function ot(Gt,ge,be){var ie=0,Fe=0,we=ge+be;return Gt>0&&we>0&&(ie=ge/we*Gt,Fe=be/we*Gt),{biasDiff:ie,biasComplementDiff:Fe}}function ht(Gt,ge,be,ie){if(be.units==="%")switch(ie){case"width":return Gt>0?be.pfValue*Gt:0;case"height":return ge>0?be.pfValue*ge:0;case"average":return Gt>0&&ge>0?be.pfValue*(Gt+ge)/2:0;case"min":return Gt>0&&ge>0?Gt>ge?be.pfValue*ge:be.pfValue*Gt:0;case"max":return Gt>0&&ge>0?Gt>ge?be.pfValue*Gt:be.pfValue*ge:0;default:return 0}else return be.units==="px"?be.pfValue:0}var dt=V.width.left.value;V.width.left.units==="px"&&V.width.val>0&&(dt=dt*100/V.width.val);var Lt=V.width.right.value;V.width.right.units==="px"&&V.width.val>0&&(Lt=Lt*100/V.width.val);var kt=V.height.top.value;V.height.top.units==="px"&&V.height.val>0&&(kt=kt*100/V.height.val);var Dt=V.height.bottom.value;V.height.bottom.units==="px"&&V.height.val>0&&(Dt=Dt*100/V.height.val);var Pt=ot(V.width.val-Y.w,dt,Lt),$t=Pt.biasDiff,Zt=Pt.biasComplementDiff,Yt=ot(V.height.val-Y.h,kt,Dt),qt=Yt.biasDiff,ne=Yt.biasComplementDiff;$.autoPadding=ht(Y.w,Y.h,P.pstyle("padding"),P.pstyle("padding-relative-to").value),$.autoWidth=Math.max(Y.w,V.width.val),rt.x=(-$t+Y.x1+Y.x2+Zt)/2,$.autoHeight=Math.max(Y.h,V.height.val),rt.y=(-qt+Y.y1+Y.y2+ne)/2}for(var T=0;Tg.x2?L:g.x2,g.y1=Tg.y2?O:g.y2,g.w=g.x2-g.x1,g.h=g.y2-g.y1)},L3=function(g,x){return x==null?g:Ep(g,x.x1,x.y1,x.x2,x.y2)},Fk=function(g,x,T){return yp(g,x,T)},tC=function(g,x,T){if(!x.cy().headless()){var L=x._private,O=L.rstyle,P=O.arrowWidth/2,$=x.pstyle(T+"-arrow-shape").value,q,S;if($!=="none"){T==="source"?(q=O.srcX,S=O.srcY):T==="target"?(q=O.tgtX,S=O.tgtY):(q=O.midX,S=O.midY);var V=L.arrowBounds=L.arrowBounds||{},Y=V[T]=V[T]||{};Y.x1=q-P,Y.y1=S-P,Y.x2=q+P,Y.y2=S+P,Y.w=Y.x2-Y.x1,Y.h=Y.y2-Y.y1,RT(Y,1),Ep(g,Y.x1,Y.y1,Y.x2,Y.y2)}}},hB=function(g,x,T){if(!x.cy().headless()){var L;T?L=T+"-":L="";var O=x._private,P=O.rstyle,$=x.pstyle(L+"label").strValue;if($){var q=x.pstyle("text-halign"),S=x.pstyle("text-valign"),V=Fk(P,"labelWidth",T),Y=Fk(P,"labelHeight",T),rt=Fk(P,"labelX",T),ot=Fk(P,"labelY",T),ht=x.pstyle(L+"text-margin-x").pfValue,dt=x.pstyle(L+"text-margin-y").pfValue,Lt=x.isEdge(),kt=x.pstyle(L+"text-rotation"),Dt=x.pstyle("text-outline-width").pfValue,Pt=x.pstyle("text-border-width").pfValue,$t=Pt/2,Zt=x.pstyle("text-background-padding").pfValue,Yt=2,qt=Y,ne=V,Gt=ne/2,ge=qt/2,be,ie,Fe,we;if(Lt)be=rt-Gt,ie=rt+Gt,Fe=ot-ge,we=ot+ge;else{switch(q.value){case"left":be=rt-ne,ie=rt;break;case"center":be=rt-Gt,ie=rt+Gt;break;case"right":be=rt,ie=rt+ne;break}switch(S.value){case"top":Fe=ot-qt,we=ot;break;case"center":Fe=ot-ge,we=ot+ge;break;case"bottom":Fe=ot,we=ot+qt;break}}be+=ht-Math.max(Dt,$t)-Zt-Yt,ie+=ht+Math.max(Dt,$t)+Zt+Yt,Fe+=dt-Math.max(Dt,$t)-Zt-Yt,we+=dt+Math.max(Dt,$t)+Zt+Yt;var bn=T||"main",ze=O.labelBounds,Ge=ze[bn]=ze[bn]||{};Ge.x1=be,Ge.y1=Fe,Ge.x2=ie,Ge.y2=we,Ge.w=ie-be,Ge.h=we-Fe;var En=Lt&&kt.strValue==="autorotate",In=kt.pfValue!=null&&kt.pfValue!==0;if(En||In){var Yn=En?Fk(O.rstyle,"labelAngle",T):kt.pfValue,Sn=Math.cos(Yn),Wn=Math.sin(Yn),rr=(be+ie)/2,wr=(Fe+we)/2;if(!Lt){switch(q.value){case"left":rr=ie;break;case"right":rr=be;break}switch(S.value){case"top":wr=we;break;case"bottom":wr=Fe;break}}var ur=function(Ea,Ci){return Ea=Ea-rr,Ci=Ci-wr,{x:Ea*Sn-Ci*Wn+rr,y:Ea*Wn+Ci*Sn+wr}},er=ur(be,Fe),vn=ur(be,we),gr=ur(ie,Fe),fr=ur(ie,we);be=Math.min(er.x,vn.x,gr.x,fr.x),ie=Math.max(er.x,vn.x,gr.x,fr.x),Fe=Math.min(er.y,vn.y,gr.y,fr.y),we=Math.max(er.y,vn.y,gr.y,fr.y)}var Jr=bn+"Rot",vi=ze[Jr]=ze[Jr]||{};vi.x1=be,vi.y1=Fe,vi.x2=ie,vi.y2=we,vi.w=ie-be,vi.h=we-Fe,Ep(g,be,Fe,ie,we),Ep(O.labelBounds.all,be,Fe,ie,we)}return g}},iJ=function(g,x){var T=g._private.cy,L=T.styleEnabled(),O=T.headless(),P=zd(),$=g._private,q=g.isNode(),S=g.isEdge(),V,Y,rt,ot,ht,dt,Lt=$.rstyle,kt=q&&L?g.pstyle("bounds-expansion").pfValue:[0],Dt=function(gs){return gs.pstyle("display").value!=="none"},Pt=!L||Dt(g)&&(!S||Dt(g.source())&&Dt(g.target()));if(Pt){var $t=0,Zt=0;L&&x.includeOverlays&&($t=g.pstyle("overlay-opacity").value,$t!==0&&(Zt=g.pstyle("overlay-padding").value));var Yt=0,qt=0;L&&x.includeUnderlays&&(Yt=g.pstyle("underlay-opacity").value,Yt!==0&&(qt=g.pstyle("underlay-padding").value));var ne=Math.max(Zt,qt),Gt=0,ge=0;if(L&&(Gt=g.pstyle("width").pfValue,ge=Gt/2),q&&x.includeNodes){var be=g.position();ht=be.x,dt=be.y;var ie=g.outerWidth(),Fe=ie/2,we=g.outerHeight(),bn=we/2;V=ht-Fe,Y=ht+Fe,rt=dt-bn,ot=dt+bn,Ep(P,V,rt,Y,ot)}else if(S&&x.includeEdges)if(L&&!O){var ze=g.pstyle("curve-style").strValue;if(V=Math.min(Lt.srcX,Lt.midX,Lt.tgtX),Y=Math.max(Lt.srcX,Lt.midX,Lt.tgtX),rt=Math.min(Lt.srcY,Lt.midY,Lt.tgtY),ot=Math.max(Lt.srcY,Lt.midY,Lt.tgtY),V-=ge,Y+=ge,rt-=ge,ot+=ge,Ep(P,V,rt,Y,ot),ze==="haystack"){var Ge=Lt.haystackPts;if(Ge&&Ge.length===2){if(V=Ge[0].x,rt=Ge[0].y,Y=Ge[1].x,ot=Ge[1].y,V>Y){var En=V;V=Y,Y=En}if(rt>ot){var In=rt;rt=ot,ot=In}Ep(P,V-ge,rt-ge,Y+ge,ot+ge)}}else if(ze==="bezier"||ze==="unbundled-bezier"||ze==="segments"||ze==="taxi"){var Yn;switch(ze){case"bezier":case"unbundled-bezier":Yn=Lt.bezierPts;break;case"segments":case"taxi":Yn=Lt.linePts;break}if(Yn!=null)for(var Sn=0;SnY){var vn=V;V=Y,Y=vn}if(rt>ot){var gr=rt;rt=ot,ot=gr}V-=ge,Y+=ge,rt-=ge,ot+=ge,Ep(P,V,rt,Y,ot)}if(L&&x.includeEdges&&S&&(tC(P,g,"mid-source"),tC(P,g,"mid-target"),tC(P,g,"source"),tC(P,g,"target")),L){var fr=g.pstyle("ghost").value==="yes";if(fr){var Jr=g.pstyle("ghost-offset-x").pfValue,vi=g.pstyle("ghost-offset-y").pfValue;Ep(P,P.x1+Jr,P.y1+vi,P.x2+Jr,P.y2+vi)}}var Xs=$.bodyBounds=$.bodyBounds||{};lN(Xs,P),SL(Xs,kt),RT(Xs,1),L&&(V=P.x1,Y=P.x2,rt=P.y1,ot=P.y2,Ep(P,V-ne,rt-ne,Y+ne,ot+ne));var Ea=$.overlayBounds=$.overlayBounds||{};lN(Ea,P),SL(Ea,kt),RT(Ea,1);var Ci=$.labelBounds=$.labelBounds||{};Ci.all!=null?NK(Ci.all):Ci.all=zd(),L&&x.includeLabels&&(x.includeMainLabels&&hB(P,g,null),S&&(x.includeSourceLabels&&hB(P,g,"source"),x.includeTargetLabels&&hB(P,g,"target")))}return P.x1=M0(P.x1),P.y1=M0(P.y1),P.x2=M0(P.x2),P.y2=M0(P.y2),P.w=M0(P.x2-P.x1),P.h=M0(P.y2-P.y1),P.w>0&&P.h>0&&Pt&&(SL(P,kt),RT(P,1)),P},fB=function(g){var x=0,T=function(P){return(P?1:0)<0&&arguments[0]!==void 0?arguments[0]:vJ,g=arguments.length>1?arguments[1]:void 0,x=0;x=0;$--)P($);return this},Cm.removeAllListeners=function(){return this.removeListener("*")},Cm.emit=Cm.trigger=function(y,g,x){var T=this.listeners,L=T.length;return this.emitting++,ft(g)||(g=[g]),mJ(this,function(O,P){x!=null&&(T=[{event:P.event,type:P.type,namespace:P.namespace,callback:x}],L=T.length);for(var $=function(V){var Y=T[V];if(Y.type===P.type&&(!Y.namespace||Y.namespace===P.namespace||Y.namespace===wJ)&&O.eventMatches(O.context,Y,P)){var rt=[P];g!=null&&aN(rt,g),O.beforeEmit(O.context,Y,P),Y.conf&&Y.conf.one&&(O.listeners=O.listeners.filter(function(dt){return dt!==Y}));var ot=O.callbackContext(O.context,Y,P),ht=Y.callback.apply(ot,rt);O.afterEmit(O.context,Y,P),ht===!1&&(P.stopPropagation(),P.preventDefault())}},q=0;q1&&!P){var $=this.length-1,q=this[$],S=q._private.data.id;this[$]=void 0,this[g]=q,O.set(S,{ele:q,index:g})}return this.length--,this},unmergeOne:function(g){g=g[0];var x=this._private,T=g._private.data.id,L=x.map,O=L.get(T);if(!O)return this;var P=O.index;return this.unmergeAt(P),this},unmerge:function(g){var x=this._private.cy;if(!g)return this;if(g&&mt(g)){var T=g;g=x.mutableElements().filter(T)}for(var L=0;L=0;x--){var T=this[x];g(T)&&this.unmergeAt(x)}return this},map:function(g,x){for(var T=[],L=this,O=0;OT&&(T=q,L=$)}return{value:T,ele:L}},min:function(g,x){for(var T=1/0,L,O=this,P=0;P=0&&O"u"?"undefined":f(Symbol))!=g&&f(Symbol.iterator)!=g;x&&(iC[Symbol.iterator]=function(){var T=this,L={value:void 0,done:!1},O=0,P=this.length;return b({next:function(){return O1&&arguments[1]!==void 0?arguments[1]:!0,T=this[0],L=T.cy();if(L.styleEnabled()&&T){this.cleanStyle();var O=T._private.style[g];return O??(x?L.style().getDefaultProperty(g):null)}},numericStyle:function(g){var x=this[0];if(x.cy().styleEnabled()&&x){var T=x.pstyle(g);return T.pfValue!==void 0?T.pfValue:T.value}},numericStyleUnits:function(g){var x=this[0];if(x.cy().styleEnabled()&&x)return x.pstyle(g).units},renderedStyle:function(g){var x=this.cy();if(!x.styleEnabled())return this;var T=this[0];if(T)return x.style().getRenderedStyle(T,g)},style:function(g,x){var T=this.cy();if(!T.styleEnabled())return this;var L=!1,O=T.style();if(ut(g)){var P=g;O.applyBypass(this,P,L),this.emitAndNotify("style")}else if(mt(g))if(x===void 0){var $=this[0];return $?O.getStylePropertyValue($,g):void 0}else O.applyBypass(this,g,x,L),this.emitAndNotify("style");else if(g===void 0){var q=this[0];return q?O.getRawStyle(q):void 0}return this},removeStyle:function(g){var x=this.cy();if(!x.styleEnabled())return this;var T=!1,L=x.style(),O=this;if(g===void 0)for(var P=0;P0&&g.push(V[0]),g.push($[0])}return this.spawn(g,!0).filter(y)},"neighborhood"),closedNeighborhood:function(g){return this.neighborhood().add(this).filter(g)},openNeighborhood:function(g){return this.neighborhood(g)}}),d1.neighbourhood=d1.neighborhood,d1.closedNeighbourhood=d1.closedNeighborhood,d1.openNeighbourhood=d1.openNeighborhood,de(d1,{source:ad(function(g){var x=this[0],T;return x&&(T=x._private.source||x.cy().collection()),T&&g?T.filter(g):T},"source"),target:ad(function(g){var x=this[0],T;return x&&(T=x._private.target||x.cy().collection()),T&&g?T.filter(g):T},"target"),sources:IB({attr:"source"}),targets:IB({attr:"target"})});function IB(y){return function(x){for(var T=[],L=0;L0);return P},component:function(){var g=this[0];return g.cy().mutableElements().components(g)[0]}}),d1.componentsOf=d1.components;var $f=function(g,x){var T=arguments.length>2&&arguments[2]!==void 0?arguments[2]:!1,L=arguments.length>3&&arguments[3]!==void 0?arguments[3]:!1;if(g===void 0){vl("A collection must have a reference to the core");return}var O=new Gb,P=!1;if(!x)x=[];else if(x.length>0&&ut(x[0])&&!nt(x[0])){P=!0;for(var $=[],q=new Y5,S=0,V=x.length;S0&&arguments[0]!==void 0?arguments[0]:!0,g=arguments.length>1&&arguments[1]!==void 0?arguments[1]:!0,x=this,T=x.cy(),L=T._private,O=[],P=[],$,q=0,S=x.length;q0){for(var In=$.length===x.length?x:new $f(T,$),Yn=0;Yn0&&arguments[0]!==void 0?arguments[0]:!0,g=arguments.length>1&&arguments[1]!==void 0?arguments[1]:!0,x=this,T=[],L={},O=x._private.cy;function P(we){for(var bn=we._private.edges,ze=0;ze0&&(y?be.emitAndNotify("remove"):g&&be.emit("remove"));for(var ie=0;ie0?ie=we:be=we;while(Math.abs(Fe)>P&&++bn<$);return we}function Zt(ge){for(var be=0,ie=1,Fe=q-1;ie!==Fe&&rt[ie]<=ge;++ie)be+=S;--ie;var we=(ge-rt[ie])/(rt[ie+1]-rt[ie]),bn=be+we*S,ze=kt(bn,y,x);return ze>=O?Dt(ge,bn):ze===0?bn:$t(ge,be,be+S)}var Yt=!1;function qt(){Yt=!0,(y!==g||x!==T)&&Pt()}var ne=function(be){return Yt||qt(),y===g&&x===T?be:be===0?0:be===1?1:Lt(Zt(be),g,T)};ne.getControlPoints=function(){return[{x:y,y:g},{x,y:T}]};var Gt="generateBezier("+[y,g,x,T]+")";return ne.toString=function(){return Gt},ne}/*! Runge-Kutta spring physics function generator. Adapted from Framer.js, copyright Koen Bok. MIT License: http://en.wikipedia.org/wiki/MIT_License */var MJ=function(){function y(T){return-T.tension*T.x-T.friction*T.v}function g(T,L,O){var P={x:T.x+O.dx*L,v:T.v+O.dv*L,tension:T.tension,friction:T.friction};return{dx:P.v,dv:y(P)}}function x(T,L){var O={dx:T.v,dv:y(T)},P=g(T,L*.5,O),$=g(T,L*.5,P),q=g(T,L,$),S=1/6*(O.dx+2*(P.dx+$.dx)+q.dx),V=1/6*(O.dv+2*(P.dv+$.dv)+q.dv);return T.x=T.x+S*L,T.v=T.v+V*L,T}return function T(L,O,P){var $={x:-1,v:0,tension:null,friction:null},q=[0],S=0,V=1/1e4,Y=16/1e3,rt,ot,ht;for(L=parseFloat(L)||500,O=parseFloat(O)||20,P=P||null,$.tension=L,$.friction=O,rt=P!==null,rt?(S=T(L,O),ot=S/P*Y):ot=Y;ht=x(ht||$,ot),q.push(1+ht.x),S+=16,Math.abs(ht.x)>V&&Math.abs(ht.v)>V;);return rt?function(dt){return q[dt*(q.length-1)|0]}:S}}(),gu=function(g,x,T,L){var O=LJ(g,x,T,L);return function(P,$,q){return P+($-P)*O(q)}},cC={linear:function(g,x,T){return g+(x-g)*T},ease:gu(.25,.1,.25,1),"ease-in":gu(.42,0,1,1),"ease-out":gu(0,0,.58,1),"ease-in-out":gu(.42,0,.58,1),"ease-in-sine":gu(.47,0,.745,.715),"ease-out-sine":gu(.39,.575,.565,1),"ease-in-out-sine":gu(.445,.05,.55,.95),"ease-in-quad":gu(.55,.085,.68,.53),"ease-out-quad":gu(.25,.46,.45,.94),"ease-in-out-quad":gu(.455,.03,.515,.955),"ease-in-cubic":gu(.55,.055,.675,.19),"ease-out-cubic":gu(.215,.61,.355,1),"ease-in-out-cubic":gu(.645,.045,.355,1),"ease-in-quart":gu(.895,.03,.685,.22),"ease-out-quart":gu(.165,.84,.44,1),"ease-in-out-quart":gu(.77,0,.175,1),"ease-in-quint":gu(.755,.05,.855,.06),"ease-out-quint":gu(.23,1,.32,1),"ease-in-out-quint":gu(.86,0,.07,1),"ease-in-expo":gu(.95,.05,.795,.035),"ease-out-expo":gu(.19,1,.22,1),"ease-in-out-expo":gu(1,0,0,1),"ease-in-circ":gu(.6,.04,.98,.335),"ease-out-circ":gu(.075,.82,.165,1),"ease-in-out-circ":gu(.785,.135,.15,.86),spring:function(g,x,T){if(T===0)return cC.linear;var L=MJ(g,x,T);return function(O,P,$){return O+(P-O)*L($)}},"cubic-bezier":gu};function FB(y,g,x,T,L){if(T===1||g===x)return x;var O=L(g,x,T);return y==null||((y.roundValue||y.color)&&(O=Math.round(O)),y.min!==void 0&&(O=Math.max(O,y.min)),y.max!==void 0&&(O=Math.min(O,y.max))),O}function NB(y,g){return y.pfValue!=null||y.value!=null?y.pfValue!=null&&(g==null||g.type.units!=="%")?y.pfValue:y.value:y}function fx(y,g,x,T,L){var O=L!=null?L.type:null;x<0?x=0:x>1&&(x=1);var P=NB(y,L),$=NB(g,L);if(X(P)&&X($))return FB(O,P,$,x,T);if(ft(P)&&ft($)){for(var q=[],S=0;S<$.length;S++){var V=P[S],Y=$[S];if(V!=null&&Y!=null){var rt=FB(O,V,Y,x,T);q.push(rt)}else q.push(Y)}return q}}function DJ(y,g,x,T){var L=!T,O=y._private,P=g._private,$=P.easing,q=P.startTime,S=T?y:y.cy(),V=S.style();if(!P.easingImpl)if($==null)P.easingImpl=cC.linear;else{var Y;if(mt($)){var rt=V.parse("transition-timing-function",$);Y=rt.value}else Y=$;var ot,ht;mt(Y)?(ot=Y,ht=[]):(ot=Y[1],ht=Y.slice(2).map(function(In){return+In})),ht.length>0?(ot==="spring"&&ht.push(P.duration),P.easingImpl=cC[ot].apply(null,ht)):P.easingImpl=cC[ot]}var dt=P.easingImpl,Lt;if(P.duration===0?Lt=1:Lt=(x-q)/P.duration,P.applying&&(Lt=P.progress),Lt<0?Lt=0:Lt>1&&(Lt=1),P.delay==null){var kt=P.startPosition,Dt=P.position;if(Dt&&L&&!y.locked()){var Pt={};$k(kt.x,Dt.x)&&(Pt.x=fx(kt.x,Dt.x,Lt,dt)),$k(kt.y,Dt.y)&&(Pt.y=fx(kt.y,Dt.y,Lt,dt)),y.position(Pt)}var $t=P.startPan,Zt=P.pan,Yt=O.pan,qt=Zt!=null&&T;qt&&($k($t.x,Zt.x)&&(Yt.x=fx($t.x,Zt.x,Lt,dt)),$k($t.y,Zt.y)&&(Yt.y=fx($t.y,Zt.y,Lt,dt)),y.emit("pan"));var ne=P.startZoom,Gt=P.zoom,ge=Gt!=null&&T;ge&&($k(ne,Gt)&&(O.zoom=_k(O.minZoom,fx(ne,Gt,Lt,dt),O.maxZoom)),y.emit("zoom")),(qt||ge)&&y.emit("viewport");var be=P.style;if(be&&be.length>0&&L){for(var ie=0;ie=0;qt--){var ne=Yt[qt];ne()}Yt.splice(0,Yt.length)},Dt=ot.length-1;Dt>=0;Dt--){var Pt=ot[Dt],$t=Pt._private;if($t.stopped){ot.splice(Dt,1),$t.hooked=!1,$t.playing=!1,$t.started=!1,kt($t.frames);continue}!$t.playing&&!$t.applying||($t.playing&&$t.applying&&($t.applying=!1),$t.started||IJ(V,Pt,y),DJ(V,Pt,y,Y),$t.applying&&($t.applying=!1),kt($t.frames),$t.step!=null&&$t.step(y),Pt.completed()&&(ot.splice(Dt,1),$t.hooked=!1,$t.playing=!1,$t.started=!1,kt($t.completes)),dt=!0)}return!Y&&ot.length===0&&ht.length===0&&T.push(V),dt}for(var O=!1,P=0;P0?g.notify("draw",x):g.notify("draw")),x.unmerge(T),g.emit("step")}var OJ={animate:Ac.animate(),animation:Ac.animation(),animated:Ac.animated(),clearQueue:Ac.clearQueue(),delay:Ac.delay(),delayAnimation:Ac.delayAnimation(),stop:Ac.stop(),addToAnimationPool:function(g){var x=this;x.styleEnabled()&&x._private.aniEles.merge(g)},stopAnimationLoop:function(){this._private.animationsRunning=!1},startAnimationLoop:function(){var g=this;if(g._private.animationsRunning=!0,!g.styleEnabled())return;function x(){g._private.animationsRunning&&Bf(function(O){BB(O,g),x()})}var T=g.renderer();T&&T.beforeRender?T.beforeRender(function(O,P){BB(P,g)},T.beforeRenderPriorities.animations):x()}},PJ={qualifierCompare:function(g,x){return g==null||x==null?g==null&&x==null:g.sameText(x)},eventMatches:function(g,x,T){var L=x.qualifier;return L!=null?g!==T.target&&nt(T.target)&&L.matches(T.target):!0},addEventFields:function(g,x){x.cy=g,x.target=g},callbackContext:function(g,x,T){return x.qualifier!=null?T.target:g}},uC=function(g){return mt(g)?new Em(g):g},RB={createEmitter:function(){var g=this._private;return g.emitter||(g.emitter=new nC(PJ,this)),this},emitter:function(){return this._private.emitter},on:function(g,x,T){return this.emitter().on(g,uC(x),T),this},removeListener:function(g,x,T){return this.emitter().removeListener(g,uC(x),T),this},removeAllListeners:function(){return this.emitter().removeAllListeners(),this},one:function(g,x,T){return this.emitter().one(g,uC(x),T),this},once:function(g,x,T){return this.emitter().one(g,uC(x),T),this},emit:function(g,x){return this.emitter().emit(g,x),this},emitAndNotify:function(g,x){return this.emit(g),this.notify(g,x),this}};Ac.eventAliasesOn(RB);var UL={png:function(g){var x=this._private.renderer;return g=g||{},x.png(g)},jpg:function(g){var x=this._private.renderer;return g=g||{},g.bg=g.bg||"#fff",x.jpg(g)}};UL.jpeg=UL.jpg;var lC={layout:function(g){var x=this;if(g==null){vl("Layout options must be specified to make a layout");return}if(g.name==null){vl("A `name` must be specified to make a layout");return}var T=g.name,L=x.extension("layout",T);if(L==null){vl("No such layout `"+T+"` found. Did you forget to import it and `cytoscape.use()` it?");return}var O;mt(g.eles)?O=x.$(g.eles):O=g.eles!=null?g.eles:x.$();var P=new L(de({},g,{cy:x,eles:O}));return P}};lC.createLayout=lC.makeLayout=lC.layout;var FJ={notify:function(g,x){var T=this._private;if(this.batching()){T.batchNotifications=T.batchNotifications||{};var L=T.batchNotifications[g]=T.batchNotifications[g]||this.collection();x!=null&&L.merge(x);return}if(T.notificationsEnabled){var O=this.renderer();this.destroyed()||!O||O.notify(g,x)}},notifications:function(g){var x=this._private;return g===void 0?x.notificationsEnabled:(x.notificationsEnabled=!!g,this)},noNotifications:function(g){this.notifications(!1),g(),this.notifications(!0)},batching:function(){return this._private.batchCount>0},startBatch:function(){var g=this._private;return g.batchCount==null&&(g.batchCount=0),g.batchCount===0&&(g.batchStyleEles=this.collection(),g.batchNotifications={}),g.batchCount++,this},endBatch:function(){var g=this._private;if(g.batchCount===0)return this;if(g.batchCount--,g.batchCount===0){g.batchStyleEles.updateStyle();var x=this.renderer();Object.keys(g.batchNotifications).forEach(function(T){var L=g.batchNotifications[T];L.empty()?x.notify(T):x.notify(T,L)})}return this},batch:function(g){return this.startBatch(),g(),this.endBatch(),this},batchData:function(g){var x=this;return this.batch(function(){for(var T=Object.keys(g),L=0;L0;)x.removeChild(x.childNodes[0]);g._private.renderer=null,g.mutableElements().forEach(function(T){var L=T._private;L.rscratch={},L.rstyle={},L.animation.current=[],L.animation.queue=[]})},onRender:function(g){return this.on("render",g)},offRender:function(g){return this.off("render",g)}};WL.invalidateDimensions=WL.resize;var hC={collection:function(g,x){return mt(g)?this.$(g):Tt(g)?g.collection():ft(g)?(x||(x={}),new $f(this,g,x.unique,x.removed)):new $f(this)},nodes:function(g){var x=this.$(function(T){return T.isNode()});return g?x.filter(g):x},edges:function(g){var x=this.$(function(T){return T.isEdge()});return g?x.filter(g):x},$:function(g){var x=this._private.elements;return g?x.filter(g):x.spawnSelf()},mutableElements:function(){return this._private.elements}};hC.elements=hC.filter=hC.$;var g1={},zk="t",BJ="f";g1.apply=function(y){for(var g=this,x=g._private,T=x.cy,L=T.collection(),O=0;O0;if(rt||Y&&ot){var ht=void 0;rt&&ot||rt?ht=S.properties:ot&&(ht=S.mappedProperties);for(var dt=0;dt1&&($t=1),$.color){var Yt=T.valueMin[0],qt=T.valueMax[0],ne=T.valueMin[1],Gt=T.valueMax[1],ge=T.valueMin[2],be=T.valueMax[2],ie=T.valueMin[3]==null?1:T.valueMin[3],Fe=T.valueMax[3]==null?1:T.valueMax[3],we=[Math.round(Yt+(qt-Yt)*$t),Math.round(ne+(Gt-ne)*$t),Math.round(ge+(be-ge)*$t),Math.round(ie+(Fe-ie)*$t)];O={bypass:T.bypass,name:T.name,value:we,strValue:"rgb("+we[0]+", "+we[1]+", "+we[2]+")"}}else if($.number){var bn=T.valueMin+(T.valueMax-T.valueMin)*$t;O=this.parse(T.name,bn,T.bypass,rt)}else return!1;if(!O)return dt(),!1;O.mapping=T,T=O;break}case P.data:{for(var ze=T.field.split("."),Ge=Y.data,En=0;En0&&O>0){for(var $={},q=!1,S=0;S0?y.delayAnimation(P).play().promise().then(Pt):Pt()}).then(function(){return y.animation({style:$,duration:O,easing:y.pstyle("transition-timing-function").value,queue:!1}).play().promise()}).then(function(){x.removeBypasses(y,L),y.emitAndNotify("style"),T.transitioning=!1})}else T.transitioning&&(this.removeBypasses(y,L),y.emitAndNotify("style"),T.transitioning=!1)},g1.checkTrigger=function(y,g,x,T,L,O){var P=this.properties[g],$=L(P);$!=null&&$(x,T)&&O(P)},g1.checkZOrderTrigger=function(y,g,x,T){var L=this;this.checkTrigger(y,g,x,T,function(O){return O.triggersZOrder},function(){L._private.cy.notify("zorder",y)})},g1.checkBoundsTrigger=function(y,g,x,T){this.checkTrigger(y,g,x,T,function(L){return L.triggersBounds},function(L){y.dirtyCompoundBoundsCache(),y.dirtyBoundingBoxCache(),L.triggersBoundsOfParallelBeziers&&(g==="curve-style"&&(x==="bezier"||T==="bezier")||g==="display"&&(x==="none"||T==="none"))&&y.parallelEdges().forEach(function(O){O.isBundledBezier()&&O.dirtyBoundingBoxCache()})})},g1.checkTriggers=function(y,g,x,T){y.dirtyStyleCache(),this.checkZOrderTrigger(y,g,x,T),this.checkBoundsTrigger(y,g,x,T)};var qk={};qk.applyBypass=function(y,g,x,T){var L=this,O=[],P=!0;if(g==="*"||g==="**"){if(x!==void 0)for(var $=0;$L.length?T=T.substr(L.length):T=""}function q(){O.length>P.length?O=O.substr(P.length):O=""}for(;;){var S=T.match(/^\s*$/);if(S)break;var V=T.match(/^\s*((?:.|\s)+?)\s*\{((?:.|\s)+?)\}/);if(!V){Sc("Halting stylesheet parsing: String stylesheet contains more to parse but no selector and block found in: "+T);break}L=V[0];var Y=V[1];if(Y!=="core"){var rt=new Em(Y);if(rt.invalid){Sc("Skipping parsing of block: Invalid selector found in string stylesheet: "+Y),$();continue}}var ot=V[2],ht=!1;O=ot;for(var dt=[];;){var Lt=O.match(/^\s*$/);if(Lt)break;var kt=O.match(/^\s*(.+?)\s*:\s*(.+?)(?:\s*;|\s*$)/);if(!kt){Sc("Skipping parsing of block: Invalid formatting of style property and value definitions found in:"+ot),ht=!0;break}P=kt[0];var Dt=kt[1],Pt=kt[2],$t=g.properties[Dt];if(!$t){Sc("Skipping property: Invalid property name in: "+P),q();continue}var Zt=x.parse(Dt,Pt);if(!Zt){Sc("Skipping property: Invalid property definition in: "+P),q();continue}dt.push({name:Dt,val:Pt}),q()}if(ht){$();break}x.selector(Y);for(var Yt=0;Yt=7&&g[0]==="d"&&(V=new RegExp($.data.regex).exec(g))){if(x)return!1;var rt=$.data;return{name:y,value:V,strValue:""+g,mapped:rt,field:V[1],bypass:x}}else if(g.length>=10&&g[0]==="m"&&(Y=new RegExp($.mapData.regex).exec(g))){if(x||S.multiple)return!1;var ot=$.mapData;if(!(S.color||S.number))return!1;var ht=this.parse(y,Y[4]);if(!ht||ht.mapped)return!1;var dt=this.parse(y,Y[5]);if(!dt||dt.mapped)return!1;if(ht.pfValue===dt.pfValue||ht.strValue===dt.strValue)return Sc("`"+y+": "+g+"` is not a valid mapper because the output range is zero; converting to `"+y+": "+ht.strValue+"`"),this.parse(y,ht.strValue);if(S.color){var Lt=ht.value,kt=dt.value,Dt=Lt[0]===kt[0]&&Lt[1]===kt[1]&&Lt[2]===kt[2]&&(Lt[3]===kt[3]||(Lt[3]==null||Lt[3]===1)&&(kt[3]==null||kt[3]===1));if(Dt)return!1}return{name:y,value:Y,strValue:""+g,mapped:ot,field:Y[1],fieldMin:parseFloat(Y[2]),fieldMax:parseFloat(Y[3]),valueMin:ht.value,valueMax:dt.value,bypass:x}}}if(S.multiple&&T!=="multiple"){var Pt;if(q?Pt=g.split(/\s+/):ft(g)?Pt=g:Pt=[g],S.evenMultiple&&Pt.length%2!==0)return null;for(var $t=[],Zt=[],Yt=[],qt="",ne=!1,Gt=0;Gt0?" ":"")+ge.strValue}return S.validate&&!S.validate($t,Zt)?null:S.singleEnum&&ne?$t.length===1&&mt($t[0])?{name:y,value:$t[0],strValue:$t[0],bypass:x}:null:{name:y,value:$t,pfValue:Yt,strValue:qt,bypass:x,units:Zt}}var be=function(){for(var fr=0;frS.max||S.strictMax&&g===S.max))return null;var ze={name:y,value:g,strValue:""+g+(ie||""),units:ie,bypass:x};return S.unitless||ie!=="px"&&ie!=="em"?ze.pfValue=g:ze.pfValue=ie==="px"||!ie?g:this.getEmSizeInPixels()*g,(ie==="ms"||ie==="s")&&(ze.pfValue=ie==="ms"?g:1e3*g),(ie==="deg"||ie==="rad")&&(ze.pfValue=ie==="rad"?g:IK(g)),ie==="%"&&(ze.pfValue=g/100),ze}else if(S.propList){var Ge=[],En=""+g;if(En!=="none"){for(var In=En.split(/\s*,\s*|\s+/),Yn=0;Yn0&&$>0&&!isNaN(T.w)&&!isNaN(T.h)&&T.w>0&&T.h>0){q=Math.min((P-2*x)/T.w,($-2*x)/T.h),q=q>this._private.maxZoom?this._private.maxZoom:q,q=q=T.minZoom&&(T.maxZoom=x),this},minZoom:function(g){return g===void 0?this._private.minZoom:this.zoomRange({min:g})},maxZoom:function(g){return g===void 0?this._private.maxZoom:this.zoomRange({max:g})},getZoomedViewport:function(g){var x=this._private,T=x.pan,L=x.zoom,O,P,$=!1;if(x.zoomingEnabled||($=!0),X(g)?P=g:ut(g)&&(P=g.level,g.position!=null?O=NT(g.position,L,T):g.renderedPosition!=null&&(O=g.renderedPosition),O!=null&&!x.panningEnabled&&($=!0)),P=P>x.maxZoom?x.maxZoom:P,P=Px.maxZoom||!x.zoomingEnabled?P=!0:(x.zoom=q,O.push("zoom"))}if(L&&(!P||!g.cancelOnFailedZoom)&&x.panningEnabled){var S=g.pan;X(S.x)&&(x.pan.x=S.x,$=!1),X(S.y)&&(x.pan.y=S.y,$=!1),$||O.push("pan")}return O.length>0&&(O.push("viewport"),this.emit(O.join(" ")),this.notify("viewport")),this},center:function(g){var x=this.getCenterPan(g);return x&&(this._private.pan=x,this.emit("pan viewport"),this.notify("viewport")),this},getCenterPan:function(g,x){if(this._private.panningEnabled){if(mt(g)){var T=g;g=this.mutableElements().filter(T)}else Tt(g)||(g=this.mutableElements());if(g.length!==0){var L=g.boundingBox(),O=this.width(),P=this.height();x=x===void 0?this._private.zoom:x;var $={x:(O-x*(L.x1+L.x2))/2,y:(P-x*(L.y1+L.y2))/2};return $}}},reset:function(){return!this._private.panningEnabled||!this._private.zoomingEnabled?this:(this.viewport({pan:{x:0,y:0},zoom:1}),this)},invalidateSize:function(){this._private.sizeCache=null},size:function(){var g=this._private,x=g.container;return g.sizeCache=g.sizeCache||(x?function(){var T=R.getComputedStyle(x),L=function(P){return parseFloat(T.getPropertyValue(P))};return{width:x.clientWidth-L("padding-left")-L("padding-right"),height:x.clientHeight-L("padding-top")-L("padding-bottom")}}():{width:1,height:1})},width:function(){return this.size().width},height:function(){return this.size().height},extent:function(){var g=this._private.pan,x=this._private.zoom,T=this.renderedExtent(),L={x1:(T.x1-g.x)/x,x2:(T.x2-g.x)/x,y1:(T.y1-g.y)/x,y2:(T.y2-g.y)/x};return L.w=L.x2-L.x1,L.h=L.y2-L.y1,L},renderedExtent:function(){var g=this.width(),x=this.height();return{x1:0,y1:0,x2:g,y2:x,w:g,h:x}},multiClickDebounceTime:function(g){if(g)this._private.multiClickDebounceTime=g;else return this._private.multiClickDebounceTime;return this}};M3.centre=M3.center,M3.autolockNodes=M3.autolock,M3.autoungrabifyNodes=M3.autoungrabify;var Hk={data:Ac.data({field:"data",bindingEvent:"data",allowBinding:!0,allowSetting:!0,settingEvent:"data",settingTriggersEvent:!0,triggerFnName:"trigger",allowGetting:!0,updateStyle:!0}),removeData:Ac.removeData({field:"data",event:"data",triggerFnName:"trigger",triggerEvent:!0,updateStyle:!0}),scratch:Ac.data({field:"scratch",bindingEvent:"scratch",allowBinding:!0,allowSetting:!0,settingEvent:"scratch",settingTriggersEvent:!0,triggerFnName:"trigger",allowGetting:!0,updateStyle:!0}),removeScratch:Ac.removeData({field:"scratch",event:"scratch",triggerFnName:"trigger",triggerEvent:!0,updateStyle:!0})};Hk.attr=Hk.data,Hk.removeAttr=Hk.removeData;var Vk=function(g){var x=this;g=de({},g);var T=g.container;T&&!U(T)&&U(T[0])&&(T=T[0]);var L=T?T._cyreg:null;L=L||{},L&&L.cy&&(L.cy.destroy(),L={});var O=L.readies=L.readies||[];T&&(T._cyreg=L),L.cy=x;var P=R!==void 0&&T!==void 0&&!g.headless,$=g;$.layout=de({name:P?"grid":"null"},$.layout),$.renderer=de({name:P?"canvas":"null"},$.renderer);var q=function(ht,dt,Lt){return dt!==void 0?dt:Lt!==void 0?Lt:ht},S=this._private={container:T,ready:!1,options:$,elements:new $f(this),listeners:[],aniEles:new $f(this),data:$.data||{},scratch:{},layout:null,renderer:null,destroyed:!1,notificationsEnabled:!0,minZoom:1e-50,maxZoom:1e50,zoomingEnabled:q(!0,$.zoomingEnabled),userZoomingEnabled:q(!0,$.userZoomingEnabled),panningEnabled:q(!0,$.panningEnabled),userPanningEnabled:q(!0,$.userPanningEnabled),boxSelectionEnabled:q(!0,$.boxSelectionEnabled),autolock:q(!1,$.autolock,$.autolockNodes),autoungrabify:q(!1,$.autoungrabify,$.autoungrabifyNodes),autounselectify:q(!1,$.autounselectify),styleEnabled:$.styleEnabled===void 0?P:$.styleEnabled,zoom:X($.zoom)?$.zoom:1,pan:{x:ut($.pan)&&X($.pan.x)?$.pan.x:0,y:ut($.pan)&&X($.pan.y)?$.pan.y:0},animation:{current:[],queue:[]},hasCompoundNodes:!1,multiClickDebounceTime:q(250,$.multiClickDebounceTime)};this.createEmitter(),this.selectionType($.selectionType),this.zoomRange({min:$.minZoom,max:$.maxZoom});var V=function(ht,dt){var Lt=ht.some(Ht);if(Lt)return ex.all(ht).then(dt);dt(ht)};S.styleEnabled&&x.setStyle([]);var Y=de({},$,$.renderer);x.initRenderer(Y);var rt=function(ht,dt,Lt){x.notifications(!1);var kt=x.mutableElements();kt.length>0&&kt.remove(),ht!=null&&(ut(ht)||ft(ht))&&x.add(ht),x.one("layoutready",function(Pt){x.notifications(!0),x.emit(Pt),x.one("load",dt),x.emitAndNotify("load")}).one("layoutstop",function(){x.one("done",Lt),x.emit("done")});var Dt=de({},x._private.options.layout);Dt.eles=x.elements(),x.layout(Dt).run()};V([$.style,$.elements],function(ot){var ht=ot[0],dt=ot[1];S.styleEnabled&&x.style().append(ht),rt(dt,function(){x.startAnimationLoop(),S.ready=!0,yt($.ready)&&x.on("ready",$.ready);for(var Lt=0;Lt0,q=zd(g.boundingBox?g.boundingBox:{x1:0,y1:0,w:x.width(),h:x.height()}),S;if(Tt(g.roots))S=g.roots;else if(ft(g.roots)){for(var V=[],Y=0;Y0;){var bn=we(),ze=ge(bn,ie);if(ze)bn.outgoers().filter(function(Ci){return Ci.isNode()&&T.has(Ci)}).forEach(Fe);else if(ze===null){Sc("Detected double maximal shift for node `"+bn.id()+"`. Bailing maximal adjustment due to cycle. Use `options.maximal: true` only on DAGs.");break}}}Gt();var Ge=0;if(g.avoidOverlap)for(var En=0;En0&&kt[0].length<=3?qs/2:0),jn=2*Math.PI/kt[qi].length*Si;return qi===0&&kt[0].length===1&&(Qt=1),{x:vi.x+Qt*Math.cos(jn),y:vi.y+Qt*Math.sin(jn)}}else{var Tr={x:vi.x+(Si+1-(Ui+1)/2)*Va,y:(qi+1)*Qs};return Tr}};return T.nodes().layoutPositions(this,g,Ea),this};var zJ={fit:!0,padding:30,boundingBox:void 0,avoidOverlap:!0,nodeDimensionsIncludeLabels:!1,spacingFactor:void 0,radius:void 0,startAngle:3/2*Math.PI,sweep:void 0,clockwise:!0,sort:void 0,animate:!1,animationDuration:500,animationEasing:void 0,animateFilter:function(g,x){return!0},ready:void 0,stop:void 0,transform:function(g,x){return x}};function pC(y){this.options=de({},zJ,y)}pC.prototype.run=function(){var y=this.options,g=y,x=y.cy,T=g.eles,L=g.counterclockwise!==void 0?!g.counterclockwise:g.clockwise,O=T.nodes().not(":parent");g.sort&&(O=O.sort(g.sort));for(var P=zd(g.boundingBox?g.boundingBox:{x1:0,y1:0,w:x.width(),h:x.height()}),$={x:P.x1+P.w/2,y:P.y1+P.h/2},q=g.sweep===void 0?2*Math.PI-2*Math.PI/O.length:g.sweep,S=q/Math.max(1,O.length-1),V,Y=0,rt=0;rt1&&g.avoidOverlap){Y*=1.75;var kt=Math.cos(S)-Math.cos(0),Dt=Math.sin(S)-Math.sin(0),Pt=Math.sqrt(Y*Y/(kt*kt+Dt*Dt));V=Math.max(Pt,V)}var $t=function(Yt,qt){var ne=g.startAngle+qt*S*(L?1:-1),Gt=V*Math.cos(ne),ge=V*Math.sin(ne),be={x:$.x+Gt,y:$.y+ge};return be};return T.nodes().layoutPositions(this,g,$t),this};var qJ={fit:!0,padding:30,startAngle:3/2*Math.PI,sweep:void 0,clockwise:!0,equidistant:!1,minNodeSpacing:10,boundingBox:void 0,avoidOverlap:!0,nodeDimensionsIncludeLabels:!1,height:void 0,width:void 0,spacingFactor:void 0,concentric:function(g){return g.degree()},levelWidth:function(g){return g.maxDegree()/4},animate:!1,animationDuration:500,animationEasing:void 0,animateFilter:function(g,x){return!0},ready:void 0,stop:void 0,transform:function(g,x){return x}};function $B(y){this.options=de({},qJ,y)}$B.prototype.run=function(){for(var y=this.options,g=y,x=g.counterclockwise!==void 0?!g.counterclockwise:g.clockwise,T=y.cy,L=g.eles,O=L.nodes().not(":parent"),P=zd(g.boundingBox?g.boundingBox:{x1:0,y1:0,w:T.width(),h:T.height()}),$={x:P.x1+P.w/2,y:P.y1+P.h/2},q=[],S=0,V=0;V0){var Zt=Math.abs(Dt[0].value-$t.value);Zt>=Lt&&(Dt=[],kt.push(Dt))}Dt.push($t)}var Yt=S+g.minNodeSpacing;if(!g.avoidOverlap){var qt=kt.length>0&&kt[0].length>1,ne=Math.min(P.w,P.h)/2-Yt,Gt=ne/(kt.length+qt?1:0);Yt=Math.min(Yt,Gt)}for(var ge=0,be=0;be1&&g.avoidOverlap){var bn=Math.cos(we)-Math.cos(0),ze=Math.sin(we)-Math.sin(0),Ge=Math.sqrt(Yt*Yt/(bn*bn+ze*ze));ge=Math.max(Ge,ge)}ie.r=ge,ge+=Yt}if(g.equidistant){for(var En=0,In=0,Yn=0;Yn=y.numIter||(XJ(T,y),T.temperature=T.temperature*y.coolingFactor,T.temperature=y.animationThreshold&&O(),Bf(Y)}};V()}else{for(;S;)S=P(q),q++;HB(T,y),$()}return this},bC.prototype.stop=function(){return this.stopped=!0,this.thread&&this.thread.stop(),this.emit("layoutstop"),this},bC.prototype.destroy=function(){return this.thread&&this.thread.stop(),this};var VJ=function(g,x,T){for(var L=T.eles.edges(),O=T.eles.nodes(),P={isCompound:g.hasCompoundNodes(),layoutNodes:[],idToIndex:{},nodeSize:O.size(),graphSet:[],indexToGraph:[],layoutEdges:[],edgeSize:L.size(),temperature:T.initialTemp,clientWidth:g.width(),clientHeight:g.width(),boundingBox:zd(T.boundingBox?T.boundingBox:{x1:0,y1:0,w:g.width(),h:g.height()})},$=T.eles.components(),q={},S=0;S<$.length;S++)for(var V=$[S],Y=0;Y0){P.graphSet.push(qt);for(var S=0;SL.count?0:L.graph},UJ=function y(g,x,T,L){var O=L.graphSet[T];if(-10)var Y=L.nodeOverlap*V,rt=Math.sqrt($*$+q*q),ot=Y*$/rt,ht=Y*q/rt;else var dt=wC(g,$,q),Lt=wC(x,-1*$,-1*q),kt=Lt.x-dt.x,Dt=Lt.y-dt.y,Pt=kt*kt+Dt*Dt,rt=Math.sqrt(Pt),Y=(g.nodeRepulsion+x.nodeRepulsion)/Pt,ot=Y*kt/rt,ht=Y*Dt/rt;g.isLocked||(g.offsetX-=ot,g.offsetY-=ht),x.isLocked||(x.offsetX+=ot,x.offsetY+=ht)}},JJ=function(g,x,T,L){if(T>0)var O=g.maxX-x.minX;else var O=x.maxX-g.minX;if(L>0)var P=g.maxY-x.minY;else var P=x.maxY-g.minY;return O>=0&&P>=0?Math.sqrt(O*O+P*P):0},wC=function(g,x,T){var L=g.positionX,O=g.positionY,P=g.height||1,$=g.width||1,q=T/x,S=P/$,V={};return x===0&&0T?(V.x=L,V.y=O+P/2,V):0x&&-1*S<=q&&q<=S?(V.x=L-$/2,V.y=O-$*T/2/x,V):0=S)?(V.x=L+P*x/2/T,V.y=O+P/2,V):(0>T&&(q<=-1*S||q>=S)&&(V.x=L-P*x/2/T,V.y=O-P/2),V)},ttt=function(g,x){for(var T=0;TT){var Lt=x.gravity*ot/dt,kt=x.gravity*ht/dt;rt.offsetX+=Lt,rt.offsetY+=kt}}}}},ntt=function(g,x){var T=[],L=0,O=-1;for(T.push.apply(T,g.graphSet[0]),O+=g.graphSet[0].length;L<=O;){var P=T[L++],$=g.idToIndex[P],q=g.layoutNodes[$],S=q.children;if(0T)var O={x:T*g/L,y:T*x/L};else var O={x:g,y:x};return O},stt=function y(g,x){var T=g.parentId;if(T!=null){var L=x.layoutNodes[x.idToIndex[T]],O=!1;if((L.maxX==null||g.maxX+L.padRight>L.maxX)&&(L.maxX=g.maxX+L.padRight,O=!0),(L.minX==null||g.minX-L.padLeftL.maxY)&&(L.maxY=g.maxY+L.padBottom,O=!0),(L.minY==null||g.minY-L.padTopkt&&(ht+=Lt+x.componentSpacing,ot=0,dt=0,Lt=0)}}},att={fit:!0,padding:30,boundingBox:void 0,avoidOverlap:!0,avoidOverlapPadding:10,nodeDimensionsIncludeLabels:!1,spacingFactor:void 0,condense:!1,rows:void 0,cols:void 0,position:function(g){},sort:void 0,animate:!1,animationDuration:500,animationEasing:void 0,animateFilter:function(g,x){return!0},ready:void 0,stop:void 0,transform:function(g,x){return x}};function VB(y){this.options=de({},att,y)}VB.prototype.run=function(){var y=this.options,g=y,x=y.cy,T=g.eles,L=T.nodes().not(":parent");g.sort&&(L=L.sort(g.sort));var O=zd(g.boundingBox?g.boundingBox:{x1:0,y1:0,w:x.width(),h:x.height()});if(O.h===0||O.w===0)T.nodes().layoutPositions(this,g,function(rr){return{x:O.x1,y:O.y1}});else{var P=L.size(),$=Math.sqrt(P*O.h/O.w),q=Math.round($),S=Math.round(O.w/O.h*$),V=function(wr){if(wr==null)return Math.min(q,S);var ur=Math.min(q,S);ur==q?q=wr:S=wr},Y=function(wr){if(wr==null)return Math.max(q,S);var ur=Math.max(q,S);ur==q?q=wr:S=wr},rt=g.rows,ot=g.cols!=null?g.cols:g.columns;if(rt!=null&&ot!=null)q=rt,S=ot;else if(rt!=null&&ot==null)q=rt,S=Math.ceil(P/q);else if(rt==null&&ot!=null)S=ot,q=Math.ceil(P/S);else if(S*q>P){var ht=V(),dt=Y();(ht-1)*dt>=P?V(ht-1):(dt-1)*ht>=P&&Y(dt-1)}else for(;S*q=P?Y(kt+1):V(Lt+1)}var Dt=O.w/S,Pt=O.h/q;if(g.condense&&(Dt=0,Pt=0),g.avoidOverlap)for(var $t=0;$t=S&&(bn=0,we++)},Ge={},En=0;En(bn=GK(y,g,ze[Ge],ze[Ge+1],ze[Ge+2],ze[Ge+3])))return Lt(qt,bn),!0}else if(Gt.edgeType==="bezier"||Gt.edgeType==="multibezier"||Gt.edgeType==="self"||Gt.edgeType==="compound"){for(var ze=Gt.allpts,Ge=0;Ge+5(bn=VK(y,g,ze[Ge],ze[Ge+1],ze[Ge+2],ze[Ge+3],ze[Ge+4],ze[Ge+5])))return Lt(qt,bn),!0}for(var En=En||ne.source,In=In||ne.target,Yn=L.getArrowWidth(ge,be),Sn=[{name:"source",x:Gt.arrowStartX,y:Gt.arrowStartY,angle:Gt.srcArrowAngle},{name:"target",x:Gt.arrowEndX,y:Gt.arrowEndY,angle:Gt.tgtArrowAngle},{name:"mid-source",x:Gt.midX,y:Gt.midY,angle:Gt.midsrcArrowAngle},{name:"mid-target",x:Gt.midX,y:Gt.midY,angle:Gt.midtgtArrowAngle}],Ge=0;Ge0&&(kt(En),kt(In))}function Pt(qt,ne,Gt){return yp(qt,ne,Gt)}function $t(qt,ne){var Gt=qt._private,ge=rt,be;ne?be=ne+"-":be="",qt.boundingBox();var ie=Gt.labelBounds[ne||"main"],Fe=qt.pstyle(be+"label").value,we=qt.pstyle("text-events").strValue==="yes";if(!(!we||!Fe)){var bn=Pt(Gt.rscratch,"labelX",ne),ze=Pt(Gt.rscratch,"labelY",ne),Ge=Pt(Gt.rscratch,"labelAngle",ne),En=qt.pstyle(be+"text-margin-x").pfValue,In=qt.pstyle(be+"text-margin-y").pfValue,Yn=ie.x1-ge-En,Sn=ie.x2+ge-En,Wn=ie.y1-ge-In,rr=ie.y2+ge-In;if(Ge){var wr=Math.cos(Ge),ur=Math.sin(Ge),er=function(Ea,Ci){return Ea=Ea-bn,Ci=Ci-ze,{x:Ea*wr-Ci*ur+bn,y:Ea*ur+Ci*wr+ze}},vn=er(Yn,Wn),gr=er(Yn,rr),fr=er(Sn,Wn),Jr=er(Sn,rr),vi=[vn.x+En,vn.y+In,fr.x+En,fr.y+In,Jr.x+En,Jr.y+In,gr.x+En,gr.y+In];if(qd(y,g,vi))return Lt(qt),!0}else if(Q5(ie,y,g))return Lt(qt),!0}}for(var Zt=P.length-1;Zt>=0;Zt--){var Yt=P[Zt];Yt.isNode()?kt(Yt)||$t(Yt):Dt(Yt)||$t(Yt)||$t(Yt,"source")||$t(Yt,"target")}return $},D3.getAllInBox=function(y,g,x,T){var L=this.getCachedZSortedEles().interactive,O=[],P=Math.min(y,x),$=Math.max(y,x),q=Math.min(g,T),S=Math.max(g,T);y=P,x=$,g=q,T=S;for(var V=zd({x1:y,y1:g,x2:x,y2:T}),Y=0;Y0?Math.max(Yi-Fo,0):Math.min(Yi+Fo,0)},Fe=ie(ge,ne),we=ie(be,Gt),bn=!1;Dt===S?kt=Math.abs(Fe)>Math.abs(we)?L:T:Dt===q||Dt===$?(kt=T,bn=!0):(Dt===O||Dt===P)&&(kt=L,bn=!0);var ze=kt===T,Ge=ze?we:Fe,En=ze?be:ge,In=uN(En),Yn=!1;!(bn&&($t||Yt))&&(Dt===$&&En<0||Dt===q&&En>0||Dt===O&&En>0||Dt===P&&En<0)&&(In*=-1,Ge=In*Math.abs(Ge),Yn=!0);var Sn;if($t){var Wn=Zt<0?1+Zt:Zt;Sn=Wn*Ge}else{var rr=Zt<0?Ge:0;Sn=rr+Zt*In}var wr=function(Yi){return Math.abs(Yi)=Math.abs(Ge)},ur=wr(Sn),er=wr(Math.abs(Ge)-Math.abs(Sn)),vn=ur||er;if(vn&&!Yn)if(ze){var gr=Math.abs(En)<=rt/2,fr=Math.abs(ge)<=ot/2;if(gr){var Jr=(V.x1+V.x2)/2,vi=V.y1,Xs=V.y2;x.segpts=[Jr,vi,Jr,Xs]}else if(fr){var Ea=(V.y1+V.y2)/2,Ci=V.x1,hi=V.x2;x.segpts=[Ci,Ea,hi,Ea]}else x.segpts=[V.x1,V.y2]}else{var gs=Math.abs(En)<=Y/2,qi=Math.abs(be)<=ht/2;if(gs){var Si=(V.y1+V.y2)/2,Ui=V.x1,Va=V.x2;x.segpts=[Ui,Si,Va,Si]}else if(qi){var Qs=(V.x1+V.x2)/2,qs=V.y1,Tr=V.y2;x.segpts=[Qs,qs,Qs,Tr]}else x.segpts=[V.x2,V.y1]}else if(ze){var Qt=V.y1+Sn+(Lt?rt/2*In:0),jn=V.x1,Sr=V.x2;x.segpts=[jn,Qt,Sr,Qt]}else{var ir=V.x1+Sn+(Lt?Y/2*In:0),sr=V.y1,Ia=V.y2;x.segpts=[ir,sr,ir,Ia]}},od.tryToCorrectInvalidPoints=function(y,g){var x=y._private.rscratch;if(x.edgeType==="bezier"){var T=g.srcPos,L=g.tgtPos,O=g.srcW,P=g.srcH,$=g.tgtW,q=g.tgtH,S=g.srcShape,V=g.tgtShape,Y=!X(x.startX)||!X(x.startY),rt=!X(x.arrowStartX)||!X(x.arrowStartY),ot=!X(x.endX)||!X(x.endY),ht=!X(x.arrowEndX)||!X(x.arrowEndY),dt=3,Lt=this.getArrowWidth(y.pstyle("width").pfValue,y.pstyle("arrow-scale").value)*this.arrowShapeWidth,kt=dt*Lt,Dt=C3({x:x.ctrlpts[0],y:x.ctrlpts[1]},{x:x.startX,y:x.startY}),Pt=Dtwe.poolIndex()){var bn=Fe;Fe=we,we=bn}var ze=Gt.srcPos=Fe.position(),Ge=Gt.tgtPos=we.position(),En=Gt.srcW=Fe.outerWidth(),In=Gt.srcH=Fe.outerHeight(),Yn=Gt.tgtW=we.outerWidth(),Sn=Gt.tgtH=we.outerHeight(),Wn=Gt.srcShape=x.nodeShapes[g.getNodeShape(Fe)],rr=Gt.tgtShape=x.nodeShapes[g.getNodeShape(we)];Gt.dirCounts={north:0,west:0,south:0,east:0,northwest:0,southwest:0,northeast:0,southeast:0};for(var wr=0;wr0){var gr=O,fr=_3(gr,K5(x)),Jr=_3(gr,K5(vn)),vi=fr;if(Jr2){var Xs=_3(gr,{x:vn[2],y:vn[3]});Xs0){var jn=P,Sr=_3(jn,K5(x)),ir=_3(jn,K5(Qt)),sr=Sr;if(ir2){var Ia=_3(jn,{x:Qt[2],y:Qt[3]});Ia=ht||qt){Lt={cp:$t,segment:Yt};break}}if(Lt)break}var ne=Lt.cp,Gt=Lt.segment,ge=(ht-kt)/Gt.length,be=Gt.t1-Gt.t0,ie=ot?Gt.t0+be*ge:Gt.t1-be*ge;ie=_k(0,ie,1),g=X5(ne.p0,ne.p1,ne.p2,ie),rt=JB(ne.p0,ne.p1,ne.p2,ie);break}case"straight":case"segments":case"haystack":{for(var Fe=0,we,bn,ze,Ge,En=T.allpts.length,In=0;In+3=ht));In+=2);var Yn=ht-bn,Sn=Yn/we;Sn=_k(0,Sn,1),g=PK(ze,Ge,Sn),rt=ZB(ze,Ge);break}}P("labelX",Y,g.x),P("labelY",Y,g.y),P("labelAutoAngle",Y,rt)}};S("source"),S("target"),this.applyLabelDimensions(y)}},Tp.applyLabelDimensions=function(y){this.applyPrefixedLabelDimensions(y),y.isEdge()&&(this.applyPrefixedLabelDimensions(y,"source"),this.applyPrefixedLabelDimensions(y,"target"))},Tp.applyPrefixedLabelDimensions=function(y,g){var x=y._private,T=this.getLabelText(y,g),L=this.calculateLabelDimensions(y,T),O=y.pstyle("line-height").pfValue,P=y.pstyle("text-wrap").strValue,$=yp(x.rscratch,"labelWrapCachedLines",g)||[],q=P!=="wrap"?1:Math.max($.length,1),S=L.height/q,V=S*O,Y=L.width,rt=L.height+(q-1)*(O-1)*S;mm(x.rstyle,"labelWidth",g,Y),mm(x.rscratch,"labelWidth",g,Y),mm(x.rstyle,"labelHeight",g,rt),mm(x.rscratch,"labelHeight",g,rt),mm(x.rscratch,"labelLineHeight",g,V)},Tp.getLabelText=function(y,g){var x=y._private,T=g?g+"-":"",L=y.pstyle(T+"label").strValue,O=y.pstyle("text-transform").value,P=function(Yn,Sn){return Sn?(mm(x.rscratch,Yn,g,Sn),Sn):yp(x.rscratch,Yn,g)};if(!L)return"";O=="none"||(O=="uppercase"?L=L.toUpperCase():O=="lowercase"&&(L=L.toLowerCase()));var $=y.pstyle("text-wrap").value;if($==="wrap"){var q=P("labelKey");if(q!=null&&P("labelWrapKey")===q)return P("labelWrapCachedText");for(var S="​",V=L.split(` +`),Y=y.pstyle("text-max-width").pfValue,rt=y.pstyle("text-overflow-wrap").value,ot=rt==="anywhere",ht=[],dt=/[\s\u200b]+/,Lt=ot?"":" ",kt=0;ktY){for(var Yt=Dt.split(dt),qt="",ne=0;neFe)break;we+=L[Ge],Ge===L.length-1&&(ze=!0)}return ze||(we+=bn),we}return L},Tp.getLabelJustification=function(y){var g=y.pstyle("text-justification").strValue,x=y.pstyle("text-halign").strValue;if(g==="auto")if(y.isNode())switch(x){case"left":return"right";case"right":return"left";default:return"center"}else return"center";else return g},Tp.calculateLabelDimensions=function(y,g){var x=this,T=rd(g,y._private.labelDimsKey),L=x.labelDimCache||(x.labelDimCache=[]),O=L[T];if(O!=null)return O;var P=0,$=y.pstyle("font-style").strValue,q=y.pstyle("font-size").pfValue,S=y.pstyle("font-family").strValue,V=y.pstyle("font-weight").strValue,Y=this.labelCalcCanvas,rt=this.labelCalcCanvasContext;if(!Y){Y=this.labelCalcCanvas=document.createElement("canvas"),rt=this.labelCalcCanvasContext=Y.getContext("2d");var ot=Y.style;ot.position="absolute",ot.left="-9999px",ot.top="-9999px",ot.zIndex="-1",ot.visibility="hidden",ot.pointerEvents="none"}rt.font="".concat($," ").concat(V," ").concat(q,"px ").concat(S);for(var ht=0,dt=0,Lt=g.split(` +`),kt=0;kt1&&arguments[1]!==void 0?arguments[1]:!0;if(g.merge(P),$)for(var q=0;q=y.desktopTapThreshold2}var mw=T(Qt);qf&&(y.hoverData.tapholdCancelled=!0);var Lm=function(){var Yb=y.hoverData.dragDelta=y.hoverData.dragDelta||[];Yb.length===0?(Yb.push(Ja[0]),Yb.push(Ja[1])):(Yb[0]+=Ja[0],Yb[1]+=Ja[1])};Sr=!0,x(Za,["mousemove","vmousemove","tapdrag"],Qt,{x:$r[0],y:$r[1]});var xx=function(){y.data.bgActivePosistion=void 0,y.hoverData.selecting||ir.emit({originalEvent:Qt,type:"boxstart",position:{x:$r[0],y:$r[1]}}),Pc[4]=1,y.hoverData.selecting=!0,y.redrawHint("select",!0),y.redraw()};if(y.hoverData.which===3){if(qf){var F3={originalEvent:Qt,type:"cxtdrag",position:{x:$r[0],y:$r[1]}};Ta?Ta.emit(F3):ir.emit(F3),y.hoverData.cxtDragged=!0,(!y.hoverData.cxtOver||Za!==y.hoverData.cxtOver)&&(y.hoverData.cxtOver&&y.hoverData.cxtOver.emit({originalEvent:Qt,type:"cxtdragout",position:{x:$r[0],y:$r[1]}}),y.hoverData.cxtOver=Za,Za&&Za.emit({originalEvent:Qt,type:"cxtdragover",position:{x:$r[0],y:$r[1]}}))}}else if(y.hoverData.dragging){if(Sr=!0,ir.panningEnabled()&&ir.userPanningEnabled()){var kx;if(y.hoverData.justStartedPan){var SC=y.hoverData.mdownPos;kx={x:($r[0]-SC[0])*sr,y:($r[1]-SC[1])*sr},y.hoverData.justStartedPan=!1}else kx={x:Ja[0]*sr,y:Ja[1]*sr};ir.panBy(kx),ir.emit("dragpan"),y.hoverData.dragged=!0}$r=y.projectIntoViewport(Qt.clientX,Qt.clientY)}else if(Pc[4]==1&&(Ta==null||Ta.pannable())){if(qf){if(!y.hoverData.dragging&&ir.boxSelectionEnabled()&&(mw||!ir.panningEnabled()||!ir.userPanningEnabled()))xx();else if(!y.hoverData.selecting&&ir.panningEnabled()&&ir.userPanningEnabled()){var N3=L(Ta,y.hoverData.downs);N3&&(y.hoverData.dragging=!0,y.hoverData.justStartedPan=!0,Pc[4]=0,y.data.bgActivePosistion=K5(Yi),y.redrawHint("select",!0),y.redraw())}Ta&&Ta.pannable()&&Ta.active()&&Ta.unactivate()}}else{if(Ta&&Ta.pannable()&&Ta.active()&&Ta.unactivate(),(!Ta||!Ta.grabbed())&&Za!=mc&&(mc&&x(mc,["mouseout","tapdragout"],Qt,{x:$r[0],y:$r[1]}),Za&&x(Za,["mouseover","tapdragover"],Qt,{x:$r[0],y:$r[1]}),y.hoverData.last=Za),Ta)if(qf){if(ir.boxSelectionEnabled()&&mw)Ta&&Ta.grabbed()&&(dt(ml),Ta.emit("freeon"),ml.emit("free"),y.dragData.didDrag&&(Ta.emit("dragfreeon"),ml.emit("dragfree"))),xx();else if(Ta&&Ta.grabbed()&&y.nodeIsDraggable(Ta)){var Hd=!y.dragData.didDrag;Hd&&y.redrawHint("eles",!0),y.dragData.didDrag=!0,y.hoverData.draggingEles||ot(ml,{inDragLayer:!0});var y1={x:0,y:0};if(X(Ja[0])&&X(Ja[1])&&(y1.x+=Ja[0],y1.y+=Ja[1],Hd)){var Vd=y.hoverData.dragDelta;Vd&&X(Vd[0])&&X(Vd[1])&&(y1.x+=Vd[0],y1.y+=Vd[1])}y.hoverData.draggingEles=!0,ml.silentShift(y1).emit("position drag"),y.redrawHint("drag",!0),y.redraw()}}else Lm();Sr=!0}if(Pc[2]=$r[0],Pc[3]=$r[1],Sr)return Qt.stopPropagation&&Qt.stopPropagation(),Qt.preventDefault&&Qt.preventDefault(),!1}},!1);var Gt,ge,be;y.registerBinding(window,"mouseup",function(Qt){var jn=y.hoverData.capture;if(jn){y.hoverData.capture=!1;var Sr=y.cy,ir=y.projectIntoViewport(Qt.clientX,Qt.clientY),sr=y.selection,Ia=y.findNearestElement(ir[0],ir[1],!0,!1),$r=y.dragData.possibleDragElements,Yi=y.hoverData.down,Fo=T(Qt);if(y.data.bgActivePosistion&&(y.redrawHint("select",!0),y.redraw()),y.hoverData.tapholdCancelled=!0,y.data.bgActivePosistion=void 0,Yi&&Yi.unactivate(),y.hoverData.which===3){var Pc={originalEvent:Qt,type:"cxttapend",position:{x:ir[0],y:ir[1]}};if(Yi?Yi.emit(Pc):Sr.emit(Pc),!y.hoverData.cxtDragged){var Za={originalEvent:Qt,type:"cxttap",position:{x:ir[0],y:ir[1]}};Yi?Yi.emit(Za):Sr.emit(Za)}y.hoverData.cxtDragged=!1,y.hoverData.which=null}else if(y.hoverData.which===1){if(x(Ia,["mouseup","tapend","vmouseup"],Qt,{x:ir[0],y:ir[1]}),!y.dragData.didDrag&&!y.hoverData.dragged&&!y.hoverData.selecting&&!y.hoverData.isOverThresholdDrag&&(x(Yi,["click","tap","vclick"],Qt,{x:ir[0],y:ir[1]}),ge=!1,Qt.timeStamp-be<=Sr.multiClickDebounceTime()?(Gt&&clearTimeout(Gt),ge=!0,be=null,x(Yi,["dblclick","dbltap","vdblclick"],Qt,{x:ir[0],y:ir[1]})):(Gt=setTimeout(function(){ge||x(Yi,["oneclick","onetap","voneclick"],Qt,{x:ir[0],y:ir[1]})},Sr.multiClickDebounceTime()),be=Qt.timeStamp)),Yi==null&&!y.dragData.didDrag&&!y.hoverData.selecting&&!y.hoverData.dragged&&!T(Qt)&&(Sr.$(g).unselect(["tapunselect"]),$r.length>0&&y.redrawHint("eles",!0),y.dragData.possibleDragElements=$r=Sr.collection()),Ia==Yi&&!y.dragData.didDrag&&!y.hoverData.selecting&&Ia!=null&&Ia._private.selectable&&(y.hoverData.dragging||(Sr.selectionType()==="additive"||Fo?Ia.selected()?Ia.unselect(["tapunselect"]):Ia.select(["tapselect"]):Fo||(Sr.$(g).unmerge(Ia).unselect(["tapunselect"]),Ia.select(["tapselect"]))),y.redrawHint("eles",!0)),y.hoverData.selecting){var mc=Sr.collection(y.getAllInBox(sr[0],sr[1],sr[2],sr[3]));y.redrawHint("select",!0),mc.length>0&&y.redrawHint("eles",!0),Sr.emit({type:"boxend",originalEvent:Qt,position:{x:ir[0],y:ir[1]}});var Ta=function(qf){return qf.selectable()&&!qf.selected()};Sr.selectionType()==="additive"||Fo||Sr.$(g).unmerge(mc).unselect(),mc.emit("box").stdFilter(Ta).select().emit("boxselect"),y.redraw()}if(y.hoverData.dragging&&(y.hoverData.dragging=!1,y.redrawHint("select",!0),y.redrawHint("eles",!0),y.redraw()),!sr[4]){y.redrawHint("drag",!0),y.redrawHint("eles",!0);var Ja=Yi&&Yi.grabbed();dt($r),Ja&&(Yi.emit("freeon"),$r.emit("free"),y.dragData.didDrag&&(Yi.emit("dragfreeon"),$r.emit("dragfree")))}}sr[4]=0,y.hoverData.down=null,y.hoverData.cxtStarted=!1,y.hoverData.draggingEles=!1,y.hoverData.selecting=!1,y.hoverData.isOverThresholdDrag=!1,y.dragData.didDrag=!1,y.hoverData.dragged=!1,y.hoverData.dragDelta=[],y.hoverData.mdownPos=null,y.hoverData.mdownGPos=null}},!1);var ie=function(Qt){if(!y.scrollingPage){var jn=y.cy,Sr=jn.zoom(),ir=jn.pan(),sr=y.projectIntoViewport(Qt.clientX,Qt.clientY),Ia=[sr[0]*Sr+ir.x,sr[1]*Sr+ir.y];if(y.hoverData.draggingEles||y.hoverData.dragging||y.hoverData.cxtStarted||qt()){Qt.preventDefault();return}if(jn.panningEnabled()&&jn.userPanningEnabled()&&jn.zoomingEnabled()&&jn.userZoomingEnabled()){Qt.preventDefault(),y.data.wheelZooming=!0,clearTimeout(y.data.wheelTimeout),y.data.wheelTimeout=setTimeout(function(){y.data.wheelZooming=!1,y.redrawHint("eles",!0),y.redraw()},150);var $r;Qt.deltaY!=null?$r=Qt.deltaY/-250:Qt.wheelDeltaY!=null?$r=Qt.wheelDeltaY/1e3:$r=Qt.wheelDelta/1e3,$r=$r*y.wheelSensitivity;var Yi=Qt.deltaMode===1;Yi&&($r*=33);var Fo=jn.zoom()*Math.pow(10,$r);Qt.type==="gesturechange"&&(Fo=y.gestureStartZoom*Qt.scale),jn.zoom({level:Fo,renderedPosition:{x:Ia[0],y:Ia[1]}}),jn.emit(Qt.type==="gesturechange"?"pinchzoom":"scrollzoom")}}};y.registerBinding(y.container,"wheel",ie,!0),y.registerBinding(window,"scroll",function(Qt){y.scrollingPage=!0,clearTimeout(y.scrollingPageTimeout),y.scrollingPageTimeout=setTimeout(function(){y.scrollingPage=!1},250)},!0),y.registerBinding(y.container,"gesturestart",function(Qt){y.gestureStartZoom=y.cy.zoom(),y.hasTouchStarted||Qt.preventDefault()},!0),y.registerBinding(y.container,"gesturechange",function(Tr){y.hasTouchStarted||ie(Tr)},!0),y.registerBinding(y.container,"mouseout",function(Qt){var jn=y.projectIntoViewport(Qt.clientX,Qt.clientY);y.cy.emit({originalEvent:Qt,type:"mouseout",position:{x:jn[0],y:jn[1]}})},!1),y.registerBinding(y.container,"mouseover",function(Qt){var jn=y.projectIntoViewport(Qt.clientX,Qt.clientY);y.cy.emit({originalEvent:Qt,type:"mouseover",position:{x:jn[0],y:jn[1]}})},!1);var Fe,we,bn,ze,Ge,En,In,Yn,Sn,Wn,rr,wr,ur,er=function(Qt,jn,Sr,ir){return Math.sqrt((Sr-Qt)*(Sr-Qt)+(ir-jn)*(ir-jn))},vn=function(Qt,jn,Sr,ir){return(Sr-Qt)*(Sr-Qt)+(ir-jn)*(ir-jn)},gr;y.registerBinding(y.container,"touchstart",gr=function(Qt){if(y.hasTouchStarted=!0,!!ne(Qt)){kt(),y.touchData.capture=!0,y.data.bgActivePosistion=void 0;var jn=y.cy,Sr=y.touchData.now,ir=y.touchData.earlier;if(Qt.touches[0]){var sr=y.projectIntoViewport(Qt.touches[0].clientX,Qt.touches[0].clientY);Sr[0]=sr[0],Sr[1]=sr[1]}if(Qt.touches[1]){var sr=y.projectIntoViewport(Qt.touches[1].clientX,Qt.touches[1].clientY);Sr[2]=sr[0],Sr[3]=sr[1]}if(Qt.touches[2]){var sr=y.projectIntoViewport(Qt.touches[2].clientX,Qt.touches[2].clientY);Sr[4]=sr[0],Sr[5]=sr[1]}if(Qt.touches[1]){y.touchData.singleTouchMoved=!0,dt(y.dragData.touchDragEles);var Ia=y.findContainerClientCoords();Sn=Ia[0],Wn=Ia[1],rr=Ia[2],wr=Ia[3],Fe=Qt.touches[0].clientX-Sn,we=Qt.touches[0].clientY-Wn,bn=Qt.touches[1].clientX-Sn,ze=Qt.touches[1].clientY-Wn,ur=0<=Fe&&Fe<=rr&&0<=bn&&bn<=rr&&0<=we&&we<=wr&&0<=ze&&ze<=wr;var $r=jn.pan(),Yi=jn.zoom();Ge=er(Fe,we,bn,ze),En=vn(Fe,we,bn,ze),In=[(Fe+bn)/2,(we+ze)/2],Yn=[(In[0]-$r.x)/Yi,(In[1]-$r.y)/Yi];var Fo=200,Pc=Fo*Fo;if(En=1){for(var _p=y.touchData.startPosition=[],Hf=0;Hf=y.touchTapThreshold2}if(jn&&y.touchData.cxt){Qt.preventDefault();var _p=Qt.touches[0].clientX-Sn,Hf=Qt.touches[0].clientY-Wn,_g=Qt.touches[1].clientX-Sn,cd=Qt.touches[1].clientY-Wn,mw=vn(_p,Hf,_g,cd),Lm=mw/En,xx=150,F3=xx*xx,kx=1.5,SC=kx*kx;if(Lm>=SC||mw>=F3){y.touchData.cxt=!1,y.data.bgActivePosistion=void 0,y.redrawHint("select",!0);var N3={originalEvent:Qt,type:"cxttapend",position:{x:sr[0],y:sr[1]}};y.touchData.start?(y.touchData.start.unactivate().emit(N3),y.touchData.start=null):ir.emit(N3)}}if(jn&&y.touchData.cxt){var N3={originalEvent:Qt,type:"cxtdrag",position:{x:sr[0],y:sr[1]}};y.data.bgActivePosistion=void 0,y.redrawHint("select",!0),y.touchData.start?y.touchData.start.emit(N3):ir.emit(N3),y.touchData.start&&(y.touchData.start._private.grabbed=!1),y.touchData.cxtDragged=!0;var Hd=y.findNearestElement(sr[0],sr[1],!0,!0);(!y.touchData.cxtOver||Hd!==y.touchData.cxtOver)&&(y.touchData.cxtOver&&y.touchData.cxtOver.emit({originalEvent:Qt,type:"cxtdragout",position:{x:sr[0],y:sr[1]}}),y.touchData.cxtOver=Hd,Hd&&Hd.emit({originalEvent:Qt,type:"cxtdragover",position:{x:sr[0],y:sr[1]}}))}else if(jn&&Qt.touches[2]&&ir.boxSelectionEnabled())Qt.preventDefault(),y.data.bgActivePosistion=void 0,this.lastThreeTouch=+new Date,y.touchData.selecting||ir.emit({originalEvent:Qt,type:"boxstart",position:{x:sr[0],y:sr[1]}}),y.touchData.selecting=!0,y.touchData.didSelect=!0,Sr[4]=1,!Sr||Sr.length===0||Sr[0]===void 0?(Sr[0]=(sr[0]+sr[2]+sr[4])/3,Sr[1]=(sr[1]+sr[3]+sr[5])/3,Sr[2]=(sr[0]+sr[2]+sr[4])/3+1,Sr[3]=(sr[1]+sr[3]+sr[5])/3+1):(Sr[2]=(sr[0]+sr[2]+sr[4])/3,Sr[3]=(sr[1]+sr[3]+sr[5])/3),y.redrawHint("select",!0),y.redraw();else if(jn&&Qt.touches[1]&&!y.touchData.didSelect&&ir.zoomingEnabled()&&ir.panningEnabled()&&ir.userZoomingEnabled()&&ir.userPanningEnabled()){Qt.preventDefault(),y.data.bgActivePosistion=void 0,y.redrawHint("select",!0);var y1=y.dragData.touchDragEles;if(y1){y.redrawHint("drag",!0);for(var Vd=0;Vd0&&!y.hoverData.draggingEles&&!y.swipePanning&&y.data.bgActivePosistion!=null&&(y.data.bgActivePosistion=void 0,y.redrawHint("select",!0),y.redraw())}},!1);var Jr;y.registerBinding(window,"touchcancel",Jr=function(Qt){var jn=y.touchData.start;y.touchData.capture=!1,jn&&jn.unactivate()});var vi,Xs,Ea,Ci;if(y.registerBinding(window,"touchend",vi=function(Qt){var jn=y.touchData.start,Sr=y.touchData.capture;if(Sr)Qt.touches.length===0&&(y.touchData.capture=!1),Qt.preventDefault();else return;var ir=y.selection;y.swipePanning=!1,y.hoverData.draggingEles=!1;var sr=y.cy,Ia=sr.zoom(),$r=y.touchData.now,Yi=y.touchData.earlier;if(Qt.touches[0]){var Fo=y.projectIntoViewport(Qt.touches[0].clientX,Qt.touches[0].clientY);$r[0]=Fo[0],$r[1]=Fo[1]}if(Qt.touches[1]){var Fo=y.projectIntoViewport(Qt.touches[1].clientX,Qt.touches[1].clientY);$r[2]=Fo[0],$r[3]=Fo[1]}if(Qt.touches[2]){var Fo=y.projectIntoViewport(Qt.touches[2].clientX,Qt.touches[2].clientY);$r[4]=Fo[0],$r[5]=Fo[1]}jn&&jn.unactivate();var Pc;if(y.touchData.cxt){if(Pc={originalEvent:Qt,type:"cxttapend",position:{x:$r[0],y:$r[1]}},jn?jn.emit(Pc):sr.emit(Pc),!y.touchData.cxtDragged){var Za={originalEvent:Qt,type:"cxttap",position:{x:$r[0],y:$r[1]}};jn?jn.emit(Za):sr.emit(Za)}y.touchData.start&&(y.touchData.start._private.grabbed=!1),y.touchData.cxt=!1,y.touchData.start=null,y.redraw();return}if(!Qt.touches[2]&&sr.boxSelectionEnabled()&&y.touchData.selecting){y.touchData.selecting=!1;var mc=sr.collection(y.getAllInBox(ir[0],ir[1],ir[2],ir[3]));ir[0]=void 0,ir[1]=void 0,ir[2]=void 0,ir[3]=void 0,ir[4]=0,y.redrawHint("select",!0),sr.emit({type:"boxend",originalEvent:Qt,position:{x:$r[0],y:$r[1]}});var Ta=function(F3){return F3.selectable()&&!F3.selected()};mc.emit("box").stdFilter(Ta).select().emit("boxselect"),mc.nonempty()&&y.redrawHint("eles",!0),y.redraw()}if(jn!=null&&jn.unactivate(),Qt.touches[2])y.data.bgActivePosistion=void 0,y.redrawHint("select",!0);else if(!Qt.touches[1]){if(!Qt.touches[0]){if(!Qt.touches[0]){y.data.bgActivePosistion=void 0,y.redrawHint("select",!0);var Ja=y.dragData.touchDragEles;if(jn!=null){var ml=jn._private.grabbed;dt(Ja),y.redrawHint("drag",!0),y.redrawHint("eles",!0),ml&&(jn.emit("freeon"),Ja.emit("free"),y.dragData.didDrag&&(jn.emit("dragfreeon"),Ja.emit("dragfree"))),x(jn,["touchend","tapend","vmouseup","tapdragout"],Qt,{x:$r[0],y:$r[1]}),jn.unactivate(),y.touchData.start=null}else{var qf=y.findNearestElement($r[0],$r[1],!0,!0);x(qf,["touchend","tapend","vmouseup","tapdragout"],Qt,{x:$r[0],y:$r[1]})}var Cp=y.touchData.startPosition[0]-$r[0],_p=Cp*Cp,Hf=y.touchData.startPosition[1]-$r[1],_g=Hf*Hf,cd=_p+_g,mw=cd*Ia*Ia;y.touchData.singleTouchMoved||(jn||sr.$(":selected").unselect(["tapunselect"]),x(jn,["tap","vclick"],Qt,{x:$r[0],y:$r[1]}),Xs=!1,Qt.timeStamp-Ci<=sr.multiClickDebounceTime()?(Ea&&clearTimeout(Ea),Xs=!0,Ci=null,x(jn,["dbltap","vdblclick"],Qt,{x:$r[0],y:$r[1]})):(Ea=setTimeout(function(){Xs||x(jn,["onetap","voneclick"],Qt,{x:$r[0],y:$r[1]})},sr.multiClickDebounceTime()),Ci=Qt.timeStamp)),jn!=null&&!y.dragData.didDrag&&jn._private.selectable&&mw"u"){var hi=[],gs=function(Qt){return{clientX:Qt.clientX,clientY:Qt.clientY,force:1,identifier:Qt.pointerId,pageX:Qt.pageX,pageY:Qt.pageY,radiusX:Qt.width/2,radiusY:Qt.height/2,screenX:Qt.screenX,screenY:Qt.screenY,target:Qt.target}},qi=function(Qt){return{event:Qt,touch:gs(Qt)}},Si=function(Qt){hi.push(qi(Qt))},Ui=function(Qt){for(var jn=0;jn0)return Sn[0]}return null},ot=Object.keys(Y),ht=0;ht0?rt:fN(O,P,g,x,T,L,$)},checkPoint:function(g,x,T,L,O,P,$){var q=Lk(L,O),S=2*q;if(dw(g,x,this.points,P,$,L,O-S,[0,-1],T)||dw(g,x,this.points,P,$,L-S,O,[0,-1],T))return!0;var V=L/2+2*T,Y=O/2+2*T,rt=[P-V,$-Y,P-V,$,P+V,$,P+V,$-Y];return!!(qd(g,x,rt)||S3(g,x,S,S,P+L/2-q,$+O/2-q,T)||S3(g,x,S,S,P-L/2+q,$+O/2-q,T))}}},bw.registerNodeShapes=function(){var y=this.nodeShapes={},g=this;this.generateEllipse(),this.generatePolygon("triangle",sd(3,0)),this.generateRoundPolygon("round-triangle",sd(3,0)),this.generatePolygon("rectangle",sd(4,0)),y.square=y.rectangle,this.generateRoundRectangle(),this.generateCutRectangle(),this.generateBarrel(),this.generateBottomRoundrectangle();{var x=[0,1,1,0,0,-1,-1,0];this.generatePolygon("diamond",x),this.generateRoundPolygon("round-diamond",x)}this.generatePolygon("pentagon",sd(5,0)),this.generateRoundPolygon("round-pentagon",sd(5,0)),this.generatePolygon("hexagon",sd(6,0)),this.generateRoundPolygon("round-hexagon",sd(6,0)),this.generatePolygon("heptagon",sd(7,0)),this.generateRoundPolygon("round-heptagon",sd(7,0)),this.generatePolygon("octagon",sd(8,0)),this.generateRoundPolygon("round-octagon",sd(8,0));var T=new Array(20);{var L=ML(5,0),O=ML(5,Math.PI/5),P=.5*(3-Math.sqrt(5));P*=1.57;for(var $=0;$=g.deqFastCost*$t)break}else if(S){if(Dt>=g.deqCost*ot||Dt>=g.deqAvgCost*rt)break}else if(Pt>=g.deqNoDrawCost*rM)break;var Zt=g.deq(T,Lt,dt);if(Zt.length>0)for(var Yt=0;Yt0&&(g.onDeqd(T,ht),!S&&g.shouldRedraw(T,ht,Lt,dt)&&O())},$=g.priority||EL;L.beforeRender(P,$(T))}}}},dtt=function(){function y(g){var x=arguments.length>1&&arguments[1]!==void 0?arguments[1]:wm;p(this,y),this.idsByKey=new Gb,this.keyForId=new Gb,this.cachesByLvl=new Gb,this.lvls=[],this.getKey=g,this.doesEleInvalidateKey=x}return m(y,[{key:"getIdsFor",value:function(x){x==null&&vl("Can not get id list for null key");var T=this.idsByKey,L=this.idsByKey.get(x);return L||(L=new Y5,T.set(x,L)),L}},{key:"addIdForKey",value:function(x,T){x!=null&&this.getIdsFor(x).add(T)}},{key:"deleteIdForKey",value:function(x,T){x!=null&&this.getIdsFor(x).delete(T)}},{key:"getNumberOfIdsForKey",value:function(x){return x==null?0:this.getIdsFor(x).size}},{key:"updateKeyMappingFor",value:function(x){var T=x.id(),L=this.keyForId.get(T),O=this.getKey(x);this.deleteIdForKey(L,T),this.addIdForKey(O,T),this.keyForId.set(T,O)}},{key:"deleteKeyMappingFor",value:function(x){var T=x.id(),L=this.keyForId.get(T);this.deleteIdForKey(L,T),this.keyForId.delete(T)}},{key:"keyHasChangedFor",value:function(x){var T=x.id(),L=this.keyForId.get(T),O=this.getKey(x);return L!==O}},{key:"isInvalid",value:function(x){return this.keyHasChangedFor(x)||this.doesEleInvalidateKey(x)}},{key:"getCachesAt",value:function(x){var T=this.cachesByLvl,L=this.lvls,O=T.get(x);return O||(O=new Gb,T.set(x,O),L.push(x)),O}},{key:"getCache",value:function(x,T){return this.getCachesAt(T).get(x)}},{key:"get",value:function(x,T){var L=this.getKey(x),O=this.getCache(L,T);return O!=null&&this.updateKeyMappingFor(x),O}},{key:"getForCachedKey",value:function(x,T){var L=this.keyForId.get(x.id()),O=this.getCache(L,T);return O}},{key:"hasCache",value:function(x,T){return this.getCachesAt(T).has(x)}},{key:"has",value:function(x,T){var L=this.getKey(x);return this.hasCache(L,T)}},{key:"setCache",value:function(x,T,L){L.key=x,this.getCachesAt(T).set(x,L)}},{key:"set",value:function(x,T,L){var O=this.getKey(x);this.setCache(O,T,L),this.updateKeyMappingFor(x)}},{key:"deleteCache",value:function(x,T){this.getCachesAt(T).delete(x)}},{key:"delete",value:function(x,T){var L=this.getKey(x);this.deleteCache(L,T)}},{key:"invalidateKey",value:function(x){var T=this;this.lvls.forEach(function(L){return T.deleteCache(x,L)})}},{key:"invalidate",value:function(x){var T=x.id(),L=this.keyForId.get(T);this.deleteKeyMappingFor(x);var O=this.doesEleInvalidateKey(x);return O&&this.invalidateKey(L),O||this.getNumberOfIdsForKey(L)===0}}]),y}(),xC=25,kC=50,px=-4,iM=3,sM=7.99,gtt=8,ptt=1024,btt=1024,rR=1024,wtt=.2,vtt=.8,mtt=10,ytt=.15,xtt=.1,ktt=.9,Ett=.9,Ttt=100,Ctt=1,bx={dequeue:"dequeue",downscale:"downscale",highQuality:"highQuality"},_tt=Rf({getKey:null,doesEleInvalidateKey:wm,drawElement:null,getBoundingBox:null,getRotationPoint:null,getRotationOffset:null,isVisible:T3,allowEdgeTxrCaching:!0,allowParentTxrCaching:!0}),Kk=function(g,x){var T=this;T.renderer=g,T.onDequeues=[];var L=_tt(x);de(T,L),T.lookup=new dtt(L.getKey,L.doesEleInvalidateKey),T.setupDequeueing()},Th=Kk.prototype;Th.reasons=bx,Th.getTextureQueue=function(y){var g=this;return g.eleImgCaches=g.eleImgCaches||{},g.eleImgCaches[y]=g.eleImgCaches[y]||[]},Th.getRetiredTextureQueue=function(y){var g=this,x=g.eleImgCaches.retired=g.eleImgCaches.retired||{},T=x[y]=x[y]||[];return T},Th.getElementQueue=function(){var y=this,g=y.eleCacheQueue=y.eleCacheQueue||new Ck(function(x,T){return T.reqs-x.reqs});return g},Th.getElementKeyToQueue=function(){var y=this,g=y.eleKeyToCacheQueue=y.eleKeyToCacheQueue||{};return g},Th.getElement=function(y,g,x,T,L){var O=this,P=this.renderer,$=P.cy.zoom(),q=this.lookup;if(!g||g.w===0||g.h===0||isNaN(g.w)||isNaN(g.h)||!y.visible()||y.removed()||!O.allowEdgeTxrCaching&&y.isEdge()||!O.allowParentTxrCaching&&y.isParent())return null;if(T==null&&(T=Math.ceil(_L($*x))),T=sM||T>iM)return null;var S=Math.pow(2,T),V=g.h*S,Y=g.w*S,rt=P.eleTextBiggerThanMin(y,S);if(!this.isVisible(y,rt))return null;var ot=q.get(y,T);if(ot&&ot.invalidated&&(ot.invalidated=!1,ot.texture.invalidatedWidth-=ot.width),ot)return ot;var ht;if(V<=xC?ht=xC:V<=kC?ht=kC:ht=Math.ceil(V/kC)*kC,V>rR||Y>btt)return null;var dt=O.getTextureQueue(ht),Lt=dt[dt.length-2],kt=function(){return O.recycleTexture(ht,Y)||O.addTexture(ht,Y)};Lt||(Lt=dt[dt.length-1]),Lt||(Lt=kt()),Lt.width-Lt.usedWidthT;be--)Gt=O.getElement(y,g,x,be,bx.downscale);ge()}else return O.queueElement(y,Yt.level-1),Yt;else{var ie;if(!Pt&&!$t&&!Zt)for(var Fe=T-1;Fe>=px;Fe--){var we=q.get(y,Fe);if(we){ie=we;break}}if(Dt(ie))return O.queueElement(y,T),ie;Lt.context.translate(Lt.usedWidth,0),Lt.context.scale(S,S),this.drawElement(Lt.context,y,g,rt,!1),Lt.context.scale(1/S,1/S),Lt.context.translate(-Lt.usedWidth,0)}return ot={x:Lt.usedWidth,texture:Lt,level:T,scale:S,width:Y,height:V,scaledLabelShown:rt},Lt.usedWidth+=Math.ceil(Y+gtt),Lt.eleCaches.push(ot),q.set(y,T,ot),O.checkTextureFullness(Lt),ot},Th.invalidateElements=function(y){for(var g=0;g=wtt*y.width&&this.retireTexture(y)},Th.checkTextureFullness=function(y){var g=this,x=g.getTextureQueue(y.height);y.usedWidth/y.width>vtt&&y.fullnessChecks>=mtt?vm(x,y):y.fullnessChecks++},Th.retireTexture=function(y){var g=this,x=y.height,T=g.getTextureQueue(x),L=this.lookup;vm(T,y),y.retired=!0;for(var O=y.eleCaches,P=0;P=g)return P.retired=!1,P.usedWidth=0,P.invalidatedWidth=0,P.fullnessChecks=0,TL(P.eleCaches),P.context.setTransform(1,0,0,1,0,0),P.context.clearRect(0,0,P.width,P.height),vm(L,P),T.push(P),P}},Th.queueElement=function(y,g){var x=this,T=x.getElementQueue(),L=x.getElementKeyToQueue(),O=this.getKey(y),P=L[O];if(P)P.level=Math.max(P.level,g),P.eles.merge(y),P.reqs++,T.updateItem(P);else{var $={eles:y.spawn().merge(y),level:g,reqs:1,key:O};T.push($),L[O]=$}},Th.dequeue=function(y){for(var g=this,x=g.getElementQueue(),T=g.getElementKeyToQueue(),L=[],O=g.lookup,P=0;P0;P++){var $=x.pop(),q=$.key,S=$.eles[0],V=O.hasCache(S,$.level);if(T[q]=null,V)continue;L.push($);var Y=g.getBoundingBox(S);g.getElement(S,Y,y,$.level,bx.dequeue)}return L},Th.removeFromQueue=function(y){var g=this,x=g.getElementQueue(),T=g.getElementKeyToQueue(),L=this.getKey(y),O=T[L];O!=null&&(O.eles.length===1?(O.reqs=W5,x.updateItem(O),x.pop(),T[L]=null):O.eles.unmerge(y))},Th.onDequeue=function(y){this.onDequeues.push(y)},Th.offDequeue=function(y){vm(this.onDequeues,y)},Th.setupDequeueing=yC.setupDequeueing({deqRedrawThreshold:Ttt,deqCost:ytt,deqAvgCost:xtt,deqNoDrawCost:ktt,deqFastCost:Ett,deq:function(g,x,T){return g.dequeue(x,T)},onDeqd:function(g,x){for(var T=0;T=EC||x>Xk)return null}T.validateLayersElesOrdering(x,y);var q=T.layersByLevel,S=Math.pow(2,x),V=q[x]=q[x]||[],Y,rt=T.levelIsComplete(x,y),ot,ht=function(){var ge=function(bn){if(T.validateLayersElesOrdering(bn,y),T.levelIsComplete(bn,y))return ot=q[bn],!0},be=function(bn){if(!ot)for(var ze=x+bn;wx<=ze&&ze<=Xk&&!ge(ze);ze+=bn);};be(1),be(-1);for(var ie=V.length-1;ie>=0;ie--){var Fe=V[ie];Fe.invalid&&vm(V,Fe)}};if(!rt)ht();else return V;var dt=function(){if(!Y){Y=zd();for(var ge=0;gefpt)return null;var Fe=T.makeLayer(Y,x);if(be!=null){var we=V.indexOf(be)+1;V.splice(we,0,Fe)}else(ge.insert===void 0||ge.insert)&&V.unshift(Fe);return Fe};if(T.skipping&&!$)return null;for(var kt=null,Dt=y.length/Stt,Pt=!$,$t=0;$t=Dt||!hN(kt.bb,Zt.boundingBox()))&&(kt=Lt({insert:!0,after:kt}),!kt))return null;ot||Pt?T.queueLayer(kt,Zt):T.drawEleInLayer(kt,Zt,x,g),kt.eles.push(Zt),qt[x]=kt}return ot||(Pt?null:V)},w1.getEleLevelForLayerLevel=function(y,g){return y},w1.drawEleInLayer=function(y,g,x,T){var L=this,O=this.renderer,P=y.context,$=g.boundingBox();$.w===0||$.h===0||!g.visible()||(x=L.getEleLevelForLayerLevel(x,T),O.setImgSmoothing(P,!1),O.drawCachedElement(P,g,null,null,x,dpt),O.setImgSmoothing(P,!0))},w1.levelIsComplete=function(y,g){var x=this,T=x.layersByLevel[y];if(!T||T.length===0)return!1;for(var L=0,O=0;O0||P.invalid)return!1;L+=P.eles.length}return L===g.length},w1.validateLayersElesOrdering=function(y,g){var x=this.layersByLevel[y];if(x)for(var T=0;T0){g=!0;break}}return g},w1.invalidateElements=function(y){var g=this;y.length!==0&&(g.lastInvalidationTime=yg(),!(y.length===0||!g.haveLayers())&&g.updateElementsInLayers(y,function(T,L,O){g.invalidateLayer(T)}))},w1.invalidateLayer=function(y){if(this.lastInvalidationTime=yg(),!y.invalid){var g=y.level,x=y.eles,T=this.layersByLevel[g];vm(T,y),y.elesQueue=[],y.invalid=!0,y.replacement&&(y.replacement.invalid=!0);for(var L=0;L3&&arguments[3]!==void 0?arguments[3]:!0,L=arguments.length>4&&arguments[4]!==void 0?arguments[4]:!0,O=arguments.length>5&&arguments[5]!==void 0?arguments[5]:!0,P=this,$=g._private.rscratch;if(!(O&&!g.visible())&&!($.badLine||$.allpts==null||isNaN($.allpts[0]))){var q;x&&(q=x,y.translate(-q.x1,-q.y1));var S=O?g.pstyle("opacity").value:1,V=O?g.pstyle("line-opacity").value:1,Y=g.pstyle("curve-style").value,rt=g.pstyle("line-style").value,ot=g.pstyle("width").pfValue,ht=g.pstyle("line-cap").value,dt=S*V,Lt=S*V,kt=function(){var ie=arguments.length>0&&arguments[0]!==void 0?arguments[0]:dt;Y==="straight-triangle"?(P.eleStrokeStyle(y,g,ie),P.drawEdgeTrianglePath(g,y,$.allpts)):(y.lineWidth=ot,y.lineCap=ht,P.eleStrokeStyle(y,g,ie),P.drawEdgePath(g,y,$.allpts,rt),y.lineCap="butt")},Dt=function(){L&&P.drawEdgeOverlay(y,g)},Pt=function(){L&&P.drawEdgeUnderlay(y,g)},$t=function(){var ie=arguments.length>0&&arguments[0]!==void 0?arguments[0]:Lt;P.drawArrowheads(y,g,ie)},Zt=function(){P.drawElementText(y,g,null,T)};y.lineJoin="round";var Yt=g.pstyle("ghost").value==="yes";if(Yt){var qt=g.pstyle("ghost-offset-x").pfValue,ne=g.pstyle("ghost-offset-y").pfValue,Gt=g.pstyle("ghost-opacity").value,ge=dt*Gt;y.translate(qt,ne),kt(ge),$t(ge),y.translate(-qt,-ne)}Pt(),kt(),$t(),Dt(),Zt(),x&&y.translate(q.x1,q.y1)}};var Ott=function(g){if(!["overlay","underlay"].includes(g))throw new Error("Invalid state");return function(x,T){if(T.visible()){var L=T.pstyle("".concat(g,"-opacity")).value;if(L!==0){var O=this,P=O.usePaths(),$=T._private.rscratch,q=T.pstyle("".concat(g,"-padding")).pfValue,S=2*q,V=T.pstyle("".concat(g,"-color")).value;x.lineWidth=S,$.edgeType==="self"&&!P?x.lineCap="butt":x.lineCap="round",O.colorStrokeStyle(x,V[0],V[1],V[2],L),O.drawEdgePath(T,x,$.allpts,"solid")}}}};vw.drawEdgeOverlay=Ott("overlay"),vw.drawEdgeUnderlay=Ott("underlay"),vw.drawEdgePath=function(y,g,x,T){var L=y._private.rscratch,O=g,P,$=!1,q=this.usePaths(),S=y.pstyle("line-dash-pattern").pfValue,V=y.pstyle("line-dash-offset").pfValue;if(q){var Y=x.join("$"),rt=L.pathCacheKey&&L.pathCacheKey===Y;rt?(P=g=L.pathCache,$=!0):(P=g=new Path2D,L.pathCacheKey=Y,L.pathCache=P)}if(O.setLineDash)switch(T){case"dotted":O.setLineDash([1,1]);break;case"dashed":O.setLineDash(S),O.lineDashOffset=V;break;case"solid":O.setLineDash([]);break}if(!$&&!L.badLine)switch(g.beginPath&&g.beginPath(),g.moveTo(x[0],x[1]),L.edgeType){case"bezier":case"self":case"compound":case"multibezier":for(var ot=2;ot+35&&arguments[5]!==void 0?arguments[5]:!0,P=this;if(T==null){if(O&&!P.eleTextBiggerThanMin(g))return}else if(T===!1)return;if(g.isNode()){var $=g.pstyle("label");if(!$||!$.value)return;var q=P.getLabelJustification(g);y.textAlign=q,y.textBaseline="bottom"}else{var S=g.element()._private.rscratch.badLine,V=g.pstyle("label"),Y=g.pstyle("source-label"),rt=g.pstyle("target-label");if(S||(!V||!V.value)&&(!Y||!Y.value)&&(!rt||!rt.value))return;y.textAlign="center",y.textBaseline="bottom"}var ot=!x,ht;x&&(ht=x,y.translate(-ht.x1,-ht.y1)),L==null?(P.drawText(y,g,null,ot,O),g.isEdge()&&(P.drawText(y,g,"source",ot,O),P.drawText(y,g,"target",ot,O))):P.drawText(y,g,L,ot,O),x&&y.translate(ht.x1,ht.y1)},vx.getFontCache=function(y){var g;this.fontCaches=this.fontCaches||[];for(var x=0;x2&&arguments[2]!==void 0?arguments[2]:!0,T=g.pstyle("font-style").strValue,L=g.pstyle("font-size").pfValue+"px",O=g.pstyle("font-family").strValue,P=g.pstyle("font-weight").strValue,$=x?g.effectiveOpacity()*g.pstyle("text-opacity").value:1,q=g.pstyle("text-outline-opacity").value*$,S=g.pstyle("color").value,V=g.pstyle("text-outline-color").value;y.font=T+" "+P+" "+L+" "+O,y.lineJoin="round",this.colorFillStyle(y,S[0],S[1],S[2],$),this.colorStrokeStyle(y,V[0],V[1],V[2],q)};function mpt(y,g,x,T,L){var O=arguments.length>5&&arguments[5]!==void 0?arguments[5]:5;y.beginPath(),y.moveTo(g+O,x),y.lineTo(g+T-O,x),y.quadraticCurveTo(g+T,x,g+T,x+O),y.lineTo(g+T,x+L-O),y.quadraticCurveTo(g+T,x+L,g+T-O,x+L),y.lineTo(g+O,x+L),y.quadraticCurveTo(g,x+L,g,x+L-O),y.lineTo(g,x+O),y.quadraticCurveTo(g,x,g+O,x),y.closePath(),y.fill()}vx.getTextAngle=function(y,g){var x,T=y._private,L=T.rscratch,O=g?g+"-":"",P=y.pstyle(O+"text-rotation"),$=yp(L,"labelAngle",g);return P.strValue==="autorotate"?x=y.isEdge()?$:0:P.strValue==="none"?x=0:x=P.pfValue,x},vx.drawText=function(y,g,x){var T=arguments.length>3&&arguments[3]!==void 0?arguments[3]:!0,L=arguments.length>4&&arguments[4]!==void 0?arguments[4]:!0,O=g._private,P=O.rscratch,$=L?g.effectiveOpacity():1;if(!(L&&($===0||g.pstyle("text-opacity").value===0))){x==="main"&&(x=null);var q=yp(P,"labelX",x),S=yp(P,"labelY",x),V,Y,rt=this.getLabelText(g,x);if(rt!=null&&rt!==""&&!isNaN(q)&&!isNaN(S)){this.setupTextStyle(y,g,L);var ot=x?x+"-":"",ht=yp(P,"labelWidth",x),dt=yp(P,"labelHeight",x),Lt=g.pstyle(ot+"text-margin-x").pfValue,kt=g.pstyle(ot+"text-margin-y").pfValue,Dt=g.isEdge(),Pt=g.pstyle("text-halign").value,$t=g.pstyle("text-valign").value;Dt&&(Pt="center",$t="center"),q+=Lt,S+=kt;var Zt;switch(T?Zt=this.getTextAngle(g,x):Zt=0,Zt!==0&&(V=q,Y=S,y.translate(V,Y),y.rotate(Zt),q=0,S=0),$t){case"top":break;case"center":S+=dt/2;break;case"bottom":S+=dt;break}var Yt=g.pstyle("text-background-opacity").value,qt=g.pstyle("text-border-opacity").value,ne=g.pstyle("text-border-width").pfValue,Gt=g.pstyle("text-background-padding").pfValue;if(Yt>0||ne>0&&qt>0){var ge=q-Gt;switch(Pt){case"left":ge-=ht;break;case"center":ge-=ht/2;break}var be=S-dt-Gt,ie=ht+2*Gt,Fe=dt+2*Gt;if(Yt>0){var we=y.fillStyle,bn=g.pstyle("text-background-color").value;y.fillStyle="rgba("+bn[0]+","+bn[1]+","+bn[2]+","+Yt*$+")";var ze=g.pstyle("text-background-shape").strValue;ze.indexOf("round")===0?mpt(y,ge,be,ie,Fe,2):y.fillRect(ge,be,ie,Fe),y.fillStyle=we}if(ne>0&&qt>0){var Ge=y.strokeStyle,En=y.lineWidth,In=g.pstyle("text-border-color").value,Yn=g.pstyle("text-border-style").value;if(y.strokeStyle="rgba("+In[0]+","+In[1]+","+In[2]+","+qt*$+")",y.lineWidth=ne,y.setLineDash)switch(Yn){case"dotted":y.setLineDash([1,1]);break;case"dashed":y.setLineDash([4,2]);break;case"double":y.lineWidth=ne/4,y.setLineDash([]);break;case"solid":y.setLineDash([]);break}if(y.strokeRect(ge,be,ie,Fe),Yn==="double"){var Sn=ne/2;y.strokeRect(ge+Sn,be+Sn,ie-Sn*2,Fe-Sn*2)}y.setLineDash&&y.setLineDash([]),y.lineWidth=En,y.strokeStyle=Ge}}var Wn=2*g.pstyle("text-outline-width").pfValue;if(Wn>0&&(y.lineWidth=Wn),g.pstyle("text-wrap").value==="wrap"){var rr=yp(P,"labelWrapCachedLines",x),wr=yp(P,"labelLineHeight",x),ur=ht/2,er=this.getLabelJustification(g);switch(er==="auto"||(Pt==="left"?er==="left"?q+=-ht:er==="center"&&(q+=-ur):Pt==="center"?er==="left"?q+=-ur:er==="right"&&(q+=ur):Pt==="right"&&(er==="center"?q+=ur:er==="right"&&(q+=ht))),$t){case"top":S-=(rr.length-1)*wr;break;case"center":case"bottom":S-=(rr.length-1)*wr;break}for(var vn=0;vn0&&y.strokeText(rr[vn],q,S),y.fillText(rr[vn],q,S),S+=wr}else Wn>0&&y.strokeText(rt,q,S),y.fillText(rt,q,S);Zt!==0&&(y.rotate(-Zt),y.translate(-V,-Y))}}};var Zk={};Zk.drawNode=function(y,g,x){var T=arguments.length>3&&arguments[3]!==void 0?arguments[3]:!0,L=arguments.length>4&&arguments[4]!==void 0?arguments[4]:!0,O=arguments.length>5&&arguments[5]!==void 0?arguments[5]:!0,P=this,$,q,S=g._private,V=S.rscratch,Y=g.position();if(!(!X(Y.x)||!X(Y.y))&&!(O&&!g.visible())){var rt=O?g.effectiveOpacity():1,ot=P.usePaths(),ht,dt=!1,Lt=g.padding();$=g.width()+2*Lt,q=g.height()+2*Lt;var kt;x&&(kt=x,y.translate(-kt.x1,-kt.y1));for(var Dt=g.pstyle("background-image"),Pt=Dt.value,$t=new Array(Pt.length),Zt=new Array(Pt.length),Yt=0,qt=0;qt0&&arguments[0]!==void 0?arguments[0]:Fe;P.eleFillStyle(y,g,Si)},En=function(){var Si=arguments.length>0&&arguments[0]!==void 0?arguments[0]:ze;P.colorStrokeStyle(y,we[0],we[1],we[2],Si)},In=g.pstyle("shape").strValue,Yn=g.pstyle("shape-polygon-points").pfValue;if(ot){y.translate(Y.x,Y.y);var Sn=P.nodePathCache=P.nodePathCache||[],Wn=id(In==="polygon"?In+","+Yn.join(","):In,""+q,""+$),rr=Sn[Wn];rr!=null?(ht=rr,dt=!0,V.pathCache=ht):(ht=new Path2D,Sn[Wn]=V.pathCache=ht)}var wr=function(){if(!dt){var Si=Y;ot&&(Si={x:0,y:0}),P.nodeShapes[P.getNodeShape(g)].draw(ht||y,Si.x,Si.y,$,q)}ot?y.fill(ht):y.fill()},ur=function(){for(var Si=arguments.length>0&&arguments[0]!==void 0?arguments[0]:rt,Ui=arguments.length>1&&arguments[1]!==void 0?arguments[1]:!0,Va=S.backgrounding,Qs=0,qs=0;qs0&&arguments[0]!==void 0?arguments[0]:!1,Ui=arguments.length>1&&arguments[1]!==void 0?arguments[1]:rt;P.hasPie(g)&&(P.drawPie(y,g,Ui),Si&&(ot||P.nodeShapes[P.getNodeShape(g)].draw(y,Y.x,Y.y,$,q)))},vn=function(){var Si=arguments.length>0&&arguments[0]!==void 0?arguments[0]:rt,Ui=(be>0?be:-be)*Si,Va=be>0?0:255;be!==0&&(P.colorFillStyle(y,Va,Va,Va,Ui),ot?y.fill(ht):y.fill())},gr=function(){if(ie>0){if(y.lineWidth=ie,y.lineCap="butt",y.setLineDash)switch(bn){case"dotted":y.setLineDash([1,1]);break;case"dashed":y.setLineDash([4,2]);break;case"solid":case"double":y.setLineDash([]);break}if(ot?y.stroke(ht):y.stroke(),bn==="double"){y.lineWidth=ie/3;var Si=y.globalCompositeOperation;y.globalCompositeOperation="destination-out",ot?y.stroke(ht):y.stroke(),y.globalCompositeOperation=Si}y.setLineDash&&y.setLineDash([])}},fr=function(){L&&P.drawNodeOverlay(y,g,Y,$,q)},Jr=function(){L&&P.drawNodeUnderlay(y,g,Y,$,q)},vi=function(){P.drawElementText(y,g,null,T)},Xs=g.pstyle("ghost").value==="yes";if(Xs){var Ea=g.pstyle("ghost-offset-x").pfValue,Ci=g.pstyle("ghost-offset-y").pfValue,hi=g.pstyle("ghost-opacity").value,gs=hi*rt;y.translate(Ea,Ci),Ge(hi*Fe),wr(),ur(gs,!0),En(hi*ze),gr(),er(be!==0||ie!==0),ur(gs,!1),vn(gs),y.translate(-Ea,-Ci)}ot&&y.translate(-Y.x,-Y.y),Jr(),ot&&y.translate(Y.x,Y.y),Ge(),wr(),ur(rt,!0),En(),gr(),er(be!==0||ie!==0),ur(rt,!1),vn(),ot&&y.translate(-Y.x,-Y.y),vi(),fr(),x&&y.translate(kt.x1,kt.y1)}};var Ptt=function(g){if(!["overlay","underlay"].includes(g))throw new Error("Invalid state");return function(x,T,L,O,P){var $=this;if(T.visible()){var q=T.pstyle("".concat(g,"-padding")).pfValue,S=T.pstyle("".concat(g,"-opacity")).value,V=T.pstyle("".concat(g,"-color")).value,Y=T.pstyle("".concat(g,"-shape")).value;if(S>0){if(L=L||T.position(),O==null||P==null){var rt=T.padding();O=T.width()+2*rt,P=T.height()+2*rt}$.colorFillStyle(x,V[0],V[1],V[2],S),$.nodeShapes[Y].draw(x,L.x,L.y,O+q*2,P+q*2),x.fill()}}}};Zk.drawNodeOverlay=Ptt("overlay"),Zk.drawNodeUnderlay=Ptt("underlay"),Zk.hasPie=function(y){return y=y[0],y._private.hasPie},Zk.drawPie=function(y,g,x,T){g=g[0],T=T||g.position();var L=g.cy().style(),O=g.pstyle("pie-size"),P=T.x,$=T.y,q=g.width(),S=g.height(),V=Math.min(q,S)/2,Y=0,rt=this.usePaths();rt&&(P=0,$=0),O.units==="%"?V=V*O.pfValue:O.pfValue!==void 0&&(V=O.pfValue/2);for(var ot=1;ot<=L.pieBackgroundN;ot++){var ht=g.pstyle("pie-"+ot+"-background-size").value,dt=g.pstyle("pie-"+ot+"-background-color").value,Lt=g.pstyle("pie-"+ot+"-background-opacity").value*x,kt=ht/100;kt+Y>1&&(kt=1-Y);var Dt=1.5*Math.PI+2*Math.PI*Y,Pt=2*Math.PI*kt,$t=Dt+Pt;ht===0||Y>=1||Y+kt>1||(y.beginPath(),y.moveTo(P,$),y.arc(P,$,V,Dt,$t),y.closePath(),this.colorFillStyle(y,dt[0],dt[1],dt[2],Lt),y.fill(),Y+=kt)}};var Tg={},ypt=100;Tg.getPixelRatio=function(){var y=this.data.contexts[0];if(this.forcedPixelRatio!=null)return this.forcedPixelRatio;var g=y.backingStorePixelRatio||y.webkitBackingStorePixelRatio||y.mozBackingStorePixelRatio||y.msBackingStorePixelRatio||y.oBackingStorePixelRatio||y.backingStorePixelRatio||1;return(window.devicePixelRatio||1)/g},Tg.paintCache=function(y){for(var g=this.paintCaches=this.paintCaches||[],x=!0,T,L=0;LP.minMbLowQualFrames&&(P.motionBlurPxRatio=P.mbPxRBlurry)),P.clearingMotionBlur&&(P.motionBlurPxRatio=1),P.textureDrawLastFrame&&!Y&&(V[P.NODE]=!0,V[P.SELECT_BOX]=!0);var Dt=q.style(),Pt=q.zoom(),$t=L!==void 0?L:Pt,Zt=q.pan(),Yt={x:Zt.x,y:Zt.y},qt={zoom:Pt,pan:{x:Zt.x,y:Zt.y}},ne=P.prevViewport,Gt=ne===void 0||qt.zoom!==ne.zoom||qt.pan.x!==ne.pan.x||qt.pan.y!==ne.pan.y;!Gt&&!(dt&&!ht)&&(P.motionBlurPxRatio=1),O&&(Yt=O),$t*=$,Yt.x*=$,Yt.y*=$;var ge=P.getCachedZSortedEles();function be(Ci,hi,gs,qi,Si){var Ui=Ci.globalCompositeOperation;Ci.globalCompositeOperation="destination-out",P.colorFillStyle(Ci,255,255,255,P.motionBlurTransparency),Ci.fillRect(hi,gs,qi,Si),Ci.globalCompositeOperation=Ui}function ie(Ci,hi){var gs,qi,Si,Ui;!P.clearingMotionBlur&&(Ci===S.bufferContexts[P.MOTIONBLUR_BUFFER_NODE]||Ci===S.bufferContexts[P.MOTIONBLUR_BUFFER_DRAG])?(gs={x:Zt.x*ot,y:Zt.y*ot},qi=Pt*ot,Si=P.canvasWidth*ot,Ui=P.canvasHeight*ot):(gs=Yt,qi=$t,Si=P.canvasWidth,Ui=P.canvasHeight),Ci.setTransform(1,0,0,1,0,0),hi==="motionBlur"?be(Ci,0,0,Si,Ui):!g&&(hi===void 0||hi)&&Ci.clearRect(0,0,Si,Ui),x||(Ci.translate(gs.x,gs.y),Ci.scale(qi,qi)),O&&Ci.translate(O.x,O.y),L&&Ci.scale(L,L)}if(Y||(P.textureDrawLastFrame=!1),Y){if(P.textureDrawLastFrame=!0,!P.textureCache){P.textureCache={},P.textureCache.bb=q.mutableElements().boundingBox(),P.textureCache.texture=P.data.bufferCanvases[P.TEXTURE_BUFFER];var Fe=P.data.bufferContexts[P.TEXTURE_BUFFER];Fe.setTransform(1,0,0,1,0,0),Fe.clearRect(0,0,P.canvasWidth*P.textureMult,P.canvasHeight*P.textureMult),P.render({forcedContext:Fe,drawOnlyNodeLayer:!0,forcedPxRatio:$*P.textureMult});var qt=P.textureCache.viewport={zoom:q.zoom(),pan:q.pan(),width:P.canvasWidth,height:P.canvasHeight};qt.mpan={x:(0-qt.pan.x)/qt.zoom,y:(0-qt.pan.y)/qt.zoom}}V[P.DRAG]=!1,V[P.NODE]=!1;var we=S.contexts[P.NODE],bn=P.textureCache.texture,qt=P.textureCache.viewport;we.setTransform(1,0,0,1,0,0),rt?be(we,0,0,qt.width,qt.height):we.clearRect(0,0,qt.width,qt.height);var ze=Dt.core("outside-texture-bg-color").value,Ge=Dt.core("outside-texture-bg-opacity").value;P.colorFillStyle(we,ze[0],ze[1],ze[2],Ge),we.fillRect(0,0,qt.width,qt.height);var Pt=q.zoom();ie(we,!1),we.clearRect(qt.mpan.x,qt.mpan.y,qt.width/qt.zoom/$,qt.height/qt.zoom/$),we.drawImage(bn,qt.mpan.x,qt.mpan.y,qt.width/qt.zoom/$,qt.height/qt.zoom/$)}else P.textureOnViewport&&!g&&(P.textureCache=null);var En=q.extent(),In=P.pinching||P.hoverData.dragging||P.swipePanning||P.data.wheelZooming||P.hoverData.draggingEles||P.cy.animated(),Yn=P.hideEdgesOnViewport&&In,Sn=[];if(Sn[P.NODE]=!V[P.NODE]&&rt&&!P.clearedForMotionBlur[P.NODE]||P.clearingMotionBlur,Sn[P.NODE]&&(P.clearedForMotionBlur[P.NODE]=!0),Sn[P.DRAG]=!V[P.DRAG]&&rt&&!P.clearedForMotionBlur[P.DRAG]||P.clearingMotionBlur,Sn[P.DRAG]&&(P.clearedForMotionBlur[P.DRAG]=!0),V[P.NODE]||x||T||Sn[P.NODE]){var Wn=rt&&!Sn[P.NODE]&&ot!==1,we=g||(Wn?P.data.bufferContexts[P.MOTIONBLUR_BUFFER_NODE]:S.contexts[P.NODE]),rr=rt&&!Wn?"motionBlur":void 0;ie(we,rr),Yn?P.drawCachedNodes(we,ge.nondrag,$,En):P.drawLayeredElements(we,ge.nondrag,$,En),P.debug&&P.drawDebugPoints(we,ge.nondrag),!x&&!rt&&(V[P.NODE]=!1)}if(!T&&(V[P.DRAG]||x||Sn[P.DRAG])){var Wn=rt&&!Sn[P.DRAG]&&ot!==1,we=g||(Wn?P.data.bufferContexts[P.MOTIONBLUR_BUFFER_DRAG]:S.contexts[P.DRAG]);ie(we,rt&&!Wn?"motionBlur":void 0),Yn?P.drawCachedNodes(we,ge.drag,$,En):P.drawCachedElements(we,ge.drag,$,En),P.debug&&P.drawDebugPoints(we,ge.drag),!x&&!rt&&(V[P.DRAG]=!1)}if(P.showFps||!T&&V[P.SELECT_BOX]&&!x){var we=g||S.contexts[P.SELECT_BOX];if(ie(we),P.selection[4]==1&&(P.hoverData.selecting||P.touchData.selecting)){var Pt=P.cy.zoom(),wr=Dt.core("selection-box-border-width").value/Pt;we.lineWidth=wr,we.fillStyle="rgba("+Dt.core("selection-box-color").value[0]+","+Dt.core("selection-box-color").value[1]+","+Dt.core("selection-box-color").value[2]+","+Dt.core("selection-box-opacity").value+")",we.fillRect(P.selection[0],P.selection[1],P.selection[2]-P.selection[0],P.selection[3]-P.selection[1]),wr>0&&(we.strokeStyle="rgba("+Dt.core("selection-box-border-color").value[0]+","+Dt.core("selection-box-border-color").value[1]+","+Dt.core("selection-box-border-color").value[2]+","+Dt.core("selection-box-opacity").value+")",we.strokeRect(P.selection[0],P.selection[1],P.selection[2]-P.selection[0],P.selection[3]-P.selection[1]))}if(S.bgActivePosistion&&!P.hoverData.selecting){var Pt=P.cy.zoom(),ur=S.bgActivePosistion;we.fillStyle="rgba("+Dt.core("active-bg-color").value[0]+","+Dt.core("active-bg-color").value[1]+","+Dt.core("active-bg-color").value[2]+","+Dt.core("active-bg-opacity").value+")",we.beginPath(),we.arc(ur.x,ur.y,Dt.core("active-bg-size").pfValue/Pt,0,2*Math.PI),we.fill()}var er=P.lastRedrawTime;if(P.showFps&&er){er=Math.round(er);var vn=Math.round(1e3/er);we.setTransform(1,0,0,1,0,0),we.fillStyle="rgba(255, 0, 0, 0.75)",we.strokeStyle="rgba(255, 0, 0, 0.75)",we.lineWidth=1,we.fillText("1 frame = "+er+" ms = "+vn+" fps",0,20);var gr=60;we.strokeRect(0,30,250,20),we.fillRect(0,30,250*Math.min(vn/gr,1),20)}x||(V[P.SELECT_BOX]=!1)}if(rt&&ot!==1){var fr=S.contexts[P.NODE],Jr=P.data.bufferCanvases[P.MOTIONBLUR_BUFFER_NODE],vi=S.contexts[P.DRAG],Xs=P.data.bufferCanvases[P.MOTIONBLUR_BUFFER_DRAG],Ea=function(hi,gs,qi){hi.setTransform(1,0,0,1,0,0),qi||!kt?hi.clearRect(0,0,P.canvasWidth,P.canvasHeight):be(hi,0,0,P.canvasWidth,P.canvasHeight);var Si=ot;hi.drawImage(gs,0,0,P.canvasWidth*Si,P.canvasHeight*Si,0,0,P.canvasWidth,P.canvasHeight)};(V[P.NODE]||Sn[P.NODE])&&(Ea(fr,Jr,Sn[P.NODE]),V[P.NODE]=!1),(V[P.DRAG]||Sn[P.DRAG])&&(Ea(vi,Xs,Sn[P.DRAG]),V[P.DRAG]=!1)}P.prevViewport=qt,P.clearingMotionBlur&&(P.clearingMotionBlur=!1,P.motionBlurCleared=!0,P.motionBlur=!0),rt&&(P.motionBlurTimeout=setTimeout(function(){P.motionBlurTimeout=null,P.clearedForMotionBlur[P.NODE]=!1,P.clearedForMotionBlur[P.DRAG]=!1,P.motionBlur=!1,P.clearingMotionBlur=!Y,P.mbFrames=0,V[P.NODE]=!0,V[P.DRAG]=!0,P.redraw()},ypt)),g||q.emit("render")};var O3={};O3.drawPolygonPath=function(y,g,x,T,L,O){var P=T/2,$=L/2;y.beginPath&&y.beginPath(),y.moveTo(g+P*O[0],x+$*O[1]);for(var q=1;q0&&P>0){ot.clearRect(0,0,O,P),ot.globalCompositeOperation="source-over";var ht=this.getCachedZSortedEles();if(y.full)ot.translate(-T.x1*S,-T.y1*S),ot.scale(S,S),this.drawElements(ot,ht),ot.scale(1/S,1/S),ot.translate(T.x1*S,T.y1*S);else{var dt=g.pan(),Lt={x:dt.x*S,y:dt.y*S};S*=g.zoom(),ot.translate(Lt.x,Lt.y),ot.scale(S,S),this.drawElements(ot,ht),ot.scale(1/S,1/S),ot.translate(-Lt.x,-Lt.y)}y.bg&&(ot.globalCompositeOperation="destination-over",ot.fillStyle=y.bg,ot.rect(0,0,O,P),ot.fill())}return rt};function xpt(y,g){for(var x=atob(y),T=new ArrayBuffer(x.length),L=new Uint8Array(T),O=0;O"u"?"undefined":f(OffscreenCanvas))!=="undefined"?x=new OffscreenCanvas(y,g):(x=document.createElement("canvas"),x.width=y,x.height=g),x},[D0,ww,vw,CC,vx,Zk,Tg,O3,_C,$tt].forEach(function(y){de(vc,y)});var mx=[{name:"null",impl:WB},{name:"base",impl:nM},{name:"canvas",impl:kpt}],Cg=[{type:"layout",extensions:ltt},{type:"renderer",extensions:mx}],Sm={},cM={};function v1(y,g,x){var T=x,L=function(ne){Sc("Can not register `"+g+"` for `"+y+"` since `"+ne+"` already exists in the prototype and can not be overridden")};if(y==="core"){if(Vk.prototype[g])return L(g);Vk.prototype[g]=x}else if(y==="collection"){if($f.prototype[g])return L(g);$f.prototype[g]=x}else if(y==="layout"){for(var O=function(ne){this.options=ne,x.call(this,ne),ut(this._private)||(this._private={}),this._private.cy=ne.cy,this._private.listeners=[],this.createEmitter()},P=O.prototype=Object.create(x.prototype),$=[],q=0;q<$.length;q++){var S=$[q];P[S]=P[S]||function(){return this}}P.start&&!P.run?P.run=function(){return this.start(),this}:!P.start&&P.run&&(P.start=function(){return this.run(),this});var V=x.prototype.stop;P.stop=function(){var qt=this.options;if(qt&&qt.animate){var ne=this.animations;if(ne)for(var Gt=0;Gtz&&(this.rect.x-=(this.labelWidth-z)/2,this.setWidth(this.labelWidth)),this.labelHeight>W&&(this.labelPos=="center"?this.rect.y-=(this.labelHeight-W)/2:this.labelPos=="top"&&(this.rect.y-=this.labelHeight-W),this.setHeight(this.labelHeight))}}},B.prototype.getInclusionTreeDepth=function(){if(this.inclusionTreeDepth==b.MAX_VALUE)throw"assert failed";return this.inclusionTreeDepth},B.prototype.transform=function(R){var z=this.rect.x;z>_.WORLD_BOUNDARY?z=_.WORLD_BOUNDARY:z<-_.WORLD_BOUNDARY&&(z=-_.WORLD_BOUNDARY);var W=this.rect.y;W>_.WORLD_BOUNDARY?W=_.WORLD_BOUNDARY:W<-_.WORLD_BOUNDARY&&(W=-_.WORLD_BOUNDARY);var et=new I(z,W),st=R.inverseTransformPoint(et);this.setLocation(st.x,st.y)},B.prototype.getLeft=function(){return this.rect.x},B.prototype.getRight=function(){return this.rect.x+this.rect.width},B.prototype.getTop=function(){return this.rect.y},B.prototype.getBottom=function(){return this.rect.y+this.rect.height},B.prototype.getParent=function(){return this.owner==null?null:this.owner.getParent()},f.exports=B},function(f,p,w){function m(b,E){b==null&&E==null?(this.x=0,this.y=0):(this.x=b,this.y=E)}m.prototype.getX=function(){return this.x},m.prototype.getY=function(){return this.y},m.prototype.setX=function(b){this.x=b},m.prototype.setY=function(b){this.y=b},m.prototype.getDifference=function(b){return new DimensionD(this.x-b.x,this.y-b.y)},m.prototype.getCopy=function(){return new m(this.x,this.y)},m.prototype.translate=function(b){return this.x+=b.width,this.y+=b.height,this},f.exports=m},function(f,p,w){var m=w(2),b=w(10),E=w(0),_=w(6),A=w(3),I=w(1),B=w(13),N=w(12),R=w(11);function z(et,st,at){m.call(this,at),this.estimatedSize=b.MIN_VALUE,this.margin=E.DEFAULT_GRAPH_MARGIN,this.edges=[],this.nodes=[],this.isConnected=!1,this.parent=et,st!=null&&st instanceof _?this.graphManager=st:st!=null&&st instanceof Layout&&(this.graphManager=st.graphManager)}z.prototype=Object.create(m.prototype);for(var W in m)z[W]=m[W];z.prototype.getNodes=function(){return this.nodes},z.prototype.getEdges=function(){return this.edges},z.prototype.getGraphManager=function(){return this.graphManager},z.prototype.getParent=function(){return this.parent},z.prototype.getLeft=function(){return this.left},z.prototype.getRight=function(){return this.right},z.prototype.getTop=function(){return this.top},z.prototype.getBottom=function(){return this.bottom},z.prototype.isConnected=function(){return this.isConnected},z.prototype.add=function(et,st,at){if(st==null&&at==null){var bt=et;if(this.graphManager==null)throw"Graph has no graph mgr!";if(this.getNodes().indexOf(bt)>-1)throw"Node already in graph!";return bt.owner=this,this.getNodes().push(bt),bt}else{var mt=et;if(!(this.getNodes().indexOf(st)>-1&&this.getNodes().indexOf(at)>-1))throw"Source or target not in graph!";if(!(st.owner==at.owner&&st.owner==this))throw"Both owners must be this graph!";return st.owner!=at.owner?null:(mt.source=st,mt.target=at,mt.isInterGraph=!1,this.getEdges().push(mt),st.edges.push(mt),at!=st&&at.edges.push(mt),mt)}},z.prototype.remove=function(et){var st=et;if(et instanceof A){if(st==null)throw"Node is null!";if(!(st.owner!=null&&st.owner==this))throw"Owner graph is invalid!";if(this.graphManager==null)throw"Owner graph manager is invalid!";for(var at=st.edges.slice(),bt,mt=at.length,yt=0;yt-1&&vt>-1))throw"Source and/or target doesn't know this edge!";bt.source.edges.splice(ut,1),bt.target!=bt.source&&bt.target.edges.splice(vt,1);var ft=bt.source.owner.getEdges().indexOf(bt);if(ft==-1)throw"Not in owner's edge list!";bt.source.owner.getEdges().splice(ft,1)}},z.prototype.updateLeftTop=function(){for(var et=b.MAX_VALUE,st=b.MAX_VALUE,at,bt,mt,yt=this.getNodes(),ft=yt.length,ut=0;utat&&(et=at),st>bt&&(st=bt)}return et==b.MAX_VALUE?null:(yt[0].getParent().paddingLeft!=null?mt=yt[0].getParent().paddingLeft:mt=this.margin,this.left=st-mt,this.top=et-mt,new N(this.left,this.top))},z.prototype.updateBounds=function(et){for(var st=b.MAX_VALUE,at=-b.MAX_VALUE,bt=b.MAX_VALUE,mt=-b.MAX_VALUE,yt,ft,ut,vt,X,pt=this.nodes,U=pt.length,Tt=0;Ttyt&&(st=yt),atut&&(bt=ut),mtyt&&(st=yt),atut&&(bt=ut),mt=this.nodes.length){var U=0;at.forEach(function(Tt){Tt.owner==et&&U++}),U==this.nodes.length&&(this.isConnected=!0)}},f.exports=z},function(f,p,w){var m,b=w(1);function E(_){m=w(5),this.layout=_,this.graphs=[],this.edges=[]}E.prototype.addRoot=function(){var _=this.layout.newGraph(),A=this.layout.newNode(null),I=this.add(_,A);return this.setRootGraph(I),this.rootGraph},E.prototype.add=function(_,A,I,B,N){if(I==null&&B==null&&N==null){if(_==null)throw"Graph is null!";if(A==null)throw"Parent node is null!";if(this.graphs.indexOf(_)>-1)throw"Graph already in this graph mgr!";if(this.graphs.push(_),_.parent!=null)throw"Already has a parent!";if(A.child!=null)throw"Already has a child!";return _.parent=A,A.child=_,_}else{N=I,B=A,I=_;var R=B.getOwner(),z=N.getOwner();if(!(R!=null&&R.getGraphManager()==this))throw"Source not in this graph mgr!";if(!(z!=null&&z.getGraphManager()==this))throw"Target not in this graph mgr!";if(R==z)return I.isInterGraph=!1,R.add(I,B,N);if(I.isInterGraph=!0,I.source=B,I.target=N,this.edges.indexOf(I)>-1)throw"Edge already in inter-graph edge list!";if(this.edges.push(I),!(I.source!=null&&I.target!=null))throw"Edge source and/or target is null!";if(!(I.source.edges.indexOf(I)==-1&&I.target.edges.indexOf(I)==-1))throw"Edge already in source and/or target incidency list!";return I.source.edges.push(I),I.target.edges.push(I),I}},E.prototype.remove=function(_){if(_ instanceof m){var A=_;if(A.getGraphManager()!=this)throw"Graph not in this graph mgr";if(!(A==this.rootGraph||A.parent!=null&&A.parent.graphManager==this))throw"Invalid parent node!";var I=[];I=I.concat(A.getEdges());for(var B,N=I.length,R=0;R=_.getRight()?A[0]+=Math.min(_.getX()-E.getX(),E.getRight()-_.getRight()):_.getX()<=E.getX()&&_.getRight()>=E.getRight()&&(A[0]+=Math.min(E.getX()-_.getX(),_.getRight()-E.getRight())),E.getY()<=_.getY()&&E.getBottom()>=_.getBottom()?A[1]+=Math.min(_.getY()-E.getY(),E.getBottom()-_.getBottom()):_.getY()<=E.getY()&&_.getBottom()>=E.getBottom()&&(A[1]+=Math.min(E.getY()-_.getY(),_.getBottom()-E.getBottom()));var N=Math.abs((_.getCenterY()-E.getCenterY())/(_.getCenterX()-E.getCenterX()));_.getCenterY()===E.getCenterY()&&_.getCenterX()===E.getCenterX()&&(N=1);var R=N*A[0],z=A[1]/N;A[0]R)return A[0]=I,A[1]=W,A[2]=N,A[3]=pt,!1;if(BN)return A[0]=z,A[1]=B,A[2]=vt,A[3]=R,!1;if(IN?(A[0]=st,A[1]=at,It=!0):(A[0]=et,A[1]=W,It=!0):Bt===Z&&(I>N?(A[0]=z,A[1]=W,It=!0):(A[0]=bt,A[1]=at,It=!0)),-Et===Z?N>I?(A[2]=X,A[3]=pt,Ot=!0):(A[2]=vt,A[3]=ut,Ot=!0):Et===Z&&(N>I?(A[2]=ft,A[3]=ut,Ot=!0):(A[2]=U,A[3]=pt,Ot=!0)),It&&Ot)return!1;if(I>N?B>R?(Ct=this.getCardinalDirection(Bt,Z,4),xt=this.getCardinalDirection(Et,Z,2)):(Ct=this.getCardinalDirection(-Bt,Z,3),xt=this.getCardinalDirection(-Et,Z,1)):B>R?(Ct=this.getCardinalDirection(-Bt,Z,1),xt=this.getCardinalDirection(-Et,Z,3)):(Ct=this.getCardinalDirection(Bt,Z,2),xt=this.getCardinalDirection(Et,Z,4)),!It)switch(Ct){case 1:Le=W,Ht=I+-yt/Z,A[0]=Ht,A[1]=Le;break;case 2:Ht=bt,Le=B+mt*Z,A[0]=Ht,A[1]=Le;break;case 3:Le=at,Ht=I+yt/Z,A[0]=Ht,A[1]=Le;break;case 4:Ht=st,Le=B+-mt*Z,A[0]=Ht,A[1]=Le;break}if(!Ot)switch(xt){case 1:gn=ut,Ft=N+-nt/Z,A[2]=Ft,A[3]=gn;break;case 2:Ft=U,gn=R+Tt*Z,A[2]=Ft,A[3]=gn;break;case 3:gn=pt,Ft=N+nt/Z,A[2]=Ft,A[3]=gn;break;case 4:Ft=X,gn=R+-Tt*Z,A[2]=Ft,A[3]=gn;break}}return!1},b.getCardinalDirection=function(E,_,A){return E>_?A:1+A%4},b.getIntersection=function(E,_,A,I){if(I==null)return this.getIntersection2(E,_,A);var B=E.x,N=E.y,R=_.x,z=_.y,W=A.x,et=A.y,st=I.x,at=I.y,bt=void 0,mt=void 0,yt=void 0,ft=void 0,ut=void 0,vt=void 0,X=void 0,pt=void 0,U=void 0;return yt=z-N,ut=B-R,X=R*N-B*z,ft=at-et,vt=W-st,pt=st*et-W*at,U=yt*vt-ft*ut,U===0?null:(bt=(ut*pt-vt*X)/U,mt=(ft*X-yt*pt)/U,new m(bt,mt))},b.angleOfVector=function(E,_,A,I){var B=void 0;return E!==A?(B=Math.atan((I-_)/(A-E)),A0?1:b<0?-1:0},m.floor=function(b){return b<0?Math.ceil(b):Math.floor(b)},m.ceil=function(b){return b<0?Math.floor(b):Math.ceil(b)},f.exports=m},function(f,p,w){function m(){}m.MAX_VALUE=2147483647,m.MIN_VALUE=-2147483648,f.exports=m},function(f,p,w){var m=function(){function B(N,R){for(var z=0;z"u"?"undefined":m(E);return E==null||_!="object"&&_!="function"},f.exports=b},function(f,p,w){function m(W){if(Array.isArray(W)){for(var et=0,st=Array(W.length);et0&&et;){for(yt.push(ut[0]);yt.length>0&&et;){var vt=yt[0];yt.splice(0,1),mt.add(vt);for(var X=vt.getEdges(),bt=0;bt-1&&ut.splice(nt,1)}mt=new Set,ft=new Map}}return W},z.prototype.createDummyNodesForBendpoints=function(W){for(var et=[],st=W.source,at=this.graphManager.calcLowestCommonAncestor(W.source,W.target),bt=0;bt0){for(var at=this.edgeToDummyNodes.get(st),bt=0;bt=0&&et.splice(pt,1);var U=ft.getNeighborsList();U.forEach(function(It){if(st.indexOf(It)<0){var Ot=at.get(It),Bt=Ot-1;Bt==1&&vt.push(It),at.set(It,Bt)}})}st=st.concat(vt),(et.length==1||et.length==2)&&(bt=!0,mt=et[0])}return mt},z.prototype.setGraphManager=function(W){this.graphManager=W},f.exports=z},function(f,p,w){function m(){}m.seed=1,m.x=0,m.nextDouble=function(){return m.x=Math.sin(m.seed++)*1e4,m.x-Math.floor(m.x)},f.exports=m},function(f,p,w){var m=w(4);function b(E,_){this.lworldOrgX=0,this.lworldOrgY=0,this.ldeviceOrgX=0,this.ldeviceOrgY=0,this.lworldExtX=1,this.lworldExtY=1,this.ldeviceExtX=1,this.ldeviceExtY=1}b.prototype.getWorldOrgX=function(){return this.lworldOrgX},b.prototype.setWorldOrgX=function(E){this.lworldOrgX=E},b.prototype.getWorldOrgY=function(){return this.lworldOrgY},b.prototype.setWorldOrgY=function(E){this.lworldOrgY=E},b.prototype.getWorldExtX=function(){return this.lworldExtX},b.prototype.setWorldExtX=function(E){this.lworldExtX=E},b.prototype.getWorldExtY=function(){return this.lworldExtY},b.prototype.setWorldExtY=function(E){this.lworldExtY=E},b.prototype.getDeviceOrgX=function(){return this.ldeviceOrgX},b.prototype.setDeviceOrgX=function(E){this.ldeviceOrgX=E},b.prototype.getDeviceOrgY=function(){return this.ldeviceOrgY},b.prototype.setDeviceOrgY=function(E){this.ldeviceOrgY=E},b.prototype.getDeviceExtX=function(){return this.ldeviceExtX},b.prototype.setDeviceExtX=function(E){this.ldeviceExtX=E},b.prototype.getDeviceExtY=function(){return this.ldeviceExtY},b.prototype.setDeviceExtY=function(E){this.ldeviceExtY=E},b.prototype.transformX=function(E){var _=0,A=this.lworldExtX;return A!=0&&(_=this.ldeviceOrgX+(E-this.lworldOrgX)*this.ldeviceExtX/A),_},b.prototype.transformY=function(E){var _=0,A=this.lworldExtY;return A!=0&&(_=this.ldeviceOrgY+(E-this.lworldOrgY)*this.ldeviceExtY/A),_},b.prototype.inverseTransformX=function(E){var _=0,A=this.ldeviceExtX;return A!=0&&(_=this.lworldOrgX+(E-this.ldeviceOrgX)*this.lworldExtX/A),_},b.prototype.inverseTransformY=function(E){var _=0,A=this.ldeviceExtY;return A!=0&&(_=this.lworldOrgY+(E-this.ldeviceOrgY)*this.lworldExtY/A),_},b.prototype.inverseTransformPoint=function(E){var _=new m(this.inverseTransformX(E.x),this.inverseTransformY(E.y));return _},f.exports=b},function(f,p,w){function m(R){if(Array.isArray(R)){for(var z=0,W=Array(R.length);zE.ADAPTATION_LOWER_NODE_LIMIT&&(this.coolingFactor=Math.max(this.coolingFactor*E.COOLING_ADAPTATION_FACTOR,this.coolingFactor-(R-E.ADAPTATION_LOWER_NODE_LIMIT)/(E.ADAPTATION_UPPER_NODE_LIMIT-E.ADAPTATION_LOWER_NODE_LIMIT)*this.coolingFactor*(1-E.COOLING_ADAPTATION_FACTOR))),this.maxNodeDisplacement=E.MAX_NODE_DISPLACEMENT_INCREMENTAL):(R>E.ADAPTATION_LOWER_NODE_LIMIT?this.coolingFactor=Math.max(E.COOLING_ADAPTATION_FACTOR,1-(R-E.ADAPTATION_LOWER_NODE_LIMIT)/(E.ADAPTATION_UPPER_NODE_LIMIT-E.ADAPTATION_LOWER_NODE_LIMIT)*(1-E.COOLING_ADAPTATION_FACTOR)):this.coolingFactor=1,this.initialCoolingFactor=this.coolingFactor,this.maxNodeDisplacement=E.MAX_NODE_DISPLACEMENT),this.maxIterations=Math.max(this.getAllNodes().length*5,this.maxIterations),this.totalDisplacementThreshold=this.displacementThresholdPerNode*this.getAllNodes().length,this.repulsionRange=this.calcRepulsionRange()},B.prototype.calcSpringForces=function(){for(var R=this.getAllEdges(),z,W=0;W0&&arguments[0]!==void 0?arguments[0]:!0,z=arguments.length>1&&arguments[1]!==void 0?arguments[1]:!1,W,et,st,at,bt=this.getAllNodes(),mt;if(this.useFRGridVariant)for(this.totalIterations%E.GRID_CALCULATION_CHECK_PERIOD==1&&R&&this.updateGrid(),mt=new Set,W=0;Wyt||mt>yt)&&(R.gravitationForceX=-this.gravityConstant*st,R.gravitationForceY=-this.gravityConstant*at)):(yt=z.getEstimatedSize()*this.compoundGravityRangeFactor,(bt>yt||mt>yt)&&(R.gravitationForceX=-this.gravityConstant*st*this.compoundGravityConstant,R.gravitationForceY=-this.gravityConstant*at*this.compoundGravityConstant))},B.prototype.isConverged=function(){var R,z=!1;return this.totalIterations>this.maxIterations/3&&(z=Math.abs(this.totalDisplacement-this.oldTotalDisplacement)<2),R=this.totalDisplacement=bt.length||yt>=bt[0].length)){for(var ft=0;ftB}}]),A}();f.exports=_},function(f,p,w){var m=function(){function _(A,I){for(var B=0;B2&&arguments[2]!==void 0?arguments[2]:1,N=arguments.length>3&&arguments[3]!==void 0?arguments[3]:-1,R=arguments.length>4&&arguments[4]!==void 0?arguments[4]:-1;b(this,_),this.sequence1=A,this.sequence2=I,this.match_score=B,this.mismatch_penalty=N,this.gap_penalty=R,this.iMax=A.length+1,this.jMax=I.length+1,this.grid=new Array(this.iMax);for(var z=0;z=0;A--){var I=this.listeners[A];I.event===E&&I.callback===_&&this.listeners.splice(A,1)}},b.emit=function(E,_){for(var A=0;AI.coolingFactor*I.maxNodeDisplacement&&(this.displacementX=I.coolingFactor*I.maxNodeDisplacement*E.sign(this.displacementX)),Math.abs(this.displacementY)>I.coolingFactor*I.maxNodeDisplacement&&(this.displacementY=I.coolingFactor*I.maxNodeDisplacement*E.sign(this.displacementY)),this.child==null?this.moveBy(this.displacementX,this.displacementY):this.child.getNodes().length==0?this.moveBy(this.displacementX,this.displacementY):this.propogateDisplacementToChildren(this.displacementX,this.displacementY),I.totalDisplacement+=Math.abs(this.displacementX)+Math.abs(this.displacementY),this.springForceX=0,this.springForceY=0,this.repulsionForceX=0,this.repulsionForceY=0,this.gravitationForceX=0,this.gravitationForceY=0,this.displacementX=0,this.displacementY=0},_.prototype.propogateDisplacementToChildren=function(I,B){for(var N=this.getChild().getNodes(),R,z=0;z0)this.positionNodesRadially(ut);else{this.reduceTrees(),this.graphManager.resetAllNodesToApplyGravitation();var vt=new Set(this.getAllNodes()),X=this.nodesWithGravity.filter(function(pt){return vt.has(pt)});this.graphManager.setAllNodesToApplyGravitation(X),this.positionNodesRandomly()}}return this.initSpringEmbedder(),this.runSpringEmbedder(),!0},yt.prototype.tick=function(){if(this.totalIterations++,this.totalIterations===this.maxIterations&&!this.isTreeGrowing&&!this.isGrowthFinished)if(this.prunedNodesAll.length>0)this.isTreeGrowing=!0;else return!0;if(this.totalIterations%N.CONVERGENCE_CHECK_PERIOD==0&&!this.isTreeGrowing&&!this.isGrowthFinished){if(this.isConverged())if(this.prunedNodesAll.length>0)this.isTreeGrowing=!0;else return!0;this.coolingCycle++,this.layoutQuality==0?this.coolingAdjuster=this.coolingCycle:this.layoutQuality==1&&(this.coolingAdjuster=this.coolingCycle/3),this.coolingFactor=Math.max(this.initialCoolingFactor-Math.pow(this.coolingCycle,Math.log(100*(this.initialCoolingFactor-this.finalTemperature))/Math.log(this.maxCoolingCycle))/100*this.coolingAdjuster,this.finalTemperature),this.animationPeriod=Math.ceil(this.initialAnimationPeriod*Math.sqrt(this.coolingFactor))}if(this.isTreeGrowing){if(this.growTreeIterations%10==0)if(this.prunedNodesAll.length>0){this.graphManager.updateBounds(),this.updateGrid(),this.growTree(this.prunedNodesAll),this.graphManager.resetAllNodesToApplyGravitation();var ut=new Set(this.getAllNodes()),vt=this.nodesWithGravity.filter(function(U){return ut.has(U)});this.graphManager.setAllNodesToApplyGravitation(vt),this.graphManager.updateBounds(),this.updateGrid(),this.coolingFactor=N.DEFAULT_COOLING_FACTOR_INCREMENTAL}else this.isTreeGrowing=!1,this.isGrowthFinished=!0;this.growTreeIterations++}if(this.isGrowthFinished){if(this.isConverged())return!0;this.afterGrowthIterations%10==0&&(this.graphManager.updateBounds(),this.updateGrid()),this.coolingFactor=N.DEFAULT_COOLING_FACTOR_INCREMENTAL*((100-this.afterGrowthIterations)/100),this.afterGrowthIterations++}var X=!this.isTreeGrowing&&!this.isGrowthFinished,pt=this.growTreeIterations%10==1&&this.isTreeGrowing||this.afterGrowthIterations%10==1&&this.isGrowthFinished;return this.totalDisplacement=0,this.graphManager.updateBounds(),this.calcSpringForces(),this.calcRepulsionForces(X,pt),this.calcGravitationalForces(),this.moveNodes(),this.animate(),!1},yt.prototype.getPositionsData=function(){for(var ut=this.graphManager.getAllNodes(),vt={},X=0;X1){var It;for(It=0;Itpt&&(pt=Math.floor(nt.y)),Tt=Math.floor(nt.x+B.DEFAULT_COMPONENT_SEPERATION)}this.transform(new W(R.WORLD_CENTER_X-nt.x/2,R.WORLD_CENTER_Y-nt.y/2))},yt.radialLayout=function(ut,vt,X){var pt=Math.max(this.maxDiagonalInTree(ut),B.DEFAULT_RADIAL_SEPARATION);yt.branchRadialLayout(vt,null,0,359,0,pt);var U=bt.calculateBounds(ut),Tt=new mt;Tt.setDeviceOrgX(U.getMinX()),Tt.setDeviceOrgY(U.getMinY()),Tt.setWorldOrgX(X.x),Tt.setWorldOrgY(X.y);for(var nt=0;nt1;){var gn=Ft[0];Ft.splice(0,1);var Se=Z.indexOf(gn);Se>=0&&Z.splice(Se,1),Ht--,Ct--}vt!=null?Le=(Z.indexOf(Ft[0])+1)%Ht:Le=0;for(var me=Math.abs(pt-X)/Ct,Ve=Le;xt!=Ct;Ve=++Ve%Ht){var Ye=Z[Ve].getOtherEnd(ut);if(Ye!=vt){var ce=(X+xt*me)%360,ke=(ce+me)%360;yt.branchRadialLayout(Ye,ut,ce,ke,U+Tt,Tt),xt++}}},yt.maxDiagonalInTree=function(ut){for(var vt=st.MIN_VALUE,X=0;Xvt&&(vt=U)}return vt},yt.prototype.calcRepulsionRange=function(){return 2*(this.level+1)*this.idealEdgeLength},yt.prototype.groupZeroDegreeMembers=function(){var ut=this,vt={};this.memberGroups={},this.idToDummyNode={};for(var X=[],pt=this.graphManager.getAllNodes(),U=0;U"u"&&(vt[It]=[]),vt[It]=vt[It].concat(Tt)}Object.keys(vt).forEach(function(Ot){if(vt[Ot].length>1){var Bt="DummyCompound_"+Ot;ut.memberGroups[Bt]=vt[Ot];var Et=vt[Ot][0].getParent(),Z=new A(ut.graphManager);Z.id=Bt,Z.paddingLeft=Et.paddingLeft||0,Z.paddingRight=Et.paddingRight||0,Z.paddingBottom=Et.paddingBottom||0,Z.paddingTop=Et.paddingTop||0,ut.idToDummyNode[Bt]=Z;var Ct=ut.getGraphManager().add(ut.newGraph(),Z),xt=Et.getChild();xt.add(Z);for(var Ht=0;Ht=0;ut--){var vt=this.compoundOrder[ut],X=vt.id,pt=vt.paddingLeft,U=vt.paddingTop;this.adjustLocations(this.tiledMemberPack[X],vt.rect.x,vt.rect.y,pt,U)}},yt.prototype.repopulateZeroDegreeMembers=function(){var ut=this,vt=this.tiledZeroDegreePack;Object.keys(vt).forEach(function(X){var pt=ut.idToDummyNode[X],U=pt.paddingLeft,Tt=pt.paddingTop;ut.adjustLocations(vt[X],pt.rect.x,pt.rect.y,U,Tt)})},yt.prototype.getToBeTiled=function(ut){var vt=ut.id;if(this.toBeTiled[vt]!=null)return this.toBeTiled[vt];var X=ut.getChild();if(X==null)return this.toBeTiled[vt]=!1,!1;for(var pt=X.getNodes(),U=0;U0)return this.toBeTiled[vt]=!1,!1;if(Tt.getChild()==null){this.toBeTiled[Tt.id]=!1;continue}if(!this.getToBeTiled(Tt))return this.toBeTiled[vt]=!1,!1}return this.toBeTiled[vt]=!0,!0},yt.prototype.getNodeDegree=function(ut){ut.id;for(var vt=ut.getEdges(),X=0,pt=0;ptOt&&(Ot=Et.rect.height)}X+=Ot+ut.verticalPadding}},yt.prototype.tileCompoundMembers=function(ut,vt){var X=this;this.tiledMemberPack=[],Object.keys(ut).forEach(function(pt){var U=vt[pt];X.tiledMemberPack[pt]=X.tileNodes(ut[pt],U.paddingLeft+U.paddingRight),U.rect.width=X.tiledMemberPack[pt].width,U.rect.height=X.tiledMemberPack[pt].height})},yt.prototype.tileNodes=function(ut,vt){var X=B.TILING_PADDING_VERTICAL,pt=B.TILING_PADDING_HORIZONTAL,U={rows:[],rowWidth:[],rowHeight:[],width:0,height:vt,verticalPadding:X,horizontalPadding:pt};ut.sort(function(It,Ot){return It.rect.width*It.rect.height>Ot.rect.width*Ot.rect.height?-1:It.rect.width*It.rect.height0&&(nt+=ut.horizontalPadding),ut.rowWidth[X]=nt,ut.width0&&(It+=ut.verticalPadding);var Ot=0;It>ut.rowHeight[X]&&(Ot=ut.rowHeight[X],ut.rowHeight[X]=It,Ot=ut.rowHeight[X]-Ot),ut.height+=Ot,ut.rows[X].push(vt)},yt.prototype.getShortestRowIndex=function(ut){for(var vt=-1,X=Number.MAX_VALUE,pt=0;ptX&&(vt=pt,X=ut.rowWidth[pt]);return vt},yt.prototype.canAddHorizontal=function(ut,vt,X){var pt=this.getShortestRowIndex(ut);if(pt<0)return!0;var U=ut.rowWidth[pt];if(U+ut.horizontalPadding+vt<=ut.width)return!0;var Tt=0;ut.rowHeight[pt]0&&(Tt=X+ut.verticalPadding-ut.rowHeight[pt]);var nt;ut.width-U>=vt+ut.horizontalPadding?nt=(ut.height+Tt)/(U+vt+ut.horizontalPadding):nt=(ut.height+Tt)/ut.width,Tt=X+ut.verticalPadding;var It;return ut.widthTt&&vt!=X){pt.splice(-1,1),ut.rows[X].push(U),ut.rowWidth[vt]=ut.rowWidth[vt]-Tt,ut.rowWidth[X]=ut.rowWidth[X]+Tt,ut.width=ut.rowWidth[instance.getLongestRowIndex(ut)];for(var nt=Number.MIN_VALUE,It=0;Itnt&&(nt=pt[It].height);vt>0&&(nt+=ut.verticalPadding);var Ot=ut.rowHeight[vt]+ut.rowHeight[X];ut.rowHeight[vt]=nt,ut.rowHeight[X]0)for(var xt=U;xt<=Tt;xt++)Ct[0]+=this.grid[xt][nt-1].length+this.grid[xt][nt].length-1;if(Tt0)for(var xt=nt;xt<=It;xt++)Ct[3]+=this.grid[U-1][xt].length+this.grid[U][xt].length-1;for(var Ht=st.MAX_VALUE,Le,Ft,gn=0;gn0){var It;It=mt.getGraphManager().add(mt.newGraph(),X),this.processChildrenList(It,vt,mt)}}},W.prototype.stop=function(){return this.stopped=!0,this};var st=function(bt){bt("layout","cose-bilkent",W)};typeof cytoscape<"u"&&st(cytoscape),p.exports=st}])})})(h$t);var uYe=h$t.exports;const lYe=G7(uYe);l$t.use(lYe);function g$t(i,a,f,p){c$t.drawNode(i,a,f,p),a.children&&a.children.forEach((w,m)=>{g$t(i,w,f<0?m:f,p)})}function hYe(i,a){a.edges().map((f,p)=>{const w=f.data();if(f[0]._private.bodyBounds){const m=f[0]._private.rscratch;Ut.trace("Edge: ",p,w),i.insert("path").attr("d",`M ${m.startX},${m.startY} L ${m.midX},${m.midY} L${m.endX},${m.endY} `).attr("class","edge section-edge-"+w.section+" edge-depth-"+w.depth)}})}function p$t(i,a,f,p){a.add({group:"nodes",data:{id:i.id,labelText:i.descr,height:i.height,width:i.width,level:p,nodeId:i.id,padding:i.padding,type:i.type},position:{x:i.x,y:i.y}}),i.children&&i.children.forEach(w=>{p$t(w,a,f,p+1),a.add({group:"edges",data:{id:`${i.id}_${w.id}`,source:i.id,target:w.id,depth:p,section:w.section}})})}function fYe(i,a){return new Promise(f=>{const p=yr("body").append("div").attr("id","cy").attr("style","display:none"),w=l$t({container:document.getElementById("cy"),style:[{selector:"edge",style:{"curve-style":"bezier"}}]});p.remove(),p$t(i,w,a,0),w.nodes().forEach(function(m){m.layoutDimensions=()=>{const b=m.data();return{w:b.width,h:b.height}}}),w.layout({name:"cose-bilkent",quality:"proof",styleEnabled:!1,animate:!1}).run(),w.ready(m=>{Ut.info("Ready",m),f(w)})})}function dYe(i){i.nodes().map((a,f)=>{const p=a.data();p.x=a.position().x,p.y=a.position().y,c$t.positionNode(p);const w=Jgt(p.nodeId);Ut.info("Id:",f,"Position: (",a.position().x,", ",a.position().y,")",p),w.attr("transform",`translate(${a.position().x-p.width/2}, ${a.position().y-p.height/2})`),w.attr("attr",`apa-${f})`)})}const gYe={draw:async(i,a,f,p)=>{const w=Oe();w.htmlLabels=!1,Ut.debug(`Rendering mindmap diagram +`+i,p.parser);const m=Oe().securityLevel;let b;m==="sandbox"&&(b=yr("#i"+a));const _=yr(m==="sandbox"?b.nodes()[0].contentDocument.body:"body").select("#"+a);_.append("g");const A=p.db.getMindmap(),I=_.append("g");I.attr("class","mindmap-edges");const B=_.append("g");B.attr("class","mindmap-nodes"),g$t(B,A,-1,w);const N=await fYe(A,w);hYe(I,N),dYe(N),fT(void 0,_,w.mindmap.padding,w.mindmap.useMaxWidth)}},pYe=i=>{let a="";for(let f=0;f` + .edge { + stroke-width: 3; + } + ${pYe(i)} + .section-root rect, .section-root path, .section-root circle, .section-root polygon { + fill: ${i.git0}; + } + .section-root text { + fill: ${i.gitBranchLabel0}; + } + .icon-container { + height:100%; + display: flex; + justify-content: center; + align-items: center; + } + .edge { + fill: none; + } + .mindmap-node-label { + dy: 1em; + alignment-baseline: middle; + text-anchor: middle; + dominant-baseline: middle; + text-align: center; + } +`}},Symbol.toStringTag,{value:"Module"}));var npt=function(){var i=function(E,_,A,I){for(A=A||{},I=E.length;I--;A[E[I]]=_);return A},a=[1,9],f=[1,10],p=[1,5,10,12],w={trace:function(){},yy:{},symbols_:{error:2,start:3,SANKEY:4,NEWLINE:5,csv:6,opt_eof:7,record:8,csv_tail:9,EOF:10,"field[source]":11,COMMA:12,"field[target]":13,"field[value]":14,field:15,escaped:16,non_escaped:17,DQUOTE:18,ESCAPED_TEXT:19,NON_ESCAPED_TEXT:20,$accept:0,$end:1},terminals_:{2:"error",4:"SANKEY",5:"NEWLINE",10:"EOF",11:"field[source]",12:"COMMA",13:"field[target]",14:"field[value]",18:"DQUOTE",19:"ESCAPED_TEXT",20:"NON_ESCAPED_TEXT"},productions_:[0,[3,4],[6,2],[9,2],[9,0],[7,1],[7,0],[8,5],[15,1],[15,1],[16,3],[17,1]],performAction:function(_,A,I,B,N,R,z){var W=R.length-1;switch(N){case 7:const et=B.findOrCreateNode(R[W-4].trim().replaceAll('""','"')),st=B.findOrCreateNode(R[W-2].trim().replaceAll('""','"')),at=parseFloat(R[W].trim());B.addLink(et,st,at);break;case 8:case 9:case 11:this.$=R[W];break;case 10:this.$=R[W-1];break}},table:[{3:1,4:[1,2]},{1:[3]},{5:[1,3]},{6:4,8:5,15:6,16:7,17:8,18:a,20:f},{1:[2,6],7:11,10:[1,12]},i(f,[2,4],{9:13,5:[1,14]}),{12:[1,15]},i(p,[2,8]),i(p,[2,9]),{19:[1,16]},i(p,[2,11]),{1:[2,1]},{1:[2,5]},i(f,[2,2]),{6:17,8:5,15:6,16:7,17:8,18:a,20:f},{15:18,16:7,17:8,18:a,20:f},{18:[1,19]},i(f,[2,3]),{12:[1,20]},i(p,[2,10]),{15:21,16:7,17:8,18:a,20:f},i([1,5,10],[2,7])],defaultActions:{11:[2,1],12:[2,5]},parseError:function(_,A){if(A.recoverable)this.trace(_);else{var I=new Error(_);throw I.hash=A,I}},parse:function(_){var A=this,I=[0],B=[],N=[null],R=[],z=this.table,W="",et=0,st=0,at=2,bt=1,mt=R.slice.call(arguments,1),yt=Object.create(this.lexer),ft={yy:{}};for(var ut in this.yy)Object.prototype.hasOwnProperty.call(this.yy,ut)&&(ft.yy[ut]=this.yy[ut]);yt.setInput(_,ft.yy),ft.yy.lexer=yt,ft.yy.parser=this,typeof yt.yylloc>"u"&&(yt.yylloc={});var vt=yt.yylloc;R.push(vt);var X=yt.options&&yt.options.ranges;typeof ft.yy.parseError=="function"?this.parseError=ft.yy.parseError:this.parseError=Object.getPrototypeOf(this).parseError;function pt(){var Ht;return Ht=B.pop()||yt.lex()||bt,typeof Ht!="number"&&(Ht instanceof Array&&(B=Ht,Ht=B.pop()),Ht=A.symbols_[Ht]||Ht),Ht}for(var U,Tt,nt,It,Ot={},Bt,Et,Z,Ct;;){if(Tt=I[I.length-1],this.defaultActions[Tt]?nt=this.defaultActions[Tt]:((U===null||typeof U>"u")&&(U=pt()),nt=z[Tt]&&z[Tt][U]),typeof nt>"u"||!nt.length||!nt[0]){var xt="";Ct=[];for(Bt in z[Tt])this.terminals_[Bt]&&Bt>at&&Ct.push("'"+this.terminals_[Bt]+"'");yt.showPosition?xt="Parse error on line "+(et+1)+`: +`+yt.showPosition()+` +Expecting `+Ct.join(", ")+", got '"+(this.terminals_[U]||U)+"'":xt="Parse error on line "+(et+1)+": Unexpected "+(U==bt?"end of input":"'"+(this.terminals_[U]||U)+"'"),this.parseError(xt,{text:yt.match,token:this.terminals_[U]||U,line:yt.yylineno,loc:vt,expected:Ct})}if(nt[0]instanceof Array&&nt.length>1)throw new Error("Parse Error: multiple actions possible at state: "+Tt+", token: "+U);switch(nt[0]){case 1:I.push(U),N.push(yt.yytext),R.push(yt.yylloc),I.push(nt[1]),U=null,st=yt.yyleng,W=yt.yytext,et=yt.yylineno,vt=yt.yylloc;break;case 2:if(Et=this.productions_[nt[1]][1],Ot.$=N[N.length-Et],Ot._$={first_line:R[R.length-(Et||1)].first_line,last_line:R[R.length-1].last_line,first_column:R[R.length-(Et||1)].first_column,last_column:R[R.length-1].last_column},X&&(Ot._$.range=[R[R.length-(Et||1)].range[0],R[R.length-1].range[1]]),It=this.performAction.apply(Ot,[W,st,et,ft.yy,nt[1],N,R].concat(mt)),typeof It<"u")return It;Et&&(I=I.slice(0,-1*Et*2),N=N.slice(0,-1*Et),R=R.slice(0,-1*Et)),I.push(this.productions_[nt[1]][0]),N.push(Ot.$),R.push(Ot._$),Z=z[I[I.length-2]][I[I.length-1]],I.push(Z);break;case 3:return!0}}return!0}},m=function(){var E={EOF:1,parseError:function(A,I){if(this.yy.parser)this.yy.parser.parseError(A,I);else throw new Error(A)},setInput:function(_,A){return this.yy=A||this.yy||{},this._input=_,this._more=this._backtrack=this.done=!1,this.yylineno=this.yyleng=0,this.yytext=this.matched=this.match="",this.conditionStack=["INITIAL"],this.yylloc={first_line:1,first_column:0,last_line:1,last_column:0},this.options.ranges&&(this.yylloc.range=[0,0]),this.offset=0,this},input:function(){var _=this._input[0];this.yytext+=_,this.yyleng++,this.offset++,this.match+=_,this.matched+=_;var A=_.match(/(?:\r\n?|\n).*/g);return A?(this.yylineno++,this.yylloc.last_line++):this.yylloc.last_column++,this.options.ranges&&this.yylloc.range[1]++,this._input=this._input.slice(1),_},unput:function(_){var A=_.length,I=_.split(/(?:\r\n?|\n)/g);this._input=_+this._input,this.yytext=this.yytext.substr(0,this.yytext.length-A),this.offset-=A;var B=this.match.split(/(?:\r\n?|\n)/g);this.match=this.match.substr(0,this.match.length-1),this.matched=this.matched.substr(0,this.matched.length-1),I.length-1&&(this.yylineno-=I.length-1);var N=this.yylloc.range;return this.yylloc={first_line:this.yylloc.first_line,last_line:this.yylineno+1,first_column:this.yylloc.first_column,last_column:I?(I.length===B.length?this.yylloc.first_column:0)+B[B.length-I.length].length-I[0].length:this.yylloc.first_column-A},this.options.ranges&&(this.yylloc.range=[N[0],N[0]+this.yyleng-A]),this.yyleng=this.yytext.length,this},more:function(){return this._more=!0,this},reject:function(){if(this.options.backtrack_lexer)this._backtrack=!0;else return this.parseError("Lexical error on line "+(this.yylineno+1)+`. You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true). +`+this.showPosition(),{text:"",token:null,line:this.yylineno});return this},less:function(_){this.unput(this.match.slice(_))},pastInput:function(){var _=this.matched.substr(0,this.matched.length-this.match.length);return(_.length>20?"...":"")+_.substr(-20).replace(/\n/g,"")},upcomingInput:function(){var _=this.match;return _.length<20&&(_+=this._input.substr(0,20-_.length)),(_.substr(0,20)+(_.length>20?"...":"")).replace(/\n/g,"")},showPosition:function(){var _=this.pastInput(),A=new Array(_.length+1).join("-");return _+this.upcomingInput()+` +`+A+"^"},test_match:function(_,A){var I,B,N;if(this.options.backtrack_lexer&&(N={yylineno:this.yylineno,yylloc:{first_line:this.yylloc.first_line,last_line:this.last_line,first_column:this.yylloc.first_column,last_column:this.yylloc.last_column},yytext:this.yytext,match:this.match,matches:this.matches,matched:this.matched,yyleng:this.yyleng,offset:this.offset,_more:this._more,_input:this._input,yy:this.yy,conditionStack:this.conditionStack.slice(0),done:this.done},this.options.ranges&&(N.yylloc.range=this.yylloc.range.slice(0))),B=_[0].match(/(?:\r\n?|\n).*/g),B&&(this.yylineno+=B.length),this.yylloc={first_line:this.yylloc.last_line,last_line:this.yylineno+1,first_column:this.yylloc.last_column,last_column:B?B[B.length-1].length-B[B.length-1].match(/\r?\n?/)[0].length:this.yylloc.last_column+_[0].length},this.yytext+=_[0],this.match+=_[0],this.matches=_,this.yyleng=this.yytext.length,this.options.ranges&&(this.yylloc.range=[this.offset,this.offset+=this.yyleng]),this._more=!1,this._backtrack=!1,this._input=this._input.slice(_[0].length),this.matched+=_[0],I=this.performAction.call(this,this.yy,this,A,this.conditionStack[this.conditionStack.length-1]),this.done&&this._input&&(this.done=!1),I)return I;if(this._backtrack){for(var R in N)this[R]=N[R];return!1}return!1},next:function(){if(this.done)return this.EOF;this._input||(this.done=!0);var _,A,I,B;this._more||(this.yytext="",this.match="");for(var N=this._currentRules(),R=0;RA[0].length)){if(A=I,B=R,this.options.backtrack_lexer){if(_=this.test_match(I,N[R]),_!==!1)return _;if(this._backtrack){A=!1;continue}else return!1}else if(!this.options.flex)break}return A?(_=this.test_match(A,N[B]),_!==!1?_:!1):this._input===""?this.EOF:this.parseError("Lexical error on line "+(this.yylineno+1)+`. Unrecognized text. +`+this.showPosition(),{text:"",token:null,line:this.yylineno})},lex:function(){var A=this.next();return A||this.lex()},begin:function(A){this.conditionStack.push(A)},popState:function(){var A=this.conditionStack.length-1;return A>0?this.conditionStack.pop():this.conditionStack[0]},_currentRules:function(){return this.conditionStack.length&&this.conditionStack[this.conditionStack.length-1]?this.conditions[this.conditionStack[this.conditionStack.length-1]].rules:this.conditions.INITIAL.rules},topState:function(A){return A=this.conditionStack.length-1-Math.abs(A||0),A>=0?this.conditionStack[A]:"INITIAL"},pushState:function(A){this.begin(A)},stateStackSize:function(){return this.conditionStack.length},options:{easy_keword_rules:!0},performAction:function(A,I,B,N){switch(B){case 0:return this.pushState("csv"),4;case 1:return 10;case 2:return 5;case 3:return 12;case 4:return this.pushState("escaped_text"),18;case 5:return 20;case 6:return this.popState("escaped_text"),18;case 7:return 19}},rules:[/^(?:sankey-beta\b)/,/^(?:$)/,/^(?:((\u000D\u000A)|(\u000A)))/,/^(?:(\u002C))/,/^(?:(\u0022))/,/^(?:([\u0020-\u0021\u0023-\u002B\u002D-\u007E])*)/,/^(?:(\u0022)(?!(\u0022)))/,/^(?:(([\u0020-\u0021\u0023-\u002B\u002D-\u007E])|(\u002C)|(\u000D)|(\u000A)|(\u0022)(\u0022))*)/],conditions:{csv:{rules:[1,2,3,4,5,6,7],inclusive:!1},escaped_text:{rules:[6,7],inclusive:!1},INITIAL:{rules:[0,1,2,3,4,5,6,7],inclusive:!0}}};return E}();w.lexer=m;function b(){this.yy={}}return b.prototype=w,w.Parser=b,new b}();npt.parser=npt;const rK=npt;let iK=[],sK=[],kL={};const wYe=()=>{iK=[],sK=[],kL={},hg()};class vYe{constructor(a,f,p=0){this.source=a,this.target=f,this.value=p}}const mYe=(i,a,f)=>{iK.push(new vYe(i,a,f))};class yYe{constructor(a){this.ID=a}}const xYe={nodesMap:kL,getConfig:()=>Oe().sankey,getNodes:()=>sK,getLinks:()=>iK,getGraph:()=>({nodes:sK.map(i=>({id:i.ID})),links:iK.map(i=>({source:i.source.ID,target:i.target.ID,value:i.value}))}),addLink:mYe,findOrCreateNode:i=>(i=Kr.sanitizeText(i,Oe()),kL[i]||(kL[i]=new yYe(i),sK.push(kL[i])),kL[i]),getAccTitle:fg,setAccTitle:E0,getAccDescription:gg,setAccDescription:dg,getDiagramTitle:pg,setDiagramTitle:Nb,clear:wYe};function b$t(i,a){let f;if(a===void 0)for(const p of i)p!=null&&(f=p)&&(f=p);else{let p=-1;for(let w of i)(w=a(w,++p,i))!=null&&(f=w)&&(f=w)}return f}function w$t(i,a){let f;if(a===void 0)for(const p of i)p!=null&&(f>p||f===void 0&&p>=p)&&(f=p);else{let p=-1;for(let w of i)(w=a(w,++p,i))!=null&&(f>w||f===void 0&&w>=w)&&(f=w)}return f}function rpt(i,a){let f=0;if(a===void 0)for(let p of i)(p=+p)&&(f+=p);else{let p=-1;for(let w of i)(w=+a(w,++p,i))&&(f+=w)}return f}function kYe(i){return i.target.depth}function EYe(i){return i.depth}function TYe(i,a){return a-1-i.height}function v$t(i,a){return i.sourceLinks.length?i.depth:a-1}function CYe(i){return i.targetLinks.length?i.depth:i.sourceLinks.length?w$t(i.sourceLinks,kYe)-1:0}function aK(i){return function(){return i}}function m$t(i,a){return oK(i.source,a.source)||i.index-a.index}function y$t(i,a){return oK(i.target,a.target)||i.index-a.index}function oK(i,a){return i.y0-a.y0}function ipt(i){return i.value}function _Ye(i){return i.index}function SYe(i){return i.nodes}function AYe(i){return i.links}function x$t(i,a){const f=i.get(a);if(!f)throw new Error("missing: "+a);return f}function k$t({nodes:i}){for(const a of i){let f=a.y0,p=f;for(const w of a.sourceLinks)w.y0=f+w.width/2,f+=w.width;for(const w of a.targetLinks)w.y1=p+w.width/2,p+=w.width}}function LYe(){let i=0,a=0,f=1,p=1,w=24,m=8,b,E=_Ye,_=v$t,A,I,B=SYe,N=AYe,R=6;function z(){const Ot={nodes:B.apply(null,arguments),links:N.apply(null,arguments)};return W(Ot),et(Ot),st(Ot),at(Ot),yt(Ot),k$t(Ot),Ot}z.update=function(Ot){return k$t(Ot),Ot},z.nodeId=function(Ot){return arguments.length?(E=typeof Ot=="function"?Ot:aK(Ot),z):E},z.nodeAlign=function(Ot){return arguments.length?(_=typeof Ot=="function"?Ot:aK(Ot),z):_},z.nodeSort=function(Ot){return arguments.length?(A=Ot,z):A},z.nodeWidth=function(Ot){return arguments.length?(w=+Ot,z):w},z.nodePadding=function(Ot){return arguments.length?(m=b=+Ot,z):m},z.nodes=function(Ot){return arguments.length?(B=typeof Ot=="function"?Ot:aK(Ot),z):B},z.links=function(Ot){return arguments.length?(N=typeof Ot=="function"?Ot:aK(Ot),z):N},z.linkSort=function(Ot){return arguments.length?(I=Ot,z):I},z.size=function(Ot){return arguments.length?(i=a=0,f=+Ot[0],p=+Ot[1],z):[f-i,p-a]},z.extent=function(Ot){return arguments.length?(i=+Ot[0][0],f=+Ot[1][0],a=+Ot[0][1],p=+Ot[1][1],z):[[i,a],[f,p]]},z.iterations=function(Ot){return arguments.length?(R=+Ot,z):R};function W({nodes:Ot,links:Bt}){for(const[Z,Ct]of Ot.entries())Ct.index=Z,Ct.sourceLinks=[],Ct.targetLinks=[];const Et=new Map(Ot.map((Z,Ct)=>[E(Z,Ct,Ot),Z]));for(const[Z,Ct]of Bt.entries()){Ct.index=Z;let{source:xt,target:Ht}=Ct;typeof xt!="object"&&(xt=Ct.source=x$t(Et,xt)),typeof Ht!="object"&&(Ht=Ct.target=x$t(Et,Ht)),xt.sourceLinks.push(Ct),Ht.targetLinks.push(Ct)}if(I!=null)for(const{sourceLinks:Z,targetLinks:Ct}of Ot)Z.sort(I),Ct.sort(I)}function et({nodes:Ot}){for(const Bt of Ot)Bt.value=Bt.fixedValue===void 0?Math.max(rpt(Bt.sourceLinks,ipt),rpt(Bt.targetLinks,ipt)):Bt.fixedValue}function st({nodes:Ot}){const Bt=Ot.length;let Et=new Set(Ot),Z=new Set,Ct=0;for(;Et.size;){for(const xt of Et){xt.depth=Ct;for(const{target:Ht}of xt.sourceLinks)Z.add(Ht)}if(++Ct>Bt)throw new Error("circular link");Et=Z,Z=new Set}}function at({nodes:Ot}){const Bt=Ot.length;let Et=new Set(Ot),Z=new Set,Ct=0;for(;Et.size;){for(const xt of Et){xt.height=Ct;for(const{source:Ht}of xt.targetLinks)Z.add(Ht)}if(++Ct>Bt)throw new Error("circular link");Et=Z,Z=new Set}}function bt({nodes:Ot}){const Bt=b$t(Ot,Ct=>Ct.depth)+1,Et=(f-i-w)/(Bt-1),Z=new Array(Bt);for(const Ct of Ot){const xt=Math.max(0,Math.min(Bt-1,Math.floor(_.call(null,Ct,Bt))));Ct.layer=xt,Ct.x0=i+xt*Et,Ct.x1=Ct.x0+w,Z[xt]?Z[xt].push(Ct):Z[xt]=[Ct]}if(A)for(const Ct of Z)Ct.sort(A);return Z}function mt(Ot){const Bt=w$t(Ot,Et=>(p-a-(Et.length-1)*b)/rpt(Et,ipt));for(const Et of Ot){let Z=a;for(const Ct of Et){Ct.y0=Z,Ct.y1=Z+Ct.value*Bt,Z=Ct.y1+b;for(const xt of Ct.sourceLinks)xt.width=xt.value*Bt}Z=(p-Z+b)/(Et.length+1);for(let Ct=0;CtEt.length)-1)),mt(Bt);for(let Et=0;Et0))continue;let gn=(Le/Ft-Ht.y0)*Bt;Ht.y0+=gn,Ht.y1+=gn,U(Ht)}A===void 0&&xt.sort(oK),vt(xt,Et)}}function ut(Ot,Bt,Et){for(let Z=Ot.length,Ct=Z-2;Ct>=0;--Ct){const xt=Ot[Ct];for(const Ht of xt){let Le=0,Ft=0;for(const{target:Se,value:me}of Ht.sourceLinks){let Ve=me*(Se.layer-Ht.layer);Le+=It(Ht,Se)*Ve,Ft+=Ve}if(!(Ft>0))continue;let gn=(Le/Ft-Ht.y0)*Bt;Ht.y0+=gn,Ht.y1+=gn,U(Ht)}A===void 0&&xt.sort(oK),vt(xt,Et)}}function vt(Ot,Bt){const Et=Ot.length>>1,Z=Ot[Et];pt(Ot,Z.y0-b,Et-1,Bt),X(Ot,Z.y1+b,Et+1,Bt),pt(Ot,p,Ot.length-1,Bt),X(Ot,a,0,Bt)}function X(Ot,Bt,Et,Z){for(;Et1e-6&&(Ct.y0+=xt,Ct.y1+=xt),Bt=Ct.y1+b}}function pt(Ot,Bt,Et,Z){for(;Et>=0;--Et){const Ct=Ot[Et],xt=(Ct.y1-Bt)*Z;xt>1e-6&&(Ct.y0-=xt,Ct.y1-=xt),Bt=Ct.y0-b}}function U({sourceLinks:Ot,targetLinks:Bt}){if(I===void 0){for(const{source:{sourceLinks:Et}}of Bt)Et.sort(y$t);for(const{target:{targetLinks:Et}}of Ot)Et.sort(m$t)}}function Tt(Ot){if(I===void 0)for(const{sourceLinks:Bt,targetLinks:Et}of Ot)Bt.sort(y$t),Et.sort(m$t)}function nt(Ot,Bt){let Et=Ot.y0-(Ot.sourceLinks.length-1)*b/2;for(const{target:Z,width:Ct}of Ot.sourceLinks){if(Z===Bt)break;Et+=Ct+b}for(const{source:Z,width:Ct}of Bt.targetLinks){if(Z===Ot)break;Et-=Ct}return Et}function It(Ot,Bt){let Et=Bt.y0-(Bt.targetLinks.length-1)*b/2;for(const{source:Z,width:Ct}of Bt.targetLinks){if(Z===Ot)break;Et+=Ct+b}for(const{target:Z,width:Ct}of Ot.sourceLinks){if(Z===Bt)break;Et-=Ct}return Et}return z}var spt=Math.PI,apt=2*spt,OT=1e-6,MYe=apt-OT;function opt(){this._x0=this._y0=this._x1=this._y1=null,this._=""}function E$t(){return new opt}opt.prototype=E$t.prototype={constructor:opt,moveTo:function(i,a){this._+="M"+(this._x0=this._x1=+i)+","+(this._y0=this._y1=+a)},closePath:function(){this._x1!==null&&(this._x1=this._x0,this._y1=this._y0,this._+="Z")},lineTo:function(i,a){this._+="L"+(this._x1=+i)+","+(this._y1=+a)},quadraticCurveTo:function(i,a,f,p){this._+="Q"+ +i+","+ +a+","+(this._x1=+f)+","+(this._y1=+p)},bezierCurveTo:function(i,a,f,p,w,m){this._+="C"+ +i+","+ +a+","+ +f+","+ +p+","+(this._x1=+w)+","+(this._y1=+m)},arcTo:function(i,a,f,p,w){i=+i,a=+a,f=+f,p=+p,w=+w;var m=this._x1,b=this._y1,E=f-i,_=p-a,A=m-i,I=b-a,B=A*A+I*I;if(w<0)throw new Error("negative radius: "+w);if(this._x1===null)this._+="M"+(this._x1=i)+","+(this._y1=a);else if(B>OT)if(!(Math.abs(I*E-_*A)>OT)||!w)this._+="L"+(this._x1=i)+","+(this._y1=a);else{var N=f-m,R=p-b,z=E*E+_*_,W=N*N+R*R,et=Math.sqrt(z),st=Math.sqrt(B),at=w*Math.tan((spt-Math.acos((z+B-W)/(2*et*st)))/2),bt=at/st,mt=at/et;Math.abs(bt-1)>OT&&(this._+="L"+(i+bt*A)+","+(a+bt*I)),this._+="A"+w+","+w+",0,0,"+ +(I*N>A*R)+","+(this._x1=i+mt*E)+","+(this._y1=a+mt*_)}},arc:function(i,a,f,p,w,m){i=+i,a=+a,f=+f,m=!!m;var b=f*Math.cos(p),E=f*Math.sin(p),_=i+b,A=a+E,I=1^m,B=m?p-w:w-p;if(f<0)throw new Error("negative radius: "+f);this._x1===null?this._+="M"+_+","+A:(Math.abs(this._x1-_)>OT||Math.abs(this._y1-A)>OT)&&(this._+="L"+_+","+A),f&&(B<0&&(B=B%apt+apt),B>MYe?this._+="A"+f+","+f+",0,1,"+I+","+(i-b)+","+(a-E)+"A"+f+","+f+",0,1,"+I+","+(this._x1=_)+","+(this._y1=A):B>OT&&(this._+="A"+f+","+f+",0,"+ +(B>=spt)+","+I+","+(this._x1=i+f*Math.cos(w))+","+(this._y1=a+f*Math.sin(w))))},rect:function(i,a,f,p){this._+="M"+(this._x0=this._x1=+i)+","+(this._y0=this._y1=+a)+"h"+ +f+"v"+ +p+"h"+-f+"Z"},toString:function(){return this._}};function T$t(i){return function(){return i}}function DYe(i){return i[0]}function IYe(i){return i[1]}var OYe=Array.prototype.slice;function PYe(i){return i.source}function FYe(i){return i.target}function NYe(i){var a=PYe,f=FYe,p=DYe,w=IYe,m=null;function b(){var E,_=OYe.call(arguments),A=a.apply(this,_),I=f.apply(this,_);if(m||(m=E=E$t()),i(m,+p.apply(this,(_[0]=A,_)),+w.apply(this,_),+p.apply(this,(_[0]=I,_)),+w.apply(this,_)),E)return m=null,E+""||null}return b.source=function(E){return arguments.length?(a=E,b):a},b.target=function(E){return arguments.length?(f=E,b):f},b.x=function(E){return arguments.length?(p=typeof E=="function"?E:T$t(+E),b):p},b.y=function(E){return arguments.length?(w=typeof E=="function"?E:T$t(+E),b):w},b.context=function(E){return arguments.length?(m=E??null,b):m},b}function BYe(i,a,f,p,w){i.moveTo(a,f),i.bezierCurveTo(a=(a+p)/2,f,a,w,p,w)}function RYe(){return NYe(BYe)}function jYe(i){return[i.source.x1,i.y0]}function $Ye(i){return[i.target.x0,i.y1]}function zYe(){return RYe().source(jYe).target($Ye)}const C$t=class RLt{static next(a){return new RLt(a+ ++RLt.count)}constructor(a){this.id=a,this.href=`#${a}`}toString(){return"url("+this.href+")"}};C$t.count=0;let _$t=C$t;const qYe={left:EYe,right:TYe,center:CYe,justify:v$t},HYe={draw:function(i,a,f,p){const{securityLevel:w,sankey:m}=Oe(),b=SOt.sankey;let E;w==="sandbox"&&(E=yr("#i"+a));const _=yr(w==="sandbox"?E.nodes()[0].contentDocument.body:"body"),A=w==="sandbox"?_.select(`[id="${a}"]`):yr(`[id="${a}"]`),I=(m==null?void 0:m.width)??b.width,B=(m==null?void 0:m.height)??b.width,N=(m==null?void 0:m.useMaxWidth)??b.useMaxWidth,R=(m==null?void 0:m.nodeAlignment)??b.nodeAlignment,z=(m==null?void 0:m.prefix)??b.prefix,W=(m==null?void 0:m.suffix)??b.suffix,et=(m==null?void 0:m.showValues)??b.showValues;k0(A,B,I,N);const st=p.db.getGraph(),at=qYe[R],bt=10;LYe().nodeId(pt=>pt.id).nodeWidth(bt).nodePadding(10+(et?15:0)).nodeAlign(at).extent([[0,0],[I,B]])(st);const yt=XU(X7e);A.append("g").attr("class","nodes").selectAll(".node").data(st.nodes).join("g").attr("class","node").attr("id",pt=>(pt.uid=_$t.next("node-")).id).attr("transform",function(pt){return"translate("+pt.x0+","+pt.y0+")"}).attr("x",pt=>pt.x0).attr("y",pt=>pt.y0).append("rect").attr("height",pt=>pt.y1-pt.y0).attr("width",pt=>pt.x1-pt.x0).attr("fill",pt=>yt(pt.id));const ft=({id:pt,value:U})=>et?`${pt} +${z}${Math.round(U*100)/100}${W}`:pt;A.append("g").attr("class","node-labels").attr("font-family","sans-serif").attr("font-size",14).selectAll("text").data(st.nodes).join("text").attr("x",pt=>pt.x0(pt.y1+pt.y0)/2).attr("dy",`${et?"0":"0.35"}em`).attr("text-anchor",pt=>pt.x0(U.uid=_$t.next("linearGradient-")).id).attr("gradientUnits","userSpaceOnUse").attr("x1",U=>U.source.x1).attr("x2",U=>U.target.x0);pt.append("stop").attr("offset","0%").attr("stop-color",U=>yt(U.source.id)),pt.append("stop").attr("offset","100%").attr("stop-color",U=>yt(U.target.id))}let X;switch(vt){case"gradient":X=pt=>pt.uid;break;case"source":X=pt=>yt(pt.source.id);break;case"target":X=pt=>yt(pt.target.id);break;default:X=vt}ut.append("path").attr("d",zYe()).attr("stroke",X).attr("stroke-width",pt=>Math.max(1,pt.width))}},VYe=i=>i.replaceAll(/^[^\S\n\r]+|[^\S\n\r]+$/g,"").replaceAll(/([\n\r])+/g,` +`).trim(),GYe=rK.parse.bind(rK);rK.parse=i=>GYe(VYe(i));const UYe=Object.freeze(Object.defineProperty({__proto__:null,diagram:{parser:rK,db:xYe,renderer:HYe}},Symbol.toStringTag,{value:"Module"}));return Bb}); diff --git a/static/js/mermaid-8.13.4.min.js b/static/js/mermaid-8.13.4.min.js deleted file mode 100644 index 7ea93c7cb0c40..0000000000000 --- a/static/js/mermaid-8.13.4.min.js +++ /dev/null @@ -1,3 +0,0 @@ -/*! For license information please see mermaid.min.js.LICENSE.txt */ -!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.mermaid=e():t.mermaid=e()}("undefined"!=typeof self?self:this,(function(){return(()=>{var t={5051:(t,e,n)=>{t=n.nmd(t);var r=function(){var t=function(t,e,n,r){for(n=n||{},r=t.length;r--;n[t[r]]=e);return n},e=[1,6],n=[1,7],r=[1,8],i=[1,9],a=[1,12],o=[1,11],s=[1,15,24],c=[1,19],u=[1,31],l=[1,34],h=[1,32],f=[1,33],d=[1,35],p=[1,36],y=[1,37],g=[1,38],m=[1,41],v=[1,42],b=[1,43],_=[1,44],x=[15,24],w=[1,56],k=[1,57],T=[1,58],E=[1,59],C=[1,60],S=[1,61],A=[15,24,31,38,39,47,50,51,52,53,54,55,60,62],M=[15,24,29,31,38,39,43,47,50,51,52,53,54,55,60,62,77,78,79,80],N=[7,8,9,10,15,18,22,24],D=[47,77,78,79,80],O=[47,54,55,77,78,79,80],B=[47,50,51,52,53,77,78,79,80],L=[15,24,31],I=[1,93],R={trace:function(){},yy:{},symbols_:{error:2,start:3,mermaidDoc:4,direction:5,directive:6,direction_tb:7,direction_bt:8,direction_rl:9,direction_lr:10,graphConfig:11,openDirective:12,typeDirective:13,closeDirective:14,NEWLINE:15,":":16,argDirective:17,open_directive:18,type_directive:19,arg_directive:20,close_directive:21,CLASS_DIAGRAM:22,statements:23,EOF:24,statement:25,className:26,alphaNumToken:27,classLiteralName:28,GENERICTYPE:29,relationStatement:30,LABEL:31,classStatement:32,methodStatement:33,annotationStatement:34,clickStatement:35,cssClassStatement:36,CLASS:37,STYLE_SEPARATOR:38,STRUCT_START:39,members:40,STRUCT_STOP:41,ANNOTATION_START:42,ANNOTATION_END:43,MEMBER:44,SEPARATOR:45,relation:46,STR:47,relationType:48,lineType:49,AGGREGATION:50,EXTENSION:51,COMPOSITION:52,DEPENDENCY:53,LINE:54,DOTTED_LINE:55,CALLBACK:56,LINK:57,LINK_TARGET:58,CLICK:59,CALLBACK_NAME:60,CALLBACK_ARGS:61,HREF:62,CSSCLASS:63,commentToken:64,textToken:65,graphCodeTokens:66,textNoTagsToken:67,TAGSTART:68,TAGEND:69,"==":70,"--":71,PCT:72,DEFAULT:73,SPACE:74,MINUS:75,keywords:76,UNICODE_TEXT:77,NUM:78,ALPHA:79,BQUOTE_STR:80,$accept:0,$end:1},terminals_:{2:"error",7:"direction_tb",8:"direction_bt",9:"direction_rl",10:"direction_lr",15:"NEWLINE",16:":",18:"open_directive",19:"type_directive",20:"arg_directive",21:"close_directive",22:"CLASS_DIAGRAM",24:"EOF",29:"GENERICTYPE",31:"LABEL",37:"CLASS",38:"STYLE_SEPARATOR",39:"STRUCT_START",41:"STRUCT_STOP",42:"ANNOTATION_START",43:"ANNOTATION_END",44:"MEMBER",45:"SEPARATOR",47:"STR",50:"AGGREGATION",51:"EXTENSION",52:"COMPOSITION",53:"DEPENDENCY",54:"LINE",55:"DOTTED_LINE",56:"CALLBACK",57:"LINK",58:"LINK_TARGET",59:"CLICK",60:"CALLBACK_NAME",61:"CALLBACK_ARGS",62:"HREF",63:"CSSCLASS",66:"graphCodeTokens",68:"TAGSTART",69:"TAGEND",70:"==",71:"--",72:"PCT",73:"DEFAULT",74:"SPACE",75:"MINUS",76:"keywords",77:"UNICODE_TEXT",78:"NUM",79:"ALPHA",80:"BQUOTE_STR"},productions_:[0,[3,1],[3,1],[3,2],[5,1],[5,1],[5,1],[5,1],[4,1],[6,4],[6,6],[12,1],[13,1],[17,1],[14,1],[11,4],[23,1],[23,2],[23,3],[26,1],[26,1],[26,2],[26,2],[26,2],[25,1],[25,2],[25,1],[25,1],[25,1],[25,1],[25,1],[25,1],[25,1],[32,2],[32,4],[32,5],[32,7],[34,4],[40,1],[40,2],[33,1],[33,2],[33,1],[33,1],[30,3],[30,4],[30,4],[30,5],[46,3],[46,2],[46,2],[46,1],[48,1],[48,1],[48,1],[48,1],[49,1],[49,1],[35,3],[35,4],[35,3],[35,4],[35,4],[35,5],[35,3],[35,4],[35,4],[35,5],[35,3],[35,4],[35,4],[35,5],[36,3],[64,1],[64,1],[65,1],[65,1],[65,1],[65,1],[65,1],[65,1],[65,1],[67,1],[67,1],[67,1],[67,1],[27,1],[27,1],[27,1],[28,1]],performAction:function(t,e,n,r,i,a,o){var s=a.length-1;switch(i){case 4:r.setDirection("TB");break;case 5:r.setDirection("BT");break;case 6:r.setDirection("RL");break;case 7:r.setDirection("LR");break;case 11:r.parseDirective("%%{","open_directive");break;case 12:r.parseDirective(a[s],"type_directive");break;case 13:a[s]=a[s].trim().replace(/'/g,'"'),r.parseDirective(a[s],"arg_directive");break;case 14:r.parseDirective("}%%","close_directive","class");break;case 19:case 20:this.$=a[s];break;case 21:this.$=a[s-1]+a[s];break;case 22:case 23:this.$=a[s-1]+"~"+a[s];break;case 24:r.addRelation(a[s]);break;case 25:a[s-1].title=r.cleanupLabel(a[s]),r.addRelation(a[s-1]);break;case 33:r.addClass(a[s]);break;case 34:r.addClass(a[s-2]),r.setCssClass(a[s-2],a[s]);break;case 35:r.addClass(a[s-3]),r.addMembers(a[s-3],a[s-1]);break;case 36:r.addClass(a[s-5]),r.setCssClass(a[s-5],a[s-3]),r.addMembers(a[s-5],a[s-1]);break;case 37:r.addAnnotation(a[s],a[s-2]);break;case 38:this.$=[a[s]];break;case 39:a[s].push(a[s-1]),this.$=a[s];break;case 40:break;case 41:r.addMember(a[s-1],r.cleanupLabel(a[s]));break;case 42:case 43:break;case 44:this.$={id1:a[s-2],id2:a[s],relation:a[s-1],relationTitle1:"none",relationTitle2:"none"};break;case 45:this.$={id1:a[s-3],id2:a[s],relation:a[s-1],relationTitle1:a[s-2],relationTitle2:"none"};break;case 46:this.$={id1:a[s-3],id2:a[s],relation:a[s-2],relationTitle1:"none",relationTitle2:a[s-1]};break;case 47:this.$={id1:a[s-4],id2:a[s],relation:a[s-2],relationTitle1:a[s-3],relationTitle2:a[s-1]};break;case 48:this.$={type1:a[s-2],type2:a[s],lineType:a[s-1]};break;case 49:this.$={type1:"none",type2:a[s],lineType:a[s-1]};break;case 50:this.$={type1:a[s-1],type2:"none",lineType:a[s]};break;case 51:this.$={type1:"none",type2:"none",lineType:a[s]};break;case 52:this.$=r.relationType.AGGREGATION;break;case 53:this.$=r.relationType.EXTENSION;break;case 54:this.$=r.relationType.COMPOSITION;break;case 55:this.$=r.relationType.DEPENDENCY;break;case 56:this.$=r.lineType.LINE;break;case 57:this.$=r.lineType.DOTTED_LINE;break;case 58:case 64:this.$=a[s-2],r.setClickEvent(a[s-1],a[s]);break;case 59:case 65:this.$=a[s-3],r.setClickEvent(a[s-2],a[s-1]),r.setTooltip(a[s-2],a[s]);break;case 60:case 68:this.$=a[s-2],r.setLink(a[s-1],a[s]);break;case 61:this.$=a[s-3],r.setLink(a[s-2],a[s-1],a[s]);break;case 62:case 70:this.$=a[s-3],r.setLink(a[s-2],a[s-1]),r.setTooltip(a[s-2],a[s]);break;case 63:case 71:this.$=a[s-4],r.setLink(a[s-3],a[s-2],a[s]),r.setTooltip(a[s-3],a[s-1]);break;case 66:this.$=a[s-3],r.setClickEvent(a[s-2],a[s-1],a[s]);break;case 67:this.$=a[s-4],r.setClickEvent(a[s-3],a[s-2],a[s-1]),r.setTooltip(a[s-3],a[s]);break;case 69:this.$=a[s-3],r.setLink(a[s-2],a[s-1],a[s]);break;case 72:r.setCssClass(a[s-1],a[s])}},table:[{3:1,4:2,5:3,6:4,7:e,8:n,9:r,10:i,11:5,12:10,18:a,22:o},{1:[3]},{1:[2,1]},{1:[2,2]},{3:13,4:2,5:3,6:4,7:e,8:n,9:r,10:i,11:5,12:10,18:a,22:o},{1:[2,8]},t(s,[2,4]),t(s,[2,5]),t(s,[2,6]),t(s,[2,7]),{13:14,19:[1,15]},{15:[1,16]},{19:[2,11]},{1:[2,3]},{14:17,16:[1,18],21:c},t([16,21],[2,12]),{5:29,6:28,7:e,8:n,9:r,10:i,12:10,18:a,23:20,25:21,26:30,27:39,28:40,30:22,32:23,33:24,34:25,35:26,36:27,37:u,42:l,44:h,45:f,56:d,57:p,59:y,63:g,77:m,78:v,79:b,80:_},{15:[1,45]},{17:46,20:[1,47]},{15:[2,14]},{24:[1,48]},{15:[1,49],24:[2,16]},t(x,[2,24],{31:[1,50]}),t(x,[2,26]),t(x,[2,27]),t(x,[2,28]),t(x,[2,29]),t(x,[2,30]),t(x,[2,31]),t(x,[2,32]),t(x,[2,40],{46:51,48:54,49:55,31:[1,53],47:[1,52],50:w,51:k,52:T,53:E,54:C,55:S}),{26:62,27:39,28:40,77:m,78:v,79:b,80:_},t(x,[2,42]),t(x,[2,43]),{27:63,77:m,78:v,79:b},{26:64,27:39,28:40,77:m,78:v,79:b,80:_},{26:65,27:39,28:40,77:m,78:v,79:b,80:_},{26:66,27:39,28:40,77:m,78:v,79:b,80:_},{47:[1,67]},t(A,[2,19],{27:39,28:40,26:68,29:[1,69],77:m,78:v,79:b,80:_}),t(A,[2,20],{29:[1,70]}),t(M,[2,86]),t(M,[2,87]),t(M,[2,88]),t([15,24,29,31,38,39,47,50,51,52,53,54,55,60,62],[2,89]),t(N,[2,9]),{14:71,21:c},{21:[2,13]},{1:[2,15]},{5:29,6:28,7:e,8:n,9:r,10:i,12:10,18:a,23:72,24:[2,17],25:21,26:30,27:39,28:40,30:22,32:23,33:24,34:25,35:26,36:27,37:u,42:l,44:h,45:f,56:d,57:p,59:y,63:g,77:m,78:v,79:b,80:_},t(x,[2,25]),{26:73,27:39,28:40,47:[1,74],77:m,78:v,79:b,80:_},{46:75,48:54,49:55,50:w,51:k,52:T,53:E,54:C,55:S},t(x,[2,41]),{49:76,54:C,55:S},t(D,[2,51],{48:77,50:w,51:k,52:T,53:E}),t(O,[2,52]),t(O,[2,53]),t(O,[2,54]),t(O,[2,55]),t(B,[2,56]),t(B,[2,57]),t(x,[2,33],{38:[1,78],39:[1,79]}),{43:[1,80]},{47:[1,81]},{47:[1,82]},{60:[1,83],62:[1,84]},{27:85,77:m,78:v,79:b},t(A,[2,21]),t(A,[2,22]),t(A,[2,23]),{15:[1,86]},{24:[2,18]},t(L,[2,44]),{26:87,27:39,28:40,77:m,78:v,79:b,80:_},{26:88,27:39,28:40,47:[1,89],77:m,78:v,79:b,80:_},t(D,[2,50],{48:90,50:w,51:k,52:T,53:E}),t(D,[2,49]),{27:91,77:m,78:v,79:b},{40:92,44:I},{26:94,27:39,28:40,77:m,78:v,79:b,80:_},t(x,[2,58],{47:[1,95]}),t(x,[2,60],{47:[1,97],58:[1,96]}),t(x,[2,64],{47:[1,98],61:[1,99]}),t(x,[2,68],{47:[1,101],58:[1,100]}),t(x,[2,72]),t(N,[2,10]),t(L,[2,46]),t(L,[2,45]),{26:102,27:39,28:40,77:m,78:v,79:b,80:_},t(D,[2,48]),t(x,[2,34],{39:[1,103]}),{41:[1,104]},{40:105,41:[2,38],44:I},t(x,[2,37]),t(x,[2,59]),t(x,[2,61]),t(x,[2,62],{58:[1,106]}),t(x,[2,65]),t(x,[2,66],{47:[1,107]}),t(x,[2,69]),t(x,[2,70],{58:[1,108]}),t(L,[2,47]),{40:109,44:I},t(x,[2,35]),{41:[2,39]},t(x,[2,63]),t(x,[2,67]),t(x,[2,71]),{41:[1,110]},t(x,[2,36])],defaultActions:{2:[2,1],3:[2,2],5:[2,8],12:[2,11],13:[2,3],19:[2,14],47:[2,13],48:[2,15],72:[2,18],105:[2,39]},parseError:function(t,e){if(!e.recoverable){var n=new Error(t);throw n.hash=e,n}this.trace(t)},parse:function(t){var e=this,n=[0],r=[],i=[null],a=[],o=this.table,s="",c=0,u=0,l=0,h=2,f=1,d=a.slice.call(arguments,1),p=Object.create(this.lexer),y={yy:{}};for(var g in this.yy)Object.prototype.hasOwnProperty.call(this.yy,g)&&(y.yy[g]=this.yy[g]);p.setInput(t,y.yy),y.yy.lexer=p,y.yy.parser=this,void 0===p.yylloc&&(p.yylloc={});var m=p.yylloc;a.push(m);var v=p.options&&p.options.ranges;function b(){var t;return"number"!=typeof(t=r.pop()||p.lex()||f)&&(t instanceof Array&&(t=(r=t).pop()),t=e.symbols_[t]||t),t}"function"==typeof y.yy.parseError?this.parseError=y.yy.parseError:this.parseError=Object.getPrototypeOf(this).parseError;for(var _,x,w,k,T,E,C,S,A,M={};;){if(w=n[n.length-1],this.defaultActions[w]?k=this.defaultActions[w]:(null==_&&(_=b()),k=o[w]&&o[w][_]),void 0===k||!k.length||!k[0]){var N="";for(E in A=[],o[w])this.terminals_[E]&&E>h&&A.push("'"+this.terminals_[E]+"'");N=p.showPosition?"Parse error on line "+(c+1)+":\n"+p.showPosition()+"\nExpecting "+A.join(", ")+", got '"+(this.terminals_[_]||_)+"'":"Parse error on line "+(c+1)+": Unexpected "+(_==f?"end of input":"'"+(this.terminals_[_]||_)+"'"),this.parseError(N,{text:p.match,token:this.terminals_[_]||_,line:p.yylineno,loc:m,expected:A})}if(k[0]instanceof Array&&k.length>1)throw new Error("Parse Error: multiple actions possible at state: "+w+", token: "+_);switch(k[0]){case 1:n.push(_),i.push(p.yytext),a.push(p.yylloc),n.push(k[1]),_=null,x?(_=x,x=null):(u=p.yyleng,s=p.yytext,c=p.yylineno,m=p.yylloc,l>0&&l--);break;case 2:if(C=this.productions_[k[1]][1],M.$=i[i.length-C],M._$={first_line:a[a.length-(C||1)].first_line,last_line:a[a.length-1].last_line,first_column:a[a.length-(C||1)].first_column,last_column:a[a.length-1].last_column},v&&(M._$.range=[a[a.length-(C||1)].range[0],a[a.length-1].range[1]]),void 0!==(T=this.performAction.apply(M,[s,u,c,y.yy,k[1],i,a].concat(d))))return T;C&&(n=n.slice(0,-1*C*2),i=i.slice(0,-1*C),a=a.slice(0,-1*C)),n.push(this.productions_[k[1]][0]),i.push(M.$),a.push(M._$),S=o[n[n.length-2]][n[n.length-1]],n.push(S);break;case 3:return!0}}return!0}},F={EOF:1,parseError:function(t,e){if(!this.yy.parser)throw new Error(t);this.yy.parser.parseError(t,e)},setInput:function(t,e){return this.yy=e||this.yy||{},this._input=t,this._more=this._backtrack=this.done=!1,this.yylineno=this.yyleng=0,this.yytext=this.matched=this.match="",this.conditionStack=["INITIAL"],this.yylloc={first_line:1,first_column:0,last_line:1,last_column:0},this.options.ranges&&(this.yylloc.range=[0,0]),this.offset=0,this},input:function(){var t=this._input[0];return this.yytext+=t,this.yyleng++,this.offset++,this.match+=t,this.matched+=t,t.match(/(?:\r\n?|\n).*/g)?(this.yylineno++,this.yylloc.last_line++):this.yylloc.last_column++,this.options.ranges&&this.yylloc.range[1]++,this._input=this._input.slice(1),t},unput:function(t){var e=t.length,n=t.split(/(?:\r\n?|\n)/g);this._input=t+this._input,this.yytext=this.yytext.substr(0,this.yytext.length-e),this.offset-=e;var r=this.match.split(/(?:\r\n?|\n)/g);this.match=this.match.substr(0,this.match.length-1),this.matched=this.matched.substr(0,this.matched.length-1),n.length-1&&(this.yylineno-=n.length-1);var i=this.yylloc.range;return this.yylloc={first_line:this.yylloc.first_line,last_line:this.yylineno+1,first_column:this.yylloc.first_column,last_column:n?(n.length===r.length?this.yylloc.first_column:0)+r[r.length-n.length].length-n[0].length:this.yylloc.first_column-e},this.options.ranges&&(this.yylloc.range=[i[0],i[0]+this.yyleng-e]),this.yyleng=this.yytext.length,this},more:function(){return this._more=!0,this},reject:function(){return this.options.backtrack_lexer?(this._backtrack=!0,this):this.parseError("Lexical error on line "+(this.yylineno+1)+". You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true).\n"+this.showPosition(),{text:"",token:null,line:this.yylineno})},less:function(t){this.unput(this.match.slice(t))},pastInput:function(){var t=this.matched.substr(0,this.matched.length-this.match.length);return(t.length>20?"...":"")+t.substr(-20).replace(/\n/g,"")},upcomingInput:function(){var t=this.match;return t.length<20&&(t+=this._input.substr(0,20-t.length)),(t.substr(0,20)+(t.length>20?"...":"")).replace(/\n/g,"")},showPosition:function(){var t=this.pastInput(),e=new Array(t.length+1).join("-");return t+this.upcomingInput()+"\n"+e+"^"},test_match:function(t,e){var n,r,i;if(this.options.backtrack_lexer&&(i={yylineno:this.yylineno,yylloc:{first_line:this.yylloc.first_line,last_line:this.last_line,first_column:this.yylloc.first_column,last_column:this.yylloc.last_column},yytext:this.yytext,match:this.match,matches:this.matches,matched:this.matched,yyleng:this.yyleng,offset:this.offset,_more:this._more,_input:this._input,yy:this.yy,conditionStack:this.conditionStack.slice(0),done:this.done},this.options.ranges&&(i.yylloc.range=this.yylloc.range.slice(0))),(r=t[0].match(/(?:\r\n?|\n).*/g))&&(this.yylineno+=r.length),this.yylloc={first_line:this.yylloc.last_line,last_line:this.yylineno+1,first_column:this.yylloc.last_column,last_column:r?r[r.length-1].length-r[r.length-1].match(/\r?\n?/)[0].length:this.yylloc.last_column+t[0].length},this.yytext+=t[0],this.match+=t[0],this.matches=t,this.yyleng=this.yytext.length,this.options.ranges&&(this.yylloc.range=[this.offset,this.offset+=this.yyleng]),this._more=!1,this._backtrack=!1,this._input=this._input.slice(t[0].length),this.matched+=t[0],n=this.performAction.call(this,this.yy,this,e,this.conditionStack[this.conditionStack.length-1]),this.done&&this._input&&(this.done=!1),n)return n;if(this._backtrack){for(var a in i)this[a]=i[a];return!1}return!1},next:function(){if(this.done)return this.EOF;var t,e,n,r;this._input||(this.done=!0),this._more||(this.yytext="",this.match="");for(var i=this._currentRules(),a=0;ae[0].length)){if(e=n,r=a,this.options.backtrack_lexer){if(!1!==(t=this.test_match(n,i[a])))return t;if(this._backtrack){e=!1;continue}return!1}if(!this.options.flex)break}return e?!1!==(t=this.test_match(e,i[r]))&&t:""===this._input?this.EOF:this.parseError("Lexical error on line "+(this.yylineno+1)+". Unrecognized text.\n"+this.showPosition(),{text:"",token:null,line:this.yylineno})},lex:function(){return this.next()||this.lex()},begin:function(t){this.conditionStack.push(t)},popState:function(){return this.conditionStack.length-1>0?this.conditionStack.pop():this.conditionStack[0]},_currentRules:function(){return this.conditionStack.length&&this.conditionStack[this.conditionStack.length-1]?this.conditions[this.conditionStack[this.conditionStack.length-1]].rules:this.conditions.INITIAL.rules},topState:function(t){return(t=this.conditionStack.length-1-Math.abs(t||0))>=0?this.conditionStack[t]:"INITIAL"},pushState:function(t){this.begin(t)},stateStackSize:function(){return this.conditionStack.length},options:{},performAction:function(t,e,n,r){switch(n){case 0:return this.begin("open_directive"),18;case 1:return 7;case 2:return 8;case 3:return 9;case 4:return 10;case 5:return this.begin("type_directive"),19;case 6:return this.popState(),this.begin("arg_directive"),16;case 7:return this.popState(),this.popState(),21;case 8:return 20;case 9:case 10:break;case 11:return 15;case 12:break;case 13:case 14:return 22;case 15:return this.begin("struct"),39;case 16:return"EOF_IN_STRUCT";case 17:return"OPEN_IN_STRUCT";case 18:return this.popState(),41;case 19:break;case 20:return"MEMBER";case 21:return 37;case 22:return 63;case 23:return 56;case 24:return 57;case 25:return 59;case 26:return 42;case 27:return 43;case 28:this.begin("generic");break;case 29:this.popState();break;case 30:return"GENERICTYPE";case 31:this.begin("string");break;case 32:this.popState();break;case 33:return"STR";case 34:this.begin("bqstring");break;case 35:this.popState();break;case 36:return"BQUOTE_STR";case 37:this.begin("href");break;case 38:this.popState();break;case 39:return 62;case 40:this.begin("callback_name");break;case 41:this.popState();break;case 42:this.popState(),this.begin("callback_args");break;case 43:return 60;case 44:this.popState();break;case 45:return 61;case 46:case 47:case 48:case 49:return 58;case 50:case 51:return 51;case 52:case 53:return 53;case 54:return 52;case 55:return 50;case 56:return 54;case 57:return 55;case 58:return 31;case 59:return 38;case 60:return 75;case 61:return"DOT";case 62:return"PLUS";case 63:return 72;case 64:case 65:return"EQUALS";case 66:return 79;case 67:return"PUNCTUATION";case 68:return 78;case 69:return 77;case 70:return 74;case 71:return 24}},rules:[/^(?:%%\{)/,/^(?:.*direction\s+TB[^\n]*)/,/^(?:.*direction\s+BT[^\n]*)/,/^(?:.*direction\s+RL[^\n]*)/,/^(?:.*direction\s+LR[^\n]*)/,/^(?:((?:(?!\}%%)[^:.])*))/,/^(?::)/,/^(?:\}%%)/,/^(?:((?:(?!\}%%).|\n)*))/,/^(?:%%(?!\{)*[^\n]*(\r?\n?)+)/,/^(?:%%[^\n]*(\r?\n)*)/,/^(?:\s*(\r?\n)+)/,/^(?:\s+)/,/^(?:classDiagram-v2\b)/,/^(?:classDiagram\b)/,/^(?:[{])/,/^(?:$)/,/^(?:[{])/,/^(?:[}])/,/^(?:[\n])/,/^(?:[^{}\n]*)/,/^(?:class\b)/,/^(?:cssClass\b)/,/^(?:callback\b)/,/^(?:link\b)/,/^(?:click\b)/,/^(?:<<)/,/^(?:>>)/,/^(?:[~])/,/^(?:[~])/,/^(?:[^~]*)/,/^(?:["])/,/^(?:["])/,/^(?:[^"]*)/,/^(?:[`])/,/^(?:[`])/,/^(?:[^`]+)/,/^(?:href[\s]+["])/,/^(?:["])/,/^(?:[^"]*)/,/^(?:call[\s]+)/,/^(?:\([\s]*\))/,/^(?:\()/,/^(?:[^(]*)/,/^(?:\))/,/^(?:[^)]*)/,/^(?:_self\b)/,/^(?:_blank\b)/,/^(?:_parent\b)/,/^(?:_top\b)/,/^(?:\s*<\|)/,/^(?:\s*\|>)/,/^(?:\s*>)/,/^(?:\s*<)/,/^(?:\s*\*)/,/^(?:\s*o\b)/,/^(?:--)/,/^(?:\.\.)/,/^(?::{1}[^:\n;]+)/,/^(?::{3})/,/^(?:-)/,/^(?:\.)/,/^(?:\+)/,/^(?:%)/,/^(?:=)/,/^(?:=)/,/^(?:\w+)/,/^(?:[!"#$%&'*+,-.`?\\/])/,/^(?:[0-9]+)/,/^(?:[\u00AA\u00B5\u00BA\u00C0-\u00D6\u00D8-\u00F6]|[\u00F8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377]|[\u037A-\u037D\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5]|[\u03F7-\u0481\u048A-\u0527\u0531-\u0556\u0559\u0561-\u0587\u05D0-\u05EA]|[\u05F0-\u05F2\u0620-\u064A\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE]|[\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA]|[\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u08A0]|[\u08A2-\u08AC\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0977]|[\u0979-\u097F\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2]|[\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09F0\u09F1\u0A05-\u0A0A]|[\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39]|[\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8]|[\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0B05-\u0B0C]|[\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C]|[\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99]|[\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0]|[\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C33\u0C35-\u0C39\u0C3D]|[\u0C58\u0C59\u0C60\u0C61\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3]|[\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D05-\u0D0C\u0D0E-\u0D10]|[\u0D12-\u0D3A\u0D3D\u0D4E\u0D60\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1]|[\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E81]|[\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3]|[\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6]|[\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A]|[\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081]|[\u108E\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D]|[\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0]|[\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310]|[\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F4\u1401-\u166C]|[\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u1700-\u170C\u170E-\u1711]|[\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7]|[\u17DC\u1820-\u1877\u1880-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191C]|[\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19C1-\u19C7\u1A00-\u1A16]|[\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-\u1B4B\u1B83-\u1BA0\u1BAE\u1BAF]|[\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\u1CE9-\u1CEC]|[\u1CEE-\u1CF1\u1CF5\u1CF6\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D]|[\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D]|[\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3]|[\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F]|[\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128]|[\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2183\u2184]|[\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3]|[\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6]|[\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE]|[\u2DD0-\u2DD6\u2DD8-\u2DDE\u2E2F\u3005\u3006\u3031-\u3035\u303B\u303C]|[\u3041-\u3096\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D]|[\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FCC]|[\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B]|[\uA640-\uA66E\uA67F-\uA697\uA6A0-\uA6E5\uA717-\uA71F\uA722-\uA788]|[\uA78B-\uA78E\uA790-\uA793\uA7A0-\uA7AA\uA7F8-\uA801\uA803-\uA805]|[\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB]|[\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF\uAA00-\uAA28]|[\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA80-\uAAAF\uAAB1\uAAB5]|[\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4]|[\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E]|[\uABC0-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D]|[\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36]|[\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D]|[\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC]|[\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF]|[\uFFD2-\uFFD7\uFFDA-\uFFDC])/,/^(?:\s)/,/^(?:$)/],conditions:{arg_directive:{rules:[7,8],inclusive:!1},type_directive:{rules:[6,7],inclusive:!1},open_directive:{rules:[5],inclusive:!1},callback_args:{rules:[44,45],inclusive:!1},callback_name:{rules:[41,42,43],inclusive:!1},href:{rules:[38,39],inclusive:!1},struct:{rules:[16,17,18,19,20],inclusive:!1},generic:{rules:[29,30],inclusive:!1},bqstring:{rules:[35,36],inclusive:!1},string:{rules:[32,33],inclusive:!1},INITIAL:{rules:[0,1,2,3,4,9,10,11,12,13,14,15,21,22,23,24,25,26,27,28,31,34,37,40,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71],inclusive:!0}}};function P(){this.yy={}}return R.lexer=F,P.prototype=R,R.Parser=P,new P}();e.parser=r,e.Parser=r.Parser,e.parse=function(){return r.parse.apply(r,arguments)},e.main=function(t){t[1]||(console.log("Usage: "+t[0]+" FILE"),process.exit(1));var r=n(8218).readFileSync(n(6470).normalize(t[1]),"utf8");return e.parser.parse(r)},n.c[n.s]===t&&e.main(process.argv.slice(1))},4701:(t,e,n)=>{t=n.nmd(t);var r=function(){var t=function(t,e,n,r){for(n=n||{},r=t.length;r--;n[t[r]]=e);return n},e=[1,2],n=[1,5],r=[6,9,11,23,40],i=[1,17],a=[1,20],o=[1,25],s=[1,26],c=[1,27],u=[1,28],l=[1,37],h=[23,37,38],f=[4,6,9,11,23,40],d=[33,34,35,36],p=[22,29],y={trace:function(){},yy:{},symbols_:{error:2,start:3,ER_DIAGRAM:4,document:5,EOF:6,directive:7,line:8,SPACE:9,statement:10,NEWLINE:11,openDirective:12,typeDirective:13,closeDirective:14,":":15,argDirective:16,entityName:17,relSpec:18,role:19,BLOCK_START:20,attributes:21,BLOCK_STOP:22,ALPHANUM:23,attribute:24,attributeType:25,attributeName:26,attributeKeyType:27,COMMENT:28,ATTRIBUTE_WORD:29,ATTRIBUTE_KEY:30,cardinality:31,relType:32,ZERO_OR_ONE:33,ZERO_OR_MORE:34,ONE_OR_MORE:35,ONLY_ONE:36,NON_IDENTIFYING:37,IDENTIFYING:38,WORD:39,open_directive:40,type_directive:41,arg_directive:42,close_directive:43,$accept:0,$end:1},terminals_:{2:"error",4:"ER_DIAGRAM",6:"EOF",9:"SPACE",11:"NEWLINE",15:":",20:"BLOCK_START",22:"BLOCK_STOP",23:"ALPHANUM",28:"COMMENT",29:"ATTRIBUTE_WORD",30:"ATTRIBUTE_KEY",33:"ZERO_OR_ONE",34:"ZERO_OR_MORE",35:"ONE_OR_MORE",36:"ONLY_ONE",37:"NON_IDENTIFYING",38:"IDENTIFYING",39:"WORD",40:"open_directive",41:"type_directive",42:"arg_directive",43:"close_directive"},productions_:[0,[3,3],[3,2],[5,0],[5,2],[8,2],[8,1],[8,1],[8,1],[7,4],[7,6],[10,1],[10,5],[10,4],[10,3],[10,1],[17,1],[21,1],[21,2],[24,2],[24,3],[24,3],[24,4],[25,1],[26,1],[27,1],[18,3],[31,1],[31,1],[31,1],[31,1],[32,1],[32,1],[19,1],[19,1],[12,1],[13,1],[16,1],[14,1]],performAction:function(t,e,n,r,i,a,o){var s=a.length-1;switch(i){case 1:break;case 3:this.$=[];break;case 4:a[s-1].push(a[s]),this.$=a[s-1];break;case 5:case 6:this.$=a[s];break;case 7:case 8:this.$=[];break;case 12:r.addEntity(a[s-4]),r.addEntity(a[s-2]),r.addRelationship(a[s-4],a[s],a[s-2],a[s-3]);break;case 13:r.addEntity(a[s-3]),r.addAttributes(a[s-3],a[s-1]);break;case 14:r.addEntity(a[s-2]);break;case 15:r.addEntity(a[s]);break;case 16:this.$=a[s];break;case 17:this.$=[a[s]];break;case 18:a[s].push(a[s-1]),this.$=a[s];break;case 19:this.$={attributeType:a[s-1],attributeName:a[s]};break;case 20:this.$={attributeType:a[s-2],attributeName:a[s-1],attributeKeyType:a[s]};break;case 21:this.$={attributeType:a[s-2],attributeName:a[s-1],attributeComment:a[s]};break;case 22:this.$={attributeType:a[s-3],attributeName:a[s-2],attributeKeyType:a[s-1],attributeComment:a[s]};break;case 23:case 24:case 25:this.$=a[s];break;case 26:this.$={cardA:a[s],relType:a[s-1],cardB:a[s-2]};break;case 27:this.$=r.Cardinality.ZERO_OR_ONE;break;case 28:this.$=r.Cardinality.ZERO_OR_MORE;break;case 29:this.$=r.Cardinality.ONE_OR_MORE;break;case 30:this.$=r.Cardinality.ONLY_ONE;break;case 31:this.$=r.Identification.NON_IDENTIFYING;break;case 32:this.$=r.Identification.IDENTIFYING;break;case 33:this.$=a[s].replace(/"/g,"");break;case 34:this.$=a[s];break;case 35:r.parseDirective("%%{","open_directive");break;case 36:r.parseDirective(a[s],"type_directive");break;case 37:a[s]=a[s].trim().replace(/'/g,'"'),r.parseDirective(a[s],"arg_directive");break;case 38:r.parseDirective("}%%","close_directive","er")}},table:[{3:1,4:e,7:3,12:4,40:n},{1:[3]},t(r,[2,3],{5:6}),{3:7,4:e,7:3,12:4,40:n},{13:8,41:[1,9]},{41:[2,35]},{6:[1,10],7:15,8:11,9:[1,12],10:13,11:[1,14],12:4,17:16,23:i,40:n},{1:[2,2]},{14:18,15:[1,19],43:a},t([15,43],[2,36]),t(r,[2,8],{1:[2,1]}),t(r,[2,4]),{7:15,10:21,12:4,17:16,23:i,40:n},t(r,[2,6]),t(r,[2,7]),t(r,[2,11]),t(r,[2,15],{18:22,31:24,20:[1,23],33:o,34:s,35:c,36:u}),t([6,9,11,15,20,23,33,34,35,36,40],[2,16]),{11:[1,29]},{16:30,42:[1,31]},{11:[2,38]},t(r,[2,5]),{17:32,23:i},{21:33,22:[1,34],24:35,25:36,29:l},{32:38,37:[1,39],38:[1,40]},t(h,[2,27]),t(h,[2,28]),t(h,[2,29]),t(h,[2,30]),t(f,[2,9]),{14:41,43:a},{43:[2,37]},{15:[1,42]},{22:[1,43]},t(r,[2,14]),{21:44,22:[2,17],24:35,25:36,29:l},{26:45,29:[1,46]},{29:[2,23]},{31:47,33:o,34:s,35:c,36:u},t(d,[2,31]),t(d,[2,32]),{11:[1,48]},{19:49,23:[1,51],39:[1,50]},t(r,[2,13]),{22:[2,18]},t(p,[2,19],{27:52,28:[1,53],30:[1,54]}),t([22,28,29,30],[2,24]),{23:[2,26]},t(f,[2,10]),t(r,[2,12]),t(r,[2,33]),t(r,[2,34]),t(p,[2,20],{28:[1,55]}),t(p,[2,21]),t([22,28,29],[2,25]),t(p,[2,22])],defaultActions:{5:[2,35],7:[2,2],20:[2,38],31:[2,37],37:[2,23],44:[2,18],47:[2,26]},parseError:function(t,e){if(!e.recoverable){var n=new Error(t);throw n.hash=e,n}this.trace(t)},parse:function(t){var e=this,n=[0],r=[],i=[null],a=[],o=this.table,s="",c=0,u=0,l=0,h=2,f=1,d=a.slice.call(arguments,1),p=Object.create(this.lexer),y={yy:{}};for(var g in this.yy)Object.prototype.hasOwnProperty.call(this.yy,g)&&(y.yy[g]=this.yy[g]);p.setInput(t,y.yy),y.yy.lexer=p,y.yy.parser=this,void 0===p.yylloc&&(p.yylloc={});var m=p.yylloc;a.push(m);var v=p.options&&p.options.ranges;function b(){var t;return"number"!=typeof(t=r.pop()||p.lex()||f)&&(t instanceof Array&&(t=(r=t).pop()),t=e.symbols_[t]||t),t}"function"==typeof y.yy.parseError?this.parseError=y.yy.parseError:this.parseError=Object.getPrototypeOf(this).parseError;for(var _,x,w,k,T,E,C,S,A,M={};;){if(w=n[n.length-1],this.defaultActions[w]?k=this.defaultActions[w]:(null==_&&(_=b()),k=o[w]&&o[w][_]),void 0===k||!k.length||!k[0]){var N="";for(E in A=[],o[w])this.terminals_[E]&&E>h&&A.push("'"+this.terminals_[E]+"'");N=p.showPosition?"Parse error on line "+(c+1)+":\n"+p.showPosition()+"\nExpecting "+A.join(", ")+", got '"+(this.terminals_[_]||_)+"'":"Parse error on line "+(c+1)+": Unexpected "+(_==f?"end of input":"'"+(this.terminals_[_]||_)+"'"),this.parseError(N,{text:p.match,token:this.terminals_[_]||_,line:p.yylineno,loc:m,expected:A})}if(k[0]instanceof Array&&k.length>1)throw new Error("Parse Error: multiple actions possible at state: "+w+", token: "+_);switch(k[0]){case 1:n.push(_),i.push(p.yytext),a.push(p.yylloc),n.push(k[1]),_=null,x?(_=x,x=null):(u=p.yyleng,s=p.yytext,c=p.yylineno,m=p.yylloc,l>0&&l--);break;case 2:if(C=this.productions_[k[1]][1],M.$=i[i.length-C],M._$={first_line:a[a.length-(C||1)].first_line,last_line:a[a.length-1].last_line,first_column:a[a.length-(C||1)].first_column,last_column:a[a.length-1].last_column},v&&(M._$.range=[a[a.length-(C||1)].range[0],a[a.length-1].range[1]]),void 0!==(T=this.performAction.apply(M,[s,u,c,y.yy,k[1],i,a].concat(d))))return T;C&&(n=n.slice(0,-1*C*2),i=i.slice(0,-1*C),a=a.slice(0,-1*C)),n.push(this.productions_[k[1]][0]),i.push(M.$),a.push(M._$),S=o[n[n.length-2]][n[n.length-1]],n.push(S);break;case 3:return!0}}return!0}},g={EOF:1,parseError:function(t,e){if(!this.yy.parser)throw new Error(t);this.yy.parser.parseError(t,e)},setInput:function(t,e){return this.yy=e||this.yy||{},this._input=t,this._more=this._backtrack=this.done=!1,this.yylineno=this.yyleng=0,this.yytext=this.matched=this.match="",this.conditionStack=["INITIAL"],this.yylloc={first_line:1,first_column:0,last_line:1,last_column:0},this.options.ranges&&(this.yylloc.range=[0,0]),this.offset=0,this},input:function(){var t=this._input[0];return this.yytext+=t,this.yyleng++,this.offset++,this.match+=t,this.matched+=t,t.match(/(?:\r\n?|\n).*/g)?(this.yylineno++,this.yylloc.last_line++):this.yylloc.last_column++,this.options.ranges&&this.yylloc.range[1]++,this._input=this._input.slice(1),t},unput:function(t){var e=t.length,n=t.split(/(?:\r\n?|\n)/g);this._input=t+this._input,this.yytext=this.yytext.substr(0,this.yytext.length-e),this.offset-=e;var r=this.match.split(/(?:\r\n?|\n)/g);this.match=this.match.substr(0,this.match.length-1),this.matched=this.matched.substr(0,this.matched.length-1),n.length-1&&(this.yylineno-=n.length-1);var i=this.yylloc.range;return this.yylloc={first_line:this.yylloc.first_line,last_line:this.yylineno+1,first_column:this.yylloc.first_column,last_column:n?(n.length===r.length?this.yylloc.first_column:0)+r[r.length-n.length].length-n[0].length:this.yylloc.first_column-e},this.options.ranges&&(this.yylloc.range=[i[0],i[0]+this.yyleng-e]),this.yyleng=this.yytext.length,this},more:function(){return this._more=!0,this},reject:function(){return this.options.backtrack_lexer?(this._backtrack=!0,this):this.parseError("Lexical error on line "+(this.yylineno+1)+". You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true).\n"+this.showPosition(),{text:"",token:null,line:this.yylineno})},less:function(t){this.unput(this.match.slice(t))},pastInput:function(){var t=this.matched.substr(0,this.matched.length-this.match.length);return(t.length>20?"...":"")+t.substr(-20).replace(/\n/g,"")},upcomingInput:function(){var t=this.match;return t.length<20&&(t+=this._input.substr(0,20-t.length)),(t.substr(0,20)+(t.length>20?"...":"")).replace(/\n/g,"")},showPosition:function(){var t=this.pastInput(),e=new Array(t.length+1).join("-");return t+this.upcomingInput()+"\n"+e+"^"},test_match:function(t,e){var n,r,i;if(this.options.backtrack_lexer&&(i={yylineno:this.yylineno,yylloc:{first_line:this.yylloc.first_line,last_line:this.last_line,first_column:this.yylloc.first_column,last_column:this.yylloc.last_column},yytext:this.yytext,match:this.match,matches:this.matches,matched:this.matched,yyleng:this.yyleng,offset:this.offset,_more:this._more,_input:this._input,yy:this.yy,conditionStack:this.conditionStack.slice(0),done:this.done},this.options.ranges&&(i.yylloc.range=this.yylloc.range.slice(0))),(r=t[0].match(/(?:\r\n?|\n).*/g))&&(this.yylineno+=r.length),this.yylloc={first_line:this.yylloc.last_line,last_line:this.yylineno+1,first_column:this.yylloc.last_column,last_column:r?r[r.length-1].length-r[r.length-1].match(/\r?\n?/)[0].length:this.yylloc.last_column+t[0].length},this.yytext+=t[0],this.match+=t[0],this.matches=t,this.yyleng=this.yytext.length,this.options.ranges&&(this.yylloc.range=[this.offset,this.offset+=this.yyleng]),this._more=!1,this._backtrack=!1,this._input=this._input.slice(t[0].length),this.matched+=t[0],n=this.performAction.call(this,this.yy,this,e,this.conditionStack[this.conditionStack.length-1]),this.done&&this._input&&(this.done=!1),n)return n;if(this._backtrack){for(var a in i)this[a]=i[a];return!1}return!1},next:function(){if(this.done)return this.EOF;var t,e,n,r;this._input||(this.done=!0),this._more||(this.yytext="",this.match="");for(var i=this._currentRules(),a=0;ae[0].length)){if(e=n,r=a,this.options.backtrack_lexer){if(!1!==(t=this.test_match(n,i[a])))return t;if(this._backtrack){e=!1;continue}return!1}if(!this.options.flex)break}return e?!1!==(t=this.test_match(e,i[r]))&&t:""===this._input?this.EOF:this.parseError("Lexical error on line "+(this.yylineno+1)+". Unrecognized text.\n"+this.showPosition(),{text:"",token:null,line:this.yylineno})},lex:function(){return this.next()||this.lex()},begin:function(t){this.conditionStack.push(t)},popState:function(){return this.conditionStack.length-1>0?this.conditionStack.pop():this.conditionStack[0]},_currentRules:function(){return this.conditionStack.length&&this.conditionStack[this.conditionStack.length-1]?this.conditions[this.conditionStack[this.conditionStack.length-1]].rules:this.conditions.INITIAL.rules},topState:function(t){return(t=this.conditionStack.length-1-Math.abs(t||0))>=0?this.conditionStack[t]:"INITIAL"},pushState:function(t){this.begin(t)},stateStackSize:function(){return this.conditionStack.length},options:{"case-insensitive":!0},performAction:function(t,e,n,r){switch(n){case 0:return this.begin("open_directive"),40;case 1:return this.begin("type_directive"),41;case 2:return this.popState(),this.begin("arg_directive"),15;case 3:return this.popState(),this.popState(),43;case 4:return 42;case 5:case 6:break;case 7:return 11;case 8:break;case 9:return 9;case 10:return 39;case 11:return 4;case 12:return this.begin("block"),20;case 13:break;case 14:return 30;case 15:return 29;case 16:return 28;case 17:break;case 18:return this.popState(),22;case 19:return e.yytext[0];case 20:return 33;case 21:return 34;case 22:return 35;case 23:return 36;case 24:return 33;case 25:return 34;case 26:return 35;case 27:return 37;case 28:return 38;case 29:case 30:return 37;case 31:return 23;case 32:return e.yytext[0];case 33:return 6}},rules:[/^(?:%%\{)/i,/^(?:((?:(?!\}%%)[^:.])*))/i,/^(?::)/i,/^(?:\}%%)/i,/^(?:((?:(?!\}%%).|\n)*))/i,/^(?:%(?!\{)[^\n]*)/i,/^(?:[^\}]%%[^\n]*)/i,/^(?:[\n]+)/i,/^(?:\s+)/i,/^(?:[\s]+)/i,/^(?:"[^"]*")/i,/^(?:erDiagram\b)/i,/^(?:\{)/i,/^(?:\s+)/i,/^(?:(?:PK)|(?:FK))/i,/^(?:[A-Za-z][A-Za-z0-9\-_]*)/i,/^(?:"[^"]*")/i,/^(?:[\n]+)/i,/^(?:\})/i,/^(?:.)/i,/^(?:\|o\b)/i,/^(?:\}o\b)/i,/^(?:\}\|)/i,/^(?:\|\|)/i,/^(?:o\|)/i,/^(?:o\{)/i,/^(?:\|\{)/i,/^(?:\.\.)/i,/^(?:--)/i,/^(?:\.-)/i,/^(?:-\.)/i,/^(?:[A-Za-z][A-Za-z0-9\-_]*)/i,/^(?:.)/i,/^(?:$)/i],conditions:{open_directive:{rules:[1],inclusive:!1},type_directive:{rules:[2,3],inclusive:!1},arg_directive:{rules:[3,4],inclusive:!1},block:{rules:[13,14,15,16,17,18,19],inclusive:!1},INITIAL:{rules:[0,5,6,7,8,9,10,11,12,20,21,22,23,24,25,26,27,28,29,30,31,32,33],inclusive:!0}}};function m(){this.yy={}}return y.lexer=g,m.prototype=y,y.Parser=m,new m}();e.parser=r,e.Parser=r.Parser,e.parse=function(){return r.parse.apply(r,arguments)},e.main=function(t){t[1]||(console.log("Usage: "+t[0]+" FILE"),process.exit(1));var r=n(8009).readFileSync(n(6470).normalize(t[1]),"utf8");return e.parser.parse(r)},n.c[n.s]===t&&e.main(process.argv.slice(1))},7805:(t,e,n)=>{t=n.nmd(t);var r=function(){var t=function(t,e,n,r){for(n=n||{},r=t.length;r--;n[t[r]]=e);return n},e=[1,9],n=[1,7],r=[1,6],i=[1,8],a=[1,20,21,22,23,38,47,76,77,78,79,80,81,95,96,99,100,101,103,104,110,111,112,113,114,115,116,117,118,119],o=[2,10],s=[1,20],c=[1,21],u=[1,22],l=[1,23],h=[1,30],f=[1,59],d=[1,33],p=[1,34],y=[1,35],g=[1,36],m=[1,37],v=[1,53],b=[1,48],_=[1,50],x=[1,45],w=[1,49],k=[1,52],T=[1,56],E=[1,57],C=[1,38],S=[1,39],A=[1,40],M=[1,41],N=[1,58],D=[1,47],O=[1,51],B=[1,54],L=[1,55],I=[1,46],R=[1,62],F=[1,67],P=[1,20,21,22,23,38,42,47,76,77,78,79,80,81,95,96,99,100,101,103,104,110,111,112,113,114,115,116,117,118,119],j=[1,71],Y=[1,70],z=[1,72],U=[20,21,23,70,71],q=[1,93],$=[1,98],H=[1,95],W=[1,100],V=[1,103],G=[1,101],X=[1,102],Z=[1,96],Q=[1,108],K=[1,107],J=[1,97],tt=[1,99],et=[1,104],nt=[1,105],rt=[1,106],it=[1,109],at=[20,21,22,23,70,71],ot=[20,21,22,23,48,70,71],st=[20,21,22,23,40,47,48,50,52,54,56,58,60,62,63,65,70,71,81,95,96,99,100,101,103,104,114,115,116,117,118,119],ct=[20,21,23],ut=[20,21,23,47,70,71,81,95,96,99,100,101,103,104,114,115,116,117,118,119],lt=[1,12,20,21,22,23,24,38,42,47,76,77,78,79,80,81,95,96,99,100,101,103,104,110,111,112,113,114,115,116,117,118,119],ht=[47,81,95,96,99,100,101,103,104,114,115,116,117,118,119],ft=[1,141],dt=[1,149],pt=[1,150],yt=[1,151],gt=[1,152],mt=[1,136],vt=[1,137],bt=[1,133],_t=[1,144],xt=[1,145],wt=[1,146],kt=[1,147],Tt=[1,148],Et=[1,153],Ct=[1,154],St=[1,139],At=[1,142],Mt=[1,138],Nt=[1,135],Dt=[20,21,22,23,38,42,47,76,77,78,79,80,81,95,96,99,100,101,103,104,110,111,112,113,114,115,116,117,118,119],Ot=[1,157],Bt=[20,21,22,23,26,47,81,95,96,99,100,101,103,104,114,115,116,117,118,119],Lt=[20,21,22,23,24,26,38,40,41,42,47,51,53,55,57,59,61,62,64,66,70,71,72,76,77,78,79,80,81,82,85,95,96,99,100,101,103,104,105,106,114,115,116,117,118,119],It=[12,21,22,24],Rt=[22,96],Ft=[1,238],Pt=[1,242],jt=[1,239],Yt=[1,236],zt=[1,233],Ut=[1,234],qt=[1,235],$t=[1,237],Ht=[1,240],Wt=[1,241],Vt=[1,243],Gt=[1,260],Xt=[20,21,23,96],Zt=[20,21,22,23,76,92,95,96,99,100,101,102,103,104,105],Qt={trace:function(){},yy:{},symbols_:{error:2,start:3,mermaidDoc:4,directive:5,openDirective:6,typeDirective:7,closeDirective:8,separator:9,":":10,argDirective:11,open_directive:12,type_directive:13,arg_directive:14,close_directive:15,graphConfig:16,document:17,line:18,statement:19,SEMI:20,NEWLINE:21,SPACE:22,EOF:23,GRAPH:24,NODIR:25,DIR:26,FirstStmtSeperator:27,ending:28,endToken:29,spaceList:30,spaceListNewline:31,verticeStatement:32,styleStatement:33,linkStyleStatement:34,classDefStatement:35,classStatement:36,clickStatement:37,subgraph:38,text:39,SQS:40,SQE:41,end:42,direction:43,link:44,node:45,vertex:46,AMP:47,STYLE_SEPARATOR:48,idString:49,PS:50,PE:51,"(-":52,"-)":53,STADIUMSTART:54,STADIUMEND:55,SUBROUTINESTART:56,SUBROUTINEEND:57,CYLINDERSTART:58,CYLINDEREND:59,DIAMOND_START:60,DIAMOND_STOP:61,TAGEND:62,TRAPSTART:63,TRAPEND:64,INVTRAPSTART:65,INVTRAPEND:66,linkStatement:67,arrowText:68,TESTSTR:69,START_LINK:70,LINK:71,PIPE:72,textToken:73,STR:74,keywords:75,STYLE:76,LINKSTYLE:77,CLASSDEF:78,CLASS:79,CLICK:80,DOWN:81,UP:82,textNoTags:83,textNoTagsToken:84,DEFAULT:85,stylesOpt:86,alphaNum:87,CALLBACKNAME:88,CALLBACKARGS:89,HREF:90,LINK_TARGET:91,HEX:92,numList:93,INTERPOLATE:94,NUM:95,COMMA:96,style:97,styleComponent:98,ALPHA:99,COLON:100,MINUS:101,UNIT:102,BRKT:103,DOT:104,PCT:105,TAGSTART:106,alphaNumToken:107,idStringToken:108,alphaNumStatement:109,direction_tb:110,direction_bt:111,direction_rl:112,direction_lr:113,PUNCTUATION:114,UNICODE_TEXT:115,PLUS:116,EQUALS:117,MULT:118,UNDERSCORE:119,graphCodeTokens:120,ARROW_CROSS:121,ARROW_POINT:122,ARROW_CIRCLE:123,ARROW_OPEN:124,QUOTE:125,$accept:0,$end:1},terminals_:{2:"error",10:":",12:"open_directive",13:"type_directive",14:"arg_directive",15:"close_directive",20:"SEMI",21:"NEWLINE",22:"SPACE",23:"EOF",24:"GRAPH",25:"NODIR",26:"DIR",38:"subgraph",40:"SQS",41:"SQE",42:"end",47:"AMP",48:"STYLE_SEPARATOR",50:"PS",51:"PE",52:"(-",53:"-)",54:"STADIUMSTART",55:"STADIUMEND",56:"SUBROUTINESTART",57:"SUBROUTINEEND",58:"CYLINDERSTART",59:"CYLINDEREND",60:"DIAMOND_START",61:"DIAMOND_STOP",62:"TAGEND",63:"TRAPSTART",64:"TRAPEND",65:"INVTRAPSTART",66:"INVTRAPEND",69:"TESTSTR",70:"START_LINK",71:"LINK",72:"PIPE",74:"STR",76:"STYLE",77:"LINKSTYLE",78:"CLASSDEF",79:"CLASS",80:"CLICK",81:"DOWN",82:"UP",85:"DEFAULT",88:"CALLBACKNAME",89:"CALLBACKARGS",90:"HREF",91:"LINK_TARGET",92:"HEX",94:"INTERPOLATE",95:"NUM",96:"COMMA",99:"ALPHA",100:"COLON",101:"MINUS",102:"UNIT",103:"BRKT",104:"DOT",105:"PCT",106:"TAGSTART",110:"direction_tb",111:"direction_bt",112:"direction_rl",113:"direction_lr",114:"PUNCTUATION",115:"UNICODE_TEXT",116:"PLUS",117:"EQUALS",118:"MULT",119:"UNDERSCORE",121:"ARROW_CROSS",122:"ARROW_POINT",123:"ARROW_CIRCLE",124:"ARROW_OPEN",125:"QUOTE"},productions_:[0,[3,1],[3,2],[5,4],[5,6],[6,1],[7,1],[11,1],[8,1],[4,2],[17,0],[17,2],[18,1],[18,1],[18,1],[18,1],[18,1],[16,2],[16,2],[16,2],[16,3],[28,2],[28,1],[29,1],[29,1],[29,1],[27,1],[27,1],[27,2],[31,2],[31,2],[31,1],[31,1],[30,2],[30,1],[19,2],[19,2],[19,2],[19,2],[19,2],[19,2],[19,9],[19,6],[19,4],[19,1],[9,1],[9,1],[9,1],[32,3],[32,4],[32,2],[32,1],[45,1],[45,5],[45,3],[46,4],[46,6],[46,4],[46,4],[46,4],[46,4],[46,4],[46,4],[46,6],[46,4],[46,4],[46,4],[46,4],[46,4],[46,1],[44,2],[44,3],[44,3],[44,1],[44,3],[67,1],[68,3],[39,1],[39,2],[39,1],[75,1],[75,1],[75,1],[75,1],[75,1],[75,1],[75,1],[75,1],[75,1],[75,1],[75,1],[83,1],[83,2],[35,5],[35,5],[36,5],[37,2],[37,4],[37,3],[37,5],[37,2],[37,4],[37,4],[37,6],[37,2],[37,4],[37,2],[37,4],[37,4],[37,6],[33,5],[33,5],[34,5],[34,5],[34,9],[34,9],[34,7],[34,7],[93,1],[93,3],[86,1],[86,3],[97,1],[97,2],[98,1],[98,1],[98,1],[98,1],[98,1],[98,1],[98,1],[98,1],[98,1],[98,1],[98,1],[73,1],[73,1],[73,1],[73,1],[73,1],[73,1],[84,1],[84,1],[84,1],[84,1],[49,1],[49,2],[87,1],[87,2],[109,1],[109,1],[109,1],[109,1],[43,1],[43,1],[43,1],[43,1],[107,1],[107,1],[107,1],[107,1],[107,1],[107,1],[107,1],[107,1],[107,1],[107,1],[107,1],[107,1],[107,1],[108,1],[108,1],[108,1],[108,1],[108,1],[108,1],[108,1],[108,1],[108,1],[108,1],[108,1],[108,1],[108,1],[108,1],[108,1],[120,1],[120,1],[120,1],[120,1],[120,1],[120,1],[120,1],[120,1],[120,1],[120,1],[120,1],[120,1],[120,1],[120,1],[120,1],[120,1],[120,1],[120,1],[120,1],[120,1],[120,1],[120,1],[120,1],[120,1],[120,1]],performAction:function(t,e,n,r,i,a,o){var s=a.length-1;switch(i){case 5:r.parseDirective("%%{","open_directive");break;case 6:r.parseDirective(a[s],"type_directive");break;case 7:a[s]=a[s].trim().replace(/'/g,'"'),r.parseDirective(a[s],"arg_directive");break;case 8:r.parseDirective("}%%","close_directive","flowchart");break;case 10:this.$=[];break;case 11:a[s]!==[]&&a[s-1].push(a[s]),this.$=a[s-1];break;case 12:case 77:case 79:case 91:case 147:case 149:case 150:this.$=a[s];break;case 19:r.setDirection("TB"),this.$="TB";break;case 20:r.setDirection(a[s-1]),this.$=a[s-1];break;case 35:this.$=a[s-1].nodes;break;case 36:case 37:case 38:case 39:case 40:this.$=[];break;case 41:this.$=r.addSubGraph(a[s-6],a[s-1],a[s-4]);break;case 42:this.$=r.addSubGraph(a[s-3],a[s-1],a[s-3]);break;case 43:this.$=r.addSubGraph(void 0,a[s-1],void 0);break;case 48:r.addLink(a[s-2].stmt,a[s],a[s-1]),this.$={stmt:a[s],nodes:a[s].concat(a[s-2].nodes)};break;case 49:r.addLink(a[s-3].stmt,a[s-1],a[s-2]),this.$={stmt:a[s-1],nodes:a[s-1].concat(a[s-3].nodes)};break;case 50:this.$={stmt:a[s-1],nodes:a[s-1]};break;case 51:this.$={stmt:a[s],nodes:a[s]};break;case 52:this.$=[a[s]];break;case 53:this.$=a[s-4].concat(a[s]);break;case 54:this.$=[a[s-2]],r.setClass(a[s-2],a[s]);break;case 55:this.$=a[s-3],r.addVertex(a[s-3],a[s-1],"square");break;case 56:this.$=a[s-5],r.addVertex(a[s-5],a[s-2],"circle");break;case 57:this.$=a[s-3],r.addVertex(a[s-3],a[s-1],"ellipse");break;case 58:this.$=a[s-3],r.addVertex(a[s-3],a[s-1],"stadium");break;case 59:this.$=a[s-3],r.addVertex(a[s-3],a[s-1],"subroutine");break;case 60:this.$=a[s-3],r.addVertex(a[s-3],a[s-1],"cylinder");break;case 61:this.$=a[s-3],r.addVertex(a[s-3],a[s-1],"round");break;case 62:this.$=a[s-3],r.addVertex(a[s-3],a[s-1],"diamond");break;case 63:this.$=a[s-5],r.addVertex(a[s-5],a[s-2],"hexagon");break;case 64:this.$=a[s-3],r.addVertex(a[s-3],a[s-1],"odd");break;case 65:this.$=a[s-3],r.addVertex(a[s-3],a[s-1],"trapezoid");break;case 66:this.$=a[s-3],r.addVertex(a[s-3],a[s-1],"inv_trapezoid");break;case 67:this.$=a[s-3],r.addVertex(a[s-3],a[s-1],"lean_right");break;case 68:this.$=a[s-3],r.addVertex(a[s-3],a[s-1],"lean_left");break;case 69:this.$=a[s],r.addVertex(a[s]);break;case 70:a[s-1].text=a[s],this.$=a[s-1];break;case 71:case 72:a[s-2].text=a[s-1],this.$=a[s-2];break;case 73:this.$=a[s];break;case 74:var c=r.destructLink(a[s],a[s-2]);this.$={type:c.type,stroke:c.stroke,length:c.length,text:a[s-1]};break;case 75:c=r.destructLink(a[s]),this.$={type:c.type,stroke:c.stroke,length:c.length};break;case 76:this.$=a[s-1];break;case 78:case 92:case 148:this.$=a[s-1]+""+a[s];break;case 93:case 94:this.$=a[s-4],r.addClass(a[s-2],a[s]);break;case 95:this.$=a[s-4],r.setClass(a[s-2],a[s]);break;case 96:case 104:this.$=a[s-1],r.setClickEvent(a[s-1],a[s]);break;case 97:case 105:this.$=a[s-3],r.setClickEvent(a[s-3],a[s-2]),r.setTooltip(a[s-3],a[s]);break;case 98:this.$=a[s-2],r.setClickEvent(a[s-2],a[s-1],a[s]);break;case 99:this.$=a[s-4],r.setClickEvent(a[s-4],a[s-3],a[s-2]),r.setTooltip(a[s-4],a[s]);break;case 100:case 106:this.$=a[s-1],r.setLink(a[s-1],a[s]);break;case 101:case 107:this.$=a[s-3],r.setLink(a[s-3],a[s-2]),r.setTooltip(a[s-3],a[s]);break;case 102:case 108:this.$=a[s-3],r.setLink(a[s-3],a[s-2],a[s]);break;case 103:case 109:this.$=a[s-5],r.setLink(a[s-5],a[s-4],a[s]),r.setTooltip(a[s-5],a[s-2]);break;case 110:this.$=a[s-4],r.addVertex(a[s-2],void 0,void 0,a[s]);break;case 111:case 113:this.$=a[s-4],r.updateLink(a[s-2],a[s]);break;case 112:this.$=a[s-4],r.updateLink([a[s-2]],a[s]);break;case 114:this.$=a[s-8],r.updateLinkInterpolate([a[s-6]],a[s-2]),r.updateLink([a[s-6]],a[s]);break;case 115:this.$=a[s-8],r.updateLinkInterpolate(a[s-6],a[s-2]),r.updateLink(a[s-6],a[s]);break;case 116:this.$=a[s-6],r.updateLinkInterpolate([a[s-4]],a[s]);break;case 117:this.$=a[s-6],r.updateLinkInterpolate(a[s-4],a[s]);break;case 118:case 120:this.$=[a[s]];break;case 119:case 121:a[s-2].push(a[s]),this.$=a[s-2];break;case 123:this.$=a[s-1]+a[s];break;case 145:this.$=a[s];break;case 146:this.$=a[s-1]+""+a[s];break;case 151:this.$="v";break;case 152:this.$="-";break;case 153:this.$={stmt:"dir",value:"TB"};break;case 154:this.$={stmt:"dir",value:"BT"};break;case 155:this.$={stmt:"dir",value:"RL"};break;case 156:this.$={stmt:"dir",value:"LR"}}},table:[{3:1,4:2,5:3,6:5,12:e,16:4,21:n,22:r,24:i},{1:[3]},{1:[2,1]},{3:10,4:2,5:3,6:5,12:e,16:4,21:n,22:r,24:i},t(a,o,{17:11}),{7:12,13:[1,13]},{16:14,21:n,22:r,24:i},{16:15,21:n,22:r,24:i},{25:[1,16],26:[1,17]},{13:[2,5]},{1:[2,2]},{1:[2,9],18:18,19:19,20:s,21:c,22:u,23:l,32:24,33:25,34:26,35:27,36:28,37:29,38:h,43:31,45:32,46:42,47:f,49:43,76:d,77:p,78:y,79:g,80:m,81:v,95:b,96:_,99:x,100:w,101:k,103:T,104:E,108:44,110:C,111:S,112:A,113:M,114:N,115:D,116:O,117:B,118:L,119:I},{8:60,10:[1,61],15:R},t([10,15],[2,6]),t(a,[2,17]),t(a,[2,18]),t(a,[2,19]),{20:[1,64],21:[1,65],22:F,27:63,30:66},t(P,[2,11]),t(P,[2,12]),t(P,[2,13]),t(P,[2,14]),t(P,[2,15]),t(P,[2,16]),{9:68,20:j,21:Y,23:z,44:69,67:73,70:[1,74],71:[1,75]},{9:76,20:j,21:Y,23:z},{9:77,20:j,21:Y,23:z},{9:78,20:j,21:Y,23:z},{9:79,20:j,21:Y,23:z},{9:80,20:j,21:Y,23:z},{9:82,20:j,21:Y,22:[1,81],23:z},t(P,[2,44]),t(U,[2,51],{30:83,22:F}),{22:[1,84]},{22:[1,85]},{22:[1,86]},{22:[1,87]},{26:q,47:$,74:[1,91],81:H,87:90,88:[1,88],90:[1,89],95:W,96:V,99:G,100:X,101:Z,103:Q,104:K,107:94,109:92,114:J,115:tt,116:et,117:nt,118:rt,119:it},t(P,[2,153]),t(P,[2,154]),t(P,[2,155]),t(P,[2,156]),t(at,[2,52],{48:[1,110]}),t(ot,[2,69],{108:121,40:[1,111],47:f,50:[1,112],52:[1,113],54:[1,114],56:[1,115],58:[1,116],60:[1,117],62:[1,118],63:[1,119],65:[1,120],81:v,95:b,96:_,99:x,100:w,101:k,103:T,104:E,114:N,115:D,116:O,117:B,118:L,119:I}),t(st,[2,145]),t(st,[2,170]),t(st,[2,171]),t(st,[2,172]),t(st,[2,173]),t(st,[2,174]),t(st,[2,175]),t(st,[2,176]),t(st,[2,177]),t(st,[2,178]),t(st,[2,179]),t(st,[2,180]),t(st,[2,181]),t(st,[2,182]),t(st,[2,183]),t(st,[2,184]),{9:122,20:j,21:Y,23:z},{11:123,14:[1,124]},t(ct,[2,8]),t(a,[2,20]),t(a,[2,26]),t(a,[2,27]),{21:[1,125]},t(ut,[2,34],{30:126,22:F}),t(P,[2,35]),{45:127,46:42,47:f,49:43,81:v,95:b,96:_,99:x,100:w,101:k,103:T,104:E,108:44,114:N,115:D,116:O,117:B,118:L,119:I},t(lt,[2,45]),t(lt,[2,46]),t(lt,[2,47]),t(ht,[2,73],{68:128,69:[1,129],72:[1,130]}),{22:ft,24:dt,26:pt,38:yt,39:131,42:gt,47:$,62:mt,70:vt,73:132,74:bt,75:143,76:_t,77:xt,78:wt,79:kt,80:Tt,81:Et,82:Ct,84:134,85:St,95:W,96:V,99:G,100:X,101:At,103:Q,104:K,105:Mt,106:Nt,107:140,114:J,115:tt,116:et,117:nt,118:rt,119:it},t([47,69,72,81,95,96,99,100,101,103,104,114,115,116,117,118,119],[2,75]),t(P,[2,36]),t(P,[2,37]),t(P,[2,38]),t(P,[2,39]),t(P,[2,40]),{22:ft,24:dt,26:pt,38:yt,39:155,42:gt,47:$,62:mt,70:vt,73:132,74:bt,75:143,76:_t,77:xt,78:wt,79:kt,80:Tt,81:Et,82:Ct,84:134,85:St,95:W,96:V,99:G,100:X,101:At,103:Q,104:K,105:Mt,106:Nt,107:140,114:J,115:tt,116:et,117:nt,118:rt,119:it},t(Dt,o,{17:156}),t(U,[2,50],{47:Ot}),{26:q,47:$,81:H,87:158,92:[1,159],95:W,96:V,99:G,100:X,101:Z,103:Q,104:K,107:94,109:92,114:J,115:tt,116:et,117:nt,118:rt,119:it},{85:[1,160],93:161,95:[1,162]},{26:q,47:$,81:H,85:[1,163],87:164,95:W,96:V,99:G,100:X,101:Z,103:Q,104:K,107:94,109:92,114:J,115:tt,116:et,117:nt,118:rt,119:it},{26:q,47:$,81:H,87:165,95:W,96:V,99:G,100:X,101:Z,103:Q,104:K,107:94,109:92,114:J,115:tt,116:et,117:nt,118:rt,119:it},t(ct,[2,96],{22:[1,166],89:[1,167]}),t(ct,[2,100],{22:[1,168]}),t(ct,[2,104],{107:94,109:170,22:[1,169],26:q,47:$,81:H,95:W,96:V,99:G,100:X,101:Z,103:Q,104:K,114:J,115:tt,116:et,117:nt,118:rt,119:it}),t(ct,[2,106],{22:[1,171]}),t(Bt,[2,147]),t(Bt,[2,149]),t(Bt,[2,150]),t(Bt,[2,151]),t(Bt,[2,152]),t(Lt,[2,157]),t(Lt,[2,158]),t(Lt,[2,159]),t(Lt,[2,160]),t(Lt,[2,161]),t(Lt,[2,162]),t(Lt,[2,163]),t(Lt,[2,164]),t(Lt,[2,165]),t(Lt,[2,166]),t(Lt,[2,167]),t(Lt,[2,168]),t(Lt,[2,169]),{47:f,49:172,81:v,95:b,96:_,99:x,100:w,101:k,103:T,104:E,108:44,114:N,115:D,116:O,117:B,118:L,119:I},{22:ft,24:dt,26:pt,38:yt,39:173,42:gt,47:$,62:mt,70:vt,73:132,74:bt,75:143,76:_t,77:xt,78:wt,79:kt,80:Tt,81:Et,82:Ct,84:134,85:St,95:W,96:V,99:G,100:X,101:At,103:Q,104:K,105:Mt,106:Nt,107:140,114:J,115:tt,116:et,117:nt,118:rt,119:it},{22:ft,24:dt,26:pt,38:yt,39:175,42:gt,47:$,50:[1,174],62:mt,70:vt,73:132,74:bt,75:143,76:_t,77:xt,78:wt,79:kt,80:Tt,81:Et,82:Ct,84:134,85:St,95:W,96:V,99:G,100:X,101:At,103:Q,104:K,105:Mt,106:Nt,107:140,114:J,115:tt,116:et,117:nt,118:rt,119:it},{22:ft,24:dt,26:pt,38:yt,39:176,42:gt,47:$,62:mt,70:vt,73:132,74:bt,75:143,76:_t,77:xt,78:wt,79:kt,80:Tt,81:Et,82:Ct,84:134,85:St,95:W,96:V,99:G,100:X,101:At,103:Q,104:K,105:Mt,106:Nt,107:140,114:J,115:tt,116:et,117:nt,118:rt,119:it},{22:ft,24:dt,26:pt,38:yt,39:177,42:gt,47:$,62:mt,70:vt,73:132,74:bt,75:143,76:_t,77:xt,78:wt,79:kt,80:Tt,81:Et,82:Ct,84:134,85:St,95:W,96:V,99:G,100:X,101:At,103:Q,104:K,105:Mt,106:Nt,107:140,114:J,115:tt,116:et,117:nt,118:rt,119:it},{22:ft,24:dt,26:pt,38:yt,39:178,42:gt,47:$,62:mt,70:vt,73:132,74:bt,75:143,76:_t,77:xt,78:wt,79:kt,80:Tt,81:Et,82:Ct,84:134,85:St,95:W,96:V,99:G,100:X,101:At,103:Q,104:K,105:Mt,106:Nt,107:140,114:J,115:tt,116:et,117:nt,118:rt,119:it},{22:ft,24:dt,26:pt,38:yt,39:179,42:gt,47:$,62:mt,70:vt,73:132,74:bt,75:143,76:_t,77:xt,78:wt,79:kt,80:Tt,81:Et,82:Ct,84:134,85:St,95:W,96:V,99:G,100:X,101:At,103:Q,104:K,105:Mt,106:Nt,107:140,114:J,115:tt,116:et,117:nt,118:rt,119:it},{22:ft,24:dt,26:pt,38:yt,39:180,42:gt,47:$,60:[1,181],62:mt,70:vt,73:132,74:bt,75:143,76:_t,77:xt,78:wt,79:kt,80:Tt,81:Et,82:Ct,84:134,85:St,95:W,96:V,99:G,100:X,101:At,103:Q,104:K,105:Mt,106:Nt,107:140,114:J,115:tt,116:et,117:nt,118:rt,119:it},{22:ft,24:dt,26:pt,38:yt,39:182,42:gt,47:$,62:mt,70:vt,73:132,74:bt,75:143,76:_t,77:xt,78:wt,79:kt,80:Tt,81:Et,82:Ct,84:134,85:St,95:W,96:V,99:G,100:X,101:At,103:Q,104:K,105:Mt,106:Nt,107:140,114:J,115:tt,116:et,117:nt,118:rt,119:it},{22:ft,24:dt,26:pt,38:yt,39:183,42:gt,47:$,62:mt,70:vt,73:132,74:bt,75:143,76:_t,77:xt,78:wt,79:kt,80:Tt,81:Et,82:Ct,84:134,85:St,95:W,96:V,99:G,100:X,101:At,103:Q,104:K,105:Mt,106:Nt,107:140,114:J,115:tt,116:et,117:nt,118:rt,119:it},{22:ft,24:dt,26:pt,38:yt,39:184,42:gt,47:$,62:mt,70:vt,73:132,74:bt,75:143,76:_t,77:xt,78:wt,79:kt,80:Tt,81:Et,82:Ct,84:134,85:St,95:W,96:V,99:G,100:X,101:At,103:Q,104:K,105:Mt,106:Nt,107:140,114:J,115:tt,116:et,117:nt,118:rt,119:it},t(st,[2,146]),t(It,[2,3]),{8:185,15:R},{15:[2,7]},t(a,[2,28]),t(ut,[2,33]),t(U,[2,48],{30:186,22:F}),t(ht,[2,70],{22:[1,187]}),{22:[1,188]},{22:ft,24:dt,26:pt,38:yt,39:189,42:gt,47:$,62:mt,70:vt,73:132,74:bt,75:143,76:_t,77:xt,78:wt,79:kt,80:Tt,81:Et,82:Ct,84:134,85:St,95:W,96:V,99:G,100:X,101:At,103:Q,104:K,105:Mt,106:Nt,107:140,114:J,115:tt,116:et,117:nt,118:rt,119:it},{22:ft,24:dt,26:pt,38:yt,42:gt,47:$,62:mt,70:vt,71:[1,190],73:191,75:143,76:_t,77:xt,78:wt,79:kt,80:Tt,81:Et,82:Ct,84:134,85:St,95:W,96:V,99:G,100:X,101:At,103:Q,104:K,105:Mt,106:Nt,107:140,114:J,115:tt,116:et,117:nt,118:rt,119:it},t(Lt,[2,77]),t(Lt,[2,79]),t(Lt,[2,135]),t(Lt,[2,136]),t(Lt,[2,137]),t(Lt,[2,138]),t(Lt,[2,139]),t(Lt,[2,140]),t(Lt,[2,141]),t(Lt,[2,142]),t(Lt,[2,143]),t(Lt,[2,144]),t(Lt,[2,80]),t(Lt,[2,81]),t(Lt,[2,82]),t(Lt,[2,83]),t(Lt,[2,84]),t(Lt,[2,85]),t(Lt,[2,86]),t(Lt,[2,87]),t(Lt,[2,88]),t(Lt,[2,89]),t(Lt,[2,90]),{9:193,20:j,21:Y,22:ft,23:z,24:dt,26:pt,38:yt,40:[1,192],42:gt,47:$,62:mt,70:vt,73:191,75:143,76:_t,77:xt,78:wt,79:kt,80:Tt,81:Et,82:Ct,84:134,85:St,95:W,96:V,99:G,100:X,101:At,103:Q,104:K,105:Mt,106:Nt,107:140,114:J,115:tt,116:et,117:nt,118:rt,119:it},{18:18,19:19,20:s,21:c,22:u,23:l,32:24,33:25,34:26,35:27,36:28,37:29,38:h,42:[1,194],43:31,45:32,46:42,47:f,49:43,76:d,77:p,78:y,79:g,80:m,81:v,95:b,96:_,99:x,100:w,101:k,103:T,104:E,108:44,110:C,111:S,112:A,113:M,114:N,115:D,116:O,117:B,118:L,119:I},{22:F,30:195},{22:[1,196],26:q,47:$,81:H,95:W,96:V,99:G,100:X,101:Z,103:Q,104:K,107:94,109:170,114:J,115:tt,116:et,117:nt,118:rt,119:it},{22:[1,197]},{22:[1,198]},{22:[1,199],96:[1,200]},t(Rt,[2,118]),{22:[1,201]},{22:[1,202],26:q,47:$,81:H,95:W,96:V,99:G,100:X,101:Z,103:Q,104:K,107:94,109:170,114:J,115:tt,116:et,117:nt,118:rt,119:it},{22:[1,203],26:q,47:$,81:H,95:W,96:V,99:G,100:X,101:Z,103:Q,104:K,107:94,109:170,114:J,115:tt,116:et,117:nt,118:rt,119:it},{74:[1,204]},t(ct,[2,98],{22:[1,205]}),{74:[1,206],91:[1,207]},{74:[1,208]},t(Bt,[2,148]),{74:[1,209],91:[1,210]},t(at,[2,54],{108:121,47:f,81:v,95:b,96:_,99:x,100:w,101:k,103:T,104:E,114:N,115:D,116:O,117:B,118:L,119:I}),{22:ft,24:dt,26:pt,38:yt,41:[1,211],42:gt,47:$,62:mt,70:vt,73:191,75:143,76:_t,77:xt,78:wt,79:kt,80:Tt,81:Et,82:Ct,84:134,85:St,95:W,96:V,99:G,100:X,101:At,103:Q,104:K,105:Mt,106:Nt,107:140,114:J,115:tt,116:et,117:nt,118:rt,119:it},{22:ft,24:dt,26:pt,38:yt,39:212,42:gt,47:$,62:mt,70:vt,73:132,74:bt,75:143,76:_t,77:xt,78:wt,79:kt,80:Tt,81:Et,82:Ct,84:134,85:St,95:W,96:V,99:G,100:X,101:At,103:Q,104:K,105:Mt,106:Nt,107:140,114:J,115:tt,116:et,117:nt,118:rt,119:it},{22:ft,24:dt,26:pt,38:yt,42:gt,47:$,51:[1,213],62:mt,70:vt,73:191,75:143,76:_t,77:xt,78:wt,79:kt,80:Tt,81:Et,82:Ct,84:134,85:St,95:W,96:V,99:G,100:X,101:At,103:Q,104:K,105:Mt,106:Nt,107:140,114:J,115:tt,116:et,117:nt,118:rt,119:it},{22:ft,24:dt,26:pt,38:yt,42:gt,47:$,53:[1,214],62:mt,70:vt,73:191,75:143,76:_t,77:xt,78:wt,79:kt,80:Tt,81:Et,82:Ct,84:134,85:St,95:W,96:V,99:G,100:X,101:At,103:Q,104:K,105:Mt,106:Nt,107:140,114:J,115:tt,116:et,117:nt,118:rt,119:it},{22:ft,24:dt,26:pt,38:yt,42:gt,47:$,55:[1,215],62:mt,70:vt,73:191,75:143,76:_t,77:xt,78:wt,79:kt,80:Tt,81:Et,82:Ct,84:134,85:St,95:W,96:V,99:G,100:X,101:At,103:Q,104:K,105:Mt,106:Nt,107:140,114:J,115:tt,116:et,117:nt,118:rt,119:it},{22:ft,24:dt,26:pt,38:yt,42:gt,47:$,57:[1,216],62:mt,70:vt,73:191,75:143,76:_t,77:xt,78:wt,79:kt,80:Tt,81:Et,82:Ct,84:134,85:St,95:W,96:V,99:G,100:X,101:At,103:Q,104:K,105:Mt,106:Nt,107:140,114:J,115:tt,116:et,117:nt,118:rt,119:it},{22:ft,24:dt,26:pt,38:yt,42:gt,47:$,59:[1,217],62:mt,70:vt,73:191,75:143,76:_t,77:xt,78:wt,79:kt,80:Tt,81:Et,82:Ct,84:134,85:St,95:W,96:V,99:G,100:X,101:At,103:Q,104:K,105:Mt,106:Nt,107:140,114:J,115:tt,116:et,117:nt,118:rt,119:it},{22:ft,24:dt,26:pt,38:yt,42:gt,47:$,61:[1,218],62:mt,70:vt,73:191,75:143,76:_t,77:xt,78:wt,79:kt,80:Tt,81:Et,82:Ct,84:134,85:St,95:W,96:V,99:G,100:X,101:At,103:Q,104:K,105:Mt,106:Nt,107:140,114:J,115:tt,116:et,117:nt,118:rt,119:it},{22:ft,24:dt,26:pt,38:yt,39:219,42:gt,47:$,62:mt,70:vt,73:132,74:bt,75:143,76:_t,77:xt,78:wt,79:kt,80:Tt,81:Et,82:Ct,84:134,85:St,95:W,96:V,99:G,100:X,101:At,103:Q,104:K,105:Mt,106:Nt,107:140,114:J,115:tt,116:et,117:nt,118:rt,119:it},{22:ft,24:dt,26:pt,38:yt,41:[1,220],42:gt,47:$,62:mt,70:vt,73:191,75:143,76:_t,77:xt,78:wt,79:kt,80:Tt,81:Et,82:Ct,84:134,85:St,95:W,96:V,99:G,100:X,101:At,103:Q,104:K,105:Mt,106:Nt,107:140,114:J,115:tt,116:et,117:nt,118:rt,119:it},{22:ft,24:dt,26:pt,38:yt,42:gt,47:$,62:mt,64:[1,221],66:[1,222],70:vt,73:191,75:143,76:_t,77:xt,78:wt,79:kt,80:Tt,81:Et,82:Ct,84:134,85:St,95:W,96:V,99:G,100:X,101:At,103:Q,104:K,105:Mt,106:Nt,107:140,114:J,115:tt,116:et,117:nt,118:rt,119:it},{22:ft,24:dt,26:pt,38:yt,42:gt,47:$,62:mt,64:[1,224],66:[1,223],70:vt,73:191,75:143,76:_t,77:xt,78:wt,79:kt,80:Tt,81:Et,82:Ct,84:134,85:St,95:W,96:V,99:G,100:X,101:At,103:Q,104:K,105:Mt,106:Nt,107:140,114:J,115:tt,116:et,117:nt,118:rt,119:it},{9:225,20:j,21:Y,23:z},t(U,[2,49],{47:Ot}),t(ht,[2,72]),t(ht,[2,71]),{22:ft,24:dt,26:pt,38:yt,42:gt,47:$,62:mt,70:vt,72:[1,226],73:191,75:143,76:_t,77:xt,78:wt,79:kt,80:Tt,81:Et,82:Ct,84:134,85:St,95:W,96:V,99:G,100:X,101:At,103:Q,104:K,105:Mt,106:Nt,107:140,114:J,115:tt,116:et,117:nt,118:rt,119:it},t(ht,[2,74]),t(Lt,[2,78]),{22:ft,24:dt,26:pt,38:yt,39:227,42:gt,47:$,62:mt,70:vt,73:132,74:bt,75:143,76:_t,77:xt,78:wt,79:kt,80:Tt,81:Et,82:Ct,84:134,85:St,95:W,96:V,99:G,100:X,101:At,103:Q,104:K,105:Mt,106:Nt,107:140,114:J,115:tt,116:et,117:nt,118:rt,119:it},t(Dt,o,{17:228}),t(P,[2,43]),{46:229,47:f,49:43,81:v,95:b,96:_,99:x,100:w,101:k,103:T,104:E,108:44,114:N,115:D,116:O,117:B,118:L,119:I},{22:Ft,76:Pt,86:230,92:jt,95:Yt,97:231,98:232,99:zt,100:Ut,101:qt,102:$t,103:Ht,104:Wt,105:Vt},{22:Ft,76:Pt,86:244,92:jt,95:Yt,97:231,98:232,99:zt,100:Ut,101:qt,102:$t,103:Ht,104:Wt,105:Vt},{22:Ft,76:Pt,86:245,92:jt,94:[1,246],95:Yt,97:231,98:232,99:zt,100:Ut,101:qt,102:$t,103:Ht,104:Wt,105:Vt},{22:Ft,76:Pt,86:247,92:jt,94:[1,248],95:Yt,97:231,98:232,99:zt,100:Ut,101:qt,102:$t,103:Ht,104:Wt,105:Vt},{95:[1,249]},{22:Ft,76:Pt,86:250,92:jt,95:Yt,97:231,98:232,99:zt,100:Ut,101:qt,102:$t,103:Ht,104:Wt,105:Vt},{22:Ft,76:Pt,86:251,92:jt,95:Yt,97:231,98:232,99:zt,100:Ut,101:qt,102:$t,103:Ht,104:Wt,105:Vt},{26:q,47:$,81:H,87:252,95:W,96:V,99:G,100:X,101:Z,103:Q,104:K,107:94,109:92,114:J,115:tt,116:et,117:nt,118:rt,119:it},t(ct,[2,97]),{74:[1,253]},t(ct,[2,101],{22:[1,254]}),t(ct,[2,102]),t(ct,[2,105]),t(ct,[2,107],{22:[1,255]}),t(ct,[2,108]),t(ot,[2,55]),{22:ft,24:dt,26:pt,38:yt,42:gt,47:$,51:[1,256],62:mt,70:vt,73:191,75:143,76:_t,77:xt,78:wt,79:kt,80:Tt,81:Et,82:Ct,84:134,85:St,95:W,96:V,99:G,100:X,101:At,103:Q,104:K,105:Mt,106:Nt,107:140,114:J,115:tt,116:et,117:nt,118:rt,119:it},t(ot,[2,61]),t(ot,[2,57]),t(ot,[2,58]),t(ot,[2,59]),t(ot,[2,60]),t(ot,[2,62]),{22:ft,24:dt,26:pt,38:yt,42:gt,47:$,61:[1,257],62:mt,70:vt,73:191,75:143,76:_t,77:xt,78:wt,79:kt,80:Tt,81:Et,82:Ct,84:134,85:St,95:W,96:V,99:G,100:X,101:At,103:Q,104:K,105:Mt,106:Nt,107:140,114:J,115:tt,116:et,117:nt,118:rt,119:it},t(ot,[2,64]),t(ot,[2,65]),t(ot,[2,67]),t(ot,[2,66]),t(ot,[2,68]),t(It,[2,4]),t([22,47,81,95,96,99,100,101,103,104,114,115,116,117,118,119],[2,76]),{22:ft,24:dt,26:pt,38:yt,41:[1,258],42:gt,47:$,62:mt,70:vt,73:191,75:143,76:_t,77:xt,78:wt,79:kt,80:Tt,81:Et,82:Ct,84:134,85:St,95:W,96:V,99:G,100:X,101:At,103:Q,104:K,105:Mt,106:Nt,107:140,114:J,115:tt,116:et,117:nt,118:rt,119:it},{18:18,19:19,20:s,21:c,22:u,23:l,32:24,33:25,34:26,35:27,36:28,37:29,38:h,42:[1,259],43:31,45:32,46:42,47:f,49:43,76:d,77:p,78:y,79:g,80:m,81:v,95:b,96:_,99:x,100:w,101:k,103:T,104:E,108:44,110:C,111:S,112:A,113:M,114:N,115:D,116:O,117:B,118:L,119:I},t(at,[2,53]),t(ct,[2,110],{96:Gt}),t(Xt,[2,120],{98:261,22:Ft,76:Pt,92:jt,95:Yt,99:zt,100:Ut,101:qt,102:$t,103:Ht,104:Wt,105:Vt}),t(Zt,[2,122]),t(Zt,[2,124]),t(Zt,[2,125]),t(Zt,[2,126]),t(Zt,[2,127]),t(Zt,[2,128]),t(Zt,[2,129]),t(Zt,[2,130]),t(Zt,[2,131]),t(Zt,[2,132]),t(Zt,[2,133]),t(Zt,[2,134]),t(ct,[2,111],{96:Gt}),t(ct,[2,112],{96:Gt}),{22:[1,262]},t(ct,[2,113],{96:Gt}),{22:[1,263]},t(Rt,[2,119]),t(ct,[2,93],{96:Gt}),t(ct,[2,94],{96:Gt}),t(ct,[2,95],{107:94,109:170,26:q,47:$,81:H,95:W,96:V,99:G,100:X,101:Z,103:Q,104:K,114:J,115:tt,116:et,117:nt,118:rt,119:it}),t(ct,[2,99]),{91:[1,264]},{91:[1,265]},{51:[1,266]},{61:[1,267]},{9:268,20:j,21:Y,23:z},t(P,[2,42]),{22:Ft,76:Pt,92:jt,95:Yt,97:269,98:232,99:zt,100:Ut,101:qt,102:$t,103:Ht,104:Wt,105:Vt},t(Zt,[2,123]),{26:q,47:$,81:H,87:270,95:W,96:V,99:G,100:X,101:Z,103:Q,104:K,107:94,109:92,114:J,115:tt,116:et,117:nt,118:rt,119:it},{26:q,47:$,81:H,87:271,95:W,96:V,99:G,100:X,101:Z,103:Q,104:K,107:94,109:92,114:J,115:tt,116:et,117:nt,118:rt,119:it},t(ct,[2,103]),t(ct,[2,109]),t(ot,[2,56]),t(ot,[2,63]),t(Dt,o,{17:272}),t(Xt,[2,121],{98:261,22:Ft,76:Pt,92:jt,95:Yt,99:zt,100:Ut,101:qt,102:$t,103:Ht,104:Wt,105:Vt}),t(ct,[2,116],{107:94,109:170,22:[1,273],26:q,47:$,81:H,95:W,96:V,99:G,100:X,101:Z,103:Q,104:K,114:J,115:tt,116:et,117:nt,118:rt,119:it}),t(ct,[2,117],{107:94,109:170,22:[1,274],26:q,47:$,81:H,95:W,96:V,99:G,100:X,101:Z,103:Q,104:K,114:J,115:tt,116:et,117:nt,118:rt,119:it}),{18:18,19:19,20:s,21:c,22:u,23:l,32:24,33:25,34:26,35:27,36:28,37:29,38:h,42:[1,275],43:31,45:32,46:42,47:f,49:43,76:d,77:p,78:y,79:g,80:m,81:v,95:b,96:_,99:x,100:w,101:k,103:T,104:E,108:44,110:C,111:S,112:A,113:M,114:N,115:D,116:O,117:B,118:L,119:I},{22:Ft,76:Pt,86:276,92:jt,95:Yt,97:231,98:232,99:zt,100:Ut,101:qt,102:$t,103:Ht,104:Wt,105:Vt},{22:Ft,76:Pt,86:277,92:jt,95:Yt,97:231,98:232,99:zt,100:Ut,101:qt,102:$t,103:Ht,104:Wt,105:Vt},t(P,[2,41]),t(ct,[2,114],{96:Gt}),t(ct,[2,115],{96:Gt})],defaultActions:{2:[2,1],9:[2,5],10:[2,2],124:[2,7]},parseError:function(t,e){if(!e.recoverable){var n=new Error(t);throw n.hash=e,n}this.trace(t)},parse:function(t){var e=this,n=[0],r=[],i=[null],a=[],o=this.table,s="",c=0,u=0,l=0,h=2,f=1,d=a.slice.call(arguments,1),p=Object.create(this.lexer),y={yy:{}};for(var g in this.yy)Object.prototype.hasOwnProperty.call(this.yy,g)&&(y.yy[g]=this.yy[g]);p.setInput(t,y.yy),y.yy.lexer=p,y.yy.parser=this,void 0===p.yylloc&&(p.yylloc={});var m=p.yylloc;a.push(m);var v=p.options&&p.options.ranges;function b(){var t;return"number"!=typeof(t=r.pop()||p.lex()||f)&&(t instanceof Array&&(t=(r=t).pop()),t=e.symbols_[t]||t),t}"function"==typeof y.yy.parseError?this.parseError=y.yy.parseError:this.parseError=Object.getPrototypeOf(this).parseError;for(var _,x,w,k,T,E,C,S,A,M={};;){if(w=n[n.length-1],this.defaultActions[w]?k=this.defaultActions[w]:(null==_&&(_=b()),k=o[w]&&o[w][_]),void 0===k||!k.length||!k[0]){var N="";for(E in A=[],o[w])this.terminals_[E]&&E>h&&A.push("'"+this.terminals_[E]+"'");N=p.showPosition?"Parse error on line "+(c+1)+":\n"+p.showPosition()+"\nExpecting "+A.join(", ")+", got '"+(this.terminals_[_]||_)+"'":"Parse error on line "+(c+1)+": Unexpected "+(_==f?"end of input":"'"+(this.terminals_[_]||_)+"'"),this.parseError(N,{text:p.match,token:this.terminals_[_]||_,line:p.yylineno,loc:m,expected:A})}if(k[0]instanceof Array&&k.length>1)throw new Error("Parse Error: multiple actions possible at state: "+w+", token: "+_);switch(k[0]){case 1:n.push(_),i.push(p.yytext),a.push(p.yylloc),n.push(k[1]),_=null,x?(_=x,x=null):(u=p.yyleng,s=p.yytext,c=p.yylineno,m=p.yylloc,l>0&&l--);break;case 2:if(C=this.productions_[k[1]][1],M.$=i[i.length-C],M._$={first_line:a[a.length-(C||1)].first_line,last_line:a[a.length-1].last_line,first_column:a[a.length-(C||1)].first_column,last_column:a[a.length-1].last_column},v&&(M._$.range=[a[a.length-(C||1)].range[0],a[a.length-1].range[1]]),void 0!==(T=this.performAction.apply(M,[s,u,c,y.yy,k[1],i,a].concat(d))))return T;C&&(n=n.slice(0,-1*C*2),i=i.slice(0,-1*C),a=a.slice(0,-1*C)),n.push(this.productions_[k[1]][0]),i.push(M.$),a.push(M._$),S=o[n[n.length-2]][n[n.length-1]],n.push(S);break;case 3:return!0}}return!0}},Kt={EOF:1,parseError:function(t,e){if(!this.yy.parser)throw new Error(t);this.yy.parser.parseError(t,e)},setInput:function(t,e){return this.yy=e||this.yy||{},this._input=t,this._more=this._backtrack=this.done=!1,this.yylineno=this.yyleng=0,this.yytext=this.matched=this.match="",this.conditionStack=["INITIAL"],this.yylloc={first_line:1,first_column:0,last_line:1,last_column:0},this.options.ranges&&(this.yylloc.range=[0,0]),this.offset=0,this},input:function(){var t=this._input[0];return this.yytext+=t,this.yyleng++,this.offset++,this.match+=t,this.matched+=t,t.match(/(?:\r\n?|\n).*/g)?(this.yylineno++,this.yylloc.last_line++):this.yylloc.last_column++,this.options.ranges&&this.yylloc.range[1]++,this._input=this._input.slice(1),t},unput:function(t){var e=t.length,n=t.split(/(?:\r\n?|\n)/g);this._input=t+this._input,this.yytext=this.yytext.substr(0,this.yytext.length-e),this.offset-=e;var r=this.match.split(/(?:\r\n?|\n)/g);this.match=this.match.substr(0,this.match.length-1),this.matched=this.matched.substr(0,this.matched.length-1),n.length-1&&(this.yylineno-=n.length-1);var i=this.yylloc.range;return this.yylloc={first_line:this.yylloc.first_line,last_line:this.yylineno+1,first_column:this.yylloc.first_column,last_column:n?(n.length===r.length?this.yylloc.first_column:0)+r[r.length-n.length].length-n[0].length:this.yylloc.first_column-e},this.options.ranges&&(this.yylloc.range=[i[0],i[0]+this.yyleng-e]),this.yyleng=this.yytext.length,this},more:function(){return this._more=!0,this},reject:function(){return this.options.backtrack_lexer?(this._backtrack=!0,this):this.parseError("Lexical error on line "+(this.yylineno+1)+". You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true).\n"+this.showPosition(),{text:"",token:null,line:this.yylineno})},less:function(t){this.unput(this.match.slice(t))},pastInput:function(){var t=this.matched.substr(0,this.matched.length-this.match.length);return(t.length>20?"...":"")+t.substr(-20).replace(/\n/g,"")},upcomingInput:function(){var t=this.match;return t.length<20&&(t+=this._input.substr(0,20-t.length)),(t.substr(0,20)+(t.length>20?"...":"")).replace(/\n/g,"")},showPosition:function(){var t=this.pastInput(),e=new Array(t.length+1).join("-");return t+this.upcomingInput()+"\n"+e+"^"},test_match:function(t,e){var n,r,i;if(this.options.backtrack_lexer&&(i={yylineno:this.yylineno,yylloc:{first_line:this.yylloc.first_line,last_line:this.last_line,first_column:this.yylloc.first_column,last_column:this.yylloc.last_column},yytext:this.yytext,match:this.match,matches:this.matches,matched:this.matched,yyleng:this.yyleng,offset:this.offset,_more:this._more,_input:this._input,yy:this.yy,conditionStack:this.conditionStack.slice(0),done:this.done},this.options.ranges&&(i.yylloc.range=this.yylloc.range.slice(0))),(r=t[0].match(/(?:\r\n?|\n).*/g))&&(this.yylineno+=r.length),this.yylloc={first_line:this.yylloc.last_line,last_line:this.yylineno+1,first_column:this.yylloc.last_column,last_column:r?r[r.length-1].length-r[r.length-1].match(/\r?\n?/)[0].length:this.yylloc.last_column+t[0].length},this.yytext+=t[0],this.match+=t[0],this.matches=t,this.yyleng=this.yytext.length,this.options.ranges&&(this.yylloc.range=[this.offset,this.offset+=this.yyleng]),this._more=!1,this._backtrack=!1,this._input=this._input.slice(t[0].length),this.matched+=t[0],n=this.performAction.call(this,this.yy,this,e,this.conditionStack[this.conditionStack.length-1]),this.done&&this._input&&(this.done=!1),n)return n;if(this._backtrack){for(var a in i)this[a]=i[a];return!1}return!1},next:function(){if(this.done)return this.EOF;var t,e,n,r;this._input||(this.done=!0),this._more||(this.yytext="",this.match="");for(var i=this._currentRules(),a=0;ae[0].length)){if(e=n,r=a,this.options.backtrack_lexer){if(!1!==(t=this.test_match(n,i[a])))return t;if(this._backtrack){e=!1;continue}return!1}if(!this.options.flex)break}return e?!1!==(t=this.test_match(e,i[r]))&&t:""===this._input?this.EOF:this.parseError("Lexical error on line "+(this.yylineno+1)+". Unrecognized text.\n"+this.showPosition(),{text:"",token:null,line:this.yylineno})},lex:function(){return this.next()||this.lex()},begin:function(t){this.conditionStack.push(t)},popState:function(){return this.conditionStack.length-1>0?this.conditionStack.pop():this.conditionStack[0]},_currentRules:function(){return this.conditionStack.length&&this.conditionStack[this.conditionStack.length-1]?this.conditions[this.conditionStack[this.conditionStack.length-1]].rules:this.conditions.INITIAL.rules},topState:function(t){return(t=this.conditionStack.length-1-Math.abs(t||0))>=0?this.conditionStack[t]:"INITIAL"},pushState:function(t){this.begin(t)},stateStackSize:function(){return this.conditionStack.length},options:{},performAction:function(t,e,n,r){switch(n){case 0:return this.begin("open_directive"),12;case 1:return this.begin("type_directive"),13;case 2:return this.popState(),this.begin("arg_directive"),10;case 3:return this.popState(),this.popState(),15;case 4:return 14;case 5:case 6:break;case 7:this.begin("string");break;case 8:this.popState();break;case 9:return"STR";case 10:return 76;case 11:return 85;case 12:return 77;case 13:return 94;case 14:return 78;case 15:return 79;case 16:this.begin("href");break;case 17:this.popState();break;case 18:return 90;case 19:this.begin("callbackname");break;case 20:this.popState();break;case 21:this.popState(),this.begin("callbackargs");break;case 22:return 88;case 23:this.popState();break;case 24:return 89;case 25:this.begin("click");break;case 26:this.popState();break;case 27:return 80;case 28:case 29:return t.lex.firstGraph()&&this.begin("dir"),24;case 30:return 38;case 31:return 42;case 32:case 33:case 34:case 35:return 91;case 36:return this.popState(),25;case 37:case 38:case 39:case 40:case 41:case 42:case 43:case 44:case 45:case 46:return this.popState(),26;case 47:return 110;case 48:return 111;case 49:return 112;case 50:return 113;case 51:return 95;case 52:return 103;case 53:return 48;case 54:return 100;case 55:return 47;case 56:return 20;case 57:return 96;case 58:return 118;case 59:case 60:case 61:return 71;case 62:case 63:case 64:return 70;case 65:return 52;case 66:return 53;case 67:return 54;case 68:return 55;case 69:return 56;case 70:return 57;case 71:return 58;case 72:return 59;case 73:return 101;case 74:return 104;case 75:return 119;case 76:return 116;case 77:return 105;case 78:case 79:return 117;case 80:return 106;case 81:return 62;case 82:return 82;case 83:return"SEP";case 84:return 81;case 85:return 99;case 86:return 64;case 87:return 63;case 88:return 66;case 89:return 65;case 90:return 114;case 91:return 115;case 92:return 72;case 93:return 50;case 94:return 51;case 95:return 40;case 96:return 41;case 97:return 60;case 98:return 61;case 99:return 125;case 100:return 21;case 101:return 22;case 102:return 23}},rules:[/^(?:%%\{)/,/^(?:((?:(?!\}%%)[^:.])*))/,/^(?::)/,/^(?:\}%%)/,/^(?:((?:(?!\}%%).|\n)*))/,/^(?:%%(?!\{)[^\n]*)/,/^(?:[^\}]%%[^\n]*)/,/^(?:["])/,/^(?:["])/,/^(?:[^"]*)/,/^(?:style\b)/,/^(?:default\b)/,/^(?:linkStyle\b)/,/^(?:interpolate\b)/,/^(?:classDef\b)/,/^(?:class\b)/,/^(?:href[\s]+["])/,/^(?:["])/,/^(?:[^"]*)/,/^(?:call[\s]+)/,/^(?:\([\s]*\))/,/^(?:\()/,/^(?:[^(]*)/,/^(?:\))/,/^(?:[^)]*)/,/^(?:click[\s]+)/,/^(?:[\s\n])/,/^(?:[^\s\n]*)/,/^(?:graph\b)/,/^(?:flowchart\b)/,/^(?:subgraph\b)/,/^(?:end\b\s*)/,/^(?:_self\b)/,/^(?:_blank\b)/,/^(?:_parent\b)/,/^(?:_top\b)/,/^(?:(\r?\n)*\s*\n)/,/^(?:\s*LR\b)/,/^(?:\s*RL\b)/,/^(?:\s*TB\b)/,/^(?:\s*BT\b)/,/^(?:\s*TD\b)/,/^(?:\s*BR\b)/,/^(?:\s*<)/,/^(?:\s*>)/,/^(?:\s*\^)/,/^(?:\s*v\b)/,/^(?:.*direction\s+TB[^\n]*)/,/^(?:.*direction\s+BT[^\n]*)/,/^(?:.*direction\s+RL[^\n]*)/,/^(?:.*direction\s+LR[^\n]*)/,/^(?:[0-9]+)/,/^(?:#)/,/^(?::::)/,/^(?::)/,/^(?:&)/,/^(?:;)/,/^(?:,)/,/^(?:\*)/,/^(?:\s*[xo<]?--+[-xo>]\s*)/,/^(?:\s*[xo<]?==+[=xo>]\s*)/,/^(?:\s*[xo<]?-?\.+-[xo>]?\s*)/,/^(?:\s*[xo<]?--\s*)/,/^(?:\s*[xo<]?==\s*)/,/^(?:\s*[xo<]?-\.\s*)/,/^(?:\(-)/,/^(?:-\))/,/^(?:\(\[)/,/^(?:\]\))/,/^(?:\[\[)/,/^(?:\]\])/,/^(?:\[\()/,/^(?:\)\])/,/^(?:-)/,/^(?:\.)/,/^(?:[\_])/,/^(?:\+)/,/^(?:%)/,/^(?:=)/,/^(?:=)/,/^(?:<)/,/^(?:>)/,/^(?:\^)/,/^(?:\\\|)/,/^(?:v\b)/,/^(?:[A-Za-z]+)/,/^(?:\\\])/,/^(?:\[\/)/,/^(?:\/\])/,/^(?:\[\\)/,/^(?:[!"#$%&'*+,-.`?\\_/])/,/^(?:[\u00AA\u00B5\u00BA\u00C0-\u00D6\u00D8-\u00F6]|[\u00F8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377]|[\u037A-\u037D\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5]|[\u03F7-\u0481\u048A-\u0527\u0531-\u0556\u0559\u0561-\u0587\u05D0-\u05EA]|[\u05F0-\u05F2\u0620-\u064A\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE]|[\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA]|[\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u08A0]|[\u08A2-\u08AC\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0977]|[\u0979-\u097F\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2]|[\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09F0\u09F1\u0A05-\u0A0A]|[\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39]|[\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8]|[\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0B05-\u0B0C]|[\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C]|[\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99]|[\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0]|[\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C33\u0C35-\u0C39\u0C3D]|[\u0C58\u0C59\u0C60\u0C61\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3]|[\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D05-\u0D0C\u0D0E-\u0D10]|[\u0D12-\u0D3A\u0D3D\u0D4E\u0D60\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1]|[\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E81]|[\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3]|[\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6]|[\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A]|[\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081]|[\u108E\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D]|[\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0]|[\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310]|[\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F4\u1401-\u166C]|[\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u1700-\u170C\u170E-\u1711]|[\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7]|[\u17DC\u1820-\u1877\u1880-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191C]|[\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19C1-\u19C7\u1A00-\u1A16]|[\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-\u1B4B\u1B83-\u1BA0\u1BAE\u1BAF]|[\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\u1CE9-\u1CEC]|[\u1CEE-\u1CF1\u1CF5\u1CF6\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D]|[\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D]|[\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3]|[\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F]|[\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128]|[\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2183\u2184]|[\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3]|[\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6]|[\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE]|[\u2DD0-\u2DD6\u2DD8-\u2DDE\u2E2F\u3005\u3006\u3031-\u3035\u303B\u303C]|[\u3041-\u3096\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D]|[\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FCC]|[\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B]|[\uA640-\uA66E\uA67F-\uA697\uA6A0-\uA6E5\uA717-\uA71F\uA722-\uA788]|[\uA78B-\uA78E\uA790-\uA793\uA7A0-\uA7AA\uA7F8-\uA801\uA803-\uA805]|[\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB]|[\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF\uAA00-\uAA28]|[\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA80-\uAAAF\uAAB1\uAAB5]|[\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4]|[\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E]|[\uABC0-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D]|[\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36]|[\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D]|[\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC]|[\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF]|[\uFFD2-\uFFD7\uFFDA-\uFFDC])/,/^(?:\|)/,/^(?:\()/,/^(?:\))/,/^(?:\[)/,/^(?:\])/,/^(?:\{)/,/^(?:\})/,/^(?:")/,/^(?:(\r?\n)+)/,/^(?:\s)/,/^(?:$)/],conditions:{close_directive:{rules:[],inclusive:!1},arg_directive:{rules:[3,4],inclusive:!1},type_directive:{rules:[2,3],inclusive:!1},open_directive:{rules:[1],inclusive:!1},callbackargs:{rules:[23,24],inclusive:!1},callbackname:{rules:[20,21,22],inclusive:!1},href:{rules:[17,18],inclusive:!1},click:{rules:[26,27],inclusive:!1},vertex:{rules:[],inclusive:!1},dir:{rules:[36,37,38,39,40,41,42,43,44,45,46],inclusive:!1},string:{rules:[8,9],inclusive:!1},INITIAL:{rules:[0,5,6,7,10,11,12,13,14,15,16,19,25,28,29,30,31,32,33,34,35,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102],inclusive:!0}}};function Jt(){this.yy={}}return Qt.lexer=Kt,Jt.prototype=Qt,Qt.Parser=Jt,new Jt}();e.parser=r,e.Parser=r.Parser,e.parse=function(){return r.parse.apply(r,arguments)},e.main=function(t){t[1]||(console.log("Usage: "+t[0]+" FILE"),process.exit(1));var r=n(5354).readFileSync(n(6470).normalize(t[1]),"utf8");return e.parser.parse(r)},n.c[n.s]===t&&e.main(process.argv.slice(1))},2055:(t,e,n)=>{t=n.nmd(t);var r=function(){var t=function(t,e,n,r){for(n=n||{},r=t.length;r--;n[t[r]]=e);return n},e=[1,3],n=[1,5],r=[7,9,11,12,13,14,15,16,17,18,19,20,22,29,34],i=[1,15],a=[1,16],o=[1,17],s=[1,18],c=[1,19],u=[1,20],l=[1,21],h=[1,22],f=[1,23],d=[1,25],p=[1,27],y=[1,30],g=[5,7,9,11,12,13,14,15,16,17,18,19,20,22,29,34],m={trace:function(){},yy:{},symbols_:{error:2,start:3,directive:4,gantt:5,document:6,EOF:7,line:8,SPACE:9,statement:10,NL:11,dateFormat:12,inclusiveEndDates:13,topAxis:14,axisFormat:15,excludes:16,includes:17,todayMarker:18,title:19,section:20,clickStatement:21,taskTxt:22,taskData:23,openDirective:24,typeDirective:25,closeDirective:26,":":27,argDirective:28,click:29,callbackname:30,callbackargs:31,href:32,clickStatementDebug:33,open_directive:34,type_directive:35,arg_directive:36,close_directive:37,$accept:0,$end:1},terminals_:{2:"error",5:"gantt",7:"EOF",9:"SPACE",11:"NL",12:"dateFormat",13:"inclusiveEndDates",14:"topAxis",15:"axisFormat",16:"excludes",17:"includes",18:"todayMarker",19:"title",20:"section",22:"taskTxt",23:"taskData",27:":",29:"click",30:"callbackname",31:"callbackargs",32:"href",34:"open_directive",35:"type_directive",36:"arg_directive",37:"close_directive"},productions_:[0,[3,2],[3,3],[6,0],[6,2],[8,2],[8,1],[8,1],[8,1],[10,1],[10,1],[10,1],[10,1],[10,1],[10,1],[10,1],[10,1],[10,1],[10,1],[10,2],[10,1],[4,4],[4,6],[21,2],[21,3],[21,3],[21,4],[21,3],[21,4],[21,2],[33,2],[33,3],[33,3],[33,4],[33,3],[33,4],[33,2],[24,1],[25,1],[28,1],[26,1]],performAction:function(t,e,n,r,i,a,o){var s=a.length-1;switch(i){case 2:return a[s-1];case 3:this.$=[];break;case 4:a[s-1].push(a[s]),this.$=a[s-1];break;case 5:case 6:this.$=a[s];break;case 7:case 8:this.$=[];break;case 9:r.setDateFormat(a[s].substr(11)),this.$=a[s].substr(11);break;case 10:r.enableInclusiveEndDates(),this.$=a[s].substr(18);break;case 11:r.TopAxis(),this.$=a[s].substr(8);break;case 12:r.setAxisFormat(a[s].substr(11)),this.$=a[s].substr(11);break;case 13:r.setExcludes(a[s].substr(9)),this.$=a[s].substr(9);break;case 14:r.setIncludes(a[s].substr(9)),this.$=a[s].substr(9);break;case 15:r.setTodayMarker(a[s].substr(12)),this.$=a[s].substr(12);break;case 16:r.setTitle(a[s].substr(6)),this.$=a[s].substr(6);break;case 17:r.addSection(a[s].substr(8)),this.$=a[s].substr(8);break;case 19:r.addTask(a[s-1],a[s]),this.$="task";break;case 23:this.$=a[s-1],r.setClickEvent(a[s-1],a[s],null);break;case 24:this.$=a[s-2],r.setClickEvent(a[s-2],a[s-1],a[s]);break;case 25:this.$=a[s-2],r.setClickEvent(a[s-2],a[s-1],null),r.setLink(a[s-2],a[s]);break;case 26:this.$=a[s-3],r.setClickEvent(a[s-3],a[s-2],a[s-1]),r.setLink(a[s-3],a[s]);break;case 27:this.$=a[s-2],r.setClickEvent(a[s-2],a[s],null),r.setLink(a[s-2],a[s-1]);break;case 28:this.$=a[s-3],r.setClickEvent(a[s-3],a[s-1],a[s]),r.setLink(a[s-3],a[s-2]);break;case 29:this.$=a[s-1],r.setLink(a[s-1],a[s]);break;case 30:case 36:this.$=a[s-1]+" "+a[s];break;case 31:case 32:case 34:this.$=a[s-2]+" "+a[s-1]+" "+a[s];break;case 33:case 35:this.$=a[s-3]+" "+a[s-2]+" "+a[s-1]+" "+a[s];break;case 37:r.parseDirective("%%{","open_directive");break;case 38:r.parseDirective(a[s],"type_directive");break;case 39:a[s]=a[s].trim().replace(/'/g,'"'),r.parseDirective(a[s],"arg_directive");break;case 40:r.parseDirective("}%%","close_directive","gantt")}},table:[{3:1,4:2,5:e,24:4,34:n},{1:[3]},{3:6,4:2,5:e,24:4,34:n},t(r,[2,3],{6:7}),{25:8,35:[1,9]},{35:[2,37]},{1:[2,1]},{4:26,7:[1,10],8:11,9:[1,12],10:13,11:[1,14],12:i,13:a,14:o,15:s,16:c,17:u,18:l,19:h,20:f,21:24,22:d,24:4,29:p,34:n},{26:28,27:[1,29],37:y},t([27,37],[2,38]),t(r,[2,8],{1:[2,2]}),t(r,[2,4]),{4:26,10:31,12:i,13:a,14:o,15:s,16:c,17:u,18:l,19:h,20:f,21:24,22:d,24:4,29:p,34:n},t(r,[2,6]),t(r,[2,7]),t(r,[2,9]),t(r,[2,10]),t(r,[2,11]),t(r,[2,12]),t(r,[2,13]),t(r,[2,14]),t(r,[2,15]),t(r,[2,16]),t(r,[2,17]),t(r,[2,18]),{23:[1,32]},t(r,[2,20]),{30:[1,33],32:[1,34]},{11:[1,35]},{28:36,36:[1,37]},{11:[2,40]},t(r,[2,5]),t(r,[2,19]),t(r,[2,23],{31:[1,38],32:[1,39]}),t(r,[2,29],{30:[1,40]}),t(g,[2,21]),{26:41,37:y},{37:[2,39]},t(r,[2,24],{32:[1,42]}),t(r,[2,25]),t(r,[2,27],{31:[1,43]}),{11:[1,44]},t(r,[2,26]),t(r,[2,28]),t(g,[2,22])],defaultActions:{5:[2,37],6:[2,1],30:[2,40],37:[2,39]},parseError:function(t,e){if(!e.recoverable){var n=new Error(t);throw n.hash=e,n}this.trace(t)},parse:function(t){var e=this,n=[0],r=[],i=[null],a=[],o=this.table,s="",c=0,u=0,l=0,h=2,f=1,d=a.slice.call(arguments,1),p=Object.create(this.lexer),y={yy:{}};for(var g in this.yy)Object.prototype.hasOwnProperty.call(this.yy,g)&&(y.yy[g]=this.yy[g]);p.setInput(t,y.yy),y.yy.lexer=p,y.yy.parser=this,void 0===p.yylloc&&(p.yylloc={});var m=p.yylloc;a.push(m);var v=p.options&&p.options.ranges;function b(){var t;return"number"!=typeof(t=r.pop()||p.lex()||f)&&(t instanceof Array&&(t=(r=t).pop()),t=e.symbols_[t]||t),t}"function"==typeof y.yy.parseError?this.parseError=y.yy.parseError:this.parseError=Object.getPrototypeOf(this).parseError;for(var _,x,w,k,T,E,C,S,A,M={};;){if(w=n[n.length-1],this.defaultActions[w]?k=this.defaultActions[w]:(null==_&&(_=b()),k=o[w]&&o[w][_]),void 0===k||!k.length||!k[0]){var N="";for(E in A=[],o[w])this.terminals_[E]&&E>h&&A.push("'"+this.terminals_[E]+"'");N=p.showPosition?"Parse error on line "+(c+1)+":\n"+p.showPosition()+"\nExpecting "+A.join(", ")+", got '"+(this.terminals_[_]||_)+"'":"Parse error on line "+(c+1)+": Unexpected "+(_==f?"end of input":"'"+(this.terminals_[_]||_)+"'"),this.parseError(N,{text:p.match,token:this.terminals_[_]||_,line:p.yylineno,loc:m,expected:A})}if(k[0]instanceof Array&&k.length>1)throw new Error("Parse Error: multiple actions possible at state: "+w+", token: "+_);switch(k[0]){case 1:n.push(_),i.push(p.yytext),a.push(p.yylloc),n.push(k[1]),_=null,x?(_=x,x=null):(u=p.yyleng,s=p.yytext,c=p.yylineno,m=p.yylloc,l>0&&l--);break;case 2:if(C=this.productions_[k[1]][1],M.$=i[i.length-C],M._$={first_line:a[a.length-(C||1)].first_line,last_line:a[a.length-1].last_line,first_column:a[a.length-(C||1)].first_column,last_column:a[a.length-1].last_column},v&&(M._$.range=[a[a.length-(C||1)].range[0],a[a.length-1].range[1]]),void 0!==(T=this.performAction.apply(M,[s,u,c,y.yy,k[1],i,a].concat(d))))return T;C&&(n=n.slice(0,-1*C*2),i=i.slice(0,-1*C),a=a.slice(0,-1*C)),n.push(this.productions_[k[1]][0]),i.push(M.$),a.push(M._$),S=o[n[n.length-2]][n[n.length-1]],n.push(S);break;case 3:return!0}}return!0}},v={EOF:1,parseError:function(t,e){if(!this.yy.parser)throw new Error(t);this.yy.parser.parseError(t,e)},setInput:function(t,e){return this.yy=e||this.yy||{},this._input=t,this._more=this._backtrack=this.done=!1,this.yylineno=this.yyleng=0,this.yytext=this.matched=this.match="",this.conditionStack=["INITIAL"],this.yylloc={first_line:1,first_column:0,last_line:1,last_column:0},this.options.ranges&&(this.yylloc.range=[0,0]),this.offset=0,this},input:function(){var t=this._input[0];return this.yytext+=t,this.yyleng++,this.offset++,this.match+=t,this.matched+=t,t.match(/(?:\r\n?|\n).*/g)?(this.yylineno++,this.yylloc.last_line++):this.yylloc.last_column++,this.options.ranges&&this.yylloc.range[1]++,this._input=this._input.slice(1),t},unput:function(t){var e=t.length,n=t.split(/(?:\r\n?|\n)/g);this._input=t+this._input,this.yytext=this.yytext.substr(0,this.yytext.length-e),this.offset-=e;var r=this.match.split(/(?:\r\n?|\n)/g);this.match=this.match.substr(0,this.match.length-1),this.matched=this.matched.substr(0,this.matched.length-1),n.length-1&&(this.yylineno-=n.length-1);var i=this.yylloc.range;return this.yylloc={first_line:this.yylloc.first_line,last_line:this.yylineno+1,first_column:this.yylloc.first_column,last_column:n?(n.length===r.length?this.yylloc.first_column:0)+r[r.length-n.length].length-n[0].length:this.yylloc.first_column-e},this.options.ranges&&(this.yylloc.range=[i[0],i[0]+this.yyleng-e]),this.yyleng=this.yytext.length,this},more:function(){return this._more=!0,this},reject:function(){return this.options.backtrack_lexer?(this._backtrack=!0,this):this.parseError("Lexical error on line "+(this.yylineno+1)+". You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true).\n"+this.showPosition(),{text:"",token:null,line:this.yylineno})},less:function(t){this.unput(this.match.slice(t))},pastInput:function(){var t=this.matched.substr(0,this.matched.length-this.match.length);return(t.length>20?"...":"")+t.substr(-20).replace(/\n/g,"")},upcomingInput:function(){var t=this.match;return t.length<20&&(t+=this._input.substr(0,20-t.length)),(t.substr(0,20)+(t.length>20?"...":"")).replace(/\n/g,"")},showPosition:function(){var t=this.pastInput(),e=new Array(t.length+1).join("-");return t+this.upcomingInput()+"\n"+e+"^"},test_match:function(t,e){var n,r,i;if(this.options.backtrack_lexer&&(i={yylineno:this.yylineno,yylloc:{first_line:this.yylloc.first_line,last_line:this.last_line,first_column:this.yylloc.first_column,last_column:this.yylloc.last_column},yytext:this.yytext,match:this.match,matches:this.matches,matched:this.matched,yyleng:this.yyleng,offset:this.offset,_more:this._more,_input:this._input,yy:this.yy,conditionStack:this.conditionStack.slice(0),done:this.done},this.options.ranges&&(i.yylloc.range=this.yylloc.range.slice(0))),(r=t[0].match(/(?:\r\n?|\n).*/g))&&(this.yylineno+=r.length),this.yylloc={first_line:this.yylloc.last_line,last_line:this.yylineno+1,first_column:this.yylloc.last_column,last_column:r?r[r.length-1].length-r[r.length-1].match(/\r?\n?/)[0].length:this.yylloc.last_column+t[0].length},this.yytext+=t[0],this.match+=t[0],this.matches=t,this.yyleng=this.yytext.length,this.options.ranges&&(this.yylloc.range=[this.offset,this.offset+=this.yyleng]),this._more=!1,this._backtrack=!1,this._input=this._input.slice(t[0].length),this.matched+=t[0],n=this.performAction.call(this,this.yy,this,e,this.conditionStack[this.conditionStack.length-1]),this.done&&this._input&&(this.done=!1),n)return n;if(this._backtrack){for(var a in i)this[a]=i[a];return!1}return!1},next:function(){if(this.done)return this.EOF;var t,e,n,r;this._input||(this.done=!0),this._more||(this.yytext="",this.match="");for(var i=this._currentRules(),a=0;ae[0].length)){if(e=n,r=a,this.options.backtrack_lexer){if(!1!==(t=this.test_match(n,i[a])))return t;if(this._backtrack){e=!1;continue}return!1}if(!this.options.flex)break}return e?!1!==(t=this.test_match(e,i[r]))&&t:""===this._input?this.EOF:this.parseError("Lexical error on line "+(this.yylineno+1)+". Unrecognized text.\n"+this.showPosition(),{text:"",token:null,line:this.yylineno})},lex:function(){return this.next()||this.lex()},begin:function(t){this.conditionStack.push(t)},popState:function(){return this.conditionStack.length-1>0?this.conditionStack.pop():this.conditionStack[0]},_currentRules:function(){return this.conditionStack.length&&this.conditionStack[this.conditionStack.length-1]?this.conditions[this.conditionStack[this.conditionStack.length-1]].rules:this.conditions.INITIAL.rules},topState:function(t){return(t=this.conditionStack.length-1-Math.abs(t||0))>=0?this.conditionStack[t]:"INITIAL"},pushState:function(t){this.begin(t)},stateStackSize:function(){return this.conditionStack.length},options:{"case-insensitive":!0},performAction:function(t,e,n,r){switch(n){case 0:return this.begin("open_directive"),34;case 1:return this.begin("type_directive"),35;case 2:return this.popState(),this.begin("arg_directive"),27;case 3:return this.popState(),this.popState(),37;case 4:return 36;case 5:case 6:case 7:break;case 8:return 11;case 9:case 10:case 11:break;case 12:this.begin("href");break;case 13:this.popState();break;case 14:return 32;case 15:this.begin("callbackname");break;case 16:this.popState();break;case 17:this.popState(),this.begin("callbackargs");break;case 18:return 30;case 19:this.popState();break;case 20:return 31;case 21:this.begin("click");break;case 22:this.popState();break;case 23:return 29;case 24:return 5;case 25:return 12;case 26:return 13;case 27:return 14;case 28:return 15;case 29:return 17;case 30:return 16;case 31:return 18;case 32:return"date";case 33:return 19;case 34:return 20;case 35:return 22;case 36:return 23;case 37:return 27;case 38:return 7;case 39:return"INVALID"}},rules:[/^(?:%%\{)/i,/^(?:((?:(?!\}%%)[^:.])*))/i,/^(?::)/i,/^(?:\}%%)/i,/^(?:((?:(?!\}%%).|\n)*))/i,/^(?:%%(?!\{)*[^\n]*)/i,/^(?:[^\}]%%*[^\n]*)/i,/^(?:%%*[^\n]*[\n]*)/i,/^(?:[\n]+)/i,/^(?:\s+)/i,/^(?:#[^\n]*)/i,/^(?:%[^\n]*)/i,/^(?:href[\s]+["])/i,/^(?:["])/i,/^(?:[^"]*)/i,/^(?:call[\s]+)/i,/^(?:\([\s]*\))/i,/^(?:\()/i,/^(?:[^(]*)/i,/^(?:\))/i,/^(?:[^)]*)/i,/^(?:click[\s]+)/i,/^(?:[\s\n])/i,/^(?:[^\s\n]*)/i,/^(?:gantt\b)/i,/^(?:dateFormat\s[^#\n;]+)/i,/^(?:inclusiveEndDates\b)/i,/^(?:topAxis\b)/i,/^(?:axisFormat\s[^#\n;]+)/i,/^(?:includes\s[^#\n;]+)/i,/^(?:excludes\s[^#\n;]+)/i,/^(?:todayMarker\s[^\n;]+)/i,/^(?:\d\d\d\d-\d\d-\d\d\b)/i,/^(?:title\s[^#\n;]+)/i,/^(?:section\s[^#:\n;]+)/i,/^(?:[^#:\n;]+)/i,/^(?::[^#\n;]+)/i,/^(?::)/i,/^(?:$)/i,/^(?:.)/i],conditions:{close_directive:{rules:[],inclusive:!1},arg_directive:{rules:[3,4],inclusive:!1},type_directive:{rules:[2,3],inclusive:!1},open_directive:{rules:[1],inclusive:!1},callbackargs:{rules:[19,20],inclusive:!1},callbackname:{rules:[16,17,18],inclusive:!1},href:{rules:[13,14],inclusive:!1},click:{rules:[22,23],inclusive:!1},INITIAL:{rules:[0,5,6,7,8,9,10,11,12,15,21,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39],inclusive:!0}}};function b(){this.yy={}}return m.lexer=v,b.prototype=m,m.Parser=b,new b}();e.parser=r,e.Parser=r.Parser,e.parse=function(){return r.parse.apply(r,arguments)},e.main=function(t){t[1]||(console.log("Usage: "+t[0]+" FILE"),process.exit(1));var r=n(6878).readFileSync(n(6470).normalize(t[1]),"utf8");return e.parser.parse(r)},n.c[n.s]===t&&e.main(process.argv.slice(1))},8454:(t,e,n)=>{t=n.nmd(t);var r=function(){var t=function(t,e,n,r){for(n=n||{},r=t.length;r--;n[t[r]]=e);return n},e=[2,3],n=[1,7],r=[7,12,15,17,19,20,21],i=[7,11,12,15,17,19,20,21],a=[2,20],o=[1,32],s={trace:function(){},yy:{},symbols_:{error:2,start:3,GG:4,":":5,document:6,EOF:7,DIR:8,options:9,body:10,OPT:11,NL:12,line:13,statement:14,COMMIT:15,commit_arg:16,BRANCH:17,ID:18,CHECKOUT:19,MERGE:20,RESET:21,reset_arg:22,STR:23,HEAD:24,reset_parents:25,CARET:26,$accept:0,$end:1},terminals_:{2:"error",4:"GG",5:":",7:"EOF",8:"DIR",11:"OPT",12:"NL",15:"COMMIT",17:"BRANCH",18:"ID",19:"CHECKOUT",20:"MERGE",21:"RESET",23:"STR",24:"HEAD",26:"CARET"},productions_:[0,[3,4],[3,5],[6,0],[6,2],[9,2],[9,1],[10,0],[10,2],[13,2],[13,1],[14,2],[14,2],[14,2],[14,2],[14,2],[16,0],[16,1],[22,2],[22,2],[25,0],[25,2]],performAction:function(t,e,n,r,i,a,o){var s=a.length-1;switch(i){case 1:return a[s-1];case 2:return r.setDirection(a[s-3]),a[s-1];case 4:r.setOptions(a[s-1]),this.$=a[s];break;case 5:a[s-1]+=a[s],this.$=a[s-1];break;case 7:this.$=[];break;case 8:a[s-1].push(a[s]),this.$=a[s-1];break;case 9:this.$=a[s-1];break;case 11:r.commit(a[s]);break;case 12:r.branch(a[s]);break;case 13:r.checkout(a[s]);break;case 14:r.merge(a[s]);break;case 15:r.reset(a[s]);break;case 16:this.$="";break;case 17:this.$=a[s];break;case 18:this.$=a[s-1]+":"+a[s];break;case 19:this.$=a[s-1]+":"+r.count,r.count=0;break;case 20:r.count=0;break;case 21:r.count+=1}},table:[{3:1,4:[1,2]},{1:[3]},{5:[1,3],8:[1,4]},{6:5,7:e,9:6,12:n},{5:[1,8]},{7:[1,9]},t(r,[2,7],{10:10,11:[1,11]}),t(i,[2,6]),{6:12,7:e,9:6,12:n},{1:[2,1]},{7:[2,4],12:[1,15],13:13,14:14,15:[1,16],17:[1,17],19:[1,18],20:[1,19],21:[1,20]},t(i,[2,5]),{7:[1,21]},t(r,[2,8]),{12:[1,22]},t(r,[2,10]),{12:[2,16],16:23,23:[1,24]},{18:[1,25]},{18:[1,26]},{18:[1,27]},{18:[1,30],22:28,24:[1,29]},{1:[2,2]},t(r,[2,9]),{12:[2,11]},{12:[2,17]},{12:[2,12]},{12:[2,13]},{12:[2,14]},{12:[2,15]},{12:a,25:31,26:o},{12:a,25:33,26:o},{12:[2,18]},{12:a,25:34,26:o},{12:[2,19]},{12:[2,21]}],defaultActions:{9:[2,1],21:[2,2],23:[2,11],24:[2,17],25:[2,12],26:[2,13],27:[2,14],28:[2,15],31:[2,18],33:[2,19],34:[2,21]},parseError:function(t,e){if(!e.recoverable){var n=new Error(t);throw n.hash=e,n}this.trace(t)},parse:function(t){var e=this,n=[0],r=[],i=[null],a=[],o=this.table,s="",c=0,u=0,l=0,h=2,f=1,d=a.slice.call(arguments,1),p=Object.create(this.lexer),y={yy:{}};for(var g in this.yy)Object.prototype.hasOwnProperty.call(this.yy,g)&&(y.yy[g]=this.yy[g]);p.setInput(t,y.yy),y.yy.lexer=p,y.yy.parser=this,void 0===p.yylloc&&(p.yylloc={});var m=p.yylloc;a.push(m);var v=p.options&&p.options.ranges;function b(){var t;return"number"!=typeof(t=r.pop()||p.lex()||f)&&(t instanceof Array&&(t=(r=t).pop()),t=e.symbols_[t]||t),t}"function"==typeof y.yy.parseError?this.parseError=y.yy.parseError:this.parseError=Object.getPrototypeOf(this).parseError;for(var _,x,w,k,T,E,C,S,A,M={};;){if(w=n[n.length-1],this.defaultActions[w]?k=this.defaultActions[w]:(null==_&&(_=b()),k=o[w]&&o[w][_]),void 0===k||!k.length||!k[0]){var N="";for(E in A=[],o[w])this.terminals_[E]&&E>h&&A.push("'"+this.terminals_[E]+"'");N=p.showPosition?"Parse error on line "+(c+1)+":\n"+p.showPosition()+"\nExpecting "+A.join(", ")+", got '"+(this.terminals_[_]||_)+"'":"Parse error on line "+(c+1)+": Unexpected "+(_==f?"end of input":"'"+(this.terminals_[_]||_)+"'"),this.parseError(N,{text:p.match,token:this.terminals_[_]||_,line:p.yylineno,loc:m,expected:A})}if(k[0]instanceof Array&&k.length>1)throw new Error("Parse Error: multiple actions possible at state: "+w+", token: "+_);switch(k[0]){case 1:n.push(_),i.push(p.yytext),a.push(p.yylloc),n.push(k[1]),_=null,x?(_=x,x=null):(u=p.yyleng,s=p.yytext,c=p.yylineno,m=p.yylloc,l>0&&l--);break;case 2:if(C=this.productions_[k[1]][1],M.$=i[i.length-C],M._$={first_line:a[a.length-(C||1)].first_line,last_line:a[a.length-1].last_line,first_column:a[a.length-(C||1)].first_column,last_column:a[a.length-1].last_column},v&&(M._$.range=[a[a.length-(C||1)].range[0],a[a.length-1].range[1]]),void 0!==(T=this.performAction.apply(M,[s,u,c,y.yy,k[1],i,a].concat(d))))return T;C&&(n=n.slice(0,-1*C*2),i=i.slice(0,-1*C),a=a.slice(0,-1*C)),n.push(this.productions_[k[1]][0]),i.push(M.$),a.push(M._$),S=o[n[n.length-2]][n[n.length-1]],n.push(S);break;case 3:return!0}}return!0}},c={EOF:1,parseError:function(t,e){if(!this.yy.parser)throw new Error(t);this.yy.parser.parseError(t,e)},setInput:function(t,e){return this.yy=e||this.yy||{},this._input=t,this._more=this._backtrack=this.done=!1,this.yylineno=this.yyleng=0,this.yytext=this.matched=this.match="",this.conditionStack=["INITIAL"],this.yylloc={first_line:1,first_column:0,last_line:1,last_column:0},this.options.ranges&&(this.yylloc.range=[0,0]),this.offset=0,this},input:function(){var t=this._input[0];return this.yytext+=t,this.yyleng++,this.offset++,this.match+=t,this.matched+=t,t.match(/(?:\r\n?|\n).*/g)?(this.yylineno++,this.yylloc.last_line++):this.yylloc.last_column++,this.options.ranges&&this.yylloc.range[1]++,this._input=this._input.slice(1),t},unput:function(t){var e=t.length,n=t.split(/(?:\r\n?|\n)/g);this._input=t+this._input,this.yytext=this.yytext.substr(0,this.yytext.length-e),this.offset-=e;var r=this.match.split(/(?:\r\n?|\n)/g);this.match=this.match.substr(0,this.match.length-1),this.matched=this.matched.substr(0,this.matched.length-1),n.length-1&&(this.yylineno-=n.length-1);var i=this.yylloc.range;return this.yylloc={first_line:this.yylloc.first_line,last_line:this.yylineno+1,first_column:this.yylloc.first_column,last_column:n?(n.length===r.length?this.yylloc.first_column:0)+r[r.length-n.length].length-n[0].length:this.yylloc.first_column-e},this.options.ranges&&(this.yylloc.range=[i[0],i[0]+this.yyleng-e]),this.yyleng=this.yytext.length,this},more:function(){return this._more=!0,this},reject:function(){return this.options.backtrack_lexer?(this._backtrack=!0,this):this.parseError("Lexical error on line "+(this.yylineno+1)+". You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true).\n"+this.showPosition(),{text:"",token:null,line:this.yylineno})},less:function(t){this.unput(this.match.slice(t))},pastInput:function(){var t=this.matched.substr(0,this.matched.length-this.match.length);return(t.length>20?"...":"")+t.substr(-20).replace(/\n/g,"")},upcomingInput:function(){var t=this.match;return t.length<20&&(t+=this._input.substr(0,20-t.length)),(t.substr(0,20)+(t.length>20?"...":"")).replace(/\n/g,"")},showPosition:function(){var t=this.pastInput(),e=new Array(t.length+1).join("-");return t+this.upcomingInput()+"\n"+e+"^"},test_match:function(t,e){var n,r,i;if(this.options.backtrack_lexer&&(i={yylineno:this.yylineno,yylloc:{first_line:this.yylloc.first_line,last_line:this.last_line,first_column:this.yylloc.first_column,last_column:this.yylloc.last_column},yytext:this.yytext,match:this.match,matches:this.matches,matched:this.matched,yyleng:this.yyleng,offset:this.offset,_more:this._more,_input:this._input,yy:this.yy,conditionStack:this.conditionStack.slice(0),done:this.done},this.options.ranges&&(i.yylloc.range=this.yylloc.range.slice(0))),(r=t[0].match(/(?:\r\n?|\n).*/g))&&(this.yylineno+=r.length),this.yylloc={first_line:this.yylloc.last_line,last_line:this.yylineno+1,first_column:this.yylloc.last_column,last_column:r?r[r.length-1].length-r[r.length-1].match(/\r?\n?/)[0].length:this.yylloc.last_column+t[0].length},this.yytext+=t[0],this.match+=t[0],this.matches=t,this.yyleng=this.yytext.length,this.options.ranges&&(this.yylloc.range=[this.offset,this.offset+=this.yyleng]),this._more=!1,this._backtrack=!1,this._input=this._input.slice(t[0].length),this.matched+=t[0],n=this.performAction.call(this,this.yy,this,e,this.conditionStack[this.conditionStack.length-1]),this.done&&this._input&&(this.done=!1),n)return n;if(this._backtrack){for(var a in i)this[a]=i[a];return!1}return!1},next:function(){if(this.done)return this.EOF;var t,e,n,r;this._input||(this.done=!0),this._more||(this.yytext="",this.match="");for(var i=this._currentRules(),a=0;ae[0].length)){if(e=n,r=a,this.options.backtrack_lexer){if(!1!==(t=this.test_match(n,i[a])))return t;if(this._backtrack){e=!1;continue}return!1}if(!this.options.flex)break}return e?!1!==(t=this.test_match(e,i[r]))&&t:""===this._input?this.EOF:this.parseError("Lexical error on line "+(this.yylineno+1)+". Unrecognized text.\n"+this.showPosition(),{text:"",token:null,line:this.yylineno})},lex:function(){return this.next()||this.lex()},begin:function(t){this.conditionStack.push(t)},popState:function(){return this.conditionStack.length-1>0?this.conditionStack.pop():this.conditionStack[0]},_currentRules:function(){return this.conditionStack.length&&this.conditionStack[this.conditionStack.length-1]?this.conditions[this.conditionStack[this.conditionStack.length-1]].rules:this.conditions.INITIAL.rules},topState:function(t){return(t=this.conditionStack.length-1-Math.abs(t||0))>=0?this.conditionStack[t]:"INITIAL"},pushState:function(t){this.begin(t)},stateStackSize:function(){return this.conditionStack.length},options:{"case-insensitive":!0},performAction:function(t,e,n,r){switch(n){case 0:return 12;case 1:case 2:case 3:break;case 4:return 4;case 5:return 15;case 6:return 17;case 7:return 20;case 8:return 21;case 9:return 19;case 10:case 11:return 8;case 12:return 5;case 13:return 26;case 14:this.begin("options");break;case 15:this.popState();break;case 16:return 11;case 17:this.begin("string");break;case 18:this.popState();break;case 19:return 23;case 20:return 18;case 21:return 7}},rules:[/^(?:(\r?\n)+)/i,/^(?:\s+)/i,/^(?:#[^\n]*)/i,/^(?:%[^\n]*)/i,/^(?:gitGraph\b)/i,/^(?:commit\b)/i,/^(?:branch\b)/i,/^(?:merge\b)/i,/^(?:reset\b)/i,/^(?:checkout\b)/i,/^(?:LR\b)/i,/^(?:BT\b)/i,/^(?::)/i,/^(?:\^)/i,/^(?:options\r?\n)/i,/^(?:end\r?\n)/i,/^(?:[^\n]+\r?\n)/i,/^(?:["])/i,/^(?:["])/i,/^(?:[^"]*)/i,/^(?:[a-zA-Z][-_\.a-zA-Z0-9]*[-_a-zA-Z0-9])/i,/^(?:$)/i],conditions:{options:{rules:[15,16],inclusive:!1},string:{rules:[18,19],inclusive:!1},INITIAL:{rules:[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,17,20,21],inclusive:!0}}};function u(){this.yy={}}return s.lexer=c,u.prototype=s,s.Parser=u,new u}();e.parser=r,e.Parser=r.Parser,e.parse=function(){return r.parse.apply(r,arguments)},e.main=function(t){t[1]||(console.log("Usage: "+t[0]+" FILE"),process.exit(1));var r=n(8183).readFileSync(n(6470).normalize(t[1]),"utf8");return e.parser.parse(r)},n.c[n.s]===t&&e.main(process.argv.slice(1))},4645:(t,e,n)=>{t=n.nmd(t);var r=function(){var t=function(t,e,n,r){for(n=n||{},r=t.length;r--;n[t[r]]=e);return n},e=[6,9,10],n={trace:function(){},yy:{},symbols_:{error:2,start:3,info:4,document:5,EOF:6,line:7,statement:8,NL:9,showInfo:10,$accept:0,$end:1},terminals_:{2:"error",4:"info",6:"EOF",9:"NL",10:"showInfo"},productions_:[0,[3,3],[5,0],[5,2],[7,1],[7,1],[8,1]],performAction:function(t,e,n,r,i,a,o){switch(a.length,i){case 1:return r;case 4:break;case 6:r.setInfo(!0)}},table:[{3:1,4:[1,2]},{1:[3]},t(e,[2,2],{5:3}),{6:[1,4],7:5,8:6,9:[1,7],10:[1,8]},{1:[2,1]},t(e,[2,3]),t(e,[2,4]),t(e,[2,5]),t(e,[2,6])],defaultActions:{4:[2,1]},parseError:function(t,e){if(!e.recoverable){var n=new Error(t);throw n.hash=e,n}this.trace(t)},parse:function(t){var e=this,n=[0],r=[],i=[null],a=[],o=this.table,s="",c=0,u=0,l=0,h=2,f=1,d=a.slice.call(arguments,1),p=Object.create(this.lexer),y={yy:{}};for(var g in this.yy)Object.prototype.hasOwnProperty.call(this.yy,g)&&(y.yy[g]=this.yy[g]);p.setInput(t,y.yy),y.yy.lexer=p,y.yy.parser=this,void 0===p.yylloc&&(p.yylloc={});var m=p.yylloc;a.push(m);var v=p.options&&p.options.ranges;function b(){var t;return"number"!=typeof(t=r.pop()||p.lex()||f)&&(t instanceof Array&&(t=(r=t).pop()),t=e.symbols_[t]||t),t}"function"==typeof y.yy.parseError?this.parseError=y.yy.parseError:this.parseError=Object.getPrototypeOf(this).parseError;for(var _,x,w,k,T,E,C,S,A,M={};;){if(w=n[n.length-1],this.defaultActions[w]?k=this.defaultActions[w]:(null==_&&(_=b()),k=o[w]&&o[w][_]),void 0===k||!k.length||!k[0]){var N="";for(E in A=[],o[w])this.terminals_[E]&&E>h&&A.push("'"+this.terminals_[E]+"'");N=p.showPosition?"Parse error on line "+(c+1)+":\n"+p.showPosition()+"\nExpecting "+A.join(", ")+", got '"+(this.terminals_[_]||_)+"'":"Parse error on line "+(c+1)+": Unexpected "+(_==f?"end of input":"'"+(this.terminals_[_]||_)+"'"),this.parseError(N,{text:p.match,token:this.terminals_[_]||_,line:p.yylineno,loc:m,expected:A})}if(k[0]instanceof Array&&k.length>1)throw new Error("Parse Error: multiple actions possible at state: "+w+", token: "+_);switch(k[0]){case 1:n.push(_),i.push(p.yytext),a.push(p.yylloc),n.push(k[1]),_=null,x?(_=x,x=null):(u=p.yyleng,s=p.yytext,c=p.yylineno,m=p.yylloc,l>0&&l--);break;case 2:if(C=this.productions_[k[1]][1],M.$=i[i.length-C],M._$={first_line:a[a.length-(C||1)].first_line,last_line:a[a.length-1].last_line,first_column:a[a.length-(C||1)].first_column,last_column:a[a.length-1].last_column},v&&(M._$.range=[a[a.length-(C||1)].range[0],a[a.length-1].range[1]]),void 0!==(T=this.performAction.apply(M,[s,u,c,y.yy,k[1],i,a].concat(d))))return T;C&&(n=n.slice(0,-1*C*2),i=i.slice(0,-1*C),a=a.slice(0,-1*C)),n.push(this.productions_[k[1]][0]),i.push(M.$),a.push(M._$),S=o[n[n.length-2]][n[n.length-1]],n.push(S);break;case 3:return!0}}return!0}},r={EOF:1,parseError:function(t,e){if(!this.yy.parser)throw new Error(t);this.yy.parser.parseError(t,e)},setInput:function(t,e){return this.yy=e||this.yy||{},this._input=t,this._more=this._backtrack=this.done=!1,this.yylineno=this.yyleng=0,this.yytext=this.matched=this.match="",this.conditionStack=["INITIAL"],this.yylloc={first_line:1,first_column:0,last_line:1,last_column:0},this.options.ranges&&(this.yylloc.range=[0,0]),this.offset=0,this},input:function(){var t=this._input[0];return this.yytext+=t,this.yyleng++,this.offset++,this.match+=t,this.matched+=t,t.match(/(?:\r\n?|\n).*/g)?(this.yylineno++,this.yylloc.last_line++):this.yylloc.last_column++,this.options.ranges&&this.yylloc.range[1]++,this._input=this._input.slice(1),t},unput:function(t){var e=t.length,n=t.split(/(?:\r\n?|\n)/g);this._input=t+this._input,this.yytext=this.yytext.substr(0,this.yytext.length-e),this.offset-=e;var r=this.match.split(/(?:\r\n?|\n)/g);this.match=this.match.substr(0,this.match.length-1),this.matched=this.matched.substr(0,this.matched.length-1),n.length-1&&(this.yylineno-=n.length-1);var i=this.yylloc.range;return this.yylloc={first_line:this.yylloc.first_line,last_line:this.yylineno+1,first_column:this.yylloc.first_column,last_column:n?(n.length===r.length?this.yylloc.first_column:0)+r[r.length-n.length].length-n[0].length:this.yylloc.first_column-e},this.options.ranges&&(this.yylloc.range=[i[0],i[0]+this.yyleng-e]),this.yyleng=this.yytext.length,this},more:function(){return this._more=!0,this},reject:function(){return this.options.backtrack_lexer?(this._backtrack=!0,this):this.parseError("Lexical error on line "+(this.yylineno+1)+". You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true).\n"+this.showPosition(),{text:"",token:null,line:this.yylineno})},less:function(t){this.unput(this.match.slice(t))},pastInput:function(){var t=this.matched.substr(0,this.matched.length-this.match.length);return(t.length>20?"...":"")+t.substr(-20).replace(/\n/g,"")},upcomingInput:function(){var t=this.match;return t.length<20&&(t+=this._input.substr(0,20-t.length)),(t.substr(0,20)+(t.length>20?"...":"")).replace(/\n/g,"")},showPosition:function(){var t=this.pastInput(),e=new Array(t.length+1).join("-");return t+this.upcomingInput()+"\n"+e+"^"},test_match:function(t,e){var n,r,i;if(this.options.backtrack_lexer&&(i={yylineno:this.yylineno,yylloc:{first_line:this.yylloc.first_line,last_line:this.last_line,first_column:this.yylloc.first_column,last_column:this.yylloc.last_column},yytext:this.yytext,match:this.match,matches:this.matches,matched:this.matched,yyleng:this.yyleng,offset:this.offset,_more:this._more,_input:this._input,yy:this.yy,conditionStack:this.conditionStack.slice(0),done:this.done},this.options.ranges&&(i.yylloc.range=this.yylloc.range.slice(0))),(r=t[0].match(/(?:\r\n?|\n).*/g))&&(this.yylineno+=r.length),this.yylloc={first_line:this.yylloc.last_line,last_line:this.yylineno+1,first_column:this.yylloc.last_column,last_column:r?r[r.length-1].length-r[r.length-1].match(/\r?\n?/)[0].length:this.yylloc.last_column+t[0].length},this.yytext+=t[0],this.match+=t[0],this.matches=t,this.yyleng=this.yytext.length,this.options.ranges&&(this.yylloc.range=[this.offset,this.offset+=this.yyleng]),this._more=!1,this._backtrack=!1,this._input=this._input.slice(t[0].length),this.matched+=t[0],n=this.performAction.call(this,this.yy,this,e,this.conditionStack[this.conditionStack.length-1]),this.done&&this._input&&(this.done=!1),n)return n;if(this._backtrack){for(var a in i)this[a]=i[a];return!1}return!1},next:function(){if(this.done)return this.EOF;var t,e,n,r;this._input||(this.done=!0),this._more||(this.yytext="",this.match="");for(var i=this._currentRules(),a=0;ae[0].length)){if(e=n,r=a,this.options.backtrack_lexer){if(!1!==(t=this.test_match(n,i[a])))return t;if(this._backtrack){e=!1;continue}return!1}if(!this.options.flex)break}return e?!1!==(t=this.test_match(e,i[r]))&&t:""===this._input?this.EOF:this.parseError("Lexical error on line "+(this.yylineno+1)+". Unrecognized text.\n"+this.showPosition(),{text:"",token:null,line:this.yylineno})},lex:function(){return this.next()||this.lex()},begin:function(t){this.conditionStack.push(t)},popState:function(){return this.conditionStack.length-1>0?this.conditionStack.pop():this.conditionStack[0]},_currentRules:function(){return this.conditionStack.length&&this.conditionStack[this.conditionStack.length-1]?this.conditions[this.conditionStack[this.conditionStack.length-1]].rules:this.conditions.INITIAL.rules},topState:function(t){return(t=this.conditionStack.length-1-Math.abs(t||0))>=0?this.conditionStack[t]:"INITIAL"},pushState:function(t){this.begin(t)},stateStackSize:function(){return this.conditionStack.length},options:{"case-insensitive":!0},performAction:function(t,e,n,r){switch(n){case 0:return 4;case 1:return 9;case 2:return"space";case 3:return 10;case 4:return 6;case 5:return"TXT"}},rules:[/^(?:info\b)/i,/^(?:[\s\n\r]+)/i,/^(?:[\s]+)/i,/^(?:showInfo\b)/i,/^(?:$)/i,/^(?:.)/i],conditions:{INITIAL:{rules:[0,1,2,3,4,5],inclusive:!0}}};function i(){this.yy={}}return n.lexer=r,i.prototype=n,n.Parser=i,new i}();e.parser=r,e.Parser=r.Parser,e.parse=function(){return r.parse.apply(r,arguments)},e.main=function(t){t[1]||(console.log("Usage: "+t[0]+" FILE"),process.exit(1));var r=n(1428).readFileSync(n(6470).normalize(t[1]),"utf8");return e.parser.parse(r)},n.c[n.s]===t&&e.main(process.argv.slice(1))},5963:(t,e,n)=>{t=n.nmd(t);var r=function(){var t=function(t,e,n,r){for(n=n||{},r=t.length;r--;n[t[r]]=e);return n},e=[1,4],n=[1,5],r=[1,6],i=[1,7],a=[1,9],o=[1,11,13,20,21,22,23],s=[2,5],c=[1,6,11,13,20,21,22,23],u=[20,21,22],l=[2,8],h=[1,18],f=[1,19],d=[1,24],p=[6,20,21,22,23],y={trace:function(){},yy:{},symbols_:{error:2,start:3,eol:4,directive:5,PIE:6,document:7,showData:8,line:9,statement:10,txt:11,value:12,title:13,title_value:14,openDirective:15,typeDirective:16,closeDirective:17,":":18,argDirective:19,NEWLINE:20,";":21,EOF:22,open_directive:23,type_directive:24,arg_directive:25,close_directive:26,$accept:0,$end:1},terminals_:{2:"error",6:"PIE",8:"showData",11:"txt",12:"value",13:"title",14:"title_value",18:":",20:"NEWLINE",21:";",22:"EOF",23:"open_directive",24:"type_directive",25:"arg_directive",26:"close_directive"},productions_:[0,[3,2],[3,2],[3,2],[3,3],[7,0],[7,2],[9,2],[10,0],[10,2],[10,2],[10,1],[5,3],[5,5],[4,1],[4,1],[4,1],[15,1],[16,1],[19,1],[17,1]],performAction:function(t,e,n,r,i,a,o){var s=a.length-1;switch(i){case 4:r.setShowData(!0);break;case 7:this.$=a[s-1];break;case 9:r.addSection(a[s-1],r.cleanupValue(a[s]));break;case 10:this.$=a[s].trim(),r.setTitle(this.$);break;case 17:r.parseDirective("%%{","open_directive");break;case 18:r.parseDirective(a[s],"type_directive");break;case 19:a[s]=a[s].trim().replace(/'/g,'"'),r.parseDirective(a[s],"arg_directive");break;case 20:r.parseDirective("}%%","close_directive","pie")}},table:[{3:1,4:2,5:3,6:e,15:8,20:n,21:r,22:i,23:a},{1:[3]},{3:10,4:2,5:3,6:e,15:8,20:n,21:r,22:i,23:a},{3:11,4:2,5:3,6:e,15:8,20:n,21:r,22:i,23:a},t(o,s,{7:12,8:[1,13]}),t(c,[2,14]),t(c,[2,15]),t(c,[2,16]),{16:14,24:[1,15]},{24:[2,17]},{1:[2,1]},{1:[2,2]},t(u,l,{15:8,9:16,10:17,5:20,1:[2,3],11:h,13:f,23:a}),t(o,s,{7:21}),{17:22,18:[1,23],26:d},t([18,26],[2,18]),t(o,[2,6]),{4:25,20:n,21:r,22:i},{12:[1,26]},{14:[1,27]},t(u,[2,11]),t(u,l,{15:8,9:16,10:17,5:20,1:[2,4],11:h,13:f,23:a}),t(p,[2,12]),{19:28,25:[1,29]},t(p,[2,20]),t(o,[2,7]),t(u,[2,9]),t(u,[2,10]),{17:30,26:d},{26:[2,19]},t(p,[2,13])],defaultActions:{9:[2,17],10:[2,1],11:[2,2],29:[2,19]},parseError:function(t,e){if(!e.recoverable){var n=new Error(t);throw n.hash=e,n}this.trace(t)},parse:function(t){var e=this,n=[0],r=[],i=[null],a=[],o=this.table,s="",c=0,u=0,l=0,h=2,f=1,d=a.slice.call(arguments,1),p=Object.create(this.lexer),y={yy:{}};for(var g in this.yy)Object.prototype.hasOwnProperty.call(this.yy,g)&&(y.yy[g]=this.yy[g]);p.setInput(t,y.yy),y.yy.lexer=p,y.yy.parser=this,void 0===p.yylloc&&(p.yylloc={});var m=p.yylloc;a.push(m);var v=p.options&&p.options.ranges;function b(){var t;return"number"!=typeof(t=r.pop()||p.lex()||f)&&(t instanceof Array&&(t=(r=t).pop()),t=e.symbols_[t]||t),t}"function"==typeof y.yy.parseError?this.parseError=y.yy.parseError:this.parseError=Object.getPrototypeOf(this).parseError;for(var _,x,w,k,T,E,C,S,A,M={};;){if(w=n[n.length-1],this.defaultActions[w]?k=this.defaultActions[w]:(null==_&&(_=b()),k=o[w]&&o[w][_]),void 0===k||!k.length||!k[0]){var N="";for(E in A=[],o[w])this.terminals_[E]&&E>h&&A.push("'"+this.terminals_[E]+"'");N=p.showPosition?"Parse error on line "+(c+1)+":\n"+p.showPosition()+"\nExpecting "+A.join(", ")+", got '"+(this.terminals_[_]||_)+"'":"Parse error on line "+(c+1)+": Unexpected "+(_==f?"end of input":"'"+(this.terminals_[_]||_)+"'"),this.parseError(N,{text:p.match,token:this.terminals_[_]||_,line:p.yylineno,loc:m,expected:A})}if(k[0]instanceof Array&&k.length>1)throw new Error("Parse Error: multiple actions possible at state: "+w+", token: "+_);switch(k[0]){case 1:n.push(_),i.push(p.yytext),a.push(p.yylloc),n.push(k[1]),_=null,x?(_=x,x=null):(u=p.yyleng,s=p.yytext,c=p.yylineno,m=p.yylloc,l>0&&l--);break;case 2:if(C=this.productions_[k[1]][1],M.$=i[i.length-C],M._$={first_line:a[a.length-(C||1)].first_line,last_line:a[a.length-1].last_line,first_column:a[a.length-(C||1)].first_column,last_column:a[a.length-1].last_column},v&&(M._$.range=[a[a.length-(C||1)].range[0],a[a.length-1].range[1]]),void 0!==(T=this.performAction.apply(M,[s,u,c,y.yy,k[1],i,a].concat(d))))return T;C&&(n=n.slice(0,-1*C*2),i=i.slice(0,-1*C),a=a.slice(0,-1*C)),n.push(this.productions_[k[1]][0]),i.push(M.$),a.push(M._$),S=o[n[n.length-2]][n[n.length-1]],n.push(S);break;case 3:return!0}}return!0}},g={EOF:1,parseError:function(t,e){if(!this.yy.parser)throw new Error(t);this.yy.parser.parseError(t,e)},setInput:function(t,e){return this.yy=e||this.yy||{},this._input=t,this._more=this._backtrack=this.done=!1,this.yylineno=this.yyleng=0,this.yytext=this.matched=this.match="",this.conditionStack=["INITIAL"],this.yylloc={first_line:1,first_column:0,last_line:1,last_column:0},this.options.ranges&&(this.yylloc.range=[0,0]),this.offset=0,this},input:function(){var t=this._input[0];return this.yytext+=t,this.yyleng++,this.offset++,this.match+=t,this.matched+=t,t.match(/(?:\r\n?|\n).*/g)?(this.yylineno++,this.yylloc.last_line++):this.yylloc.last_column++,this.options.ranges&&this.yylloc.range[1]++,this._input=this._input.slice(1),t},unput:function(t){var e=t.length,n=t.split(/(?:\r\n?|\n)/g);this._input=t+this._input,this.yytext=this.yytext.substr(0,this.yytext.length-e),this.offset-=e;var r=this.match.split(/(?:\r\n?|\n)/g);this.match=this.match.substr(0,this.match.length-1),this.matched=this.matched.substr(0,this.matched.length-1),n.length-1&&(this.yylineno-=n.length-1);var i=this.yylloc.range;return this.yylloc={first_line:this.yylloc.first_line,last_line:this.yylineno+1,first_column:this.yylloc.first_column,last_column:n?(n.length===r.length?this.yylloc.first_column:0)+r[r.length-n.length].length-n[0].length:this.yylloc.first_column-e},this.options.ranges&&(this.yylloc.range=[i[0],i[0]+this.yyleng-e]),this.yyleng=this.yytext.length,this},more:function(){return this._more=!0,this},reject:function(){return this.options.backtrack_lexer?(this._backtrack=!0,this):this.parseError("Lexical error on line "+(this.yylineno+1)+". You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true).\n"+this.showPosition(),{text:"",token:null,line:this.yylineno})},less:function(t){this.unput(this.match.slice(t))},pastInput:function(){var t=this.matched.substr(0,this.matched.length-this.match.length);return(t.length>20?"...":"")+t.substr(-20).replace(/\n/g,"")},upcomingInput:function(){var t=this.match;return t.length<20&&(t+=this._input.substr(0,20-t.length)),(t.substr(0,20)+(t.length>20?"...":"")).replace(/\n/g,"")},showPosition:function(){var t=this.pastInput(),e=new Array(t.length+1).join("-");return t+this.upcomingInput()+"\n"+e+"^"},test_match:function(t,e){var n,r,i;if(this.options.backtrack_lexer&&(i={yylineno:this.yylineno,yylloc:{first_line:this.yylloc.first_line,last_line:this.last_line,first_column:this.yylloc.first_column,last_column:this.yylloc.last_column},yytext:this.yytext,match:this.match,matches:this.matches,matched:this.matched,yyleng:this.yyleng,offset:this.offset,_more:this._more,_input:this._input,yy:this.yy,conditionStack:this.conditionStack.slice(0),done:this.done},this.options.ranges&&(i.yylloc.range=this.yylloc.range.slice(0))),(r=t[0].match(/(?:\r\n?|\n).*/g))&&(this.yylineno+=r.length),this.yylloc={first_line:this.yylloc.last_line,last_line:this.yylineno+1,first_column:this.yylloc.last_column,last_column:r?r[r.length-1].length-r[r.length-1].match(/\r?\n?/)[0].length:this.yylloc.last_column+t[0].length},this.yytext+=t[0],this.match+=t[0],this.matches=t,this.yyleng=this.yytext.length,this.options.ranges&&(this.yylloc.range=[this.offset,this.offset+=this.yyleng]),this._more=!1,this._backtrack=!1,this._input=this._input.slice(t[0].length),this.matched+=t[0],n=this.performAction.call(this,this.yy,this,e,this.conditionStack[this.conditionStack.length-1]),this.done&&this._input&&(this.done=!1),n)return n;if(this._backtrack){for(var a in i)this[a]=i[a];return!1}return!1},next:function(){if(this.done)return this.EOF;var t,e,n,r;this._input||(this.done=!0),this._more||(this.yytext="",this.match="");for(var i=this._currentRules(),a=0;ae[0].length)){if(e=n,r=a,this.options.backtrack_lexer){if(!1!==(t=this.test_match(n,i[a])))return t;if(this._backtrack){e=!1;continue}return!1}if(!this.options.flex)break}return e?!1!==(t=this.test_match(e,i[r]))&&t:""===this._input?this.EOF:this.parseError("Lexical error on line "+(this.yylineno+1)+". Unrecognized text.\n"+this.showPosition(),{text:"",token:null,line:this.yylineno})},lex:function(){return this.next()||this.lex()},begin:function(t){this.conditionStack.push(t)},popState:function(){return this.conditionStack.length-1>0?this.conditionStack.pop():this.conditionStack[0]},_currentRules:function(){return this.conditionStack.length&&this.conditionStack[this.conditionStack.length-1]?this.conditions[this.conditionStack[this.conditionStack.length-1]].rules:this.conditions.INITIAL.rules},topState:function(t){return(t=this.conditionStack.length-1-Math.abs(t||0))>=0?this.conditionStack[t]:"INITIAL"},pushState:function(t){this.begin(t)},stateStackSize:function(){return this.conditionStack.length},options:{"case-insensitive":!0},performAction:function(t,e,n,r){switch(n){case 0:return this.begin("open_directive"),23;case 1:return this.begin("type_directive"),24;case 2:return this.popState(),this.begin("arg_directive"),18;case 3:return this.popState(),this.popState(),26;case 4:return 25;case 5:case 6:break;case 7:return 20;case 8:case 9:break;case 10:return this.begin("title"),13;case 11:return this.popState(),"title_value";case 12:this.begin("string");break;case 13:this.popState();break;case 14:return"txt";case 15:return 6;case 16:return 8;case 17:return"value";case 18:return 22}},rules:[/^(?:%%\{)/i,/^(?:((?:(?!\}%%)[^:.])*))/i,/^(?::)/i,/^(?:\}%%)/i,/^(?:((?:(?!\}%%).|\n)*))/i,/^(?:%%(?!\{)[^\n]*)/i,/^(?:[^\}]%%[^\n]*)/i,/^(?:[\n\r]+)/i,/^(?:%%[^\n]*)/i,/^(?:[\s]+)/i,/^(?:title\b)/i,/^(?:(?!\n||)*[^\n]*)/i,/^(?:["])/i,/^(?:["])/i,/^(?:[^"]*)/i,/^(?:pie\b)/i,/^(?:showData\b)/i,/^(?::[\s]*[\d]+(?:\.[\d]+)?)/i,/^(?:$)/i],conditions:{close_directive:{rules:[],inclusive:!1},arg_directive:{rules:[3,4],inclusive:!1},type_directive:{rules:[2,3],inclusive:!1},open_directive:{rules:[1],inclusive:!1},title:{rules:[11],inclusive:!1},string:{rules:[13,14],inclusive:!1},INITIAL:{rules:[0,5,6,7,8,9,10,12,15,16,17,18],inclusive:!0}}};function m(){this.yy={}}return y.lexer=g,m.prototype=y,y.Parser=m,new m}();e.parser=r,e.Parser=r.Parser,e.parse=function(){return r.parse.apply(r,arguments)},e.main=function(t){t[1]||(console.log("Usage: "+t[0]+" FILE"),process.exit(1));var r=n(4551).readFileSync(n(6470).normalize(t[1]),"utf8");return e.parser.parse(r)},n.c[n.s]===t&&e.main(process.argv.slice(1))},6463:(t,e,n)=>{t=n.nmd(t);var r=function(){var t=function(t,e,n,r){for(n=n||{},r=t.length;r--;n[t[r]]=e);return n},e=[1,3],n=[1,5],r=[1,17],i=[2,10],a=[1,21],o=[1,22],s=[1,23],c=[1,24],u=[1,25],l=[1,26],h=[1,19],f=[1,27],d=[1,28],p=[1,31],y=[66,67],g=[5,8,14,35,36,37,38,39,40,48,55,57,66,67],m=[5,6,8,14,35,36,37,38,39,40,48,66,67],v=[1,51],b=[1,52],_=[1,53],x=[1,54],w=[1,55],k=[1,56],T=[1,57],E=[57,58],C=[1,69],S=[1,65],A=[1,66],M=[1,67],N=[1,68],D=[1,70],O=[1,74],B=[1,75],L=[1,72],I=[1,73],R=[5,8,14,35,36,37,38,39,40,48,66,67],F={trace:function(){},yy:{},symbols_:{error:2,start:3,directive:4,NEWLINE:5,RD:6,diagram:7,EOF:8,openDirective:9,typeDirective:10,closeDirective:11,":":12,argDirective:13,open_directive:14,type_directive:15,arg_directive:16,close_directive:17,requirementDef:18,elementDef:19,relationshipDef:20,requirementType:21,requirementName:22,STRUCT_START:23,requirementBody:24,ID:25,COLONSEP:26,id:27,TEXT:28,text:29,RISK:30,riskLevel:31,VERIFYMTHD:32,verifyType:33,STRUCT_STOP:34,REQUIREMENT:35,FUNCTIONAL_REQUIREMENT:36,INTERFACE_REQUIREMENT:37,PERFORMANCE_REQUIREMENT:38,PHYSICAL_REQUIREMENT:39,DESIGN_CONSTRAINT:40,LOW_RISK:41,MED_RISK:42,HIGH_RISK:43,VERIFY_ANALYSIS:44,VERIFY_DEMONSTRATION:45,VERIFY_INSPECTION:46,VERIFY_TEST:47,ELEMENT:48,elementName:49,elementBody:50,TYPE:51,type:52,DOCREF:53,ref:54,END_ARROW_L:55,relationship:56,LINE:57,END_ARROW_R:58,CONTAINS:59,COPIES:60,DERIVES:61,SATISFIES:62,VERIFIES:63,REFINES:64,TRACES:65,unqString:66,qString:67,$accept:0,$end:1},terminals_:{2:"error",5:"NEWLINE",6:"RD",8:"EOF",12:":",14:"open_directive",15:"type_directive",16:"arg_directive",17:"close_directive",23:"STRUCT_START",25:"ID",26:"COLONSEP",28:"TEXT",30:"RISK",32:"VERIFYMTHD",34:"STRUCT_STOP",35:"REQUIREMENT",36:"FUNCTIONAL_REQUIREMENT",37:"INTERFACE_REQUIREMENT",38:"PERFORMANCE_REQUIREMENT",39:"PHYSICAL_REQUIREMENT",40:"DESIGN_CONSTRAINT",41:"LOW_RISK",42:"MED_RISK",43:"HIGH_RISK",44:"VERIFY_ANALYSIS",45:"VERIFY_DEMONSTRATION",46:"VERIFY_INSPECTION",47:"VERIFY_TEST",48:"ELEMENT",51:"TYPE",53:"DOCREF",55:"END_ARROW_L",57:"LINE",58:"END_ARROW_R",59:"CONTAINS",60:"COPIES",61:"DERIVES",62:"SATISFIES",63:"VERIFIES",64:"REFINES",65:"TRACES",66:"unqString",67:"qString"},productions_:[0,[3,3],[3,2],[3,4],[4,3],[4,5],[9,1],[10,1],[13,1],[11,1],[7,0],[7,2],[7,2],[7,2],[7,2],[7,2],[18,5],[24,5],[24,5],[24,5],[24,5],[24,2],[24,1],[21,1],[21,1],[21,1],[21,1],[21,1],[21,1],[31,1],[31,1],[31,1],[33,1],[33,1],[33,1],[33,1],[19,5],[50,5],[50,5],[50,2],[50,1],[20,5],[20,5],[56,1],[56,1],[56,1],[56,1],[56,1],[56,1],[56,1],[22,1],[22,1],[27,1],[27,1],[29,1],[29,1],[49,1],[49,1],[52,1],[52,1],[54,1],[54,1]],performAction:function(t,e,n,r,i,a,o){var s=a.length-1;switch(i){case 6:r.parseDirective("%%{","open_directive");break;case 7:r.parseDirective(a[s],"type_directive");break;case 8:a[s]=a[s].trim().replace(/'/g,'"'),r.parseDirective(a[s],"arg_directive");break;case 9:r.parseDirective("}%%","close_directive","pie");break;case 10:this.$=[];break;case 16:r.addRequirement(a[s-3],a[s-4]);break;case 17:r.setNewReqId(a[s-2]);break;case 18:r.setNewReqText(a[s-2]);break;case 19:r.setNewReqRisk(a[s-2]);break;case 20:r.setNewReqVerifyMethod(a[s-2]);break;case 23:this.$=r.RequirementType.REQUIREMENT;break;case 24:this.$=r.RequirementType.FUNCTIONAL_REQUIREMENT;break;case 25:this.$=r.RequirementType.INTERFACE_REQUIREMENT;break;case 26:this.$=r.RequirementType.PERFORMANCE_REQUIREMENT;break;case 27:this.$=r.RequirementType.PHYSICAL_REQUIREMENT;break;case 28:this.$=r.RequirementType.DESIGN_CONSTRAINT;break;case 29:this.$=r.RiskLevel.LOW_RISK;break;case 30:this.$=r.RiskLevel.MED_RISK;break;case 31:this.$=r.RiskLevel.HIGH_RISK;break;case 32:this.$=r.VerifyType.VERIFY_ANALYSIS;break;case 33:this.$=r.VerifyType.VERIFY_DEMONSTRATION;break;case 34:this.$=r.VerifyType.VERIFY_INSPECTION;break;case 35:this.$=r.VerifyType.VERIFY_TEST;break;case 36:r.addElement(a[s-3]);break;case 37:r.setNewElementType(a[s-2]);break;case 38:r.setNewElementDocRef(a[s-2]);break;case 41:r.addRelationship(a[s-2],a[s],a[s-4]);break;case 42:r.addRelationship(a[s-2],a[s-4],a[s]);break;case 43:this.$=r.Relationships.CONTAINS;break;case 44:this.$=r.Relationships.COPIES;break;case 45:this.$=r.Relationships.DERIVES;break;case 46:this.$=r.Relationships.SATISFIES;break;case 47:this.$=r.Relationships.VERIFIES;break;case 48:this.$=r.Relationships.REFINES;break;case 49:this.$=r.Relationships.TRACES}},table:[{3:1,4:2,6:e,9:4,14:n},{1:[3]},{3:7,4:2,5:[1,6],6:e,9:4,14:n},{5:[1,8]},{10:9,15:[1,10]},{15:[2,6]},{3:11,4:2,6:e,9:4,14:n},{1:[2,2]},{4:16,5:r,7:12,8:i,9:4,14:n,18:13,19:14,20:15,21:18,27:20,35:a,36:o,37:s,38:c,39:u,40:l,48:h,66:f,67:d},{11:29,12:[1,30],17:p},t([12,17],[2,7]),{1:[2,1]},{8:[1,32]},{4:16,5:r,7:33,8:i,9:4,14:n,18:13,19:14,20:15,21:18,27:20,35:a,36:o,37:s,38:c,39:u,40:l,48:h,66:f,67:d},{4:16,5:r,7:34,8:i,9:4,14:n,18:13,19:14,20:15,21:18,27:20,35:a,36:o,37:s,38:c,39:u,40:l,48:h,66:f,67:d},{4:16,5:r,7:35,8:i,9:4,14:n,18:13,19:14,20:15,21:18,27:20,35:a,36:o,37:s,38:c,39:u,40:l,48:h,66:f,67:d},{4:16,5:r,7:36,8:i,9:4,14:n,18:13,19:14,20:15,21:18,27:20,35:a,36:o,37:s,38:c,39:u,40:l,48:h,66:f,67:d},{4:16,5:r,7:37,8:i,9:4,14:n,18:13,19:14,20:15,21:18,27:20,35:a,36:o,37:s,38:c,39:u,40:l,48:h,66:f,67:d},{22:38,66:[1,39],67:[1,40]},{49:41,66:[1,42],67:[1,43]},{55:[1,44],57:[1,45]},t(y,[2,23]),t(y,[2,24]),t(y,[2,25]),t(y,[2,26]),t(y,[2,27]),t(y,[2,28]),t(g,[2,52]),t(g,[2,53]),t(m,[2,4]),{13:46,16:[1,47]},t(m,[2,9]),{1:[2,3]},{8:[2,11]},{8:[2,12]},{8:[2,13]},{8:[2,14]},{8:[2,15]},{23:[1,48]},{23:[2,50]},{23:[2,51]},{23:[1,49]},{23:[2,56]},{23:[2,57]},{56:50,59:v,60:b,61:_,62:x,63:w,64:k,65:T},{56:58,59:v,60:b,61:_,62:x,63:w,64:k,65:T},{11:59,17:p},{17:[2,8]},{5:[1,60]},{5:[1,61]},{57:[1,62]},t(E,[2,43]),t(E,[2,44]),t(E,[2,45]),t(E,[2,46]),t(E,[2,47]),t(E,[2,48]),t(E,[2,49]),{58:[1,63]},t(m,[2,5]),{5:C,24:64,25:S,28:A,30:M,32:N,34:D},{5:O,34:B,50:71,51:L,53:I},{27:76,66:f,67:d},{27:77,66:f,67:d},t(R,[2,16]),{26:[1,78]},{26:[1,79]},{26:[1,80]},{26:[1,81]},{5:C,24:82,25:S,28:A,30:M,32:N,34:D},t(R,[2,22]),t(R,[2,36]),{26:[1,83]},{26:[1,84]},{5:O,34:B,50:85,51:L,53:I},t(R,[2,40]),t(R,[2,41]),t(R,[2,42]),{27:86,66:f,67:d},{29:87,66:[1,88],67:[1,89]},{31:90,41:[1,91],42:[1,92],43:[1,93]},{33:94,44:[1,95],45:[1,96],46:[1,97],47:[1,98]},t(R,[2,21]),{52:99,66:[1,100],67:[1,101]},{54:102,66:[1,103],67:[1,104]},t(R,[2,39]),{5:[1,105]},{5:[1,106]},{5:[2,54]},{5:[2,55]},{5:[1,107]},{5:[2,29]},{5:[2,30]},{5:[2,31]},{5:[1,108]},{5:[2,32]},{5:[2,33]},{5:[2,34]},{5:[2,35]},{5:[1,109]},{5:[2,58]},{5:[2,59]},{5:[1,110]},{5:[2,60]},{5:[2,61]},{5:C,24:111,25:S,28:A,30:M,32:N,34:D},{5:C,24:112,25:S,28:A,30:M,32:N,34:D},{5:C,24:113,25:S,28:A,30:M,32:N,34:D},{5:C,24:114,25:S,28:A,30:M,32:N,34:D},{5:O,34:B,50:115,51:L,53:I},{5:O,34:B,50:116,51:L,53:I},t(R,[2,17]),t(R,[2,18]),t(R,[2,19]),t(R,[2,20]),t(R,[2,37]),t(R,[2,38])],defaultActions:{5:[2,6],7:[2,2],11:[2,1],32:[2,3],33:[2,11],34:[2,12],35:[2,13],36:[2,14],37:[2,15],39:[2,50],40:[2,51],42:[2,56],43:[2,57],47:[2,8],88:[2,54],89:[2,55],91:[2,29],92:[2,30],93:[2,31],95:[2,32],96:[2,33],97:[2,34],98:[2,35],100:[2,58],101:[2,59],103:[2,60],104:[2,61]},parseError:function(t,e){if(!e.recoverable){var n=new Error(t);throw n.hash=e,n}this.trace(t)},parse:function(t){var e=this,n=[0],r=[],i=[null],a=[],o=this.table,s="",c=0,u=0,l=0,h=2,f=1,d=a.slice.call(arguments,1),p=Object.create(this.lexer),y={yy:{}};for(var g in this.yy)Object.prototype.hasOwnProperty.call(this.yy,g)&&(y.yy[g]=this.yy[g]);p.setInput(t,y.yy),y.yy.lexer=p,y.yy.parser=this,void 0===p.yylloc&&(p.yylloc={});var m=p.yylloc;a.push(m);var v=p.options&&p.options.ranges;function b(){var t;return"number"!=typeof(t=r.pop()||p.lex()||f)&&(t instanceof Array&&(t=(r=t).pop()),t=e.symbols_[t]||t),t}"function"==typeof y.yy.parseError?this.parseError=y.yy.parseError:this.parseError=Object.getPrototypeOf(this).parseError;for(var _,x,w,k,T,E,C,S,A,M={};;){if(w=n[n.length-1],this.defaultActions[w]?k=this.defaultActions[w]:(null==_&&(_=b()),k=o[w]&&o[w][_]),void 0===k||!k.length||!k[0]){var N="";for(E in A=[],o[w])this.terminals_[E]&&E>h&&A.push("'"+this.terminals_[E]+"'");N=p.showPosition?"Parse error on line "+(c+1)+":\n"+p.showPosition()+"\nExpecting "+A.join(", ")+", got '"+(this.terminals_[_]||_)+"'":"Parse error on line "+(c+1)+": Unexpected "+(_==f?"end of input":"'"+(this.terminals_[_]||_)+"'"),this.parseError(N,{text:p.match,token:this.terminals_[_]||_,line:p.yylineno,loc:m,expected:A})}if(k[0]instanceof Array&&k.length>1)throw new Error("Parse Error: multiple actions possible at state: "+w+", token: "+_);switch(k[0]){case 1:n.push(_),i.push(p.yytext),a.push(p.yylloc),n.push(k[1]),_=null,x?(_=x,x=null):(u=p.yyleng,s=p.yytext,c=p.yylineno,m=p.yylloc,l>0&&l--);break;case 2:if(C=this.productions_[k[1]][1],M.$=i[i.length-C],M._$={first_line:a[a.length-(C||1)].first_line,last_line:a[a.length-1].last_line,first_column:a[a.length-(C||1)].first_column,last_column:a[a.length-1].last_column},v&&(M._$.range=[a[a.length-(C||1)].range[0],a[a.length-1].range[1]]),void 0!==(T=this.performAction.apply(M,[s,u,c,y.yy,k[1],i,a].concat(d))))return T;C&&(n=n.slice(0,-1*C*2),i=i.slice(0,-1*C),a=a.slice(0,-1*C)),n.push(this.productions_[k[1]][0]),i.push(M.$),a.push(M._$),S=o[n[n.length-2]][n[n.length-1]],n.push(S);break;case 3:return!0}}return!0}},P={EOF:1,parseError:function(t,e){if(!this.yy.parser)throw new Error(t);this.yy.parser.parseError(t,e)},setInput:function(t,e){return this.yy=e||this.yy||{},this._input=t,this._more=this._backtrack=this.done=!1,this.yylineno=this.yyleng=0,this.yytext=this.matched=this.match="",this.conditionStack=["INITIAL"],this.yylloc={first_line:1,first_column:0,last_line:1,last_column:0},this.options.ranges&&(this.yylloc.range=[0,0]),this.offset=0,this},input:function(){var t=this._input[0];return this.yytext+=t,this.yyleng++,this.offset++,this.match+=t,this.matched+=t,t.match(/(?:\r\n?|\n).*/g)?(this.yylineno++,this.yylloc.last_line++):this.yylloc.last_column++,this.options.ranges&&this.yylloc.range[1]++,this._input=this._input.slice(1),t},unput:function(t){var e=t.length,n=t.split(/(?:\r\n?|\n)/g);this._input=t+this._input,this.yytext=this.yytext.substr(0,this.yytext.length-e),this.offset-=e;var r=this.match.split(/(?:\r\n?|\n)/g);this.match=this.match.substr(0,this.match.length-1),this.matched=this.matched.substr(0,this.matched.length-1),n.length-1&&(this.yylineno-=n.length-1);var i=this.yylloc.range;return this.yylloc={first_line:this.yylloc.first_line,last_line:this.yylineno+1,first_column:this.yylloc.first_column,last_column:n?(n.length===r.length?this.yylloc.first_column:0)+r[r.length-n.length].length-n[0].length:this.yylloc.first_column-e},this.options.ranges&&(this.yylloc.range=[i[0],i[0]+this.yyleng-e]),this.yyleng=this.yytext.length,this},more:function(){return this._more=!0,this},reject:function(){return this.options.backtrack_lexer?(this._backtrack=!0,this):this.parseError("Lexical error on line "+(this.yylineno+1)+". You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true).\n"+this.showPosition(),{text:"",token:null,line:this.yylineno})},less:function(t){this.unput(this.match.slice(t))},pastInput:function(){var t=this.matched.substr(0,this.matched.length-this.match.length);return(t.length>20?"...":"")+t.substr(-20).replace(/\n/g,"")},upcomingInput:function(){var t=this.match;return t.length<20&&(t+=this._input.substr(0,20-t.length)),(t.substr(0,20)+(t.length>20?"...":"")).replace(/\n/g,"")},showPosition:function(){var t=this.pastInput(),e=new Array(t.length+1).join("-");return t+this.upcomingInput()+"\n"+e+"^"},test_match:function(t,e){var n,r,i;if(this.options.backtrack_lexer&&(i={yylineno:this.yylineno,yylloc:{first_line:this.yylloc.first_line,last_line:this.last_line,first_column:this.yylloc.first_column,last_column:this.yylloc.last_column},yytext:this.yytext,match:this.match,matches:this.matches,matched:this.matched,yyleng:this.yyleng,offset:this.offset,_more:this._more,_input:this._input,yy:this.yy,conditionStack:this.conditionStack.slice(0),done:this.done},this.options.ranges&&(i.yylloc.range=this.yylloc.range.slice(0))),(r=t[0].match(/(?:\r\n?|\n).*/g))&&(this.yylineno+=r.length),this.yylloc={first_line:this.yylloc.last_line,last_line:this.yylineno+1,first_column:this.yylloc.last_column,last_column:r?r[r.length-1].length-r[r.length-1].match(/\r?\n?/)[0].length:this.yylloc.last_column+t[0].length},this.yytext+=t[0],this.match+=t[0],this.matches=t,this.yyleng=this.yytext.length,this.options.ranges&&(this.yylloc.range=[this.offset,this.offset+=this.yyleng]),this._more=!1,this._backtrack=!1,this._input=this._input.slice(t[0].length),this.matched+=t[0],n=this.performAction.call(this,this.yy,this,e,this.conditionStack[this.conditionStack.length-1]),this.done&&this._input&&(this.done=!1),n)return n;if(this._backtrack){for(var a in i)this[a]=i[a];return!1}return!1},next:function(){if(this.done)return this.EOF;var t,e,n,r;this._input||(this.done=!0),this._more||(this.yytext="",this.match="");for(var i=this._currentRules(),a=0;ae[0].length)){if(e=n,r=a,this.options.backtrack_lexer){if(!1!==(t=this.test_match(n,i[a])))return t;if(this._backtrack){e=!1;continue}return!1}if(!this.options.flex)break}return e?!1!==(t=this.test_match(e,i[r]))&&t:""===this._input?this.EOF:this.parseError("Lexical error on line "+(this.yylineno+1)+". Unrecognized text.\n"+this.showPosition(),{text:"",token:null,line:this.yylineno})},lex:function(){return this.next()||this.lex()},begin:function(t){this.conditionStack.push(t)},popState:function(){return this.conditionStack.length-1>0?this.conditionStack.pop():this.conditionStack[0]},_currentRules:function(){return this.conditionStack.length&&this.conditionStack[this.conditionStack.length-1]?this.conditions[this.conditionStack[this.conditionStack.length-1]].rules:this.conditions.INITIAL.rules},topState:function(t){return(t=this.conditionStack.length-1-Math.abs(t||0))>=0?this.conditionStack[t]:"INITIAL"},pushState:function(t){this.begin(t)},stateStackSize:function(){return this.conditionStack.length},options:{"case-insensitive":!0},performAction:function(t,e,n,r){switch(n){case 0:return this.begin("open_directive"),14;case 1:return this.begin("type_directive"),15;case 2:return this.popState(),this.begin("arg_directive"),12;case 3:return this.popState(),this.popState(),17;case 4:return 16;case 5:return 5;case 6:case 7:case 8:break;case 9:return 8;case 10:return 6;case 11:return 23;case 12:return 34;case 13:return 26;case 14:return 25;case 15:return 28;case 16:return 30;case 17:return 32;case 18:return 35;case 19:return 36;case 20:return 37;case 21:return 38;case 22:return 39;case 23:return 40;case 24:return 41;case 25:return 42;case 26:return 43;case 27:return 44;case 28:return 45;case 29:return 46;case 30:return 47;case 31:return 48;case 32:return 59;case 33:return 60;case 34:return 61;case 35:return 62;case 36:return 63;case 37:return 64;case 38:return 65;case 39:return 51;case 40:return 53;case 41:return 55;case 42:return 58;case 43:return 57;case 44:this.begin("string");break;case 45:this.popState();break;case 46:return"qString";case 47:return e.yytext=e.yytext.trim(),66}},rules:[/^(?:%%\{)/i,/^(?:((?:(?!\}%%)[^:.])*))/i,/^(?::)/i,/^(?:\}%%)/i,/^(?:((?:(?!\}%%).|\n)*))/i,/^(?:(\r?\n)+)/i,/^(?:\s+)/i,/^(?:#[^\n]*)/i,/^(?:%[^\n]*)/i,/^(?:$)/i,/^(?:requirementDiagram\b)/i,/^(?:\{)/i,/^(?:\})/i,/^(?::)/i,/^(?:id\b)/i,/^(?:text\b)/i,/^(?:risk\b)/i,/^(?:verifyMethod\b)/i,/^(?:requirement\b)/i,/^(?:functionalRequirement\b)/i,/^(?:interfaceRequirement\b)/i,/^(?:performanceRequirement\b)/i,/^(?:physicalRequirement\b)/i,/^(?:designConstraint\b)/i,/^(?:low\b)/i,/^(?:medium\b)/i,/^(?:high\b)/i,/^(?:analysis\b)/i,/^(?:demonstration\b)/i,/^(?:inspection\b)/i,/^(?:test\b)/i,/^(?:element\b)/i,/^(?:contains\b)/i,/^(?:copies\b)/i,/^(?:derives\b)/i,/^(?:satisfies\b)/i,/^(?:verifies\b)/i,/^(?:refines\b)/i,/^(?:traces\b)/i,/^(?:type\b)/i,/^(?:docref\b)/i,/^(?:<-)/i,/^(?:->)/i,/^(?:-)/i,/^(?:["])/i,/^(?:["])/i,/^(?:[^"]*)/i,/^(?:[\w][^\r\n\{\<\>\-\=]*)/i],conditions:{close_directive:{rules:[],inclusive:!1},arg_directive:{rules:[3,4],inclusive:!1},type_directive:{rules:[2,3],inclusive:!1},open_directive:{rules:[1],inclusive:!1},unqString:{rules:[],inclusive:!1},token:{rules:[],inclusive:!1},string:{rules:[45,46],inclusive:!1},INITIAL:{rules:[0,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,47],inclusive:!0}}};function j(){this.yy={}}return F.lexer=P,j.prototype=F,F.Parser=j,new j}();e.parser=r,e.Parser=r.Parser,e.parse=function(){return r.parse.apply(r,arguments)},e.main=function(t){t[1]||(console.log("Usage: "+t[0]+" FILE"),process.exit(1));var r=n(8800).readFileSync(n(6470).normalize(t[1]),"utf8");return e.parser.parse(r)},n.c[n.s]===t&&e.main(process.argv.slice(1))},9923:(t,e,n)=>{t=n.nmd(t);var r=function(){var t=function(t,e,n,r){for(n=n||{},r=t.length;r--;n[t[r]]=e);return n},e=[1,2],n=[1,3],r=[1,5],i=[1,7],a=[2,5],o=[1,15],s=[1,17],c=[1,18],u=[1,19],l=[1,21],h=[1,22],f=[1,23],d=[1,29],p=[1,30],y=[1,31],g=[1,32],m=[1,33],v=[1,34],b=[1,37],_=[1,38],x=[1,39],w=[1,40],k=[1,41],T=[1,42],E=[1,45],C=[1,4,5,16,20,22,23,24,30,32,33,34,35,36,38,40,41,42,46,47,48,49,57,67],S=[1,58],A=[4,5,16,20,22,23,24,30,32,33,34,35,36,38,42,46,47,48,49,57,67],M=[4,5,16,20,22,23,24,30,32,33,34,35,36,38,41,42,46,47,48,49,57,67],N=[4,5,16,20,22,23,24,30,32,33,34,35,36,38,40,42,46,47,48,49,57,67],D=[55,56,57],O=[1,4,5,7,16,20,22,23,24,30,32,33,34,35,36,38,40,41,42,46,47,48,49,57,67],B={trace:function(){},yy:{},symbols_:{error:2,start:3,SPACE:4,NEWLINE:5,directive:6,SD:7,document:8,line:9,statement:10,openDirective:11,typeDirective:12,closeDirective:13,":":14,argDirective:15,participant:16,actor:17,AS:18,restOfLine:19,participant_actor:20,signal:21,autonumber:22,activate:23,deactivate:24,note_statement:25,links_statement:26,link_statement:27,properties_statement:28,details_statement:29,title:30,text2:31,loop:32,end:33,rect:34,opt:35,alt:36,else_sections:37,par:38,par_sections:39,and:40,else:41,note:42,placement:43,over:44,actor_pair:45,links:46,link:47,properties:48,details:49,spaceList:50,",":51,left_of:52,right_of:53,signaltype:54,"+":55,"-":56,ACTOR:57,SOLID_OPEN_ARROW:58,DOTTED_OPEN_ARROW:59,SOLID_ARROW:60,DOTTED_ARROW:61,SOLID_CROSS:62,DOTTED_CROSS:63,SOLID_POINT:64,DOTTED_POINT:65,TXT:66,open_directive:67,type_directive:68,arg_directive:69,close_directive:70,$accept:0,$end:1},terminals_:{2:"error",4:"SPACE",5:"NEWLINE",7:"SD",14:":",16:"participant",18:"AS",19:"restOfLine",20:"participant_actor",22:"autonumber",23:"activate",24:"deactivate",30:"title",32:"loop",33:"end",34:"rect",35:"opt",36:"alt",38:"par",40:"and",41:"else",42:"note",44:"over",46:"links",47:"link",48:"properties",49:"details",51:",",52:"left_of",53:"right_of",55:"+",56:"-",57:"ACTOR",58:"SOLID_OPEN_ARROW",59:"DOTTED_OPEN_ARROW",60:"SOLID_ARROW",61:"DOTTED_ARROW",62:"SOLID_CROSS",63:"DOTTED_CROSS",64:"SOLID_POINT",65:"DOTTED_POINT",66:"TXT",67:"open_directive",68:"type_directive",69:"arg_directive",70:"close_directive"},productions_:[0,[3,2],[3,2],[3,2],[3,2],[8,0],[8,2],[9,2],[9,1],[9,1],[6,4],[6,6],[10,5],[10,3],[10,5],[10,3],[10,2],[10,1],[10,3],[10,3],[10,2],[10,2],[10,2],[10,2],[10,2],[10,3],[10,4],[10,4],[10,4],[10,4],[10,4],[10,1],[39,1],[39,4],[37,1],[37,4],[25,4],[25,4],[26,3],[27,3],[28,3],[29,3],[50,2],[50,1],[45,3],[45,1],[43,1],[43,1],[21,5],[21,5],[21,4],[17,1],[54,1],[54,1],[54,1],[54,1],[54,1],[54,1],[54,1],[54,1],[31,1],[11,1],[12,1],[15,1],[13,1]],performAction:function(t,e,n,r,i,a,o){var s=a.length-1;switch(i){case 4:return r.apply(a[s]),a[s];case 5:this.$=[];break;case 6:a[s-1].push(a[s]),this.$=a[s-1];break;case 7:case 8:this.$=a[s];break;case 9:this.$=[];break;case 12:a[s-3].type="addParticipant",a[s-3].description=r.parseMessage(a[s-1]),this.$=a[s-3];break;case 13:a[s-1].type="addParticipant",this.$=a[s-1];break;case 14:a[s-3].type="addActor",a[s-3].description=r.parseMessage(a[s-1]),this.$=a[s-3];break;case 15:a[s-1].type="addActor",this.$=a[s-1];break;case 17:r.enableSequenceNumbers();break;case 18:this.$={type:"activeStart",signalType:r.LINETYPE.ACTIVE_START,actor:a[s-1]};break;case 19:this.$={type:"activeEnd",signalType:r.LINETYPE.ACTIVE_END,actor:a[s-1]};break;case 25:this.$=[{type:"setTitle",text:a[s-1]}];break;case 26:a[s-1].unshift({type:"loopStart",loopText:r.parseMessage(a[s-2]),signalType:r.LINETYPE.LOOP_START}),a[s-1].push({type:"loopEnd",loopText:a[s-2],signalType:r.LINETYPE.LOOP_END}),this.$=a[s-1];break;case 27:a[s-1].unshift({type:"rectStart",color:r.parseMessage(a[s-2]),signalType:r.LINETYPE.RECT_START}),a[s-1].push({type:"rectEnd",color:r.parseMessage(a[s-2]),signalType:r.LINETYPE.RECT_END}),this.$=a[s-1];break;case 28:a[s-1].unshift({type:"optStart",optText:r.parseMessage(a[s-2]),signalType:r.LINETYPE.OPT_START}),a[s-1].push({type:"optEnd",optText:r.parseMessage(a[s-2]),signalType:r.LINETYPE.OPT_END}),this.$=a[s-1];break;case 29:a[s-1].unshift({type:"altStart",altText:r.parseMessage(a[s-2]),signalType:r.LINETYPE.ALT_START}),a[s-1].push({type:"altEnd",signalType:r.LINETYPE.ALT_END}),this.$=a[s-1];break;case 30:a[s-1].unshift({type:"parStart",parText:r.parseMessage(a[s-2]),signalType:r.LINETYPE.PAR_START}),a[s-1].push({type:"parEnd",signalType:r.LINETYPE.PAR_END}),this.$=a[s-1];break;case 33:this.$=a[s-3].concat([{type:"and",parText:r.parseMessage(a[s-1]),signalType:r.LINETYPE.PAR_AND},a[s]]);break;case 35:this.$=a[s-3].concat([{type:"else",altText:r.parseMessage(a[s-1]),signalType:r.LINETYPE.ALT_ELSE},a[s]]);break;case 36:this.$=[a[s-1],{type:"addNote",placement:a[s-2],actor:a[s-1].actor,text:a[s]}];break;case 37:a[s-2]=[].concat(a[s-1],a[s-1]).slice(0,2),a[s-2][0]=a[s-2][0].actor,a[s-2][1]=a[s-2][1].actor,this.$=[a[s-1],{type:"addNote",placement:r.PLACEMENT.OVER,actor:a[s-2].slice(0,2),text:a[s]}];break;case 38:this.$=[a[s-1],{type:"addLinks",actor:a[s-1].actor,text:a[s]}];break;case 39:this.$=[a[s-1],{type:"addALink",actor:a[s-1].actor,text:a[s]}];break;case 40:this.$=[a[s-1],{type:"addProperties",actor:a[s-1].actor,text:a[s]}];break;case 41:this.$=[a[s-1],{type:"addDetails",actor:a[s-1].actor,text:a[s]}];break;case 44:this.$=[a[s-2],a[s]];break;case 45:this.$=a[s];break;case 46:this.$=r.PLACEMENT.LEFTOF;break;case 47:this.$=r.PLACEMENT.RIGHTOF;break;case 48:this.$=[a[s-4],a[s-1],{type:"addMessage",from:a[s-4].actor,to:a[s-1].actor,signalType:a[s-3],msg:a[s]},{type:"activeStart",signalType:r.LINETYPE.ACTIVE_START,actor:a[s-1]}];break;case 49:this.$=[a[s-4],a[s-1],{type:"addMessage",from:a[s-4].actor,to:a[s-1].actor,signalType:a[s-3],msg:a[s]},{type:"activeEnd",signalType:r.LINETYPE.ACTIVE_END,actor:a[s-4]}];break;case 50:this.$=[a[s-3],a[s-1],{type:"addMessage",from:a[s-3].actor,to:a[s-1].actor,signalType:a[s-2],msg:a[s]}];break;case 51:this.$={type:"addParticipant",actor:a[s]};break;case 52:this.$=r.LINETYPE.SOLID_OPEN;break;case 53:this.$=r.LINETYPE.DOTTED_OPEN;break;case 54:this.$=r.LINETYPE.SOLID;break;case 55:this.$=r.LINETYPE.DOTTED;break;case 56:this.$=r.LINETYPE.SOLID_CROSS;break;case 57:this.$=r.LINETYPE.DOTTED_CROSS;break;case 58:this.$=r.LINETYPE.SOLID_POINT;break;case 59:this.$=r.LINETYPE.DOTTED_POINT;break;case 60:this.$=r.parseMessage(a[s].trim().substring(1));break;case 61:r.parseDirective("%%{","open_directive");break;case 62:r.parseDirective(a[s],"type_directive");break;case 63:a[s]=a[s].trim().replace(/'/g,'"'),r.parseDirective(a[s],"arg_directive");break;case 64:r.parseDirective("}%%","close_directive","sequence")}},table:[{3:1,4:e,5:n,6:4,7:r,11:6,67:i},{1:[3]},{3:8,4:e,5:n,6:4,7:r,11:6,67:i},{3:9,4:e,5:n,6:4,7:r,11:6,67:i},{3:10,4:e,5:n,6:4,7:r,11:6,67:i},t([1,4,5,16,20,22,23,24,30,32,34,35,36,38,42,46,47,48,49,57,67],a,{8:11}),{12:12,68:[1,13]},{68:[2,61]},{1:[2,1]},{1:[2,2]},{1:[2,3]},{1:[2,4],4:o,5:s,6:35,9:14,10:16,11:6,16:c,17:36,20:u,21:20,22:l,23:h,24:f,25:24,26:25,27:26,28:27,29:28,30:d,32:p,34:y,35:g,36:m,38:v,42:b,46:_,47:x,48:w,49:k,57:T,67:i},{13:43,14:[1,44],70:E},t([14,70],[2,62]),t(C,[2,6]),{6:35,10:46,11:6,16:c,17:36,20:u,21:20,22:l,23:h,24:f,25:24,26:25,27:26,28:27,29:28,30:d,32:p,34:y,35:g,36:m,38:v,42:b,46:_,47:x,48:w,49:k,57:T,67:i},t(C,[2,8]),t(C,[2,9]),{17:47,57:T},{17:48,57:T},{5:[1,49]},t(C,[2,17]),{17:50,57:T},{17:51,57:T},{5:[1,52]},{5:[1,53]},{5:[1,54]},{5:[1,55]},{5:[1,56]},{31:57,66:S},{19:[1,59]},{19:[1,60]},{19:[1,61]},{19:[1,62]},{19:[1,63]},t(C,[2,31]),{54:64,58:[1,65],59:[1,66],60:[1,67],61:[1,68],62:[1,69],63:[1,70],64:[1,71],65:[1,72]},{43:73,44:[1,74],52:[1,75],53:[1,76]},{17:77,57:T},{17:78,57:T},{17:79,57:T},{17:80,57:T},t([5,18,51,58,59,60,61,62,63,64,65,66],[2,51]),{5:[1,81]},{15:82,69:[1,83]},{5:[2,64]},t(C,[2,7]),{5:[1,85],18:[1,84]},{5:[1,87],18:[1,86]},t(C,[2,16]),{5:[1,88]},{5:[1,89]},t(C,[2,20]),t(C,[2,21]),t(C,[2,22]),t(C,[2,23]),t(C,[2,24]),{5:[1,90]},{5:[2,60]},t(A,a,{8:91}),t(A,a,{8:92}),t(A,a,{8:93}),t(M,a,{37:94,8:95}),t(N,a,{39:96,8:97}),{17:100,55:[1,98],56:[1,99],57:T},t(D,[2,52]),t(D,[2,53]),t(D,[2,54]),t(D,[2,55]),t(D,[2,56]),t(D,[2,57]),t(D,[2,58]),t(D,[2,59]),{17:101,57:T},{17:103,45:102,57:T},{57:[2,46]},{57:[2,47]},{31:104,66:S},{31:105,66:S},{31:106,66:S},{31:107,66:S},t(O,[2,10]),{13:108,70:E},{70:[2,63]},{19:[1,109]},t(C,[2,13]),{19:[1,110]},t(C,[2,15]),t(C,[2,18]),t(C,[2,19]),t(C,[2,25]),{4:o,5:s,6:35,9:14,10:16,11:6,16:c,17:36,20:u,21:20,22:l,23:h,24:f,25:24,26:25,27:26,28:27,29:28,30:d,32:p,33:[1,111],34:y,35:g,36:m,38:v,42:b,46:_,47:x,48:w,49:k,57:T,67:i},{4:o,5:s,6:35,9:14,10:16,11:6,16:c,17:36,20:u,21:20,22:l,23:h,24:f,25:24,26:25,27:26,28:27,29:28,30:d,32:p,33:[1,112],34:y,35:g,36:m,38:v,42:b,46:_,47:x,48:w,49:k,57:T,67:i},{4:o,5:s,6:35,9:14,10:16,11:6,16:c,17:36,20:u,21:20,22:l,23:h,24:f,25:24,26:25,27:26,28:27,29:28,30:d,32:p,33:[1,113],34:y,35:g,36:m,38:v,42:b,46:_,47:x,48:w,49:k,57:T,67:i},{33:[1,114]},{4:o,5:s,6:35,9:14,10:16,11:6,16:c,17:36,20:u,21:20,22:l,23:h,24:f,25:24,26:25,27:26,28:27,29:28,30:d,32:p,33:[2,34],34:y,35:g,36:m,38:v,41:[1,115],42:b,46:_,47:x,48:w,49:k,57:T,67:i},{33:[1,116]},{4:o,5:s,6:35,9:14,10:16,11:6,16:c,17:36,20:u,21:20,22:l,23:h,24:f,25:24,26:25,27:26,28:27,29:28,30:d,32:p,33:[2,32],34:y,35:g,36:m,38:v,40:[1,117],42:b,46:_,47:x,48:w,49:k,57:T,67:i},{17:118,57:T},{17:119,57:T},{31:120,66:S},{31:121,66:S},{31:122,66:S},{51:[1,123],66:[2,45]},{5:[2,38]},{5:[2,39]},{5:[2,40]},{5:[2,41]},{5:[1,124]},{5:[1,125]},{5:[1,126]},t(C,[2,26]),t(C,[2,27]),t(C,[2,28]),t(C,[2,29]),{19:[1,127]},t(C,[2,30]),{19:[1,128]},{31:129,66:S},{31:130,66:S},{5:[2,50]},{5:[2,36]},{5:[2,37]},{17:131,57:T},t(O,[2,11]),t(C,[2,12]),t(C,[2,14]),t(M,a,{8:95,37:132}),t(N,a,{8:97,39:133}),{5:[2,48]},{5:[2,49]},{66:[2,44]},{33:[2,35]},{33:[2,33]}],defaultActions:{7:[2,61],8:[2,1],9:[2,2],10:[2,3],45:[2,64],58:[2,60],75:[2,46],76:[2,47],83:[2,63],104:[2,38],105:[2,39],106:[2,40],107:[2,41],120:[2,50],121:[2,36],122:[2,37],129:[2,48],130:[2,49],131:[2,44],132:[2,35],133:[2,33]},parseError:function(t,e){if(!e.recoverable){var n=new Error(t);throw n.hash=e,n}this.trace(t)},parse:function(t){var e=this,n=[0],r=[],i=[null],a=[],o=this.table,s="",c=0,u=0,l=0,h=2,f=1,d=a.slice.call(arguments,1),p=Object.create(this.lexer),y={yy:{}};for(var g in this.yy)Object.prototype.hasOwnProperty.call(this.yy,g)&&(y.yy[g]=this.yy[g]);p.setInput(t,y.yy),y.yy.lexer=p,y.yy.parser=this,void 0===p.yylloc&&(p.yylloc={});var m=p.yylloc;a.push(m);var v=p.options&&p.options.ranges;function b(){var t;return"number"!=typeof(t=r.pop()||p.lex()||f)&&(t instanceof Array&&(t=(r=t).pop()),t=e.symbols_[t]||t),t}"function"==typeof y.yy.parseError?this.parseError=y.yy.parseError:this.parseError=Object.getPrototypeOf(this).parseError;for(var _,x,w,k,T,E,C,S,A,M={};;){if(w=n[n.length-1],this.defaultActions[w]?k=this.defaultActions[w]:(null==_&&(_=b()),k=o[w]&&o[w][_]),void 0===k||!k.length||!k[0]){var N="";for(E in A=[],o[w])this.terminals_[E]&&E>h&&A.push("'"+this.terminals_[E]+"'");N=p.showPosition?"Parse error on line "+(c+1)+":\n"+p.showPosition()+"\nExpecting "+A.join(", ")+", got '"+(this.terminals_[_]||_)+"'":"Parse error on line "+(c+1)+": Unexpected "+(_==f?"end of input":"'"+(this.terminals_[_]||_)+"'"),this.parseError(N,{text:p.match,token:this.terminals_[_]||_,line:p.yylineno,loc:m,expected:A})}if(k[0]instanceof Array&&k.length>1)throw new Error("Parse Error: multiple actions possible at state: "+w+", token: "+_);switch(k[0]){case 1:n.push(_),i.push(p.yytext),a.push(p.yylloc),n.push(k[1]),_=null,x?(_=x,x=null):(u=p.yyleng,s=p.yytext,c=p.yylineno,m=p.yylloc,l>0&&l--);break;case 2:if(C=this.productions_[k[1]][1],M.$=i[i.length-C],M._$={first_line:a[a.length-(C||1)].first_line,last_line:a[a.length-1].last_line,first_column:a[a.length-(C||1)].first_column,last_column:a[a.length-1].last_column},v&&(M._$.range=[a[a.length-(C||1)].range[0],a[a.length-1].range[1]]),void 0!==(T=this.performAction.apply(M,[s,u,c,y.yy,k[1],i,a].concat(d))))return T;C&&(n=n.slice(0,-1*C*2),i=i.slice(0,-1*C),a=a.slice(0,-1*C)),n.push(this.productions_[k[1]][0]),i.push(M.$),a.push(M._$),S=o[n[n.length-2]][n[n.length-1]],n.push(S);break;case 3:return!0}}return!0}},L={EOF:1,parseError:function(t,e){if(!this.yy.parser)throw new Error(t);this.yy.parser.parseError(t,e)},setInput:function(t,e){return this.yy=e||this.yy||{},this._input=t,this._more=this._backtrack=this.done=!1,this.yylineno=this.yyleng=0,this.yytext=this.matched=this.match="",this.conditionStack=["INITIAL"],this.yylloc={first_line:1,first_column:0,last_line:1,last_column:0},this.options.ranges&&(this.yylloc.range=[0,0]),this.offset=0,this},input:function(){var t=this._input[0];return this.yytext+=t,this.yyleng++,this.offset++,this.match+=t,this.matched+=t,t.match(/(?:\r\n?|\n).*/g)?(this.yylineno++,this.yylloc.last_line++):this.yylloc.last_column++,this.options.ranges&&this.yylloc.range[1]++,this._input=this._input.slice(1),t},unput:function(t){var e=t.length,n=t.split(/(?:\r\n?|\n)/g);this._input=t+this._input,this.yytext=this.yytext.substr(0,this.yytext.length-e),this.offset-=e;var r=this.match.split(/(?:\r\n?|\n)/g);this.match=this.match.substr(0,this.match.length-1),this.matched=this.matched.substr(0,this.matched.length-1),n.length-1&&(this.yylineno-=n.length-1);var i=this.yylloc.range;return this.yylloc={first_line:this.yylloc.first_line,last_line:this.yylineno+1,first_column:this.yylloc.first_column,last_column:n?(n.length===r.length?this.yylloc.first_column:0)+r[r.length-n.length].length-n[0].length:this.yylloc.first_column-e},this.options.ranges&&(this.yylloc.range=[i[0],i[0]+this.yyleng-e]),this.yyleng=this.yytext.length,this},more:function(){return this._more=!0,this},reject:function(){return this.options.backtrack_lexer?(this._backtrack=!0,this):this.parseError("Lexical error on line "+(this.yylineno+1)+". You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true).\n"+this.showPosition(),{text:"",token:null,line:this.yylineno})},less:function(t){this.unput(this.match.slice(t))},pastInput:function(){var t=this.matched.substr(0,this.matched.length-this.match.length);return(t.length>20?"...":"")+t.substr(-20).replace(/\n/g,"")},upcomingInput:function(){var t=this.match;return t.length<20&&(t+=this._input.substr(0,20-t.length)),(t.substr(0,20)+(t.length>20?"...":"")).replace(/\n/g,"")},showPosition:function(){var t=this.pastInput(),e=new Array(t.length+1).join("-");return t+this.upcomingInput()+"\n"+e+"^"},test_match:function(t,e){var n,r,i;if(this.options.backtrack_lexer&&(i={yylineno:this.yylineno,yylloc:{first_line:this.yylloc.first_line,last_line:this.last_line,first_column:this.yylloc.first_column,last_column:this.yylloc.last_column},yytext:this.yytext,match:this.match,matches:this.matches,matched:this.matched,yyleng:this.yyleng,offset:this.offset,_more:this._more,_input:this._input,yy:this.yy,conditionStack:this.conditionStack.slice(0),done:this.done},this.options.ranges&&(i.yylloc.range=this.yylloc.range.slice(0))),(r=t[0].match(/(?:\r\n?|\n).*/g))&&(this.yylineno+=r.length),this.yylloc={first_line:this.yylloc.last_line,last_line:this.yylineno+1,first_column:this.yylloc.last_column,last_column:r?r[r.length-1].length-r[r.length-1].match(/\r?\n?/)[0].length:this.yylloc.last_column+t[0].length},this.yytext+=t[0],this.match+=t[0],this.matches=t,this.yyleng=this.yytext.length,this.options.ranges&&(this.yylloc.range=[this.offset,this.offset+=this.yyleng]),this._more=!1,this._backtrack=!1,this._input=this._input.slice(t[0].length),this.matched+=t[0],n=this.performAction.call(this,this.yy,this,e,this.conditionStack[this.conditionStack.length-1]),this.done&&this._input&&(this.done=!1),n)return n;if(this._backtrack){for(var a in i)this[a]=i[a];return!1}return!1},next:function(){if(this.done)return this.EOF;var t,e,n,r;this._input||(this.done=!0),this._more||(this.yytext="",this.match="");for(var i=this._currentRules(),a=0;ae[0].length)){if(e=n,r=a,this.options.backtrack_lexer){if(!1!==(t=this.test_match(n,i[a])))return t;if(this._backtrack){e=!1;continue}return!1}if(!this.options.flex)break}return e?!1!==(t=this.test_match(e,i[r]))&&t:""===this._input?this.EOF:this.parseError("Lexical error on line "+(this.yylineno+1)+". Unrecognized text.\n"+this.showPosition(),{text:"",token:null,line:this.yylineno})},lex:function(){return this.next()||this.lex()},begin:function(t){this.conditionStack.push(t)},popState:function(){return this.conditionStack.length-1>0?this.conditionStack.pop():this.conditionStack[0]},_currentRules:function(){return this.conditionStack.length&&this.conditionStack[this.conditionStack.length-1]?this.conditions[this.conditionStack[this.conditionStack.length-1]].rules:this.conditions.INITIAL.rules},topState:function(t){return(t=this.conditionStack.length-1-Math.abs(t||0))>=0?this.conditionStack[t]:"INITIAL"},pushState:function(t){this.begin(t)},stateStackSize:function(){return this.conditionStack.length},options:{"case-insensitive":!0},performAction:function(t,e,n,r){switch(n){case 0:return this.begin("open_directive"),67;case 1:return this.begin("type_directive"),68;case 2:return this.popState(),this.begin("arg_directive"),14;case 3:return this.popState(),this.popState(),70;case 4:return 69;case 5:return 5;case 6:case 7:case 8:case 9:case 10:break;case 11:return this.begin("ID"),16;case 12:return this.begin("ID"),20;case 13:return e.yytext=e.yytext.trim(),this.begin("ALIAS"),57;case 14:return this.popState(),this.popState(),this.begin("LINE"),18;case 15:return this.popState(),this.popState(),5;case 16:return this.begin("LINE"),32;case 17:return this.begin("LINE"),34;case 18:return this.begin("LINE"),35;case 19:return this.begin("LINE"),36;case 20:return this.begin("LINE"),41;case 21:return this.begin("LINE"),38;case 22:return this.begin("LINE"),40;case 23:return this.popState(),19;case 24:return 33;case 25:return 52;case 26:return 53;case 27:return 46;case 28:return 47;case 29:return 48;case 30:return 49;case 31:return 44;case 32:return 42;case 33:return this.begin("ID"),23;case 34:return this.begin("ID"),24;case 35:return 30;case 36:return 7;case 37:return 22;case 38:return 51;case 39:return 5;case 40:return e.yytext=e.yytext.trim(),57;case 41:return 60;case 42:return 61;case 43:return 58;case 44:return 59;case 45:return 62;case 46:return 63;case 47:return 64;case 48:return 65;case 49:return 66;case 50:return 55;case 51:return 56;case 52:return 5;case 53:return"INVALID"}},rules:[/^(?:%%\{)/i,/^(?:((?:(?!\}%%)[^:.])*))/i,/^(?::)/i,/^(?:\}%%)/i,/^(?:((?:(?!\}%%).|\n)*))/i,/^(?:[\n]+)/i,/^(?:\s+)/i,/^(?:((?!\n)\s)+)/i,/^(?:#[^\n]*)/i,/^(?:%(?!\{)[^\n]*)/i,/^(?:[^\}]%%[^\n]*)/i,/^(?:participant\b)/i,/^(?:actor\b)/i,/^(?:[^\->:\n,;]+?(?=((?!\n)\s)+as(?!\n)\s|[#\n;]|$))/i,/^(?:as\b)/i,/^(?:(?:))/i,/^(?:loop\b)/i,/^(?:rect\b)/i,/^(?:opt\b)/i,/^(?:alt\b)/i,/^(?:else\b)/i,/^(?:par\b)/i,/^(?:and\b)/i,/^(?:(?:[:]?(?:no)?wrap)?[^#\n;]*)/i,/^(?:end\b)/i,/^(?:left of\b)/i,/^(?:right of\b)/i,/^(?:links\b)/i,/^(?:link\b)/i,/^(?:properties\b)/i,/^(?:details\b)/i,/^(?:over\b)/i,/^(?:note\b)/i,/^(?:activate\b)/i,/^(?:deactivate\b)/i,/^(?:title\b)/i,/^(?:sequenceDiagram\b)/i,/^(?:autonumber\b)/i,/^(?:,)/i,/^(?:;)/i,/^(?:[^\+\->:\n,;]+((?!(-x|--x|-\)|--\)))[\-]*[^\+\->:\n,;]+)*)/i,/^(?:->>)/i,/^(?:-->>)/i,/^(?:->)/i,/^(?:-->)/i,/^(?:-[x])/i,/^(?:--[x])/i,/^(?:-[\)])/i,/^(?:--[\)])/i,/^(?::(?:(?:no)?wrap)?[^#\n;]+)/i,/^(?:\+)/i,/^(?:-)/i,/^(?:$)/i,/^(?:.)/i],conditions:{open_directive:{rules:[1,8],inclusive:!1},type_directive:{rules:[2,3,8],inclusive:!1},arg_directive:{rules:[3,4,8],inclusive:!1},ID:{rules:[7,8,13],inclusive:!1},ALIAS:{rules:[7,8,14,15],inclusive:!1},LINE:{rules:[7,8,23],inclusive:!1},INITIAL:{rules:[0,5,6,8,9,10,11,12,16,17,18,19,20,21,22,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53],inclusive:!0}}};function I(){this.yy={}}return B.lexer=L,I.prototype=B,B.Parser=I,new I}();e.parser=r,e.Parser=r.Parser,e.parse=function(){return r.parse.apply(r,arguments)},e.main=function(t){t[1]||(console.log("Usage: "+t[0]+" FILE"),process.exit(1));var r=n(1993).readFileSync(n(6470).normalize(t[1]),"utf8");return e.parser.parse(r)},n.c[n.s]===t&&e.main(process.argv.slice(1))},5537:(t,e,n)=>{t=n.nmd(t);var r=function(){var t=function(t,e,n,r){for(n=n||{},r=t.length;r--;n[t[r]]=e);return n},e=[1,2],n=[1,3],r=[1,5],i=[1,7],a=[2,5],o=[1,15],s=[1,17],c=[1,19],u=[1,20],l=[1,21],h=[1,22],f=[1,30],d=[1,23],p=[1,24],y=[1,25],g=[1,26],m=[1,27],v=[1,32],b=[1,33],_=[1,34],x=[1,35],w=[1,31],k=[1,38],T=[1,4,5,14,15,17,19,20,22,23,24,25,26,27,36,37,38,39,42,45],E=[1,4,5,12,13,14,15,17,19,20,22,23,24,25,26,27,36,37,38,39,42,45],C=[1,4,5,7,14,15,17,19,20,22,23,24,25,26,27,36,37,38,39,42,45],S=[4,5,14,15,17,19,20,22,23,24,25,26,27,36,37,38,39,42,45],A={trace:function(){},yy:{},symbols_:{error:2,start:3,SPACE:4,NL:5,directive:6,SD:7,document:8,line:9,statement:10,idStatement:11,DESCR:12,"--\x3e":13,HIDE_EMPTY:14,scale:15,WIDTH:16,COMPOSIT_STATE:17,STRUCT_START:18,STRUCT_STOP:19,STATE_DESCR:20,AS:21,ID:22,FORK:23,JOIN:24,CHOICE:25,CONCURRENT:26,note:27,notePosition:28,NOTE_TEXT:29,direction:30,openDirective:31,typeDirective:32,closeDirective:33,":":34,argDirective:35,direction_tb:36,direction_bt:37,direction_rl:38,direction_lr:39,eol:40,";":41,EDGE_STATE:42,left_of:43,right_of:44,open_directive:45,type_directive:46,arg_directive:47,close_directive:48,$accept:0,$end:1},terminals_:{2:"error",4:"SPACE",5:"NL",7:"SD",12:"DESCR",13:"--\x3e",14:"HIDE_EMPTY",15:"scale",16:"WIDTH",17:"COMPOSIT_STATE",18:"STRUCT_START",19:"STRUCT_STOP",20:"STATE_DESCR",21:"AS",22:"ID",23:"FORK",24:"JOIN",25:"CHOICE",26:"CONCURRENT",27:"note",29:"NOTE_TEXT",34:":",36:"direction_tb",37:"direction_bt",38:"direction_rl",39:"direction_lr",41:";",42:"EDGE_STATE",43:"left_of",44:"right_of",45:"open_directive",46:"type_directive",47:"arg_directive",48:"close_directive"},productions_:[0,[3,2],[3,2],[3,2],[3,2],[8,0],[8,2],[9,2],[9,1],[9,1],[10,1],[10,2],[10,3],[10,4],[10,1],[10,2],[10,1],[10,4],[10,3],[10,6],[10,1],[10,1],[10,1],[10,1],[10,4],[10,4],[10,1],[10,1],[6,3],[6,5],[30,1],[30,1],[30,1],[30,1],[40,1],[40,1],[11,1],[11,1],[28,1],[28,1],[31,1],[32,1],[35,1],[33,1]],performAction:function(t,e,n,r,i,a,o){var s=a.length-1;switch(i){case 4:return r.setRootDoc(a[s]),a[s];case 5:this.$=[];break;case 6:"nl"!=a[s]&&(a[s-1].push(a[s]),this.$=a[s-1]);break;case 7:case 8:this.$=a[s];break;case 9:this.$="nl";break;case 10:this.$={stmt:"state",id:a[s],type:"default",description:""};break;case 11:this.$={stmt:"state",id:a[s-1],type:"default",description:r.trimColon(a[s])};break;case 12:this.$={stmt:"relation",state1:{stmt:"state",id:a[s-2],type:"default",description:""},state2:{stmt:"state",id:a[s],type:"default",description:""}};break;case 13:this.$={stmt:"relation",state1:{stmt:"state",id:a[s-3],type:"default",description:""},state2:{stmt:"state",id:a[s-1],type:"default",description:""},description:a[s].substr(1).trim()};break;case 17:this.$={stmt:"state",id:a[s-3],type:"default",description:"",doc:a[s-1]};break;case 18:var c=a[s],u=a[s-2].trim();if(a[s].match(":")){var l=a[s].split(":");c=l[0],u=[u,l[1]]}this.$={stmt:"state",id:c,type:"default",description:u};break;case 19:this.$={stmt:"state",id:a[s-3],type:"default",description:a[s-5],doc:a[s-1]};break;case 20:this.$={stmt:"state",id:a[s],type:"fork"};break;case 21:this.$={stmt:"state",id:a[s],type:"join"};break;case 22:this.$={stmt:"state",id:a[s],type:"choice"};break;case 23:this.$={stmt:"state",id:r.getDividerId(),type:"divider"};break;case 24:this.$={stmt:"state",id:a[s-1].trim(),note:{position:a[s-2].trim(),text:a[s].trim()}};break;case 30:r.setDirection("TB"),this.$={stmt:"dir",value:"TB"};break;case 31:r.setDirection("BT"),this.$={stmt:"dir",value:"BT"};break;case 32:r.setDirection("RL"),this.$={stmt:"dir",value:"RL"};break;case 33:r.setDirection("LR"),this.$={stmt:"dir",value:"LR"};break;case 36:case 37:this.$=a[s];break;case 40:r.parseDirective("%%{","open_directive");break;case 41:r.parseDirective(a[s],"type_directive");break;case 42:a[s]=a[s].trim().replace(/'/g,'"'),r.parseDirective(a[s],"arg_directive");break;case 43:r.parseDirective("}%%","close_directive","state")}},table:[{3:1,4:e,5:n,6:4,7:r,31:6,45:i},{1:[3]},{3:8,4:e,5:n,6:4,7:r,31:6,45:i},{3:9,4:e,5:n,6:4,7:r,31:6,45:i},{3:10,4:e,5:n,6:4,7:r,31:6,45:i},t([1,4,5,14,15,17,20,22,23,24,25,26,27,36,37,38,39,42,45],a,{8:11}),{32:12,46:[1,13]},{46:[2,40]},{1:[2,1]},{1:[2,2]},{1:[2,3]},{1:[2,4],4:o,5:s,6:28,9:14,10:16,11:18,14:c,15:u,17:l,20:h,22:f,23:d,24:p,25:y,26:g,27:m,30:29,31:6,36:v,37:b,38:_,39:x,42:w,45:i},{33:36,34:[1,37],48:k},t([34,48],[2,41]),t(T,[2,6]),{6:28,10:39,11:18,14:c,15:u,17:l,20:h,22:f,23:d,24:p,25:y,26:g,27:m,30:29,31:6,36:v,37:b,38:_,39:x,42:w,45:i},t(T,[2,8]),t(T,[2,9]),t(T,[2,10],{12:[1,40],13:[1,41]}),t(T,[2,14]),{16:[1,42]},t(T,[2,16],{18:[1,43]}),{21:[1,44]},t(T,[2,20]),t(T,[2,21]),t(T,[2,22]),t(T,[2,23]),{28:45,29:[1,46],43:[1,47],44:[1,48]},t(T,[2,26]),t(T,[2,27]),t(E,[2,36]),t(E,[2,37]),t(T,[2,30]),t(T,[2,31]),t(T,[2,32]),t(T,[2,33]),t(C,[2,28]),{35:49,47:[1,50]},t(C,[2,43]),t(T,[2,7]),t(T,[2,11]),{11:51,22:f,42:w},t(T,[2,15]),t(S,a,{8:52}),{22:[1,53]},{22:[1,54]},{21:[1,55]},{22:[2,38]},{22:[2,39]},{33:56,48:k},{48:[2,42]},t(T,[2,12],{12:[1,57]}),{4:o,5:s,6:28,9:14,10:16,11:18,14:c,15:u,17:l,19:[1,58],20:h,22:f,23:d,24:p,25:y,26:g,27:m,30:29,31:6,36:v,37:b,38:_,39:x,42:w,45:i},t(T,[2,18],{18:[1,59]}),{29:[1,60]},{22:[1,61]},t(C,[2,29]),t(T,[2,13]),t(T,[2,17]),t(S,a,{8:62}),t(T,[2,24]),t(T,[2,25]),{4:o,5:s,6:28,9:14,10:16,11:18,14:c,15:u,17:l,19:[1,63],20:h,22:f,23:d,24:p,25:y,26:g,27:m,30:29,31:6,36:v,37:b,38:_,39:x,42:w,45:i},t(T,[2,19])],defaultActions:{7:[2,40],8:[2,1],9:[2,2],10:[2,3],47:[2,38],48:[2,39],50:[2,42]},parseError:function(t,e){if(!e.recoverable){var n=new Error(t);throw n.hash=e,n}this.trace(t)},parse:function(t){var e=this,n=[0],r=[],i=[null],a=[],o=this.table,s="",c=0,u=0,l=0,h=2,f=1,d=a.slice.call(arguments,1),p=Object.create(this.lexer),y={yy:{}};for(var g in this.yy)Object.prototype.hasOwnProperty.call(this.yy,g)&&(y.yy[g]=this.yy[g]);p.setInput(t,y.yy),y.yy.lexer=p,y.yy.parser=this,void 0===p.yylloc&&(p.yylloc={});var m=p.yylloc;a.push(m);var v=p.options&&p.options.ranges;function b(){var t;return"number"!=typeof(t=r.pop()||p.lex()||f)&&(t instanceof Array&&(t=(r=t).pop()),t=e.symbols_[t]||t),t}"function"==typeof y.yy.parseError?this.parseError=y.yy.parseError:this.parseError=Object.getPrototypeOf(this).parseError;for(var _,x,w,k,T,E,C,S,A,M={};;){if(w=n[n.length-1],this.defaultActions[w]?k=this.defaultActions[w]:(null==_&&(_=b()),k=o[w]&&o[w][_]),void 0===k||!k.length||!k[0]){var N="";for(E in A=[],o[w])this.terminals_[E]&&E>h&&A.push("'"+this.terminals_[E]+"'");N=p.showPosition?"Parse error on line "+(c+1)+":\n"+p.showPosition()+"\nExpecting "+A.join(", ")+", got '"+(this.terminals_[_]||_)+"'":"Parse error on line "+(c+1)+": Unexpected "+(_==f?"end of input":"'"+(this.terminals_[_]||_)+"'"),this.parseError(N,{text:p.match,token:this.terminals_[_]||_,line:p.yylineno,loc:m,expected:A})}if(k[0]instanceof Array&&k.length>1)throw new Error("Parse Error: multiple actions possible at state: "+w+", token: "+_);switch(k[0]){case 1:n.push(_),i.push(p.yytext),a.push(p.yylloc),n.push(k[1]),_=null,x?(_=x,x=null):(u=p.yyleng,s=p.yytext,c=p.yylineno,m=p.yylloc,l>0&&l--);break;case 2:if(C=this.productions_[k[1]][1],M.$=i[i.length-C],M._$={first_line:a[a.length-(C||1)].first_line,last_line:a[a.length-1].last_line,first_column:a[a.length-(C||1)].first_column,last_column:a[a.length-1].last_column},v&&(M._$.range=[a[a.length-(C||1)].range[0],a[a.length-1].range[1]]),void 0!==(T=this.performAction.apply(M,[s,u,c,y.yy,k[1],i,a].concat(d))))return T;C&&(n=n.slice(0,-1*C*2),i=i.slice(0,-1*C),a=a.slice(0,-1*C)),n.push(this.productions_[k[1]][0]),i.push(M.$),a.push(M._$),S=o[n[n.length-2]][n[n.length-1]],n.push(S);break;case 3:return!0}}return!0}},M={EOF:1,parseError:function(t,e){if(!this.yy.parser)throw new Error(t);this.yy.parser.parseError(t,e)},setInput:function(t,e){return this.yy=e||this.yy||{},this._input=t,this._more=this._backtrack=this.done=!1,this.yylineno=this.yyleng=0,this.yytext=this.matched=this.match="",this.conditionStack=["INITIAL"],this.yylloc={first_line:1,first_column:0,last_line:1,last_column:0},this.options.ranges&&(this.yylloc.range=[0,0]),this.offset=0,this},input:function(){var t=this._input[0];return this.yytext+=t,this.yyleng++,this.offset++,this.match+=t,this.matched+=t,t.match(/(?:\r\n?|\n).*/g)?(this.yylineno++,this.yylloc.last_line++):this.yylloc.last_column++,this.options.ranges&&this.yylloc.range[1]++,this._input=this._input.slice(1),t},unput:function(t){var e=t.length,n=t.split(/(?:\r\n?|\n)/g);this._input=t+this._input,this.yytext=this.yytext.substr(0,this.yytext.length-e),this.offset-=e;var r=this.match.split(/(?:\r\n?|\n)/g);this.match=this.match.substr(0,this.match.length-1),this.matched=this.matched.substr(0,this.matched.length-1),n.length-1&&(this.yylineno-=n.length-1);var i=this.yylloc.range;return this.yylloc={first_line:this.yylloc.first_line,last_line:this.yylineno+1,first_column:this.yylloc.first_column,last_column:n?(n.length===r.length?this.yylloc.first_column:0)+r[r.length-n.length].length-n[0].length:this.yylloc.first_column-e},this.options.ranges&&(this.yylloc.range=[i[0],i[0]+this.yyleng-e]),this.yyleng=this.yytext.length,this},more:function(){return this._more=!0,this},reject:function(){return this.options.backtrack_lexer?(this._backtrack=!0,this):this.parseError("Lexical error on line "+(this.yylineno+1)+". You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true).\n"+this.showPosition(),{text:"",token:null,line:this.yylineno})},less:function(t){this.unput(this.match.slice(t))},pastInput:function(){var t=this.matched.substr(0,this.matched.length-this.match.length);return(t.length>20?"...":"")+t.substr(-20).replace(/\n/g,"")},upcomingInput:function(){var t=this.match;return t.length<20&&(t+=this._input.substr(0,20-t.length)),(t.substr(0,20)+(t.length>20?"...":"")).replace(/\n/g,"")},showPosition:function(){var t=this.pastInput(),e=new Array(t.length+1).join("-");return t+this.upcomingInput()+"\n"+e+"^"},test_match:function(t,e){var n,r,i;if(this.options.backtrack_lexer&&(i={yylineno:this.yylineno,yylloc:{first_line:this.yylloc.first_line,last_line:this.last_line,first_column:this.yylloc.first_column,last_column:this.yylloc.last_column},yytext:this.yytext,match:this.match,matches:this.matches,matched:this.matched,yyleng:this.yyleng,offset:this.offset,_more:this._more,_input:this._input,yy:this.yy,conditionStack:this.conditionStack.slice(0),done:this.done},this.options.ranges&&(i.yylloc.range=this.yylloc.range.slice(0))),(r=t[0].match(/(?:\r\n?|\n).*/g))&&(this.yylineno+=r.length),this.yylloc={first_line:this.yylloc.last_line,last_line:this.yylineno+1,first_column:this.yylloc.last_column,last_column:r?r[r.length-1].length-r[r.length-1].match(/\r?\n?/)[0].length:this.yylloc.last_column+t[0].length},this.yytext+=t[0],this.match+=t[0],this.matches=t,this.yyleng=this.yytext.length,this.options.ranges&&(this.yylloc.range=[this.offset,this.offset+=this.yyleng]),this._more=!1,this._backtrack=!1,this._input=this._input.slice(t[0].length),this.matched+=t[0],n=this.performAction.call(this,this.yy,this,e,this.conditionStack[this.conditionStack.length-1]),this.done&&this._input&&(this.done=!1),n)return n;if(this._backtrack){for(var a in i)this[a]=i[a];return!1}return!1},next:function(){if(this.done)return this.EOF;var t,e,n,r;this._input||(this.done=!0),this._more||(this.yytext="",this.match="");for(var i=this._currentRules(),a=0;ae[0].length)){if(e=n,r=a,this.options.backtrack_lexer){if(!1!==(t=this.test_match(n,i[a])))return t;if(this._backtrack){e=!1;continue}return!1}if(!this.options.flex)break}return e?!1!==(t=this.test_match(e,i[r]))&&t:""===this._input?this.EOF:this.parseError("Lexical error on line "+(this.yylineno+1)+". Unrecognized text.\n"+this.showPosition(),{text:"",token:null,line:this.yylineno})},lex:function(){return this.next()||this.lex()},begin:function(t){this.conditionStack.push(t)},popState:function(){return this.conditionStack.length-1>0?this.conditionStack.pop():this.conditionStack[0]},_currentRules:function(){return this.conditionStack.length&&this.conditionStack[this.conditionStack.length-1]?this.conditions[this.conditionStack[this.conditionStack.length-1]].rules:this.conditions.INITIAL.rules},topState:function(t){return(t=this.conditionStack.length-1-Math.abs(t||0))>=0?this.conditionStack[t]:"INITIAL"},pushState:function(t){this.begin(t)},stateStackSize:function(){return this.conditionStack.length},options:{"case-insensitive":!0},performAction:function(t,e,n,r){switch(n){case 0:return 36;case 1:return 37;case 2:return 38;case 3:return 39;case 4:return this.begin("open_directive"),45;case 5:return this.begin("type_directive"),46;case 6:return this.popState(),this.begin("arg_directive"),34;case 7:return this.popState(),this.popState(),48;case 8:return 47;case 9:case 10:break;case 11:return 5;case 12:case 13:case 14:case 15:break;case 16:return this.pushState("SCALE"),15;case 17:return 16;case 18:this.popState();break;case 19:this.pushState("STATE");break;case 20:return this.popState(),e.yytext=e.yytext.slice(0,-8).trim(),23;case 21:return this.popState(),e.yytext=e.yytext.slice(0,-8).trim(),24;case 22:return this.popState(),e.yytext=e.yytext.slice(0,-10).trim(),25;case 23:return this.popState(),e.yytext=e.yytext.slice(0,-8).trim(),23;case 24:return this.popState(),e.yytext=e.yytext.slice(0,-8).trim(),24;case 25:return this.popState(),e.yytext=e.yytext.slice(0,-10).trim(),25;case 26:return 36;case 27:return 37;case 28:return 38;case 29:return 39;case 30:this.begin("STATE_STRING");break;case 31:return this.popState(),this.pushState("STATE_ID"),"AS";case 32:return this.popState(),"ID";case 33:this.popState();break;case 34:return"STATE_DESCR";case 35:return 17;case 36:this.popState();break;case 37:return this.popState(),this.pushState("struct"),18;case 38:return this.popState(),19;case 39:break;case 40:return this.begin("NOTE"),27;case 41:return this.popState(),this.pushState("NOTE_ID"),43;case 42:return this.popState(),this.pushState("NOTE_ID"),44;case 43:this.popState(),this.pushState("FLOATING_NOTE");break;case 44:return this.popState(),this.pushState("FLOATING_NOTE_ID"),"AS";case 45:break;case 46:return"NOTE_TEXT";case 47:return this.popState(),"ID";case 48:return this.popState(),this.pushState("NOTE_TEXT"),22;case 49:return this.popState(),e.yytext=e.yytext.substr(2).trim(),29;case 50:return this.popState(),e.yytext=e.yytext.slice(0,-8).trim(),29;case 51:case 52:return 7;case 53:return 14;case 54:return 42;case 55:return 22;case 56:return e.yytext=e.yytext.trim(),12;case 57:return 13;case 58:return 26;case 59:return 5;case 60:return"INVALID"}},rules:[/^(?:.*direction\s+TB[^\n]*)/i,/^(?:.*direction\s+BT[^\n]*)/i,/^(?:.*direction\s+RL[^\n]*)/i,/^(?:.*direction\s+LR[^\n]*)/i,/^(?:%%\{)/i,/^(?:((?:(?!\}%%)[^:.])*))/i,/^(?::)/i,/^(?:\}%%)/i,/^(?:((?:(?!\}%%).|\n)*))/i,/^(?:%%(?!\{)[^\n]*)/i,/^(?:[^\}]%%[^\n]*)/i,/^(?:[\n]+)/i,/^(?:[\s]+)/i,/^(?:((?!\n)\s)+)/i,/^(?:#[^\n]*)/i,/^(?:%[^\n]*)/i,/^(?:scale\s+)/i,/^(?:\d+)/i,/^(?:\s+width\b)/i,/^(?:state\s+)/i,/^(?:.*<>)/i,/^(?:.*<>)/i,/^(?:.*<>)/i,/^(?:.*\[\[fork\]\])/i,/^(?:.*\[\[join\]\])/i,/^(?:.*\[\[choice\]\])/i,/^(?:.*direction\s+TB[^\n]*)/i,/^(?:.*direction\s+BT[^\n]*)/i,/^(?:.*direction\s+RL[^\n]*)/i,/^(?:.*direction\s+LR[^\n]*)/i,/^(?:["])/i,/^(?:\s*as\s+)/i,/^(?:[^\n\{]*)/i,/^(?:["])/i,/^(?:[^"]*)/i,/^(?:[^\n\s\{]+)/i,/^(?:\n)/i,/^(?:\{)/i,/^(?:\})/i,/^(?:[\n])/i,/^(?:note\s+)/i,/^(?:left of\b)/i,/^(?:right of\b)/i,/^(?:")/i,/^(?:\s*as\s*)/i,/^(?:["])/i,/^(?:[^"]*)/i,/^(?:[^\n]*)/i,/^(?:\s*[^:\n\s\-]+)/i,/^(?:\s*:[^:\n;]+)/i,/^(?:[\s\S]*?end note\b)/i,/^(?:stateDiagram\s+)/i,/^(?:stateDiagram-v2\s+)/i,/^(?:hide empty description\b)/i,/^(?:\[\*\])/i,/^(?:[^:\n\s\-\{]+)/i,/^(?:\s*:[^:\n;]+)/i,/^(?:-->)/i,/^(?:--)/i,/^(?:$)/i,/^(?:.)/i],conditions:{LINE:{rules:[13,14],inclusive:!1},close_directive:{rules:[13,14],inclusive:!1},arg_directive:{rules:[7,8,13,14],inclusive:!1},type_directive:{rules:[6,7,13,14],inclusive:!1},open_directive:{rules:[5,13,14],inclusive:!1},struct:{rules:[13,14,19,26,27,28,29,38,39,40,54,55,56,57,58],inclusive:!1},FLOATING_NOTE_ID:{rules:[47],inclusive:!1},FLOATING_NOTE:{rules:[44,45,46],inclusive:!1},NOTE_TEXT:{rules:[49,50],inclusive:!1},NOTE_ID:{rules:[48],inclusive:!1},NOTE:{rules:[41,42,43],inclusive:!1},SCALE:{rules:[17,18],inclusive:!1},ALIAS:{rules:[],inclusive:!1},STATE_ID:{rules:[32],inclusive:!1},STATE_STRING:{rules:[33,34],inclusive:!1},FORK_STATE:{rules:[],inclusive:!1},STATE:{rules:[13,14,20,21,22,23,24,25,30,31,35,36,37],inclusive:!1},ID:{rules:[13,14],inclusive:!1},INITIAL:{rules:[0,1,2,3,4,9,10,11,12,14,15,16,19,37,40,51,52,53,54,55,56,57,59,60],inclusive:!0}}};function N(){this.yy={}}return A.lexer=M,N.prototype=A,A.Parser=N,new N}();e.parser=r,e.Parser=r.Parser,e.parse=function(){return r.parse.apply(r,arguments)},e.main=function(t){t[1]||(console.log("Usage: "+t[0]+" FILE"),process.exit(1));var r=n(3069).readFileSync(n(6470).normalize(t[1]),"utf8");return e.parser.parse(r)},n.c[n.s]===t&&e.main(process.argv.slice(1))},6741:(t,e,n)=>{t=n.nmd(t);var r=function(){var t=function(t,e,n,r){for(n=n||{},r=t.length;r--;n[t[r]]=e);return n},e=[1,2],n=[1,5],r=[6,9,11,17,18,19,21],i=[1,15],a=[1,16],o=[1,17],s=[1,21],c=[4,6,9,11,17,18,19,21],u={trace:function(){},yy:{},symbols_:{error:2,start:3,journey:4,document:5,EOF:6,directive:7,line:8,SPACE:9,statement:10,NEWLINE:11,openDirective:12,typeDirective:13,closeDirective:14,":":15,argDirective:16,title:17,section:18,taskName:19,taskData:20,open_directive:21,type_directive:22,arg_directive:23,close_directive:24,$accept:0,$end:1},terminals_:{2:"error",4:"journey",6:"EOF",9:"SPACE",11:"NEWLINE",15:":",17:"title",18:"section",19:"taskName",20:"taskData",21:"open_directive",22:"type_directive",23:"arg_directive",24:"close_directive"},productions_:[0,[3,3],[3,2],[5,0],[5,2],[8,2],[8,1],[8,1],[8,1],[7,4],[7,6],[10,1],[10,1],[10,2],[10,1],[12,1],[13,1],[16,1],[14,1]],performAction:function(t,e,n,r,i,a,o){var s=a.length-1;switch(i){case 1:return a[s-1];case 3:this.$=[];break;case 4:a[s-1].push(a[s]),this.$=a[s-1];break;case 5:case 6:this.$=a[s];break;case 7:case 8:this.$=[];break;case 11:r.setTitle(a[s].substr(6)),this.$=a[s].substr(6);break;case 12:r.addSection(a[s].substr(8)),this.$=a[s].substr(8);break;case 13:r.addTask(a[s-1],a[s]),this.$="task";break;case 15:r.parseDirective("%%{","open_directive");break;case 16:r.parseDirective(a[s],"type_directive");break;case 17:a[s]=a[s].trim().replace(/'/g,'"'),r.parseDirective(a[s],"arg_directive");break;case 18:r.parseDirective("}%%","close_directive","journey")}},table:[{3:1,4:e,7:3,12:4,21:n},{1:[3]},t(r,[2,3],{5:6}),{3:7,4:e,7:3,12:4,21:n},{13:8,22:[1,9]},{22:[2,15]},{6:[1,10],7:18,8:11,9:[1,12],10:13,11:[1,14],12:4,17:i,18:a,19:o,21:n},{1:[2,2]},{14:19,15:[1,20],24:s},t([15,24],[2,16]),t(r,[2,8],{1:[2,1]}),t(r,[2,4]),{7:18,10:22,12:4,17:i,18:a,19:o,21:n},t(r,[2,6]),t(r,[2,7]),t(r,[2,11]),t(r,[2,12]),{20:[1,23]},t(r,[2,14]),{11:[1,24]},{16:25,23:[1,26]},{11:[2,18]},t(r,[2,5]),t(r,[2,13]),t(c,[2,9]),{14:27,24:s},{24:[2,17]},{11:[1,28]},t(c,[2,10])],defaultActions:{5:[2,15],7:[2,2],21:[2,18],26:[2,17]},parseError:function(t,e){if(!e.recoverable){var n=new Error(t);throw n.hash=e,n}this.trace(t)},parse:function(t){var e=this,n=[0],r=[],i=[null],a=[],o=this.table,s="",c=0,u=0,l=0,h=2,f=1,d=a.slice.call(arguments,1),p=Object.create(this.lexer),y={yy:{}};for(var g in this.yy)Object.prototype.hasOwnProperty.call(this.yy,g)&&(y.yy[g]=this.yy[g]);p.setInput(t,y.yy),y.yy.lexer=p,y.yy.parser=this,void 0===p.yylloc&&(p.yylloc={});var m=p.yylloc;a.push(m);var v=p.options&&p.options.ranges;function b(){var t;return"number"!=typeof(t=r.pop()||p.lex()||f)&&(t instanceof Array&&(t=(r=t).pop()),t=e.symbols_[t]||t),t}"function"==typeof y.yy.parseError?this.parseError=y.yy.parseError:this.parseError=Object.getPrototypeOf(this).parseError;for(var _,x,w,k,T,E,C,S,A,M={};;){if(w=n[n.length-1],this.defaultActions[w]?k=this.defaultActions[w]:(null==_&&(_=b()),k=o[w]&&o[w][_]),void 0===k||!k.length||!k[0]){var N="";for(E in A=[],o[w])this.terminals_[E]&&E>h&&A.push("'"+this.terminals_[E]+"'");N=p.showPosition?"Parse error on line "+(c+1)+":\n"+p.showPosition()+"\nExpecting "+A.join(", ")+", got '"+(this.terminals_[_]||_)+"'":"Parse error on line "+(c+1)+": Unexpected "+(_==f?"end of input":"'"+(this.terminals_[_]||_)+"'"),this.parseError(N,{text:p.match,token:this.terminals_[_]||_,line:p.yylineno,loc:m,expected:A})}if(k[0]instanceof Array&&k.length>1)throw new Error("Parse Error: multiple actions possible at state: "+w+", token: "+_);switch(k[0]){case 1:n.push(_),i.push(p.yytext),a.push(p.yylloc),n.push(k[1]),_=null,x?(_=x,x=null):(u=p.yyleng,s=p.yytext,c=p.yylineno,m=p.yylloc,l>0&&l--);break;case 2:if(C=this.productions_[k[1]][1],M.$=i[i.length-C],M._$={first_line:a[a.length-(C||1)].first_line,last_line:a[a.length-1].last_line,first_column:a[a.length-(C||1)].first_column,last_column:a[a.length-1].last_column},v&&(M._$.range=[a[a.length-(C||1)].range[0],a[a.length-1].range[1]]),void 0!==(T=this.performAction.apply(M,[s,u,c,y.yy,k[1],i,a].concat(d))))return T;C&&(n=n.slice(0,-1*C*2),i=i.slice(0,-1*C),a=a.slice(0,-1*C)),n.push(this.productions_[k[1]][0]),i.push(M.$),a.push(M._$),S=o[n[n.length-2]][n[n.length-1]],n.push(S);break;case 3:return!0}}return!0}},l={EOF:1,parseError:function(t,e){if(!this.yy.parser)throw new Error(t);this.yy.parser.parseError(t,e)},setInput:function(t,e){return this.yy=e||this.yy||{},this._input=t,this._more=this._backtrack=this.done=!1,this.yylineno=this.yyleng=0,this.yytext=this.matched=this.match="",this.conditionStack=["INITIAL"],this.yylloc={first_line:1,first_column:0,last_line:1,last_column:0},this.options.ranges&&(this.yylloc.range=[0,0]),this.offset=0,this},input:function(){var t=this._input[0];return this.yytext+=t,this.yyleng++,this.offset++,this.match+=t,this.matched+=t,t.match(/(?:\r\n?|\n).*/g)?(this.yylineno++,this.yylloc.last_line++):this.yylloc.last_column++,this.options.ranges&&this.yylloc.range[1]++,this._input=this._input.slice(1),t},unput:function(t){var e=t.length,n=t.split(/(?:\r\n?|\n)/g);this._input=t+this._input,this.yytext=this.yytext.substr(0,this.yytext.length-e),this.offset-=e;var r=this.match.split(/(?:\r\n?|\n)/g);this.match=this.match.substr(0,this.match.length-1),this.matched=this.matched.substr(0,this.matched.length-1),n.length-1&&(this.yylineno-=n.length-1);var i=this.yylloc.range;return this.yylloc={first_line:this.yylloc.first_line,last_line:this.yylineno+1,first_column:this.yylloc.first_column,last_column:n?(n.length===r.length?this.yylloc.first_column:0)+r[r.length-n.length].length-n[0].length:this.yylloc.first_column-e},this.options.ranges&&(this.yylloc.range=[i[0],i[0]+this.yyleng-e]),this.yyleng=this.yytext.length,this},more:function(){return this._more=!0,this},reject:function(){return this.options.backtrack_lexer?(this._backtrack=!0,this):this.parseError("Lexical error on line "+(this.yylineno+1)+". You can only invoke reject() in the lexer when the lexer is of the backtracking persuasion (options.backtrack_lexer = true).\n"+this.showPosition(),{text:"",token:null,line:this.yylineno})},less:function(t){this.unput(this.match.slice(t))},pastInput:function(){var t=this.matched.substr(0,this.matched.length-this.match.length);return(t.length>20?"...":"")+t.substr(-20).replace(/\n/g,"")},upcomingInput:function(){var t=this.match;return t.length<20&&(t+=this._input.substr(0,20-t.length)),(t.substr(0,20)+(t.length>20?"...":"")).replace(/\n/g,"")},showPosition:function(){var t=this.pastInput(),e=new Array(t.length+1).join("-");return t+this.upcomingInput()+"\n"+e+"^"},test_match:function(t,e){var n,r,i;if(this.options.backtrack_lexer&&(i={yylineno:this.yylineno,yylloc:{first_line:this.yylloc.first_line,last_line:this.last_line,first_column:this.yylloc.first_column,last_column:this.yylloc.last_column},yytext:this.yytext,match:this.match,matches:this.matches,matched:this.matched,yyleng:this.yyleng,offset:this.offset,_more:this._more,_input:this._input,yy:this.yy,conditionStack:this.conditionStack.slice(0),done:this.done},this.options.ranges&&(i.yylloc.range=this.yylloc.range.slice(0))),(r=t[0].match(/(?:\r\n?|\n).*/g))&&(this.yylineno+=r.length),this.yylloc={first_line:this.yylloc.last_line,last_line:this.yylineno+1,first_column:this.yylloc.last_column,last_column:r?r[r.length-1].length-r[r.length-1].match(/\r?\n?/)[0].length:this.yylloc.last_column+t[0].length},this.yytext+=t[0],this.match+=t[0],this.matches=t,this.yyleng=this.yytext.length,this.options.ranges&&(this.yylloc.range=[this.offset,this.offset+=this.yyleng]),this._more=!1,this._backtrack=!1,this._input=this._input.slice(t[0].length),this.matched+=t[0],n=this.performAction.call(this,this.yy,this,e,this.conditionStack[this.conditionStack.length-1]),this.done&&this._input&&(this.done=!1),n)return n;if(this._backtrack){for(var a in i)this[a]=i[a];return!1}return!1},next:function(){if(this.done)return this.EOF;var t,e,n,r;this._input||(this.done=!0),this._more||(this.yytext="",this.match="");for(var i=this._currentRules(),a=0;ae[0].length)){if(e=n,r=a,this.options.backtrack_lexer){if(!1!==(t=this.test_match(n,i[a])))return t;if(this._backtrack){e=!1;continue}return!1}if(!this.options.flex)break}return e?!1!==(t=this.test_match(e,i[r]))&&t:""===this._input?this.EOF:this.parseError("Lexical error on line "+(this.yylineno+1)+". Unrecognized text.\n"+this.showPosition(),{text:"",token:null,line:this.yylineno})},lex:function(){return this.next()||this.lex()},begin:function(t){this.conditionStack.push(t)},popState:function(){return this.conditionStack.length-1>0?this.conditionStack.pop():this.conditionStack[0]},_currentRules:function(){return this.conditionStack.length&&this.conditionStack[this.conditionStack.length-1]?this.conditions[this.conditionStack[this.conditionStack.length-1]].rules:this.conditions.INITIAL.rules},topState:function(t){return(t=this.conditionStack.length-1-Math.abs(t||0))>=0?this.conditionStack[t]:"INITIAL"},pushState:function(t){this.begin(t)},stateStackSize:function(){return this.conditionStack.length},options:{"case-insensitive":!0},performAction:function(t,e,n,r){switch(n){case 0:return this.begin("open_directive"),21;case 1:return this.begin("type_directive"),22;case 2:return this.popState(),this.begin("arg_directive"),15;case 3:return this.popState(),this.popState(),24;case 4:return 23;case 5:case 6:break;case 7:return 11;case 8:case 9:break;case 10:return 4;case 11:return 17;case 12:return 18;case 13:return 19;case 14:return 20;case 15:return 15;case 16:return 6;case 17:return"INVALID"}},rules:[/^(?:%%\{)/i,/^(?:((?:(?!\}%%)[^:.])*))/i,/^(?::)/i,/^(?:\}%%)/i,/^(?:((?:(?!\}%%).|\n)*))/i,/^(?:%(?!\{)[^\n]*)/i,/^(?:[^\}]%%[^\n]*)/i,/^(?:[\n]+)/i,/^(?:\s+)/i,/^(?:#[^\n]*)/i,/^(?:journey\b)/i,/^(?:title\s[^#\n;]+)/i,/^(?:section\s[^#:\n;]+)/i,/^(?:[^#:\n;]+)/i,/^(?::[^#\n;]+)/i,/^(?::)/i,/^(?:$)/i,/^(?:.)/i],conditions:{open_directive:{rules:[1],inclusive:!1},type_directive:{rules:[2,3],inclusive:!1},arg_directive:{rules:[3,4],inclusive:!1},INITIAL:{rules:[0,5,6,7,8,9,10,11,12,13,14,15,16,17],inclusive:!0}}};function h(){this.yy={}}return u.lexer=l,h.prototype=u,u.Parser=h,new h}();e.parser=r,e.Parser=r.Parser,e.parse=function(){return r.parse.apply(r,arguments)},e.main=function(t){t[1]||(console.log("Usage: "+t[0]+" FILE"),process.exit(1));var r=n(9143).readFileSync(n(6470).normalize(t[1]),"utf8");return e.parser.parse(r)},n.c[n.s]===t&&e.main(process.argv.slice(1))},9609:t=>{"use strict";var e=/^(%20|\s)*(javascript|data)/im,n=/[^\x20-\x7E]/gim,r=/^([^:]+):/gm,i=[".","/"];t.exports={sanitizeUrl:function(t){if(!t)return"about:blank";var a,o,s=t.replace(n,"").trim();return function(t){return i.indexOf(t[0])>-1}(s)?s:(o=s.match(r))?(a=o[0],e.test(a)?"about:blank":s):"about:blank"}}},3841:t=>{t.exports=function(t,e){return t.intersect(e)}},7458:(t,e,n)=>{"use strict";n.d(e,{default:()=>sC});var r=n(1941),i=n.n(r),a={debug:1,info:2,warn:3,error:4,fatal:5},o={debug:function(){},info:function(){},warn:function(){},error:function(){},fatal:function(){}},s=function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"fatal";isNaN(t)&&(t=t.toLowerCase(),void 0!==a[t]&&(t=a[t])),o.trace=function(){},o.debug=function(){},o.info=function(){},o.warn=function(){},o.error=function(){},o.fatal=function(){},t<=a.fatal&&(o.fatal=console.error?console.error.bind(console,c("FATAL"),"color: orange"):console.log.bind(console,"",c("FATAL"))),t<=a.error&&(o.error=console.error?console.error.bind(console,c("ERROR"),"color: orange"):console.log.bind(console,"",c("ERROR"))),t<=a.warn&&(o.warn=console.warn?console.warn.bind(console,c("WARN"),"color: orange"):console.log.bind(console,"",c("WARN"))),t<=a.info&&(o.info=console.info?console.info.bind(console,c("INFO"),"color: lightblue"):console.log.bind(console,"",c("INFO"))),t<=a.debug&&(o.debug=console.debug?console.debug.bind(console,c("DEBUG"),"color: lightgreen"):console.log.bind(console,"",c("DEBUG")))},c=function(t){var e=i()().format("ss.SSS");return"%c".concat(e," : ").concat(t," : ")};function u(t,e){let n;if(void 0===e)for(const e of t)null!=e&&(n=e)&&(n=e);else{let r=-1;for(let i of t)null!=(i=e(i,++r,t))&&(n=i)&&(n=i)}return n}function l(t,e){let n;if(void 0===e)for(const e of t)null!=e&&(n>e||void 0===n&&e>=e)&&(n=e);else{let r=-1;for(let i of t)null!=(i=e(i,++r,t))&&(n>i||void 0===n&&i>=i)&&(n=i)}return n}function h(t){return t}var f=1e-6;function d(t){return"translate("+t+",0)"}function p(t){return"translate(0,"+t+")"}function y(t){return e=>+t(e)}function g(t,e){return e=Math.max(0,t.bandwidth()-2*e)/2,t.round()&&(e=Math.round(e)),n=>+t(n)+e}function m(){return!this.__axis}function v(t,e){var n=[],r=null,i=null,a=6,o=6,s=3,c="undefined"!=typeof window&&window.devicePixelRatio>1?0:.5,u=1===t||4===t?-1:1,l=4===t||2===t?"x":"y",v=1===t||3===t?d:p;function b(d){var p=null==r?e.ticks?e.ticks.apply(e,n):e.domain():r,b=null==i?e.tickFormat?e.tickFormat.apply(e,n):h:i,_=Math.max(a,0)+s,x=e.range(),w=+x[0]+c,k=+x[x.length-1]+c,T=(e.bandwidth?g:y)(e.copy(),c),E=d.selection?d.selection():d,C=E.selectAll(".domain").data([null]),S=E.selectAll(".tick").data(p,e).order(),A=S.exit(),M=S.enter().append("g").attr("class","tick"),N=S.select("line"),D=S.select("text");C=C.merge(C.enter().insert("path",".tick").attr("class","domain").attr("stroke","currentColor")),S=S.merge(M),N=N.merge(M.append("line").attr("stroke","currentColor").attr(l+"2",u*a)),D=D.merge(M.append("text").attr("fill","currentColor").attr(l,u*_).attr("dy",1===t?"0em":3===t?"0.71em":"0.32em")),d!==E&&(C=C.transition(d),S=S.transition(d),N=N.transition(d),D=D.transition(d),A=A.transition(d).attr("opacity",f).attr("transform",(function(t){return isFinite(t=T(t))?v(t+c):this.getAttribute("transform")})),M.attr("opacity",f).attr("transform",(function(t){var e=this.parentNode.__axis;return v((e&&isFinite(e=e(t))?e:T(t))+c)}))),A.remove(),C.attr("d",4===t||2===t?o?"M"+u*o+","+w+"H"+c+"V"+k+"H"+u*o:"M"+c+","+w+"V"+k:o?"M"+w+","+u*o+"V"+c+"H"+k+"V"+u*o:"M"+w+","+c+"H"+k),S.attr("opacity",1).attr("transform",(function(t){return v(T(t)+c)})),N.attr(l+"2",u*a),D.attr(l,u*_).text(b),E.filter(m).attr("fill","none").attr("font-size",10).attr("font-family","sans-serif").attr("text-anchor",2===t?"start":4===t?"end":"middle"),E.each((function(){this.__axis=T}))}return b.scale=function(t){return arguments.length?(e=t,b):e},b.ticks=function(){return n=Array.from(arguments),b},b.tickArguments=function(t){return arguments.length?(n=null==t?[]:Array.from(t),b):n.slice()},b.tickValues=function(t){return arguments.length?(r=null==t?null:Array.from(t),b):r&&r.slice()},b.tickFormat=function(t){return arguments.length?(i=t,b):i},b.tickSize=function(t){return arguments.length?(a=o=+t,b):a},b.tickSizeInner=function(t){return arguments.length?(a=+t,b):a},b.tickSizeOuter=function(t){return arguments.length?(o=+t,b):o},b.tickPadding=function(t){return arguments.length?(s=+t,b):s},b.offset=function(t){return arguments.length?(c=+t,b):c},b}function b(){}function _(t){return null==t?b:function(){return this.querySelector(t)}}function x(t){return null==t?[]:Array.isArray(t)?t:Array.from(t)}function w(){return[]}function k(t){return null==t?w:function(){return this.querySelectorAll(t)}}function T(t){return function(){return this.matches(t)}}function E(t){return function(e){return e.matches(t)}}var C=Array.prototype.find;function S(){return this.firstElementChild}var A=Array.prototype.filter;function M(){return Array.from(this.children)}function N(t){return new Array(t.length)}function D(t,e){this.ownerDocument=t.ownerDocument,this.namespaceURI=t.namespaceURI,this._next=null,this._parent=t,this.__data__=e}function O(t){return function(){return t}}function B(t,e,n,r,i,a){for(var o,s=0,c=e.length,u=a.length;se?1:t>=e?0:NaN}D.prototype={constructor:D,appendChild:function(t){return this._parent.insertBefore(t,this._next)},insertBefore:function(t,e){return this._parent.insertBefore(t,e)},querySelector:function(t){return this._parent.querySelector(t)},querySelectorAll:function(t){return this._parent.querySelectorAll(t)}};var P="http://www.w3.org/1999/xhtml";const j={svg:"http://www.w3.org/2000/svg",xhtml:P,xlink:"http://www.w3.org/1999/xlink",xml:"http://www.w3.org/XML/1998/namespace",xmlns:"http://www.w3.org/2000/xmlns/"};function Y(t){var e=t+="",n=e.indexOf(":");return n>=0&&"xmlns"!==(e=t.slice(0,n))&&(t=t.slice(n+1)),j.hasOwnProperty(e)?{space:j[e],local:t}:t}function z(t){return function(){this.removeAttribute(t)}}function U(t){return function(){this.removeAttributeNS(t.space,t.local)}}function q(t,e){return function(){this.setAttribute(t,e)}}function $(t,e){return function(){this.setAttributeNS(t.space,t.local,e)}}function H(t,e){return function(){var n=e.apply(this,arguments);null==n?this.removeAttribute(t):this.setAttribute(t,n)}}function W(t,e){return function(){var n=e.apply(this,arguments);null==n?this.removeAttributeNS(t.space,t.local):this.setAttributeNS(t.space,t.local,n)}}function V(t){return t.ownerDocument&&t.ownerDocument.defaultView||t.document&&t||t.defaultView}function G(t){return function(){this.style.removeProperty(t)}}function X(t,e,n){return function(){this.style.setProperty(t,e,n)}}function Z(t,e,n){return function(){var r=e.apply(this,arguments);null==r?this.style.removeProperty(t):this.style.setProperty(t,r,n)}}function Q(t,e){return t.style.getPropertyValue(e)||V(t).getComputedStyle(t,null).getPropertyValue(e)}function K(t){return function(){delete this[t]}}function J(t,e){return function(){this[t]=e}}function tt(t,e){return function(){var n=e.apply(this,arguments);null==n?delete this[t]:this[t]=n}}function et(t){return t.trim().split(/^|\s+/)}function nt(t){return t.classList||new rt(t)}function rt(t){this._node=t,this._names=et(t.getAttribute("class")||"")}function it(t,e){for(var n=nt(t),r=-1,i=e.length;++r=0&&(e=t.slice(n+1),t=t.slice(0,n)),{type:t,name:e}}))}function Et(t){return function(){var e=this.__on;if(e){for(var n,r=0,i=-1,a=e.length;r=0&&(this._names.splice(e,1),this._node.setAttribute("class",this._names.join(" ")))},contains:function(t){return this._names.indexOf(t)>=0}};var Nt=[null];function Dt(t,e){this._groups=t,this._parents=e}function Ot(){return new Dt([[document.documentElement]],Nt)}Dt.prototype=Ot.prototype={constructor:Dt,select:function(t){"function"!=typeof t&&(t=_(t));for(var e=this._groups,n=e.length,r=new Array(n),i=0;i=x&&(x=_+1);!(b=g[x])&&++x=0;)(r=i[a])&&(o&&4^r.compareDocumentPosition(o)&&o.parentNode.insertBefore(r,o),o=r);return this},sort:function(t){function e(e,n){return e&&n?t(e.__data__,n.__data__):!e-!n}t||(t=F);for(var n=this._groups,r=n.length,i=new Array(r),a=0;a1?this.each((null==e?G:"function"==typeof e?Z:X)(t,e,null==n?"":n)):Q(this.node(),t)},property:function(t,e){return arguments.length>1?this.each((null==e?K:"function"==typeof e?tt:J)(t,e)):this.node()[t]},classed:function(t,e){var n=et(t+"");if(arguments.length<2){for(var r=nt(this.node()),i=-1,a=n.length;++i{}};function It(){for(var t,e=0,n=arguments.length,r={};e=0&&(n=t.slice(r+1),t=t.slice(0,r)),t&&!e.hasOwnProperty(t))throw new Error("unknown type: "+t);return{type:t,name:n}}))}function Pt(t,e){for(var n,r=0,i=t.length;r0)for(var n,r,i=new Array(n),a=0;a=0&&e._call.call(void 0,t),e=e._next;--qt}()}finally{qt=0,function(){for(var t,e,n=zt,r=1/0;n;)n._call?(r>n._time&&(r=n._time),t=n,n=n._next):(e=n._next,n._next=null,n=t?t._next=e:zt=e);Ut=t,re(r)}(),Vt=0}}function ne(){var t=Xt.now(),e=t-Wt;e>1e3&&(Gt-=e,Wt=t)}function re(t){qt||($t&&($t=clearTimeout($t)),t-Vt>24?(t<1/0&&($t=setTimeout(ee,t-Xt.now()-Gt)),Ht&&(Ht=clearInterval(Ht))):(Ht||(Wt=Xt.now(),Ht=setInterval(ne,1e3)),qt=1,Zt(ee)))}function ie(t,e,n){var r=new Jt;return e=null==e?0:+e,r.restart((n=>{r.stop(),t(n+e)}),e,n),r}Jt.prototype=te.prototype={constructor:Jt,restart:function(t,e,n){if("function"!=typeof t)throw new TypeError("callback is not a function");n=(null==n?Qt():+n)+(null==e?0:+e),this._next||Ut===this||(Ut?Ut._next=this:zt=this,Ut=this),this._call=t,this._time=n,re()},stop:function(){this._call&&(this._call=null,this._time=1/0,re())}};var ae=Yt("start","end","cancel","interrupt"),oe=[];function se(t,e,n,r,i,a){var o=t.__transition;if(o){if(n in o)return}else t.__transition={};!function(t,e,n){var r,i=t.__transition;function a(c){var u,l,h,f;if(1!==n.state)return s();for(u in i)if((f=i[u]).name===n.name){if(3===f.state)return ie(a);4===f.state?(f.state=6,f.timer.stop(),f.on.call("interrupt",t,t.__data__,f.index,f.group),delete i[u]):+u0)throw new Error("too late; already scheduled");return n}function ue(t,e){var n=le(t,e);if(n.state>3)throw new Error("too late; already running");return n}function le(t,e){var n=t.__transition;if(!n||!(n=n[e]))throw new Error("transition not found");return n}function he(t,e){return t=+t,e=+e,function(n){return t*(1-n)+e*n}}var fe,de=180/Math.PI,pe={translateX:0,translateY:0,rotate:0,skewX:0,scaleX:1,scaleY:1};function ye(t,e,n,r,i,a){var o,s,c;return(o=Math.sqrt(t*t+e*e))&&(t/=o,e/=o),(c=t*n+e*r)&&(n-=t*c,r-=e*c),(s=Math.sqrt(n*n+r*r))&&(n/=s,r/=s,c/=s),t*r180?e+=360:e-t>180&&(t+=360),a.push({i:n.push(i(n)+"rotate(",null,r)-2,x:he(t,e)})):e&&n.push(i(n)+"rotate("+e+r)}(a.rotate,o.rotate,s,c),function(t,e,n,a){t!==e?a.push({i:n.push(i(n)+"skewX(",null,r)-2,x:he(t,e)}):e&&n.push(i(n)+"skewX("+e+r)}(a.skewX,o.skewX,s,c),function(t,e,n,r,a,o){if(t!==n||e!==r){var s=a.push(i(a)+"scale(",null,",",null,")");o.push({i:s-4,x:he(t,n)},{i:s-2,x:he(e,r)})}else 1===n&&1===r||a.push(i(a)+"scale("+n+","+r+")")}(a.scaleX,a.scaleY,o.scaleX,o.scaleY,s,c),a=o=null,function(t){for(var e,n=-1,r=c.length;++n>8&15|e>>4&240,e>>4&15|240&e,(15&e)<<4|15&e,1):8===n?Ue(e>>24&255,e>>16&255,e>>8&255,(255&e)/255):4===n?Ue(e>>12&15|e>>8&240,e>>8&15|e>>4&240,e>>4&15|240&e,((15&e)<<4|15&e)/255):null):(e=De.exec(t))?new He(e[1],e[2],e[3],1):(e=Oe.exec(t))?new He(255*e[1]/100,255*e[2]/100,255*e[3]/100,1):(e=Be.exec(t))?Ue(e[1],e[2],e[3],e[4]):(e=Le.exec(t))?Ue(255*e[1]/100,255*e[2]/100,255*e[3]/100,e[4]):(e=Ie.exec(t))?Xe(e[1],e[2]/100,e[3]/100,1):(e=Re.exec(t))?Xe(e[1],e[2]/100,e[3]/100,e[4]):Fe.hasOwnProperty(t)?ze(Fe[t]):"transparent"===t?new He(NaN,NaN,NaN,0):null}function ze(t){return new He(t>>16&255,t>>8&255,255&t,1)}function Ue(t,e,n,r){return r<=0&&(t=e=n=NaN),new He(t,e,n,r)}function qe(t){return t instanceof Te||(t=Ye(t)),t?new He((t=t.rgb()).r,t.g,t.b,t.opacity):new He}function $e(t,e,n,r){return 1===arguments.length?qe(t):new He(t,e,n,null==r?1:r)}function He(t,e,n,r){this.r=+t,this.g=+e,this.b=+n,this.opacity=+r}function We(){return"#"+Ge(this.r)+Ge(this.g)+Ge(this.b)}function Ve(){var t=this.opacity;return(1===(t=isNaN(t)?1:Math.max(0,Math.min(1,t)))?"rgb(":"rgba(")+Math.max(0,Math.min(255,Math.round(this.r)||0))+", "+Math.max(0,Math.min(255,Math.round(this.g)||0))+", "+Math.max(0,Math.min(255,Math.round(this.b)||0))+(1===t?")":", "+t+")")}function Ge(t){return((t=Math.max(0,Math.min(255,Math.round(t)||0)))<16?"0":"")+t.toString(16)}function Xe(t,e,n,r){return r<=0?t=e=n=NaN:n<=0||n>=1?t=e=NaN:e<=0&&(t=NaN),new Qe(t,e,n,r)}function Ze(t){if(t instanceof Qe)return new Qe(t.h,t.s,t.l,t.opacity);if(t instanceof Te||(t=Ye(t)),!t)return new Qe;if(t instanceof Qe)return t;var e=(t=t.rgb()).r/255,n=t.g/255,r=t.b/255,i=Math.min(e,n,r),a=Math.max(e,n,r),o=NaN,s=a-i,c=(a+i)/2;return s?(o=e===a?(n-r)/s+6*(n0&&c<1?0:o,new Qe(o,s,c,t.opacity)}function Qe(t,e,n,r){this.h=+t,this.s=+e,this.l=+n,this.opacity=+r}function Ke(t,e,n){return 255*(t<60?e+(n-e)*t/60:t<180?n:t<240?e+(n-e)*(240-t)/60:e)}function Je(t,e,n,r,i){var a=t*t,o=a*t;return((1-3*t+3*a-o)*e+(4-6*a+3*o)*n+(1+3*t+3*a-3*o)*r+o*i)/6}we(Te,Ye,{copy:function(t){return Object.assign(new this.constructor,this,t)},displayable:function(){return this.rgb().displayable()},hex:Pe,formatHex:Pe,formatHsl:function(){return Ze(this).formatHsl()},formatRgb:je,toString:je}),we(He,$e,ke(Te,{brighter:function(t){return t=null==t?Ce:Math.pow(Ce,t),new He(this.r*t,this.g*t,this.b*t,this.opacity)},darker:function(t){return t=null==t?Ee:Math.pow(Ee,t),new He(this.r*t,this.g*t,this.b*t,this.opacity)},rgb:function(){return this},displayable:function(){return-.5<=this.r&&this.r<255.5&&-.5<=this.g&&this.g<255.5&&-.5<=this.b&&this.b<255.5&&0<=this.opacity&&this.opacity<=1},hex:We,formatHex:We,formatRgb:Ve,toString:Ve})),we(Qe,(function(t,e,n,r){return 1===arguments.length?Ze(t):new Qe(t,e,n,null==r?1:r)}),ke(Te,{brighter:function(t){return t=null==t?Ce:Math.pow(Ce,t),new Qe(this.h,this.s,this.l*t,this.opacity)},darker:function(t){return t=null==t?Ee:Math.pow(Ee,t),new Qe(this.h,this.s,this.l*t,this.opacity)},rgb:function(){var t=this.h%360+360*(this.h<0),e=isNaN(t)||isNaN(this.s)?0:this.s,n=this.l,r=n+(n<.5?n:1-n)*e,i=2*n-r;return new He(Ke(t>=240?t-240:t+120,i,r),Ke(t,i,r),Ke(t<120?t+240:t-120,i,r),this.opacity)},displayable:function(){return(0<=this.s&&this.s<=1||isNaN(this.s))&&0<=this.l&&this.l<=1&&0<=this.opacity&&this.opacity<=1},formatHsl:function(){var t=this.opacity;return(1===(t=isNaN(t)?1:Math.max(0,Math.min(1,t)))?"hsl(":"hsla(")+(this.h||0)+", "+100*(this.s||0)+"%, "+100*(this.l||0)+"%"+(1===t?")":", "+t+")")}}));const tn=t=>()=>t;function en(t,e){var n=e-t;return n?function(t,e){return function(n){return t+n*e}}(t,n):tn(isNaN(t)?e:t)}const nn=function t(e){var n=function(t){return 1==(t=+t)?en:function(e,n){return n-e?function(t,e,n){return t=Math.pow(t,n),e=Math.pow(e,n)-t,n=1/n,function(r){return Math.pow(t+r*e,n)}}(e,n,t):tn(isNaN(e)?n:e)}}(e);function r(t,e){var r=n((t=$e(t)).r,(e=$e(e)).r),i=n(t.g,e.g),a=n(t.b,e.b),o=en(t.opacity,e.opacity);return function(e){return t.r=r(e),t.g=i(e),t.b=a(e),t.opacity=o(e),t+""}}return r.gamma=t,r}(1);function rn(t){return function(e){var n,r,i=e.length,a=new Array(i),o=new Array(i),s=new Array(i);for(n=0;n=1?(n=1,e-1):Math.floor(n*e),i=t[r],a=t[r+1],o=r>0?t[r-1]:2*i-a,s=ra&&(i=e.slice(a,i),s[o]?s[o]+=i:s[++o]=i),(n=n[0])===(r=r[0])?s[o]?s[o]+=r:s[++o]=r:(s[++o]=null,c.push({i:o,x:he(n,r)})),a=on.lastIndex;return a=0&&(t=t.slice(0,e)),!t||"start"===t}))}(e)?ce:ue;return function(){var o=a(this,t),s=o.on;s!==r&&(i=(r=s).copy()).on(e,n),o.on=i}}var En=Bt.prototype.constructor;function Cn(t){return function(){this.style.removeProperty(t)}}function Sn(t,e,n){return function(r){this.style.setProperty(t,e.call(this,r),n)}}function An(t,e,n){var r,i;function a(){var a=e.apply(this,arguments);return a!==i&&(r=(i=a)&&Sn(t,a,n)),r}return a._value=e,a}function Mn(t){return function(e){this.textContent=t.call(this,e)}}function Nn(t){var e,n;function r(){var r=t.apply(this,arguments);return r!==n&&(e=(n=r)&&Mn(r)),e}return r._value=t,r}var Dn=0;function On(t,e,n,r){this._groups=t,this._parents=e,this._name=n,this._id=r}function Bn(){return++Dn}var Ln=Bt.prototype;On.prototype=function(t){return Bt().transition(t)}.prototype={constructor:On,select:function(t){var e=this._name,n=this._id;"function"!=typeof t&&(t=_(t));for(var r=this._groups,i=r.length,a=new Array(i),o=0;o2&&n.state<5,n.state=6,n.timer.stop(),n.on.call(r?"interrupt":"cancel",t,t.__data__,n.index,n.group),delete a[i]):o=!1;o&&delete t.__transition}}(this,t)}))},Bt.prototype.transition=function(t){var e,n;t instanceof On?(e=t._id,t=t._name):(e=Bn(),(n=In).time=Qt(),t=null==t?null:t+"");for(var r=this._groups,i=r.length,a=0;a>8&15|e>>4&240,e>>4&15|240&e,(15&e)<<4|15&e,1):8===n?sr(e>>24&255,e>>16&255,e>>8&255,(255&e)/255):4===n?sr(e>>12&15|e>>8&240,e>>8&15|e>>4&240,e>>4&15|240&e,((15&e)<<4|15&e)/255):null):(e=Zn.exec(t))?new lr(e[1],e[2],e[3],1):(e=Qn.exec(t))?new lr(255*e[1]/100,255*e[2]/100,255*e[3]/100,1):(e=Kn.exec(t))?sr(e[1],e[2],e[3],e[4]):(e=Jn.exec(t))?sr(255*e[1]/100,255*e[2]/100,255*e[3]/100,e[4]):(e=tr.exec(t))?pr(e[1],e[2]/100,e[3]/100,1):(e=er.exec(t))?pr(e[1],e[2]/100,e[3]/100,e[4]):nr.hasOwnProperty(t)?or(nr[t]):"transparent"===t?new lr(NaN,NaN,NaN,0):null}function or(t){return new lr(t>>16&255,t>>8&255,255&t,1)}function sr(t,e,n,r){return r<=0&&(t=e=n=NaN),new lr(t,e,n,r)}function cr(t){return t instanceof qn||(t=ar(t)),t?new lr((t=t.rgb()).r,t.g,t.b,t.opacity):new lr}function ur(t,e,n,r){return 1===arguments.length?cr(t):new lr(t,e,n,null==r?1:r)}function lr(t,e,n,r){this.r=+t,this.g=+e,this.b=+n,this.opacity=+r}function hr(){return"#"+dr(this.r)+dr(this.g)+dr(this.b)}function fr(){var t=this.opacity;return(1===(t=isNaN(t)?1:Math.max(0,Math.min(1,t)))?"rgb(":"rgba(")+Math.max(0,Math.min(255,Math.round(this.r)||0))+", "+Math.max(0,Math.min(255,Math.round(this.g)||0))+", "+Math.max(0,Math.min(255,Math.round(this.b)||0))+(1===t?")":", "+t+")")}function dr(t){return((t=Math.max(0,Math.min(255,Math.round(t)||0)))<16?"0":"")+t.toString(16)}function pr(t,e,n,r){return r<=0?t=e=n=NaN:n<=0||n>=1?t=e=NaN:e<=0&&(t=NaN),new gr(t,e,n,r)}function yr(t){if(t instanceof gr)return new gr(t.h,t.s,t.l,t.opacity);if(t instanceof qn||(t=ar(t)),!t)return new gr;if(t instanceof gr)return t;var e=(t=t.rgb()).r/255,n=t.g/255,r=t.b/255,i=Math.min(e,n,r),a=Math.max(e,n,r),o=NaN,s=a-i,c=(a+i)/2;return s?(o=e===a?(n-r)/s+6*(n0&&c<1?0:o,new gr(o,s,c,t.opacity)}function gr(t,e,n,r){this.h=+t,this.s=+e,this.l=+n,this.opacity=+r}function mr(t,e,n){return 255*(t<60?e+(n-e)*t/60:t<180?n:t<240?e+(n-e)*(240-t)/60:e)}zn(qn,ar,{copy:function(t){return Object.assign(new this.constructor,this,t)},displayable:function(){return this.rgb().displayable()},hex:rr,formatHex:rr,formatHsl:function(){return yr(this).formatHsl()},formatRgb:ir,toString:ir}),zn(lr,ur,Un(qn,{brighter:function(t){return t=null==t?Hn:Math.pow(Hn,t),new lr(this.r*t,this.g*t,this.b*t,this.opacity)},darker:function(t){return t=null==t?$n:Math.pow($n,t),new lr(this.r*t,this.g*t,this.b*t,this.opacity)},rgb:function(){return this},displayable:function(){return-.5<=this.r&&this.r<255.5&&-.5<=this.g&&this.g<255.5&&-.5<=this.b&&this.b<255.5&&0<=this.opacity&&this.opacity<=1},hex:hr,formatHex:hr,formatRgb:fr,toString:fr})),zn(gr,(function(t,e,n,r){return 1===arguments.length?yr(t):new gr(t,e,n,null==r?1:r)}),Un(qn,{brighter:function(t){return t=null==t?Hn:Math.pow(Hn,t),new gr(this.h,this.s,this.l*t,this.opacity)},darker:function(t){return t=null==t?$n:Math.pow($n,t),new gr(this.h,this.s,this.l*t,this.opacity)},rgb:function(){var t=this.h%360+360*(this.h<0),e=isNaN(t)||isNaN(this.s)?0:this.s,n=this.l,r=n+(n<.5?n:1-n)*e,i=2*n-r;return new lr(mr(t>=240?t-240:t+120,i,r),mr(t,i,r),mr(t<120?t+240:t-120,i,r),this.opacity)},displayable:function(){return(0<=this.s&&this.s<=1||isNaN(this.s))&&0<=this.l&&this.l<=1&&0<=this.opacity&&this.opacity<=1},formatHsl:function(){var t=this.opacity;return(1===(t=isNaN(t)?1:Math.max(0,Math.min(1,t)))?"hsl(":"hsla(")+(this.h||0)+", "+100*(this.s||0)+"%, "+100*(this.l||0)+"%"+(1===t?")":", "+t+")")}}));const vr=Math.PI/180,br=180/Math.PI,_r=.96422,xr=.82521,wr=4/29,kr=6/29,Tr=3*kr*kr;function Er(t){if(t instanceof Cr)return new Cr(t.l,t.a,t.b,t.opacity);if(t instanceof Br)return Lr(t);t instanceof lr||(t=cr(t));var e,n,r=Nr(t.r),i=Nr(t.g),a=Nr(t.b),o=Sr((.2225045*r+.7168786*i+.0606169*a)/1);return r===i&&i===a?e=n=o:(e=Sr((.4360747*r+.3850649*i+.1430804*a)/_r),n=Sr((.0139322*r+.0971045*i+.7141733*a)/xr)),new Cr(116*o-16,500*(e-o),200*(o-n),t.opacity)}function Cr(t,e,n,r){this.l=+t,this.a=+e,this.b=+n,this.opacity=+r}function Sr(t){return t>.008856451679035631?Math.pow(t,1/3):t/Tr+wr}function Ar(t){return t>kr?t*t*t:Tr*(t-wr)}function Mr(t){return 255*(t<=.0031308?12.92*t:1.055*Math.pow(t,1/2.4)-.055)}function Nr(t){return(t/=255)<=.04045?t/12.92:Math.pow((t+.055)/1.055,2.4)}function Dr(t){if(t instanceof Br)return new Br(t.h,t.c,t.l,t.opacity);if(t instanceof Cr||(t=Er(t)),0===t.a&&0===t.b)return new Br(NaN,0()=>t;function Rr(t,e){return function(n){return t+n*e}}function Fr(t,e){var n=e-t;return n?Rr(t,n):Ir(isNaN(t)?e:t)}function Pr(t){return function(e,n){var r=t((e=Or(e)).h,(n=Or(n)).h),i=Fr(e.c,n.c),a=Fr(e.l,n.l),o=Fr(e.opacity,n.opacity);return function(t){return e.h=r(t),e.c=i(t),e.l=a(t),e.opacity=o(t),e+""}}}const jr=Pr((function(t,e){var n=e-t;return n?Rr(t,n>180||n<-180?n-360*Math.round(n/360):n):Ir(isNaN(t)?e:t)}));Pr(Fr);var Yr=Math.sqrt(50),zr=Math.sqrt(10),Ur=Math.sqrt(2);function qr(t,e,n){var r=(e-t)/Math.max(0,n),i=Math.floor(Math.log(r)/Math.LN10),a=r/Math.pow(10,i);return i>=0?(a>=Yr?10:a>=zr?5:a>=Ur?2:1)*Math.pow(10,i):-Math.pow(10,-i)/(a>=Yr?10:a>=zr?5:a>=Ur?2:1)}function $r(t,e,n){var r=Math.abs(e-t)/Math.max(0,n),i=Math.pow(10,Math.floor(Math.log(r)/Math.LN10)),a=r/i;return a>=Yr?i*=10:a>=zr?i*=5:a>=Ur&&(i*=2),ee?1:t>=e?0:NaN}function Wr(t){let e=t,n=t;function r(t,e,r,i){for(null==r&&(r=0),null==i&&(i=t.length);r>>1;n(t[a],e)<0?r=a+1:i=a}return r}return 1===t.length&&(e=(e,n)=>t(e)-n,n=function(t){return(e,n)=>Hr(t(e),n)}(t)),{left:r,center:function(t,n,i,a){null==i&&(i=0),null==a&&(a=t.length);const o=r(t,n,i,a-1);return o>i&&e(t[o-1],n)>-e(t[o],n)?o-1:o},right:function(t,e,r,i){for(null==r&&(r=0),null==i&&(i=t.length);r>>1;n(t[a],e)>0?i=a:r=a+1}return r}}}const Vr=Wr(Hr),Gr=Vr.right,Xr=(Vr.left,Wr((function(t){return null===t?NaN:+t})).center,Gr);function Zr(t,e,n){t.prototype=e.prototype=n,n.constructor=t}function Qr(t,e){var n=Object.create(t.prototype);for(var r in e)n[r]=e[r];return n}function Kr(){}var Jr=.7,ti=1.4285714285714286,ei="\\s*([+-]?\\d+)\\s*",ni="\\s*([+-]?\\d*\\.?\\d+(?:[eE][+-]?\\d+)?)\\s*",ri="\\s*([+-]?\\d*\\.?\\d+(?:[eE][+-]?\\d+)?)%\\s*",ii=/^#([0-9a-f]{3,8})$/,ai=new RegExp("^rgb\\("+[ei,ei,ei]+"\\)$"),oi=new RegExp("^rgb\\("+[ri,ri,ri]+"\\)$"),si=new RegExp("^rgba\\("+[ei,ei,ei,ni]+"\\)$"),ci=new RegExp("^rgba\\("+[ri,ri,ri,ni]+"\\)$"),ui=new RegExp("^hsl\\("+[ni,ri,ri]+"\\)$"),li=new RegExp("^hsla\\("+[ni,ri,ri,ni]+"\\)$"),hi={aliceblue:15792383,antiquewhite:16444375,aqua:65535,aquamarine:8388564,azure:15794175,beige:16119260,bisque:16770244,black:0,blanchedalmond:16772045,blue:255,blueviolet:9055202,brown:10824234,burlywood:14596231,cadetblue:6266528,chartreuse:8388352,chocolate:13789470,coral:16744272,cornflowerblue:6591981,cornsilk:16775388,crimson:14423100,cyan:65535,darkblue:139,darkcyan:35723,darkgoldenrod:12092939,darkgray:11119017,darkgreen:25600,darkgrey:11119017,darkkhaki:12433259,darkmagenta:9109643,darkolivegreen:5597999,darkorange:16747520,darkorchid:10040012,darkred:9109504,darksalmon:15308410,darkseagreen:9419919,darkslateblue:4734347,darkslategray:3100495,darkslategrey:3100495,darkturquoise:52945,darkviolet:9699539,deeppink:16716947,deepskyblue:49151,dimgray:6908265,dimgrey:6908265,dodgerblue:2003199,firebrick:11674146,floralwhite:16775920,forestgreen:2263842,fuchsia:16711935,gainsboro:14474460,ghostwhite:16316671,gold:16766720,goldenrod:14329120,gray:8421504,green:32768,greenyellow:11403055,grey:8421504,honeydew:15794160,hotpink:16738740,indianred:13458524,indigo:4915330,ivory:16777200,khaki:15787660,lavender:15132410,lavenderblush:16773365,lawngreen:8190976,lemonchiffon:16775885,lightblue:11393254,lightcoral:15761536,lightcyan:14745599,lightgoldenrodyellow:16448210,lightgray:13882323,lightgreen:9498256,lightgrey:13882323,lightpink:16758465,lightsalmon:16752762,lightseagreen:2142890,lightskyblue:8900346,lightslategray:7833753,lightslategrey:7833753,lightsteelblue:11584734,lightyellow:16777184,lime:65280,limegreen:3329330,linen:16445670,magenta:16711935,maroon:8388608,mediumaquamarine:6737322,mediumblue:205,mediumorchid:12211667,mediumpurple:9662683,mediumseagreen:3978097,mediumslateblue:8087790,mediumspringgreen:64154,mediumturquoise:4772300,mediumvioletred:13047173,midnightblue:1644912,mintcream:16121850,mistyrose:16770273,moccasin:16770229,navajowhite:16768685,navy:128,oldlace:16643558,olive:8421376,olivedrab:7048739,orange:16753920,orangered:16729344,orchid:14315734,palegoldenrod:15657130,palegreen:10025880,paleturquoise:11529966,palevioletred:14381203,papayawhip:16773077,peachpuff:16767673,peru:13468991,pink:16761035,plum:14524637,powderblue:11591910,purple:8388736,rebeccapurple:6697881,red:16711680,rosybrown:12357519,royalblue:4286945,saddlebrown:9127187,salmon:16416882,sandybrown:16032864,seagreen:3050327,seashell:16774638,sienna:10506797,silver:12632256,skyblue:8900331,slateblue:6970061,slategray:7372944,slategrey:7372944,snow:16775930,springgreen:65407,steelblue:4620980,tan:13808780,teal:32896,thistle:14204888,tomato:16737095,turquoise:4251856,violet:15631086,wheat:16113331,white:16777215,whitesmoke:16119285,yellow:16776960,yellowgreen:10145074};function fi(){return this.rgb().formatHex()}function di(){return this.rgb().formatRgb()}function pi(t){var e,n;return t=(t+"").trim().toLowerCase(),(e=ii.exec(t))?(n=e[1].length,e=parseInt(e[1],16),6===n?yi(e):3===n?new bi(e>>8&15|e>>4&240,e>>4&15|240&e,(15&e)<<4|15&e,1):8===n?gi(e>>24&255,e>>16&255,e>>8&255,(255&e)/255):4===n?gi(e>>12&15|e>>8&240,e>>8&15|e>>4&240,e>>4&15|240&e,((15&e)<<4|15&e)/255):null):(e=ai.exec(t))?new bi(e[1],e[2],e[3],1):(e=oi.exec(t))?new bi(255*e[1]/100,255*e[2]/100,255*e[3]/100,1):(e=si.exec(t))?gi(e[1],e[2],e[3],e[4]):(e=ci.exec(t))?gi(255*e[1]/100,255*e[2]/100,255*e[3]/100,e[4]):(e=ui.exec(t))?ki(e[1],e[2]/100,e[3]/100,1):(e=li.exec(t))?ki(e[1],e[2]/100,e[3]/100,e[4]):hi.hasOwnProperty(t)?yi(hi[t]):"transparent"===t?new bi(NaN,NaN,NaN,0):null}function yi(t){return new bi(t>>16&255,t>>8&255,255&t,1)}function gi(t,e,n,r){return r<=0&&(t=e=n=NaN),new bi(t,e,n,r)}function mi(t){return t instanceof Kr||(t=pi(t)),t?new bi((t=t.rgb()).r,t.g,t.b,t.opacity):new bi}function vi(t,e,n,r){return 1===arguments.length?mi(t):new bi(t,e,n,null==r?1:r)}function bi(t,e,n,r){this.r=+t,this.g=+e,this.b=+n,this.opacity=+r}function _i(){return"#"+wi(this.r)+wi(this.g)+wi(this.b)}function xi(){var t=this.opacity;return(1===(t=isNaN(t)?1:Math.max(0,Math.min(1,t)))?"rgb(":"rgba(")+Math.max(0,Math.min(255,Math.round(this.r)||0))+", "+Math.max(0,Math.min(255,Math.round(this.g)||0))+", "+Math.max(0,Math.min(255,Math.round(this.b)||0))+(1===t?")":", "+t+")")}function wi(t){return((t=Math.max(0,Math.min(255,Math.round(t)||0)))<16?"0":"")+t.toString(16)}function ki(t,e,n,r){return r<=0?t=e=n=NaN:n<=0||n>=1?t=e=NaN:e<=0&&(t=NaN),new Ei(t,e,n,r)}function Ti(t){if(t instanceof Ei)return new Ei(t.h,t.s,t.l,t.opacity);if(t instanceof Kr||(t=pi(t)),!t)return new Ei;if(t instanceof Ei)return t;var e=(t=t.rgb()).r/255,n=t.g/255,r=t.b/255,i=Math.min(e,n,r),a=Math.max(e,n,r),o=NaN,s=a-i,c=(a+i)/2;return s?(o=e===a?(n-r)/s+6*(n0&&c<1?0:o,new Ei(o,s,c,t.opacity)}function Ei(t,e,n,r){this.h=+t,this.s=+e,this.l=+n,this.opacity=+r}function Ci(t,e,n){return 255*(t<60?e+(n-e)*t/60:t<180?n:t<240?e+(n-e)*(240-t)/60:e)}function Si(t,e,n,r,i){var a=t*t,o=a*t;return((1-3*t+3*a-o)*e+(4-6*a+3*o)*n+(1+3*t+3*a-3*o)*r+o*i)/6}Zr(Kr,pi,{copy:function(t){return Object.assign(new this.constructor,this,t)},displayable:function(){return this.rgb().displayable()},hex:fi,formatHex:fi,formatHsl:function(){return Ti(this).formatHsl()},formatRgb:di,toString:di}),Zr(bi,vi,Qr(Kr,{brighter:function(t){return t=null==t?ti:Math.pow(ti,t),new bi(this.r*t,this.g*t,this.b*t,this.opacity)},darker:function(t){return t=null==t?Jr:Math.pow(Jr,t),new bi(this.r*t,this.g*t,this.b*t,this.opacity)},rgb:function(){return this},displayable:function(){return-.5<=this.r&&this.r<255.5&&-.5<=this.g&&this.g<255.5&&-.5<=this.b&&this.b<255.5&&0<=this.opacity&&this.opacity<=1},hex:_i,formatHex:_i,formatRgb:xi,toString:xi})),Zr(Ei,(function(t,e,n,r){return 1===arguments.length?Ti(t):new Ei(t,e,n,null==r?1:r)}),Qr(Kr,{brighter:function(t){return t=null==t?ti:Math.pow(ti,t),new Ei(this.h,this.s,this.l*t,this.opacity)},darker:function(t){return t=null==t?Jr:Math.pow(Jr,t),new Ei(this.h,this.s,this.l*t,this.opacity)},rgb:function(){var t=this.h%360+360*(this.h<0),e=isNaN(t)||isNaN(this.s)?0:this.s,n=this.l,r=n+(n<.5?n:1-n)*e,i=2*n-r;return new bi(Ci(t>=240?t-240:t+120,i,r),Ci(t,i,r),Ci(t<120?t+240:t-120,i,r),this.opacity)},displayable:function(){return(0<=this.s&&this.s<=1||isNaN(this.s))&&0<=this.l&&this.l<=1&&0<=this.opacity&&this.opacity<=1},formatHsl:function(){var t=this.opacity;return(1===(t=isNaN(t)?1:Math.max(0,Math.min(1,t)))?"hsl(":"hsla(")+(this.h||0)+", "+100*(this.s||0)+"%, "+100*(this.l||0)+"%"+(1===t?")":", "+t+")")}}));const Ai=t=>()=>t;function Mi(t,e){var n=e-t;return n?function(t,e){return function(n){return t+n*e}}(t,n):Ai(isNaN(t)?e:t)}const Ni=function t(e){var n=function(t){return 1==(t=+t)?Mi:function(e,n){return n-e?function(t,e,n){return t=Math.pow(t,n),e=Math.pow(e,n)-t,n=1/n,function(r){return Math.pow(t+r*e,n)}}(e,n,t):Ai(isNaN(e)?n:e)}}(e);function r(t,e){var r=n((t=vi(t)).r,(e=vi(e)).r),i=n(t.g,e.g),a=n(t.b,e.b),o=Mi(t.opacity,e.opacity);return function(e){return t.r=r(e),t.g=i(e),t.b=a(e),t.opacity=o(e),t+""}}return r.gamma=t,r}(1);function Di(t){return function(e){var n,r,i=e.length,a=new Array(i),o=new Array(i),s=new Array(i);for(n=0;n=1?(n=1,e-1):Math.floor(n*e),i=t[r],a=t[r+1],o=r>0?t[r-1]:2*i-a,s=ra&&(i=e.slice(a,i),s[o]?s[o]+=i:s[++o]=i),(n=n[0])===(r=r[0])?s[o]?s[o]+=r:s[++o]=r:(s[++o]=null,c.push({i:o,x:Li(n,r)})),a=Fi.lastIndex;return ae&&(n=t,t=e,e=n),u=function(n){return Math.max(t,Math.min(e,n))}),r=c>2?Vi:Wi,i=a=null,h}function h(e){return null==e||isNaN(e=+e)?n:(i||(i=r(o.map(t),s,c)))(t(u(e)))}return h.invert=function(n){return u(e((a||(a=r(s,o.map(t),Li)))(n)))},h.domain=function(t){return arguments.length?(o=Array.from(t,Ui),l()):o.slice()},h.range=function(t){return arguments.length?(s=Array.from(t),l()):s.slice()},h.rangeRound=function(t){return s=Array.from(t),c=zi,l()},h.clamp=function(t){return arguments.length?(u=!!t||$i,l()):u!==$i},h.interpolate=function(t){return arguments.length?(c=t,l()):c},h.unknown=function(t){return arguments.length?(n=t,h):n},function(n,r){return t=n,e=r,l()}}()($i,$i)}function Zi(t,e){switch(arguments.length){case 0:break;case 1:this.range(t);break;default:this.range(e).domain(t)}return this}var Qi,Ki=/^(?:(.)?([<>=^]))?([+\-( ])?([$#])?(0)?(\d+)?(,)?(\.\d+)?(~)?([a-z%])?$/i;function Ji(t){if(!(e=Ki.exec(t)))throw new Error("invalid format: "+t);var e;return new ta({fill:e[1],align:e[2],sign:e[3],symbol:e[4],zero:e[5],width:e[6],comma:e[7],precision:e[8]&&e[8].slice(1),trim:e[9],type:e[10]})}function ta(t){this.fill=void 0===t.fill?" ":t.fill+"",this.align=void 0===t.align?">":t.align+"",this.sign=void 0===t.sign?"-":t.sign+"",this.symbol=void 0===t.symbol?"":t.symbol+"",this.zero=!!t.zero,this.width=void 0===t.width?void 0:+t.width,this.comma=!!t.comma,this.precision=void 0===t.precision?void 0:+t.precision,this.trim=!!t.trim,this.type=void 0===t.type?"":t.type+""}function ea(t,e){if((n=(t=e?t.toExponential(e-1):t.toExponential()).indexOf("e"))<0)return null;var n,r=t.slice(0,n);return[r.length>1?r[0]+r.slice(2):r,+t.slice(n+1)]}function na(t){return(t=ea(Math.abs(t)))?t[1]:NaN}function ra(t,e){var n=ea(t,e);if(!n)return t+"";var r=n[0],i=n[1];return i<0?"0."+new Array(-i).join("0")+r:r.length>i+1?r.slice(0,i+1)+"."+r.slice(i+1):r+new Array(i-r.length+2).join("0")}Ji.prototype=ta.prototype,ta.prototype.toString=function(){return this.fill+this.align+this.sign+this.symbol+(this.zero?"0":"")+(void 0===this.width?"":Math.max(1,0|this.width))+(this.comma?",":"")+(void 0===this.precision?"":"."+Math.max(0,0|this.precision))+(this.trim?"~":"")+this.type};const ia={"%":(t,e)=>(100*t).toFixed(e),b:t=>Math.round(t).toString(2),c:t=>t+"",d:function(t){return Math.abs(t=Math.round(t))>=1e21?t.toLocaleString("en").replace(/,/g,""):t.toString(10)},e:(t,e)=>t.toExponential(e),f:(t,e)=>t.toFixed(e),g:(t,e)=>t.toPrecision(e),o:t=>Math.round(t).toString(8),p:(t,e)=>ra(100*t,e),r:ra,s:function(t,e){var n=ea(t,e);if(!n)return t+"";var r=n[0],i=n[1],a=i-(Qi=3*Math.max(-8,Math.min(8,Math.floor(i/3))))+1,o=r.length;return a===o?r:a>o?r+new Array(a-o+1).join("0"):a>0?r.slice(0,a)+"."+r.slice(a):"0."+new Array(1-a).join("0")+ea(t,Math.max(0,e+a-1))[0]},X:t=>Math.round(t).toString(16).toUpperCase(),x:t=>Math.round(t).toString(16)};function aa(t){return t}var oa,sa,ca,ua=Array.prototype.map,la=["y","z","a","f","p","n","µ","m","","k","M","G","T","P","E","Z","Y"];function ha(t){var e=t.domain;return t.ticks=function(t){var n=e();return function(t,e,n){var r,i,a,o,s=-1;if(n=+n,(t=+t)==(e=+e)&&n>0)return[t];if((r=e0){let n=Math.round(t/o),r=Math.round(e/o);for(n*oe&&--r,a=new Array(i=r-n+1);++se&&--r,a=new Array(i=r-n+1);++s0;){if((i=qr(c,u,n))===r)return a[o]=c,a[s]=u,e(a);if(i>0)c=Math.floor(c/i)*i,u=Math.ceil(u/i)*i;else{if(!(i<0))break;c=Math.ceil(c*i)/i,u=Math.floor(u*i)/i}r=i}return t},t}function fa(){var t=Xi();return t.copy=function(){return Gi(t,fa())},Zi.apply(t,arguments),ha(t)}oa=function(t){var e,n,r=void 0===t.grouping||void 0===t.thousands?aa:(e=ua.call(t.grouping,Number),n=t.thousands+"",function(t,r){for(var i=t.length,a=[],o=0,s=e[0],c=0;i>0&&s>0&&(c+s+1>r&&(s=Math.max(1,r-c)),a.push(t.substring(i-=s,i+s)),!((c+=s+1)>r));)s=e[o=(o+1)%e.length];return a.reverse().join(n)}),i=void 0===t.currency?"":t.currency[0]+"",a=void 0===t.currency?"":t.currency[1]+"",o=void 0===t.decimal?".":t.decimal+"",s=void 0===t.numerals?aa:function(t){return function(e){return e.replace(/[0-9]/g,(function(e){return t[+e]}))}}(ua.call(t.numerals,String)),c=void 0===t.percent?"%":t.percent+"",u=void 0===t.minus?"−":t.minus+"",l=void 0===t.nan?"NaN":t.nan+"";function h(t){var e=(t=Ji(t)).fill,n=t.align,h=t.sign,f=t.symbol,d=t.zero,p=t.width,y=t.comma,g=t.precision,m=t.trim,v=t.type;"n"===v?(y=!0,v="g"):ia[v]||(void 0===g&&(g=12),m=!0,v="g"),(d||"0"===e&&"="===n)&&(d=!0,e="0",n="=");var b="$"===f?i:"#"===f&&/[boxX]/.test(v)?"0"+v.toLowerCase():"",_="$"===f?a:/[%p]/.test(v)?c:"",x=ia[v],w=/[defgprs%]/.test(v);function k(t){var i,a,c,f=b,k=_;if("c"===v)k=x(t)+k,t="";else{var T=(t=+t)<0||1/t<0;if(t=isNaN(t)?l:x(Math.abs(t),g),m&&(t=function(t){t:for(var e,n=t.length,r=1,i=-1;r0&&(i=0)}return i>0?t.slice(0,i)+t.slice(e+1):t}(t)),T&&0==+t&&"+"!==h&&(T=!1),f=(T?"("===h?h:u:"-"===h||"("===h?"":h)+f,k=("s"===v?la[8+Qi/3]:"")+k+(T&&"("===h?")":""),w)for(i=-1,a=t.length;++i(c=t.charCodeAt(i))||c>57){k=(46===c?o+t.slice(i+1):t.slice(i))+k,t=t.slice(0,i);break}}y&&!d&&(t=r(t,1/0));var E=f.length+t.length+k.length,C=E>1)+f+t+k+C.slice(E);break;default:t=C+f+t+k}return s(t)}return g=void 0===g?6:/[gprs]/.test(v)?Math.max(1,Math.min(21,g)):Math.max(0,Math.min(20,g)),k.toString=function(){return t+""},k}return{format:h,formatPrefix:function(t,e){var n=h(((t=Ji(t)).type="f",t)),r=3*Math.max(-8,Math.min(8,Math.floor(na(e)/3))),i=Math.pow(10,-r),a=la[8+r/3];return function(t){return n(i*t)+a}}}}({thousands:",",grouping:[3],currency:["$",""]}),sa=oa.format,ca=oa.formatPrefix;class da extends Map{constructor(t,e=ya){if(super(),Object.defineProperties(this,{_intern:{value:new Map},_key:{value:e}}),null!=t)for(const[e,n]of t)this.set(e,n)}get(t){return super.get(pa(this,t))}has(t){return super.has(pa(this,t))}set(t,e){return super.set(function({_intern:t,_key:e},n){const r=e(n);return t.has(r)?t.get(r):(t.set(r,n),n)}(this,t),e)}delete(t){return super.delete(function({_intern:t,_key:e},n){const r=e(n);return t.has(r)&&(n=t.get(n),t.delete(r)),n}(this,t))}}function pa({_intern:t,_key:e},n){const r=e(n);return t.has(r)?t.get(r):n}function ya(t){return null!==t&&"object"==typeof t?t.valueOf():t}Set;const ga=Symbol("implicit");function ma(){var t=new da,e=[],n=[],r=ga;function i(i){let a=t.get(i);if(void 0===a){if(r!==ga)return r;t.set(i,a=e.push(i)-1)}return n[a%n.length]}return i.domain=function(n){if(!arguments.length)return e.slice();e=[],t=new da;for(const r of n)t.has(r)||t.set(r,e.push(r)-1);return i},i.range=function(t){return arguments.length?(n=Array.from(t),i):n.slice()},i.unknown=function(t){return arguments.length?(r=t,i):r},i.copy=function(){return ma(e,n).unknown(r)},Zi.apply(i,arguments),i}const va=1e3,ba=6e4,_a=36e5,xa=864e5,wa=6048e5,ka=31536e6;var Ta=new Date,Ea=new Date;function Ca(t,e,n,r){function i(e){return t(e=0===arguments.length?new Date:new Date(+e)),e}return i.floor=function(e){return t(e=new Date(+e)),e},i.ceil=function(n){return t(n=new Date(n-1)),e(n,1),t(n),n},i.round=function(t){var e=i(t),n=i.ceil(t);return t-e0))return s;do{s.push(o=new Date(+n)),e(n,a),t(n)}while(o=e)for(;t(e),!n(e);)e.setTime(e-1)}),(function(t,r){if(t>=t)if(r<0)for(;++r<=0;)for(;e(t,-1),!n(t););else for(;--r>=0;)for(;e(t,1),!n(t););}))},n&&(i.count=function(e,r){return Ta.setTime(+e),Ea.setTime(+r),t(Ta),t(Ea),Math.floor(n(Ta,Ea))},i.every=function(t){return t=Math.floor(t),isFinite(t)&&t>0?t>1?i.filter(r?function(e){return r(e)%t==0}:function(e){return i.count(0,e)%t==0}):i:null}),i}var Sa=Ca((function(){}),(function(t,e){t.setTime(+t+e)}),(function(t,e){return e-t}));Sa.every=function(t){return t=Math.floor(t),isFinite(t)&&t>0?t>1?Ca((function(e){e.setTime(Math.floor(e/t)*t)}),(function(e,n){e.setTime(+e+n*t)}),(function(e,n){return(n-e)/t})):Sa:null};const Aa=Sa;Sa.range;var Ma=Ca((function(t){t.setTime(t-t.getMilliseconds())}),(function(t,e){t.setTime(+t+e*va)}),(function(t,e){return(e-t)/va}),(function(t){return t.getUTCSeconds()}));const Na=Ma;Ma.range;var Da=Ca((function(t){t.setTime(t-t.getMilliseconds()-t.getSeconds()*va)}),(function(t,e){t.setTime(+t+e*ba)}),(function(t,e){return(e-t)/ba}),(function(t){return t.getMinutes()}));const Oa=Da;Da.range;var Ba=Ca((function(t){t.setTime(t-t.getMilliseconds()-t.getSeconds()*va-t.getMinutes()*ba)}),(function(t,e){t.setTime(+t+e*_a)}),(function(t,e){return(e-t)/_a}),(function(t){return t.getHours()}));const La=Ba;Ba.range;var Ia=Ca((t=>t.setHours(0,0,0,0)),((t,e)=>t.setDate(t.getDate()+e)),((t,e)=>(e-t-(e.getTimezoneOffset()-t.getTimezoneOffset())*ba)/xa),(t=>t.getDate()-1));const Ra=Ia;function Fa(t){return Ca((function(e){e.setDate(e.getDate()-(e.getDay()+7-t)%7),e.setHours(0,0,0,0)}),(function(t,e){t.setDate(t.getDate()+7*e)}),(function(t,e){return(e-t-(e.getTimezoneOffset()-t.getTimezoneOffset())*ba)/wa}))}Ia.range;var Pa=Fa(0),ja=Fa(1),Ya=Fa(2),za=Fa(3),Ua=Fa(4),qa=Fa(5),$a=Fa(6),Ha=(Pa.range,ja.range,Ya.range,za.range,Ua.range,qa.range,$a.range,Ca((function(t){t.setDate(1),t.setHours(0,0,0,0)}),(function(t,e){t.setMonth(t.getMonth()+e)}),(function(t,e){return e.getMonth()-t.getMonth()+12*(e.getFullYear()-t.getFullYear())}),(function(t){return t.getMonth()})));const Wa=Ha;Ha.range;var Va=Ca((function(t){t.setMonth(0,1),t.setHours(0,0,0,0)}),(function(t,e){t.setFullYear(t.getFullYear()+e)}),(function(t,e){return e.getFullYear()-t.getFullYear()}),(function(t){return t.getFullYear()}));Va.every=function(t){return isFinite(t=Math.floor(t))&&t>0?Ca((function(e){e.setFullYear(Math.floor(e.getFullYear()/t)*t),e.setMonth(0,1),e.setHours(0,0,0,0)}),(function(e,n){e.setFullYear(e.getFullYear()+n*t)})):null};const Ga=Va;Va.range;var Xa=Ca((function(t){t.setUTCSeconds(0,0)}),(function(t,e){t.setTime(+t+e*ba)}),(function(t,e){return(e-t)/ba}),(function(t){return t.getUTCMinutes()}));const Za=Xa;Xa.range;var Qa=Ca((function(t){t.setUTCMinutes(0,0,0)}),(function(t,e){t.setTime(+t+e*_a)}),(function(t,e){return(e-t)/_a}),(function(t){return t.getUTCHours()}));const Ka=Qa;Qa.range;var Ja=Ca((function(t){t.setUTCHours(0,0,0,0)}),(function(t,e){t.setUTCDate(t.getUTCDate()+e)}),(function(t,e){return(e-t)/xa}),(function(t){return t.getUTCDate()-1}));const to=Ja;function eo(t){return Ca((function(e){e.setUTCDate(e.getUTCDate()-(e.getUTCDay()+7-t)%7),e.setUTCHours(0,0,0,0)}),(function(t,e){t.setUTCDate(t.getUTCDate()+7*e)}),(function(t,e){return(e-t)/wa}))}Ja.range;var no=eo(0),ro=eo(1),io=eo(2),ao=eo(3),oo=eo(4),so=eo(5),co=eo(6),uo=(no.range,ro.range,io.range,ao.range,oo.range,so.range,co.range,Ca((function(t){t.setUTCDate(1),t.setUTCHours(0,0,0,0)}),(function(t,e){t.setUTCMonth(t.getUTCMonth()+e)}),(function(t,e){return e.getUTCMonth()-t.getUTCMonth()+12*(e.getUTCFullYear()-t.getUTCFullYear())}),(function(t){return t.getUTCMonth()})));const lo=uo;uo.range;var ho=Ca((function(t){t.setUTCMonth(0,1),t.setUTCHours(0,0,0,0)}),(function(t,e){t.setUTCFullYear(t.getUTCFullYear()+e)}),(function(t,e){return e.getUTCFullYear()-t.getUTCFullYear()}),(function(t){return t.getUTCFullYear()}));ho.every=function(t){return isFinite(t=Math.floor(t))&&t>0?Ca((function(e){e.setUTCFullYear(Math.floor(e.getUTCFullYear()/t)*t),e.setUTCMonth(0,1),e.setUTCHours(0,0,0,0)}),(function(e,n){e.setUTCFullYear(e.getUTCFullYear()+n*t)})):null};const fo=ho;function po(t,e,n,r,i,a){const o=[[Na,1,va],[Na,5,5e3],[Na,15,15e3],[Na,30,3e4],[a,1,ba],[a,5,3e5],[a,15,9e5],[a,30,18e5],[i,1,_a],[i,3,108e5],[i,6,216e5],[i,12,432e5],[r,1,xa],[r,2,1728e5],[n,1,wa],[e,1,2592e6],[e,3,7776e6],[t,1,ka]];function s(e,n,r){const i=Math.abs(n-e)/r,a=Wr((([,,t])=>t)).right(o,i);if(a===o.length)return t.every($r(e/ka,n/ka,r));if(0===a)return Aa.every(Math.max($r(e,n,r),1));const[s,c]=o[i/o[a-1][2][t.toLowerCase(),e])))}function Oo(t,e,n){var r=Eo.exec(e.slice(n,n+1));return r?(t.w=+r[0],n+r[0].length):-1}function Bo(t,e,n){var r=Eo.exec(e.slice(n,n+1));return r?(t.u=+r[0],n+r[0].length):-1}function Lo(t,e,n){var r=Eo.exec(e.slice(n,n+2));return r?(t.U=+r[0],n+r[0].length):-1}function Io(t,e,n){var r=Eo.exec(e.slice(n,n+2));return r?(t.V=+r[0],n+r[0].length):-1}function Ro(t,e,n){var r=Eo.exec(e.slice(n,n+2));return r?(t.W=+r[0],n+r[0].length):-1}function Fo(t,e,n){var r=Eo.exec(e.slice(n,n+4));return r?(t.y=+r[0],n+r[0].length):-1}function Po(t,e,n){var r=Eo.exec(e.slice(n,n+2));return r?(t.y=+r[0]+(+r[0]>68?1900:2e3),n+r[0].length):-1}function jo(t,e,n){var r=/^(Z)|([+-]\d\d)(?::?(\d\d))?/.exec(e.slice(n,n+6));return r?(t.Z=r[1]?0:-(r[2]+(r[3]||"00")),n+r[0].length):-1}function Yo(t,e,n){var r=Eo.exec(e.slice(n,n+1));return r?(t.q=3*r[0]-3,n+r[0].length):-1}function zo(t,e,n){var r=Eo.exec(e.slice(n,n+2));return r?(t.m=r[0]-1,n+r[0].length):-1}function Uo(t,e,n){var r=Eo.exec(e.slice(n,n+2));return r?(t.d=+r[0],n+r[0].length):-1}function qo(t,e,n){var r=Eo.exec(e.slice(n,n+3));return r?(t.m=0,t.d=+r[0],n+r[0].length):-1}function $o(t,e,n){var r=Eo.exec(e.slice(n,n+2));return r?(t.H=+r[0],n+r[0].length):-1}function Ho(t,e,n){var r=Eo.exec(e.slice(n,n+2));return r?(t.M=+r[0],n+r[0].length):-1}function Wo(t,e,n){var r=Eo.exec(e.slice(n,n+2));return r?(t.S=+r[0],n+r[0].length):-1}function Vo(t,e,n){var r=Eo.exec(e.slice(n,n+3));return r?(t.L=+r[0],n+r[0].length):-1}function Go(t,e,n){var r=Eo.exec(e.slice(n,n+6));return r?(t.L=Math.floor(r[0]/1e3),n+r[0].length):-1}function Xo(t,e,n){var r=Co.exec(e.slice(n,n+1));return r?n+r[0].length:-1}function Zo(t,e,n){var r=Eo.exec(e.slice(n));return r?(t.Q=+r[0],n+r[0].length):-1}function Qo(t,e,n){var r=Eo.exec(e.slice(n));return r?(t.s=+r[0],n+r[0].length):-1}function Ko(t,e){return Ao(t.getDate(),e,2)}function Jo(t,e){return Ao(t.getHours(),e,2)}function ts(t,e){return Ao(t.getHours()%12||12,e,2)}function es(t,e){return Ao(1+Ra.count(Ga(t),t),e,3)}function ns(t,e){return Ao(t.getMilliseconds(),e,3)}function rs(t,e){return ns(t,e)+"000"}function is(t,e){return Ao(t.getMonth()+1,e,2)}function as(t,e){return Ao(t.getMinutes(),e,2)}function os(t,e){return Ao(t.getSeconds(),e,2)}function ss(t){var e=t.getDay();return 0===e?7:e}function cs(t,e){return Ao(Pa.count(Ga(t)-1,t),e,2)}function us(t){var e=t.getDay();return e>=4||0===e?Ua(t):Ua.ceil(t)}function ls(t,e){return t=us(t),Ao(Ua.count(Ga(t),t)+(4===Ga(t).getDay()),e,2)}function hs(t){return t.getDay()}function fs(t,e){return Ao(ja.count(Ga(t)-1,t),e,2)}function ds(t,e){return Ao(t.getFullYear()%100,e,2)}function ps(t,e){return Ao((t=us(t)).getFullYear()%100,e,2)}function ys(t,e){return Ao(t.getFullYear()%1e4,e,4)}function gs(t,e){var n=t.getDay();return Ao((t=n>=4||0===n?Ua(t):Ua.ceil(t)).getFullYear()%1e4,e,4)}function ms(t){var e=t.getTimezoneOffset();return(e>0?"-":(e*=-1,"+"))+Ao(e/60|0,"0",2)+Ao(e%60,"0",2)}function vs(t,e){return Ao(t.getUTCDate(),e,2)}function bs(t,e){return Ao(t.getUTCHours(),e,2)}function _s(t,e){return Ao(t.getUTCHours()%12||12,e,2)}function xs(t,e){return Ao(1+to.count(fo(t),t),e,3)}function ws(t,e){return Ao(t.getUTCMilliseconds(),e,3)}function ks(t,e){return ws(t,e)+"000"}function Ts(t,e){return Ao(t.getUTCMonth()+1,e,2)}function Es(t,e){return Ao(t.getUTCMinutes(),e,2)}function Cs(t,e){return Ao(t.getUTCSeconds(),e,2)}function Ss(t){var e=t.getUTCDay();return 0===e?7:e}function As(t,e){return Ao(no.count(fo(t)-1,t),e,2)}function Ms(t){var e=t.getUTCDay();return e>=4||0===e?oo(t):oo.ceil(t)}function Ns(t,e){return t=Ms(t),Ao(oo.count(fo(t),t)+(4===fo(t).getUTCDay()),e,2)}function Ds(t){return t.getUTCDay()}function Os(t,e){return Ao(ro.count(fo(t)-1,t),e,2)}function Bs(t,e){return Ao(t.getUTCFullYear()%100,e,2)}function Ls(t,e){return Ao((t=Ms(t)).getUTCFullYear()%100,e,2)}function Is(t,e){return Ao(t.getUTCFullYear()%1e4,e,4)}function Rs(t,e){var n=t.getUTCDay();return Ao((t=n>=4||0===n?oo(t):oo.ceil(t)).getUTCFullYear()%1e4,e,4)}function Fs(){return"+0000"}function Ps(){return"%"}function js(t){return+t}function Ys(t){return Math.floor(+t/1e3)}function zs(t){return new Date(t)}function Us(t){return t instanceof Date?+t:+new Date(+t)}function qs(t,e,n,r,i,a,o,s,c,u){var l=Xi(),h=l.invert,f=l.domain,d=u(".%L"),p=u(":%S"),y=u("%I:%M"),g=u("%I %p"),m=u("%a %d"),v=u("%b %d"),b=u("%B"),_=u("%Y");function x(t){return(c(t)=12)]},q:function(t){return 1+~~(t.getMonth()/3)},Q:js,s:Ys,S:os,u:ss,U:cs,V:ls,w:hs,W:fs,x:null,X:null,y:ds,Y:ys,Z:ms,"%":Ps},_={a:function(t){return o[t.getUTCDay()]},A:function(t){return a[t.getUTCDay()]},b:function(t){return c[t.getUTCMonth()]},B:function(t){return s[t.getUTCMonth()]},c:null,d:vs,e:vs,f:ks,g:Ls,G:Rs,H:bs,I:_s,j:xs,L:ws,m:Ts,M:Es,p:function(t){return i[+(t.getUTCHours()>=12)]},q:function(t){return 1+~~(t.getUTCMonth()/3)},Q:js,s:Ys,S:Cs,u:Ss,U:As,V:Ns,w:Ds,W:Os,x:null,X:null,y:Bs,Y:Is,Z:Fs,"%":Ps},x={a:function(t,e,n){var r=d.exec(e.slice(n));return r?(t.w=p.get(r[0].toLowerCase()),n+r[0].length):-1},A:function(t,e,n){var r=h.exec(e.slice(n));return r?(t.w=f.get(r[0].toLowerCase()),n+r[0].length):-1},b:function(t,e,n){var r=m.exec(e.slice(n));return r?(t.m=v.get(r[0].toLowerCase()),n+r[0].length):-1},B:function(t,e,n){var r=y.exec(e.slice(n));return r?(t.m=g.get(r[0].toLowerCase()),n+r[0].length):-1},c:function(t,n,r){return T(t,e,n,r)},d:Uo,e:Uo,f:Go,g:Po,G:Fo,H:$o,I:$o,j:qo,L:Vo,m:zo,M:Ho,p:function(t,e,n){var r=u.exec(e.slice(n));return r?(t.p=l.get(r[0].toLowerCase()),n+r[0].length):-1},q:Yo,Q:Zo,s:Qo,S:Wo,u:Bo,U:Lo,V:Io,w:Oo,W:Ro,x:function(t,e,r){return T(t,n,e,r)},X:function(t,e,n){return T(t,r,e,n)},y:Po,Y:Fo,Z:jo,"%":Xo};function w(t,e){return function(n){var r,i,a,o=[],s=-1,c=0,u=t.length;for(n instanceof Date||(n=new Date(+n));++s53)return null;"w"in a||(a.w=1),"Z"in a?(i=(r=_o(xo(a.y,0,1))).getUTCDay(),r=i>4||0===i?ro.ceil(r):ro(r),r=to.offset(r,7*(a.V-1)),a.y=r.getUTCFullYear(),a.m=r.getUTCMonth(),a.d=r.getUTCDate()+(a.w+6)%7):(i=(r=bo(xo(a.y,0,1))).getDay(),r=i>4||0===i?ja.ceil(r):ja(r),r=Ra.offset(r,7*(a.V-1)),a.y=r.getFullYear(),a.m=r.getMonth(),a.d=r.getDate()+(a.w+6)%7)}else("W"in a||"U"in a)&&("w"in a||(a.w="u"in a?a.u%7:"W"in a?1:0),i="Z"in a?_o(xo(a.y,0,1)).getUTCDay():bo(xo(a.y,0,1)).getDay(),a.m=0,a.d="W"in a?(a.w+6)%7+7*a.W-(i+5)%7:a.w+7*a.U-(i+6)%7);return"Z"in a?(a.H+=a.Z/100|0,a.M+=a.Z%100,_o(a)):bo(a)}}function T(t,e,n,r){for(var i,a,o=0,s=e.length,c=n.length;o=c)return-1;if(37===(i=e.charCodeAt(o++))){if(i=e.charAt(o++),!(a=x[i in To?e.charAt(o++):i])||(r=a(t,n,r))<0)return-1}else if(i!=n.charCodeAt(r++))return-1}return r}return b.x=w(n,b),b.X=w(r,b),b.c=w(e,b),_.x=w(n,_),_.X=w(r,_),_.c=w(e,_),{format:function(t){var e=w(t+="",b);return e.toString=function(){return t},e},parse:function(t){var e=k(t+="",!1);return e.toString=function(){return t},e},utcFormat:function(t){var e=w(t+="",_);return e.toString=function(){return t},e},utcParse:function(t){var e=k(t+="",!0);return e.toString=function(){return t},e}}}({dateTime:"%x, %X",date:"%-m/%-d/%Y",time:"%-I:%M:%S %p",periods:["AM","PM"],days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],shortDays:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],months:["January","February","March","April","May","June","July","August","September","October","November","December"],shortMonths:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"]}),ko=wo.format,wo.parse,wo.utcFormat,wo.utcParse;var Qs=Array.prototype.find;function Ks(){return this.firstElementChild}var Js=Array.prototype.filter;function tc(){return Array.from(this.children)}function ec(t){return new Array(t.length)}function nc(t,e){this.ownerDocument=t.ownerDocument,this.namespaceURI=t.namespaceURI,this._next=null,this._parent=t,this.__data__=e}function rc(t){return function(){return t}}function ic(t,e,n,r,i,a){for(var o,s=0,c=e.length,u=a.length;se?1:t>=e?0:NaN}nc.prototype={constructor:nc,appendChild:function(t){return this._parent.insertBefore(t,this._next)},insertBefore:function(t,e){return this._parent.insertBefore(t,e)},querySelector:function(t){return this._parent.querySelector(t)},querySelectorAll:function(t){return this._parent.querySelectorAll(t)}};var uc="http://www.w3.org/1999/xhtml";const lc={svg:"http://www.w3.org/2000/svg",xhtml:uc,xlink:"http://www.w3.org/1999/xlink",xml:"http://www.w3.org/XML/1998/namespace",xmlns:"http://www.w3.org/2000/xmlns/"};function hc(t){var e=t+="",n=e.indexOf(":");return n>=0&&"xmlns"!==(e=t.slice(0,n))&&(t=t.slice(n+1)),lc.hasOwnProperty(e)?{space:lc[e],local:t}:t}function fc(t){return function(){this.removeAttribute(t)}}function dc(t){return function(){this.removeAttributeNS(t.space,t.local)}}function pc(t,e){return function(){this.setAttribute(t,e)}}function yc(t,e){return function(){this.setAttributeNS(t.space,t.local,e)}}function gc(t,e){return function(){var n=e.apply(this,arguments);null==n?this.removeAttribute(t):this.setAttribute(t,n)}}function mc(t,e){return function(){var n=e.apply(this,arguments);null==n?this.removeAttributeNS(t.space,t.local):this.setAttributeNS(t.space,t.local,n)}}function vc(t){return t.ownerDocument&&t.ownerDocument.defaultView||t.document&&t||t.defaultView}function bc(t){return function(){this.style.removeProperty(t)}}function _c(t,e,n){return function(){this.style.setProperty(t,e,n)}}function xc(t,e,n){return function(){var r=e.apply(this,arguments);null==r?this.style.removeProperty(t):this.style.setProperty(t,r,n)}}function wc(t,e){return t.style.getPropertyValue(e)||vc(t).getComputedStyle(t,null).getPropertyValue(e)}function kc(t){return function(){delete this[t]}}function Tc(t,e){return function(){this[t]=e}}function Ec(t,e){return function(){var n=e.apply(this,arguments);null==n?delete this[t]:this[t]=n}}function Cc(t){return t.trim().split(/^|\s+/)}function Sc(t){return t.classList||new Ac(t)}function Ac(t){this._node=t,this._names=Cc(t.getAttribute("class")||"")}function Mc(t,e){for(var n=Sc(t),r=-1,i=e.length;++r=0&&(e=t.slice(n+1),t=t.slice(0,n)),{type:t,name:e}}))}function Zc(t){return function(){var e=this.__on;if(e){for(var n,r=0,i=-1,a=e.length;r=0&&(this._names.splice(e,1),this._node.setAttribute("class",this._names.join(" ")))},contains:function(t){return this._names.indexOf(t)>=0}};var eu=[null];function nu(t,e){this._groups=t,this._parents=e}function ru(){return new nu([[document.documentElement]],eu)}nu.prototype=ru.prototype={constructor:nu,select:function(t){"function"!=typeof t&&(t=Hs(t));for(var e=this._groups,n=e.length,r=new Array(n),i=0;i=x&&(x=_+1);!(b=g[x])&&++x=0;)(r=i[a])&&(o&&4^r.compareDocumentPosition(o)&&o.parentNode.insertBefore(r,o),o=r);return this},sort:function(t){function e(e,n){return e&&n?t(e.__data__,n.__data__):!e-!n}t||(t=cc);for(var n=this._groups,r=n.length,i=new Array(r),a=0;a1?this.each((null==e?bc:"function"==typeof e?xc:_c)(t,e,null==n?"":n)):wc(this.node(),t)},property:function(t,e){return arguments.length>1?this.each((null==e?kc:"function"==typeof e?Ec:Tc)(t,e)):this.node()[t]},classed:function(t,e){var n=Cc(t+"");if(arguments.length<2){for(var r=Sc(this.node()),i=-1,a=n.length;++iuu)if(Math.abs(l*s-c*u)>uu&&i){var f=n-a,d=r-o,p=s*s+c*c,y=f*f+d*d,g=Math.sqrt(p),m=Math.sqrt(h),v=i*Math.tan((su-Math.acos((p+h-y)/(2*g*m)))/2),b=v/m,_=v/g;Math.abs(b-1)>uu&&(this._+="L"+(t+b*u)+","+(e+b*l)),this._+="A"+i+","+i+",0,0,"+ +(l*f>u*d)+","+(this._x1=t+_*s)+","+(this._y1=e+_*c)}else this._+="L"+(this._x1=t)+","+(this._y1=e)},arc:function(t,e,n,r,i,a){t=+t,e=+e,a=!!a;var o=(n=+n)*Math.cos(r),s=n*Math.sin(r),c=t+o,u=e+s,l=1^a,h=a?r-i:i-r;if(n<0)throw new Error("negative radius: "+n);null===this._x1?this._+="M"+c+","+u:(Math.abs(this._x1-c)>uu||Math.abs(this._y1-u)>uu)&&(this._+="L"+c+","+u),n&&(h<0&&(h=h%cu+cu),h>lu?this._+="A"+n+","+n+",0,1,"+l+","+(t-o)+","+(e-s)+"A"+n+","+n+",0,1,"+l+","+(this._x1=c)+","+(this._y1=u):h>uu&&(this._+="A"+n+","+n+",0,"+ +(h>=su)+","+l+","+(this._x1=t+n*Math.cos(i))+","+(this._y1=e+n*Math.sin(i))))},rect:function(t,e,n,r){this._+="M"+(this._x0=this._x1=+t)+","+(this._y0=this._y1=+e)+"h"+ +n+"v"+ +r+"h"+-n+"Z"},toString:function(){return this._}};const du=fu;function pu(t){return function(){return t}}var yu=Math.abs,gu=Math.atan2,mu=Math.cos,vu=Math.max,bu=Math.min,_u=Math.sin,xu=Math.sqrt,wu=1e-12,ku=Math.PI,Tu=ku/2,Eu=2*ku;function Cu(t){return t>1?0:t<-1?ku:Math.acos(t)}function Su(t){return t>=1?Tu:t<=-1?-Tu:Math.asin(t)}function Au(t){return t.innerRadius}function Mu(t){return t.outerRadius}function Nu(t){return t.startAngle}function Du(t){return t.endAngle}function Ou(t){return t&&t.padAngle}function Bu(t,e,n,r,i,a,o,s){var c=n-t,u=r-e,l=o-i,h=s-a,f=h*c-l*u;if(!(f*fN*N+D*D&&(T=C,E=S),{cx:T,cy:E,x01:-l,y01:-h,x11:T*(i/x-1),y11:E*(i/x-1)}}function Iu(){var t=Au,e=Mu,n=pu(0),r=null,i=Nu,a=Du,o=Ou,s=null;function c(){var c,u,l=+t.apply(this,arguments),h=+e.apply(this,arguments),f=i.apply(this,arguments)-Tu,d=a.apply(this,arguments)-Tu,p=yu(d-f),y=d>f;if(s||(s=c=du()),hwu)if(p>Eu-wu)s.moveTo(h*mu(f),h*_u(f)),s.arc(0,0,h,f,d,!y),l>wu&&(s.moveTo(l*mu(d),l*_u(d)),s.arc(0,0,l,d,f,y));else{var g,m,v=f,b=d,_=f,x=d,w=p,k=p,T=o.apply(this,arguments)/2,E=T>wu&&(r?+r.apply(this,arguments):xu(l*l+h*h)),C=bu(yu(h-l)/2,+n.apply(this,arguments)),S=C,A=C;if(E>wu){var M=Su(E/l*_u(T)),N=Su(E/h*_u(T));(w-=2*M)>wu?(_+=M*=y?1:-1,x-=M):(w=0,_=x=(f+d)/2),(k-=2*N)>wu?(v+=N*=y?1:-1,b-=N):(k=0,v=b=(f+d)/2)}var D=h*mu(v),O=h*_u(v),B=l*mu(x),L=l*_u(x);if(C>wu){var I,R=h*mu(b),F=h*_u(b),P=l*mu(_),j=l*_u(_);if(pwu?A>wu?(g=Lu(P,j,D,O,h,A,y),m=Lu(R,F,B,L,h,A,y),s.moveTo(g.cx+g.x01,g.cy+g.y01),Awu&&w>wu?S>wu?(g=Lu(B,L,R,F,l,-S,y),m=Lu(D,O,P,j,l,-S,y),s.lineTo(g.cx+g.x01,g.cy+g.y01),St?1:e>=t?0:NaN}function qu(t){return t}function $u(){}function Hu(t,e,n){t._context.bezierCurveTo((2*t._x0+t._x1)/3,(2*t._y0+t._y1)/3,(t._x0+2*t._x1)/3,(t._y0+2*t._y1)/3,(t._x0+4*t._x1+e)/6,(t._y0+4*t._y1+n)/6)}function Wu(t){this._context=t}function Vu(t){return new Wu(t)}function Gu(t){this._context=t}function Xu(t){this._context=t}function Zu(t){this._context=t}function Qu(t){return t<0?-1:1}function Ku(t,e,n){var r=t._x1-t._x0,i=e-t._x1,a=(t._y1-t._y0)/(r||i<0&&-0),o=(n-t._y1)/(i||r<0&&-0),s=(a*i+o*r)/(r+i);return(Qu(a)+Qu(o))*Math.min(Math.abs(a),Math.abs(o),.5*Math.abs(s))||0}function Ju(t,e){var n=t._x1-t._x0;return n?(3*(t._y1-t._y0)/n-e)/2:e}function tl(t,e,n){var r=t._x0,i=t._y0,a=t._x1,o=t._y1,s=(a-r)/3;t._context.bezierCurveTo(r+s,i+s*e,a-s,o-s*n,a,o)}function el(t){this._context=t}function nl(t){this._context=new rl(t)}function rl(t){this._context=t}function il(t){this._context=t}function al(t){var e,n,r=t.length-1,i=new Array(r),a=new Array(r),o=new Array(r);for(i[0]=0,a[0]=2,o[0]=t[0]+2*t[1],e=1;e=0;--e)i[e]=(o[e]-i[e+1])/a[e];for(a[r-1]=(t[r]+i[r-1])/2,e=0;e=0&&(this._t=1-this._t,this._line=1-this._line)},point:function(t,e){switch(t=+t,e=+e,this._point){case 0:this._point=1,this._line?this._context.lineTo(t,e):this._context.moveTo(t,e);break;case 1:this._point=2;default:if(this._t<=0)this._context.lineTo(this._x,e),this._context.lineTo(t,e);else{var n=this._x*(1-this._t)+t*this._t;this._context.lineTo(n,this._y),this._context.lineTo(n,e)}}this._x=t,this._y=e}};var sl=new Date,cl=new Date;function ul(t,e,n,r){function i(e){return t(e=0===arguments.length?new Date:new Date(+e)),e}return i.floor=function(e){return t(e=new Date(+e)),e},i.ceil=function(n){return t(n=new Date(n-1)),e(n,1),t(n),n},i.round=function(t){var e=i(t),n=i.ceil(t);return t-e0))return s;do{s.push(o=new Date(+n)),e(n,a),t(n)}while(o=e)for(;t(e),!n(e);)e.setTime(e-1)}),(function(t,r){if(t>=t)if(r<0)for(;++r<=0;)for(;e(t,-1),!n(t););else for(;--r>=0;)for(;e(t,1),!n(t););}))},n&&(i.count=function(e,r){return sl.setTime(+e),cl.setTime(+r),t(sl),t(cl),Math.floor(n(sl,cl))},i.every=function(t){return t=Math.floor(t),isFinite(t)&&t>0?t>1?i.filter(r?function(e){return r(e)%t==0}:function(e){return i.count(0,e)%t==0}):i:null}),i}const ll=864e5,hl=6048e5;function fl(t){return ul((function(e){e.setUTCDate(e.getUTCDate()-(e.getUTCDay()+7-t)%7),e.setUTCHours(0,0,0,0)}),(function(t,e){t.setUTCDate(t.getUTCDate()+7*e)}),(function(t,e){return(e-t)/hl}))}var dl=fl(0),pl=fl(1),yl=fl(2),gl=fl(3),ml=fl(4),vl=fl(5),bl=fl(6),_l=(dl.range,pl.range,yl.range,gl.range,ml.range,vl.range,bl.range,ul((function(t){t.setUTCHours(0,0,0,0)}),(function(t,e){t.setUTCDate(t.getUTCDate()+e)}),(function(t,e){return(e-t)/ll}),(function(t){return t.getUTCDate()-1})));const xl=_l;function wl(t){return ul((function(e){e.setDate(e.getDate()-(e.getDay()+7-t)%7),e.setHours(0,0,0,0)}),(function(t,e){t.setDate(t.getDate()+7*e)}),(function(t,e){return(e-t-6e4*(e.getTimezoneOffset()-t.getTimezoneOffset()))/hl}))}_l.range;var kl=wl(0),Tl=wl(1),El=wl(2),Cl=wl(3),Sl=wl(4),Al=wl(5),Ml=wl(6),Nl=(kl.range,Tl.range,El.range,Cl.range,Sl.range,Al.range,Ml.range,ul((t=>t.setHours(0,0,0,0)),((t,e)=>t.setDate(t.getDate()+e)),((t,e)=>(e-t-6e4*(e.getTimezoneOffset()-t.getTimezoneOffset()))/ll),(t=>t.getDate()-1)));const Dl=Nl;Nl.range;var Ol=ul((function(t){t.setMonth(0,1),t.setHours(0,0,0,0)}),(function(t,e){t.setFullYear(t.getFullYear()+e)}),(function(t,e){return e.getFullYear()-t.getFullYear()}),(function(t){return t.getFullYear()}));Ol.every=function(t){return isFinite(t=Math.floor(t))&&t>0?ul((function(e){e.setFullYear(Math.floor(e.getFullYear()/t)*t),e.setMonth(0,1),e.setHours(0,0,0,0)}),(function(e,n){e.setFullYear(e.getFullYear()+n*t)})):null};const Bl=Ol;Ol.range;var Ll=ul((function(t){t.setUTCMonth(0,1),t.setUTCHours(0,0,0,0)}),(function(t,e){t.setUTCFullYear(t.getUTCFullYear()+e)}),(function(t,e){return e.getUTCFullYear()-t.getUTCFullYear()}),(function(t){return t.getUTCFullYear()}));Ll.every=function(t){return isFinite(t=Math.floor(t))&&t>0?ul((function(e){e.setUTCFullYear(Math.floor(e.getUTCFullYear()/t)*t),e.setUTCMonth(0,1),e.setUTCHours(0,0,0,0)}),(function(e,n){e.setUTCFullYear(e.getUTCFullYear()+n*t)})):null};const Il=Ll;function Rl(t){if(0<=t.y&&t.y<100){var e=new Date(-1,t.m,t.d,t.H,t.M,t.S,t.L);return e.setFullYear(t.y),e}return new Date(t.y,t.m,t.d,t.H,t.M,t.S,t.L)}function Fl(t){if(0<=t.y&&t.y<100){var e=new Date(Date.UTC(-1,t.m,t.d,t.H,t.M,t.S,t.L));return e.setUTCFullYear(t.y),e}return new Date(Date.UTC(t.y,t.m,t.d,t.H,t.M,t.S,t.L))}function Pl(t,e,n){return{y:t,m:e,d:n,H:0,M:0,S:0,L:0}}Ll.range;var jl,Yl,zl={"-":"",_:" ",0:"0"},Ul=/^\s*\d+/,ql=/^%/,$l=/[\\^$*+?|[\]().{}]/g;function Hl(t,e,n){var r=t<0?"-":"",i=(r?-t:t)+"",a=i.length;return r+(a[t.toLowerCase(),e])))}function Xl(t,e,n){var r=Ul.exec(e.slice(n,n+1));return r?(t.w=+r[0],n+r[0].length):-1}function Zl(t,e,n){var r=Ul.exec(e.slice(n,n+1));return r?(t.u=+r[0],n+r[0].length):-1}function Ql(t,e,n){var r=Ul.exec(e.slice(n,n+2));return r?(t.U=+r[0],n+r[0].length):-1}function Kl(t,e,n){var r=Ul.exec(e.slice(n,n+2));return r?(t.V=+r[0],n+r[0].length):-1}function Jl(t,e,n){var r=Ul.exec(e.slice(n,n+2));return r?(t.W=+r[0],n+r[0].length):-1}function th(t,e,n){var r=Ul.exec(e.slice(n,n+4));return r?(t.y=+r[0],n+r[0].length):-1}function eh(t,e,n){var r=Ul.exec(e.slice(n,n+2));return r?(t.y=+r[0]+(+r[0]>68?1900:2e3),n+r[0].length):-1}function nh(t,e,n){var r=/^(Z)|([+-]\d\d)(?::?(\d\d))?/.exec(e.slice(n,n+6));return r?(t.Z=r[1]?0:-(r[2]+(r[3]||"00")),n+r[0].length):-1}function rh(t,e,n){var r=Ul.exec(e.slice(n,n+1));return r?(t.q=3*r[0]-3,n+r[0].length):-1}function ih(t,e,n){var r=Ul.exec(e.slice(n,n+2));return r?(t.m=r[0]-1,n+r[0].length):-1}function ah(t,e,n){var r=Ul.exec(e.slice(n,n+2));return r?(t.d=+r[0],n+r[0].length):-1}function oh(t,e,n){var r=Ul.exec(e.slice(n,n+3));return r?(t.m=0,t.d=+r[0],n+r[0].length):-1}function sh(t,e,n){var r=Ul.exec(e.slice(n,n+2));return r?(t.H=+r[0],n+r[0].length):-1}function ch(t,e,n){var r=Ul.exec(e.slice(n,n+2));return r?(t.M=+r[0],n+r[0].length):-1}function uh(t,e,n){var r=Ul.exec(e.slice(n,n+2));return r?(t.S=+r[0],n+r[0].length):-1}function lh(t,e,n){var r=Ul.exec(e.slice(n,n+3));return r?(t.L=+r[0],n+r[0].length):-1}function hh(t,e,n){var r=Ul.exec(e.slice(n,n+6));return r?(t.L=Math.floor(r[0]/1e3),n+r[0].length):-1}function fh(t,e,n){var r=ql.exec(e.slice(n,n+1));return r?n+r[0].length:-1}function dh(t,e,n){var r=Ul.exec(e.slice(n));return r?(t.Q=+r[0],n+r[0].length):-1}function ph(t,e,n){var r=Ul.exec(e.slice(n));return r?(t.s=+r[0],n+r[0].length):-1}function yh(t,e){return Hl(t.getDate(),e,2)}function gh(t,e){return Hl(t.getHours(),e,2)}function mh(t,e){return Hl(t.getHours()%12||12,e,2)}function vh(t,e){return Hl(1+Dl.count(Bl(t),t),e,3)}function bh(t,e){return Hl(t.getMilliseconds(),e,3)}function _h(t,e){return bh(t,e)+"000"}function xh(t,e){return Hl(t.getMonth()+1,e,2)}function wh(t,e){return Hl(t.getMinutes(),e,2)}function kh(t,e){return Hl(t.getSeconds(),e,2)}function Th(t){var e=t.getDay();return 0===e?7:e}function Eh(t,e){return Hl(kl.count(Bl(t)-1,t),e,2)}function Ch(t){var e=t.getDay();return e>=4||0===e?Sl(t):Sl.ceil(t)}function Sh(t,e){return t=Ch(t),Hl(Sl.count(Bl(t),t)+(4===Bl(t).getDay()),e,2)}function Ah(t){return t.getDay()}function Mh(t,e){return Hl(Tl.count(Bl(t)-1,t),e,2)}function Nh(t,e){return Hl(t.getFullYear()%100,e,2)}function Dh(t,e){return Hl((t=Ch(t)).getFullYear()%100,e,2)}function Oh(t,e){return Hl(t.getFullYear()%1e4,e,4)}function Bh(t,e){var n=t.getDay();return Hl((t=n>=4||0===n?Sl(t):Sl.ceil(t)).getFullYear()%1e4,e,4)}function Lh(t){var e=t.getTimezoneOffset();return(e>0?"-":(e*=-1,"+"))+Hl(e/60|0,"0",2)+Hl(e%60,"0",2)}function Ih(t,e){return Hl(t.getUTCDate(),e,2)}function Rh(t,e){return Hl(t.getUTCHours(),e,2)}function Fh(t,e){return Hl(t.getUTCHours()%12||12,e,2)}function Ph(t,e){return Hl(1+xl.count(Il(t),t),e,3)}function jh(t,e){return Hl(t.getUTCMilliseconds(),e,3)}function Yh(t,e){return jh(t,e)+"000"}function zh(t,e){return Hl(t.getUTCMonth()+1,e,2)}function Uh(t,e){return Hl(t.getUTCMinutes(),e,2)}function qh(t,e){return Hl(t.getUTCSeconds(),e,2)}function $h(t){var e=t.getUTCDay();return 0===e?7:e}function Hh(t,e){return Hl(dl.count(Il(t)-1,t),e,2)}function Wh(t){var e=t.getUTCDay();return e>=4||0===e?ml(t):ml.ceil(t)}function Vh(t,e){return t=Wh(t),Hl(ml.count(Il(t),t)+(4===Il(t).getUTCDay()),e,2)}function Gh(t){return t.getUTCDay()}function Xh(t,e){return Hl(pl.count(Il(t)-1,t),e,2)}function Zh(t,e){return Hl(t.getUTCFullYear()%100,e,2)}function Qh(t,e){return Hl((t=Wh(t)).getUTCFullYear()%100,e,2)}function Kh(t,e){return Hl(t.getUTCFullYear()%1e4,e,4)}function Jh(t,e){var n=t.getUTCDay();return Hl((t=n>=4||0===n?ml(t):ml.ceil(t)).getUTCFullYear()%1e4,e,4)}function tf(){return"+0000"}function ef(){return"%"}function nf(t){return+t}function rf(t){return Math.floor(+t/1e3)}jl=function(t){var e=t.dateTime,n=t.date,r=t.time,i=t.periods,a=t.days,o=t.shortDays,s=t.months,c=t.shortMonths,u=Vl(i),l=Gl(i),h=Vl(a),f=Gl(a),d=Vl(o),p=Gl(o),y=Vl(s),g=Gl(s),m=Vl(c),v=Gl(c),b={a:function(t){return o[t.getDay()]},A:function(t){return a[t.getDay()]},b:function(t){return c[t.getMonth()]},B:function(t){return s[t.getMonth()]},c:null,d:yh,e:yh,f:_h,g:Dh,G:Bh,H:gh,I:mh,j:vh,L:bh,m:xh,M:wh,p:function(t){return i[+(t.getHours()>=12)]},q:function(t){return 1+~~(t.getMonth()/3)},Q:nf,s:rf,S:kh,u:Th,U:Eh,V:Sh,w:Ah,W:Mh,x:null,X:null,y:Nh,Y:Oh,Z:Lh,"%":ef},_={a:function(t){return o[t.getUTCDay()]},A:function(t){return a[t.getUTCDay()]},b:function(t){return c[t.getUTCMonth()]},B:function(t){return s[t.getUTCMonth()]},c:null,d:Ih,e:Ih,f:Yh,g:Qh,G:Jh,H:Rh,I:Fh,j:Ph,L:jh,m:zh,M:Uh,p:function(t){return i[+(t.getUTCHours()>=12)]},q:function(t){return 1+~~(t.getUTCMonth()/3)},Q:nf,s:rf,S:qh,u:$h,U:Hh,V:Vh,w:Gh,W:Xh,x:null,X:null,y:Zh,Y:Kh,Z:tf,"%":ef},x={a:function(t,e,n){var r=d.exec(e.slice(n));return r?(t.w=p.get(r[0].toLowerCase()),n+r[0].length):-1},A:function(t,e,n){var r=h.exec(e.slice(n));return r?(t.w=f.get(r[0].toLowerCase()),n+r[0].length):-1},b:function(t,e,n){var r=m.exec(e.slice(n));return r?(t.m=v.get(r[0].toLowerCase()),n+r[0].length):-1},B:function(t,e,n){var r=y.exec(e.slice(n));return r?(t.m=g.get(r[0].toLowerCase()),n+r[0].length):-1},c:function(t,n,r){return T(t,e,n,r)},d:ah,e:ah,f:hh,g:eh,G:th,H:sh,I:sh,j:oh,L:lh,m:ih,M:ch,p:function(t,e,n){var r=u.exec(e.slice(n));return r?(t.p=l.get(r[0].toLowerCase()),n+r[0].length):-1},q:rh,Q:dh,s:ph,S:uh,u:Zl,U:Ql,V:Kl,w:Xl,W:Jl,x:function(t,e,r){return T(t,n,e,r)},X:function(t,e,n){return T(t,r,e,n)},y:eh,Y:th,Z:nh,"%":fh};function w(t,e){return function(n){var r,i,a,o=[],s=-1,c=0,u=t.length;for(n instanceof Date||(n=new Date(+n));++s53)return null;"w"in a||(a.w=1),"Z"in a?(i=(r=Fl(Pl(a.y,0,1))).getUTCDay(),r=i>4||0===i?pl.ceil(r):pl(r),r=xl.offset(r,7*(a.V-1)),a.y=r.getUTCFullYear(),a.m=r.getUTCMonth(),a.d=r.getUTCDate()+(a.w+6)%7):(i=(r=Rl(Pl(a.y,0,1))).getDay(),r=i>4||0===i?Tl.ceil(r):Tl(r),r=Dl.offset(r,7*(a.V-1)),a.y=r.getFullYear(),a.m=r.getMonth(),a.d=r.getDate()+(a.w+6)%7)}else("W"in a||"U"in a)&&("w"in a||(a.w="u"in a?a.u%7:"W"in a?1:0),i="Z"in a?Fl(Pl(a.y,0,1)).getUTCDay():Rl(Pl(a.y,0,1)).getDay(),a.m=0,a.d="W"in a?(a.w+6)%7+7*a.W-(i+5)%7:a.w+7*a.U-(i+6)%7);return"Z"in a?(a.H+=a.Z/100|0,a.M+=a.Z%100,Fl(a)):Rl(a)}}function T(t,e,n,r){for(var i,a,o=0,s=e.length,c=n.length;o=c)return-1;if(37===(i=e.charCodeAt(o++))){if(i=e.charAt(o++),!(a=x[i in zl?e.charAt(o++):i])||(r=a(t,n,r))<0)return-1}else if(i!=n.charCodeAt(r++))return-1}return r}return b.x=w(n,b),b.X=w(r,b),b.c=w(e,b),_.x=w(n,_),_.X=w(r,_),_.c=w(e,_),{format:function(t){var e=w(t+="",b);return e.toString=function(){return t},e},parse:function(t){var e=k(t+="",!1);return e.toString=function(){return t},e},utcFormat:function(t){var e=w(t+="",_);return e.toString=function(){return t},e},utcParse:function(t){var e=k(t+="",!0);return e.toString=function(){return t},e}}}({dateTime:"%x, %X",date:"%-m/%-d/%Y",time:"%-I:%M:%S %p",periods:["AM","PM"],days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],shortDays:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],months:["January","February","March","April","May","June","July","August","September","October","November","December"],shortMonths:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"]}),Yl=jl.format,jl.parse,jl.utcFormat,jl.utcParse;var af={value:()=>{}};function of(){for(var t,e=0,n=arguments.length,r={};e=0&&(n=t.slice(r+1),t=t.slice(0,r)),t&&!e.hasOwnProperty(t))throw new Error("unknown type: "+t);return{type:t,name:n}}))}function uf(t,e){for(var n,r=0,i=t.length;r0)for(var n,r,i=new Array(n),a=0;a=0&&e._call.call(void 0,t),e=e._next;--pf}()}finally{pf=0,function(){for(var t,e,n=ff,r=1/0;n;)n._call?(r>n._time&&(r=n._time),t=n,n=n._next):(e=n._next,n._next=null,n=t?t._next=e:ff=e);df=t,Af(r)}(),vf=0}}function Sf(){var t=_f.now(),e=t-mf;e>1e3&&(bf-=e,mf=t)}function Af(t){pf||(yf&&(yf=clearTimeout(yf)),t-vf>24?(t<1/0&&(yf=setTimeout(Cf,t-_f.now()-bf)),gf&&(gf=clearInterval(gf))):(gf||(mf=_f.now(),gf=setInterval(Sf,1e3)),pf=1,xf(Cf)))}function Mf(t,e,n){var r=new Tf;return e=null==e?0:+e,r.restart((n=>{r.stop(),t(n+e)}),e,n),r}Tf.prototype=Ef.prototype={constructor:Tf,restart:function(t,e,n){if("function"!=typeof t)throw new TypeError("callback is not a function");n=(null==n?wf():+n)+(null==e?0:+e),this._next||df===this||(df?df._next=this:ff=this,df=this),this._call=t,this._time=n,Af()},stop:function(){this._call&&(this._call=null,this._time=1/0,Af())}};var Nf=hf("start","end","cancel","interrupt"),Df=[];function Of(t,e,n,r,i,a){var o=t.__transition;if(o){if(n in o)return}else t.__transition={};!function(t,e,n){var r,i=t.__transition;function a(c){var u,l,h,f;if(1!==n.state)return s();for(u in i)if((f=i[u]).name===n.name){if(3===f.state)return Mf(a);4===f.state?(f.state=6,f.timer.stop(),f.on.call("interrupt",t,t.__data__,f.index,f.group),delete i[u]):+u0)throw new Error("too late; already scheduled");return n}function Lf(t,e){var n=If(t,e);if(n.state>3)throw new Error("too late; already running");return n}function If(t,e){var n=t.__transition;if(!n||!(n=n[e]))throw new Error("transition not found");return n}function Rf(t,e){return t=+t,e=+e,function(n){return t*(1-n)+e*n}}var Ff,Pf=180/Math.PI,jf={translateX:0,translateY:0,rotate:0,skewX:0,scaleX:1,scaleY:1};function Yf(t,e,n,r,i,a){var o,s,c;return(o=Math.sqrt(t*t+e*e))&&(t/=o,e/=o),(c=t*n+e*r)&&(n-=t*c,r-=e*c),(s=Math.sqrt(n*n+r*r))&&(n/=s,r/=s,c/=s),t*r180?e+=360:e-t>180&&(t+=360),a.push({i:n.push(i(n)+"rotate(",null,r)-2,x:Rf(t,e)})):e&&n.push(i(n)+"rotate("+e+r)}(a.rotate,o.rotate,s,c),function(t,e,n,a){t!==e?a.push({i:n.push(i(n)+"skewX(",null,r)-2,x:Rf(t,e)}):e&&n.push(i(n)+"skewX("+e+r)}(a.skewX,o.skewX,s,c),function(t,e,n,r,a,o){if(t!==n||e!==r){var s=a.push(i(a)+"scale(",null,",",null,")");o.push({i:s-4,x:Rf(t,n)},{i:s-2,x:Rf(e,r)})}else 1===n&&1===r||a.push(i(a)+"scale("+n+","+r+")")}(a.scaleX,a.scaleY,o.scaleX,o.scaleY,s,c),a=o=null,function(t){for(var e,n=-1,r=c.length;++n=1?(n=1,e-1):Math.floor(n*e),i=t[r],a=t[r+1],o=r>0?t[r-1]:2*i-a,s=ra&&(i=e.slice(a,i),s[o]?s[o]+=i:s[++o]=i),(n=n[0])===(r=r[0])?s[o]?s[o]+=r:s[++o]=r:(s[++o]=null,c.push({i:o,x:Rf(n,r)})),a=Qf.lastIndex;return a=0&&(t=t.slice(0,e)),!t||"start"===t}))}(e)?Bf:Lf;return function(){var o=a(this,t),s=o.on;s!==r&&(i=(r=s).copy()).on(e,n),o.on=i}}var gd=iu.prototype.constructor;function md(t){return function(){this.style.removeProperty(t)}}function vd(t,e,n){return function(r){this.style.setProperty(t,e.call(this,r),n)}}function bd(t,e,n){var r,i;function a(){var a=e.apply(this,arguments);return a!==i&&(r=(i=a)&&vd(t,a,n)),r}return a._value=e,a}function _d(t){return function(e){this.textContent=t.call(this,e)}}function xd(t){var e,n;function r(){var r=t.apply(this,arguments);return r!==n&&(e=(n=r)&&_d(r)),e}return r._value=t,r}var wd=0;function kd(t,e,n,r){this._groups=t,this._parents=e,this._name=n,this._id=r}function Td(){return++wd}var Ed=iu.prototype;kd.prototype=function(t){return iu().transition(t)}.prototype={constructor:kd,select:function(t){var e=this._name,n=this._id;"function"!=typeof t&&(t=Hs(t));for(var r=this._groups,i=r.length,a=new Array(i),o=0;o2&&n.state<5,n.state=6,n.timer.stop(),n.on.call(r?"interrupt":"cancel",t,t.__data__,n.index,n.group),delete a[i]):o=!1;o&&delete t.__transition}}(this,t)}))},iu.prototype.transition=function(t){var e,n;t instanceof kd?(e=t._id,t=t._name):(e=Td(),(n=Cd).time=wf(),t=null==t?null:t+"");for(var r=this._groups,i=r.length,a=0;ae?1:t>=e?0:NaN}Yd.prototype={constructor:Yd,appendChild:function(t){return this._parent.insertBefore(t,this._next)},insertBefore:function(t,e){return this._parent.insertBefore(t,e)},querySelector:function(t){return this._parent.querySelector(t)},querySelectorAll:function(t){return this._parent.querySelectorAll(t)}};var Vd="http://www.w3.org/1999/xhtml";const Gd={svg:"http://www.w3.org/2000/svg",xhtml:Vd,xlink:"http://www.w3.org/1999/xlink",xml:"http://www.w3.org/XML/1998/namespace",xmlns:"http://www.w3.org/2000/xmlns/"};function Xd(t){var e=t+="",n=e.indexOf(":");return n>=0&&"xmlns"!==(e=t.slice(0,n))&&(t=t.slice(n+1)),Gd.hasOwnProperty(e)?{space:Gd[e],local:t}:t}function Zd(t){return function(){this.removeAttribute(t)}}function Qd(t){return function(){this.removeAttributeNS(t.space,t.local)}}function Kd(t,e){return function(){this.setAttribute(t,e)}}function Jd(t,e){return function(){this.setAttributeNS(t.space,t.local,e)}}function tp(t,e){return function(){var n=e.apply(this,arguments);null==n?this.removeAttribute(t):this.setAttribute(t,n)}}function ep(t,e){return function(){var n=e.apply(this,arguments);null==n?this.removeAttributeNS(t.space,t.local):this.setAttributeNS(t.space,t.local,n)}}function np(t){return t.ownerDocument&&t.ownerDocument.defaultView||t.document&&t||t.defaultView}function rp(t){return function(){this.style.removeProperty(t)}}function ip(t,e,n){return function(){this.style.setProperty(t,e,n)}}function ap(t,e,n){return function(){var r=e.apply(this,arguments);null==r?this.style.removeProperty(t):this.style.setProperty(t,r,n)}}function op(t,e){return t.style.getPropertyValue(e)||np(t).getComputedStyle(t,null).getPropertyValue(e)}function sp(t){return function(){delete this[t]}}function cp(t,e){return function(){this[t]=e}}function up(t,e){return function(){var n=e.apply(this,arguments);null==n?delete this[t]:this[t]=n}}function lp(t){return t.trim().split(/^|\s+/)}function hp(t){return t.classList||new fp(t)}function fp(t){this._node=t,this._names=lp(t.getAttribute("class")||"")}function dp(t,e){for(var n=hp(t),r=-1,i=e.length;++r=0&&(e=t.slice(n+1),t=t.slice(0,n)),{type:t,name:e}}))}function Lp(t){return function(){var e=this.__on;if(e){for(var n,r=0,i=-1,a=e.length;r=0&&(this._names.splice(e,1),this._node.setAttribute("class",this._names.join(" ")))},contains:function(t){return this._names.indexOf(t)>=0}};var jp=[null];function Yp(t,e){this._groups=t,this._parents=e}function zp(){return new Yp([[document.documentElement]],jp)}Yp.prototype=zp.prototype={constructor:Yp,select:function(t){"function"!=typeof t&&(t=Md(t));for(var e=this._groups,n=e.length,r=new Array(n),i=0;i=x&&(x=_+1);!(b=g[x])&&++x=0;)(r=i[a])&&(o&&4^r.compareDocumentPosition(o)&&o.parentNode.insertBefore(r,o),o=r);return this},sort:function(t){function e(e,n){return e&&n?t(e.__data__,n.__data__):!e-!n}t||(t=Wd);for(var n=this._groups,r=n.length,i=new Array(r),a=0;a1?this.each((null==e?rp:"function"==typeof e?ap:ip)(t,e,null==n?"":n)):op(this.node(),t)},property:function(t,e){return arguments.length>1?this.each((null==e?sp:"function"==typeof e?up:cp)(t,e)):this.node()[t]},classed:function(t,e){var n=lp(t+"");if(arguments.length<2){for(var r=hp(this.node()),i=-1,a=n.length;++i{}};function $p(){for(var t,e=0,n=arguments.length,r={};e=0&&(n=t.slice(r+1),t=t.slice(0,r)),t&&!e.hasOwnProperty(t))throw new Error("unknown type: "+t);return{type:t,name:n}}))}function Vp(t,e){for(var n,r=0,i=t.length;r0)for(var n,r,i=new Array(n),a=0;a=0&&e._call.call(void 0,t),e=e._next;--Kp}()}finally{Kp=0,function(){for(var t,e,n=Zp,r=1/0;n;)n._call?(r>n._time&&(r=n._time),t=n,n=n._next):(e=n._next,n._next=null,n=t?t._next=e:Zp=e);Qp=t,fy(r)}(),ny=0}}function hy(){var t=iy.now(),e=t-ey;e>1e3&&(ry-=e,ey=t)}function fy(t){Kp||(Jp&&(Jp=clearTimeout(Jp)),t-ny>24?(t<1/0&&(Jp=setTimeout(ly,t-iy.now()-ry)),ty&&(ty=clearInterval(ty))):(ty||(ey=iy.now(),ty=setInterval(hy,1e3)),Kp=1,ay(ly)))}function dy(t,e,n){var r=new cy;return e=null==e?0:+e,r.restart((n=>{r.stop(),t(n+e)}),e,n),r}cy.prototype=uy.prototype={constructor:cy,restart:function(t,e,n){if("function"!=typeof t)throw new TypeError("callback is not a function");n=(null==n?oy():+n)+(null==e?0:+e),this._next||Qp===this||(Qp?Qp._next=this:Zp=this,Qp=this),this._call=t,this._time=n,fy()},stop:function(){this._call&&(this._call=null,this._time=1/0,fy())}};var py=Xp("start","end","cancel","interrupt"),yy=[];function gy(t,e,n,r,i,a){var o=t.__transition;if(o){if(n in o)return}else t.__transition={};!function(t,e,n){var r,i=t.__transition;function a(c){var u,l,h,f;if(1!==n.state)return s();for(u in i)if((f=i[u]).name===n.name){if(3===f.state)return dy(a);4===f.state?(f.state=6,f.timer.stop(),f.on.call("interrupt",t,t.__data__,f.index,f.group),delete i[u]):+u0)throw new Error("too late; already scheduled");return n}function vy(t,e){var n=by(t,e);if(n.state>3)throw new Error("too late; already running");return n}function by(t,e){var n=t.__transition;if(!n||!(n=n[e]))throw new Error("transition not found");return n}function _y(t,e){return t=+t,e=+e,function(n){return t*(1-n)+e*n}}var xy,wy=180/Math.PI,ky={translateX:0,translateY:0,rotate:0,skewX:0,scaleX:1,scaleY:1};function Ty(t,e,n,r,i,a){var o,s,c;return(o=Math.sqrt(t*t+e*e))&&(t/=o,e/=o),(c=t*n+e*r)&&(n-=t*c,r-=e*c),(s=Math.sqrt(n*n+r*r))&&(n/=s,r/=s,c/=s),t*r180?e+=360:e-t>180&&(t+=360),a.push({i:n.push(i(n)+"rotate(",null,r)-2,x:_y(t,e)})):e&&n.push(i(n)+"rotate("+e+r)}(a.rotate,o.rotate,s,c),function(t,e,n,a){t!==e?a.push({i:n.push(i(n)+"skewX(",null,r)-2,x:_y(t,e)}):e&&n.push(i(n)+"skewX("+e+r)}(a.skewX,o.skewX,s,c),function(t,e,n,r,a,o){if(t!==n||e!==r){var s=a.push(i(a)+"scale(",null,",",null,")");o.push({i:s-4,x:_y(t,n)},{i:s-2,x:_y(e,r)})}else 1===n&&1===r||a.push(i(a)+"scale("+n+","+r+")")}(a.scaleX,a.scaleY,o.scaleX,o.scaleY,s,c),a=o=null,function(t){for(var e,n=-1,r=c.length;++n>8&15|e>>4&240,e>>4&15|240&e,(15&e)<<4|15&e,1):8===n?Qy(e>>24&255,e>>16&255,e>>8&255,(255&e)/255):4===n?Qy(e>>12&15|e>>8&240,e>>8&15|e>>4&240,e>>4&15|240&e,((15&e)<<4|15&e)/255):null):(e=Yy.exec(t))?new tg(e[1],e[2],e[3],1):(e=zy.exec(t))?new tg(255*e[1]/100,255*e[2]/100,255*e[3]/100,1):(e=Uy.exec(t))?Qy(e[1],e[2],e[3],e[4]):(e=qy.exec(t))?Qy(255*e[1]/100,255*e[2]/100,255*e[3]/100,e[4]):(e=$y.exec(t))?ig(e[1],e[2]/100,e[3]/100,1):(e=Hy.exec(t))?ig(e[1],e[2]/100,e[3]/100,e[4]):Wy.hasOwnProperty(t)?Zy(Wy[t]):"transparent"===t?new tg(NaN,NaN,NaN,0):null}function Zy(t){return new tg(t>>16&255,t>>8&255,255&t,1)}function Qy(t,e,n,r){return r<=0&&(t=e=n=NaN),new tg(t,e,n,r)}function Ky(t){return t instanceof By||(t=Xy(t)),t?new tg((t=t.rgb()).r,t.g,t.b,t.opacity):new tg}function Jy(t,e,n,r){return 1===arguments.length?Ky(t):new tg(t,e,n,null==r?1:r)}function tg(t,e,n,r){this.r=+t,this.g=+e,this.b=+n,this.opacity=+r}function eg(){return"#"+rg(this.r)+rg(this.g)+rg(this.b)}function ng(){var t=this.opacity;return(1===(t=isNaN(t)?1:Math.max(0,Math.min(1,t)))?"rgb(":"rgba(")+Math.max(0,Math.min(255,Math.round(this.r)||0))+", "+Math.max(0,Math.min(255,Math.round(this.g)||0))+", "+Math.max(0,Math.min(255,Math.round(this.b)||0))+(1===t?")":", "+t+")")}function rg(t){return((t=Math.max(0,Math.min(255,Math.round(t)||0)))<16?"0":"")+t.toString(16)}function ig(t,e,n,r){return r<=0?t=e=n=NaN:n<=0||n>=1?t=e=NaN:e<=0&&(t=NaN),new og(t,e,n,r)}function ag(t){if(t instanceof og)return new og(t.h,t.s,t.l,t.opacity);if(t instanceof By||(t=Xy(t)),!t)return new og;if(t instanceof og)return t;var e=(t=t.rgb()).r/255,n=t.g/255,r=t.b/255,i=Math.min(e,n,r),a=Math.max(e,n,r),o=NaN,s=a-i,c=(a+i)/2;return s?(o=e===a?(n-r)/s+6*(n0&&c<1?0:o,new og(o,s,c,t.opacity)}function og(t,e,n,r){this.h=+t,this.s=+e,this.l=+n,this.opacity=+r}function sg(t,e,n){return 255*(t<60?e+(n-e)*t/60:t<180?n:t<240?e+(n-e)*(240-t)/60:e)}function cg(t,e,n,r,i){var a=t*t,o=a*t;return((1-3*t+3*a-o)*e+(4-6*a+3*o)*n+(1+3*t+3*a-3*o)*r+o*i)/6}Dy(By,Xy,{copy:function(t){return Object.assign(new this.constructor,this,t)},displayable:function(){return this.rgb().displayable()},hex:Vy,formatHex:Vy,formatHsl:function(){return ag(this).formatHsl()},formatRgb:Gy,toString:Gy}),Dy(tg,Jy,Oy(By,{brighter:function(t){return t=null==t?Iy:Math.pow(Iy,t),new tg(this.r*t,this.g*t,this.b*t,this.opacity)},darker:function(t){return t=null==t?Ly:Math.pow(Ly,t),new tg(this.r*t,this.g*t,this.b*t,this.opacity)},rgb:function(){return this},displayable:function(){return-.5<=this.r&&this.r<255.5&&-.5<=this.g&&this.g<255.5&&-.5<=this.b&&this.b<255.5&&0<=this.opacity&&this.opacity<=1},hex:eg,formatHex:eg,formatRgb:ng,toString:ng})),Dy(og,(function(t,e,n,r){return 1===arguments.length?ag(t):new og(t,e,n,null==r?1:r)}),Oy(By,{brighter:function(t){return t=null==t?Iy:Math.pow(Iy,t),new og(this.h,this.s,this.l*t,this.opacity)},darker:function(t){return t=null==t?Ly:Math.pow(Ly,t),new og(this.h,this.s,this.l*t,this.opacity)},rgb:function(){var t=this.h%360+360*(this.h<0),e=isNaN(t)||isNaN(this.s)?0:this.s,n=this.l,r=n+(n<.5?n:1-n)*e,i=2*n-r;return new tg(sg(t>=240?t-240:t+120,i,r),sg(t,i,r),sg(t<120?t+240:t-120,i,r),this.opacity)},displayable:function(){return(0<=this.s&&this.s<=1||isNaN(this.s))&&0<=this.l&&this.l<=1&&0<=this.opacity&&this.opacity<=1},formatHsl:function(){var t=this.opacity;return(1===(t=isNaN(t)?1:Math.max(0,Math.min(1,t)))?"hsl(":"hsla(")+(this.h||0)+", "+100*(this.s||0)+"%, "+100*(this.l||0)+"%"+(1===t?")":", "+t+")")}}));const ug=t=>()=>t;function lg(t,e){var n=e-t;return n?function(t,e){return function(n){return t+n*e}}(t,n):ug(isNaN(t)?e:t)}const hg=function t(e){var n=function(t){return 1==(t=+t)?lg:function(e,n){return n-e?function(t,e,n){return t=Math.pow(t,n),e=Math.pow(e,n)-t,n=1/n,function(r){return Math.pow(t+r*e,n)}}(e,n,t):ug(isNaN(e)?n:e)}}(e);function r(t,e){var r=n((t=Jy(t)).r,(e=Jy(e)).r),i=n(t.g,e.g),a=n(t.b,e.b),o=lg(t.opacity,e.opacity);return function(e){return t.r=r(e),t.g=i(e),t.b=a(e),t.opacity=o(e),t+""}}return r.gamma=t,r}(1);function fg(t){return function(e){var n,r,i=e.length,a=new Array(i),o=new Array(i),s=new Array(i);for(n=0;n=1?(n=1,e-1):Math.floor(n*e),i=t[r],a=t[r+1],o=r>0?t[r-1]:2*i-a,s=ra&&(i=e.slice(a,i),s[o]?s[o]+=i:s[++o]=i),(n=n[0])===(r=r[0])?s[o]?s[o]+=r:s[++o]=r:(s[++o]=null,c.push({i:o,x:_y(n,r)})),a=pg.lastIndex;return a=0&&(t=t.slice(0,e)),!t||"start"===t}))}(e)?my:vy;return function(){var o=a(this,t),s=o.on;s!==r&&(i=(r=s).copy()).on(e,n),o.on=i}}var Bg=Up.prototype.constructor;function Lg(t){return function(){this.style.removeProperty(t)}}function Ig(t,e,n){return function(r){this.style.setProperty(t,e.call(this,r),n)}}function Rg(t,e,n){var r,i;function a(){var a=e.apply(this,arguments);return a!==i&&(r=(i=a)&&Ig(t,a,n)),r}return a._value=e,a}function Fg(t){return function(e){this.textContent=t.call(this,e)}}function Pg(t){var e,n;function r(){var r=t.apply(this,arguments);return r!==n&&(e=(n=r)&&Fg(r)),e}return r._value=t,r}var jg=0;function Yg(t,e,n,r){this._groups=t,this._parents=e,this._name=n,this._id=r}function zg(){return++jg}var Ug=Up.prototype;Yg.prototype=function(t){return Up().transition(t)}.prototype={constructor:Yg,select:function(t){var e=this._name,n=this._id;"function"!=typeof t&&(t=Md(t));for(var r=this._groups,i=r.length,a=new Array(i),o=0;o2&&n.state<5,n.state=6,n.timer.stop(),n.on.call(r?"interrupt":"cancel",t,t.__data__,n.index,n.group),delete a[i]):o=!1;o&&delete t.__transition}}(this,t)}))},Up.prototype.transition=function(t){var e,n;t instanceof Yg?(e=t._id,t=t._name):(e=zg(),(n=qg).time=oy(),t=null==t?null:t+"");for(var r=this._groups,i=r.length,a=0;a0?Jg(hm,--um):0,sm--,10===lm&&(sm=1,om--),lm}function pm(){return lm=um2||vm(lm)>3?"":" "}function xm(t,e){for(;--e&&pm()&&!(lm<48||lm>102||lm>57&&lm<65||lm>70&&lm<97););return mm(t,gm()+(e<6&&32==ym()&&32==pm()))}function wm(t){for(;pm();)switch(lm){case t:return um;case 34:case 39:return wm(34===t||39===t?t:lm);case 40:41===t&&wm(t);break;case 92:pm()}return um}function km(t,e){for(;pm()&&t+lm!==57&&(t+lm!==84||47!==ym()););return"/*"+mm(e,um-1)+"*"+Zg(47===t?t:pm())}function Tm(t){for(;!vm(ym());)pm();return mm(t,um)}function Em(t){return function(t){return hm="",t}(Cm("",null,null,null,[""],t=function(t){return om=sm=1,cm=em(hm=t),um=0,[]}(t),0,[0],t))}function Cm(t,e,n,r,i,a,o,s,c){for(var u=0,l=0,h=o,f=0,d=0,p=0,y=1,g=1,m=1,v=0,b="",_=i,x=a,w=r,k=b;g;)switch(p=v,v=pm()){case 34:case 39:case 91:case 40:k+=bm(v);break;case 9:case 10:case 13:case 32:k+=_m(p);break;case 92:k+=xm(gm()-1,7);continue;case 47:switch(ym()){case 42:case 47:rm(Am(km(pm(),gm()),e,n),c);break;default:k+="/"}break;case 123*y:s[u++]=em(k)*m;case 125*y:case 59:case 0:switch(v){case 0:case 125:g=0;case 59+l:d>0&&em(k)-h&&rm(d>32?Mm(k+";",r,n,h-1):Mm(Kg(k," ","")+";",r,n,h-2),c);break;case 59:k+=";";default:if(rm(w=Sm(k,e,n,u,l,i,s,b,_=[],x=[],h),a),123===v)if(0===l)Cm(k,e,w,w,_,a,h,s,x);else switch(f){case 100:case 109:case 115:Cm(t,w,w,r&&rm(Sm(t,w,w,0,0,i,s,b,i,_=[],h),x),i,x,h,s,r?_:x);break;default:Cm(k,w,w,w,[""],x,h,s,x)}}u=l=d=0,y=m=1,b=k="",h=o;break;case 58:h=1+em(k),d=p;default:if(y<1)if(123==v)--y;else if(125==v&&0==y++&&125==dm())continue;switch(k+=Zg(v),v*y){case 38:m=l>0?1:(k+="\f",-1);break;case 44:s[u++]=(em(k)-1)*m,m=1;break;case 64:45===ym()&&(k+=bm(pm())),f=ym(),l=em(b=k+=Tm(gm())),v++;break;case 45:45===p&&2==em(k)&&(y=0)}}return a}function Sm(t,e,n,r,i,a,o,s,c,u,l){for(var h=i-1,f=0===i?a:[""],d=nm(f),p=0,y=0,g=0;p0?f[m]+" "+v:Kg(v,/&\f/g,f[m])))&&(c[g++]=b);return fm(t,e,n,0===i?Vg:s,c,u,l)}function Am(t,e,n){return fm(t,e,n,Wg,Zg(lm),tm(t,2,-2),0)}function Mm(t,e,n,r){return fm(t,e,n,Gg,tm(t,0,r),tm(t,r+1,-1),r)}const Nm="8.13.4";var Dm=n(9609),Om=n(7856),Bm=n.n(Om),Lm=function(t){for(var e="",n=0;n>=0;){if(!((n=t.indexOf("=0)){e+=t,n=-1;break}e+=t.substr(0,n),(n=(t=t.substr(n+1)).indexOf("<\/script>"))>=0&&(n+=9,t=t.substr(n))}return(e=(e=(e=(e=e.replace(/script>/gi,"#")).replace(/script>/gi,"#")).replace(/javascript:/gi,"#")).replace(/onerror=/gi,"onerror:")).replace(/